diff --git a/lib/mayaUsd/render/vp2RenderDelegate/basisCurves.cpp b/lib/mayaUsd/render/vp2RenderDelegate/basisCurves.cpp index 5e8f6cd1bd..63ee6ab859 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/basisCurves.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/basisCurves.cpp @@ -509,7 +509,7 @@ void HdVP2BasisCurves::Sync( const TfToken& renderTag = delegate->GetRenderTag(id); #endif - _SyncSharedData(_sharedData, delegate, dirtyBits, reprToken, id, _reprs, renderTag); + _SyncSharedData(_sharedData, delegate, dirtyBits, reprToken, *this, _reprs, renderTag); *dirtyBits = HdChangeTracker::Clean; @@ -566,6 +566,8 @@ void HdVP2BasisCurves::_UpdateDrawItem( // doesn't need to extract index data from topology. Points use non-indexed // draw. const bool isBoundingBoxItem = (drawMode == MHWRender::MGeometry::kBoundingBox); + const bool isHighlightItem = drawItem->ContainsUsage(HdVP2DrawItem::kSelectionHighlight); + const bool inTemplateMode = _displayType == MayaUsdRPrim::kTemplate; #ifdef MAYA_NEW_POINT_SNAPPING_SUPPORT constexpr bool isPointSnappingItem = false; @@ -699,8 +701,8 @@ void HdVP2BasisCurves::_UpdateDrawItem( if (material) { MHWRender::MShaderInstance* shader = material->GetSurfaceShader(); - if (shader != nullptr - && (shader != drawItemData._shader || shader != stateToCommit._shader)) { + drawItemData._shaderIsFallback = (shader == nullptr); + if (shader != nullptr && shader != drawItemData._shader) { drawItemData._shader = shader; stateToCommit._shader = shader; stateToCommit._isTransparent = shader->isTransparent(); @@ -718,6 +720,8 @@ void HdVP2BasisCurves::_UpdateDrawItem( drawItemData._primitiveStride = primitiveStride; stateToCommit._primitiveStride = &drawItemData._primitiveStride; } + } else { + drawItemData._shaderIsFallback = true; } } @@ -776,7 +780,7 @@ void HdVP2BasisCurves::_UpdateDrawItem( // Use fallback shader if there is no material binding or we failed to create a shader // instance from the material. - if (!stateToCommit._shader) { + if (drawItemData._shaderIsFallback) { MHWRender::MShaderInstance* shader = nullptr; MHWRender::MGeometry::Primitive primitiveType = MHWRender::MGeometry::kLines; int primitiveStride = 0; @@ -934,7 +938,7 @@ void HdVP2BasisCurves::_UpdateDrawItem( // If the item is used for both regular draw and selection highlight, // it needs to display both wireframe color and selection highlight // with one color vertex buffer. - if (drawItem->ContainsUsage(HdVP2DrawItem::kSelectionHighlight)) { + if (isHighlightItem) { const MColor colors[] = { drawScene.GetWireframeColor(), drawScene.GetSelectionHighlightColor(HdPrimTypeTokens->basisCurves), @@ -986,21 +990,25 @@ void HdVP2BasisCurves::_UpdateDrawItem( } else { // Non-instanced Rprims. if (itemDirtyBits & (DirtySelectionHighlight | HdChangeTracker::DirtyDisplayStyle)) { - if (drawItem->ContainsUsage(HdVP2DrawItem::kRegular) - && drawItem->ContainsUsage(HdVP2DrawItem::kSelectionHighlight)) { + if (drawItem->ContainsUsage(HdVP2DrawItem::kRegular) && isHighlightItem) { MHWRender::MShaderInstance* shader = nullptr; auto primitiveType = MHWRender::MGeometry::kLines; int primitiveStride = 0; - const MColor& color - = (_selectionStatus != kUnselected ? drawScene.GetSelectionHighlightColor( - _selectionStatus == kFullyLead ? TfToken() - : HdPrimTypeTokens->basisCurves) - : drawScene.GetWireframeColor()); + MColor color; + if (inTemplateMode) { + color = drawScene.GetTemplateColor(_selectionStatus != kUnselected); + } else { + color + = (_selectionStatus != kUnselected ? drawScene.GetSelectionHighlightColor( + _selectionStatus == kFullyLead ? TfToken() + : HdPrimTypeTokens->basisCurves) + : drawScene.GetWireframeColor()); + } if (desc.geomStyle == HdBasisCurvesGeomStylePatch) { - if (_selectionStatus != kUnselected) { + if (_selectionStatus != kUnselected || inTemplateMode) { if (refineLevel <= 0) { shader = _delegate->Get3dSolidShader(color); } else { @@ -1060,19 +1068,26 @@ void HdVP2BasisCurves::_UpdateDrawItem( | HdChangeTracker::DirtyPrimvar | HdChangeTracker::DirtyTopology | DirtySelectionHighlight)); -#ifdef MAYA_NEW_POINT_SNAPPING_SUPPORT - if ((itemDirtyBits & DirtySelectionHighlight) && !isBoundingBoxItem) { + // update selection mask if dirty + if (itemDirtyBits & DirtySelectionHighlight) { MSelectionMask selectionMask(MSelectionMask::kSelectNurbsCurves); - // Only unselected Rprims can be used for point snapping. - if (_selectionStatus == kUnselected) { - selectionMask.addMask(MSelectionMask::kSelectPointsForGravity); +#ifdef MAYA_NEW_POINT_SNAPPING_SUPPORT + if (!isBoundingBoxItem) { + // Only unselected Rprims can be used for point snapping. + if (_selectionStatus == kUnselected) { + selectionMask.addMask(MSelectionMask::kSelectPointsForGravity); + } + } +#endif + // In template mode, items should have no selection + if (inTemplateMode) { + selectionMask = MSelectionMask(); } // The function is thread-safe, thus called in place to keep simple. renderItem->setSelectionMask(selectionMask); } -#endif // Reset dirty bits because we've prepared commit state for this draw item. drawItem->ResetDirtyBits(); diff --git a/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.cpp b/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.cpp index c94b42d6b9..78d43826c8 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.cpp @@ -563,10 +563,12 @@ void MayaUsdRPrim::_SyncSharedData( HdSceneDelegate* delegate, HdDirtyBits const* dirtyBits, TfToken const& reprToken, - SdfPath const& id, + HdRprim const& refThis, ReprVector const& reprs, TfToken const& renderTag) { + const SdfPath& id = refThis.GetId(); + if (HdChangeTracker::IsExtentDirty(*dirtyBits, id)) { sharedData.bounds.SetRange(delegate->GetExtent(id)); } @@ -588,32 +590,40 @@ void MayaUsdRPrim::_SyncSharedData( bool displayLayerVisibility = true; // objects in the default display layer are visible #ifdef MAYA_HAS_DISPLAY_LAYER_API bool hideOnPlayback = false; + _displayType = kNormal; // Maya Display Layers do not have a representation in USD, so a prim can be // visible from USD's point of view, but hidden from Maya's point of view. // In Maya Display Layer visibility really hides the render items vs. using // render item filtering (like for example the "Show" menu). So we want to // set the "enabled" state of the MRenderItem. - // Get all the display layers the object is affected by. If any of those layers - // are invisible, the object is invisible. - MFnDisplayLayerManager displayLayerManager( - MFnDisplayLayerManager::currentDisplayLayerManager()); - MStatus status; - auto* const param = static_cast(_delegate->GetRenderParam()); - ProxyRenderDelegate& drawScene = param->GetDrawScene(); - MDagPath proxyDagPath = drawScene.GetProxyShapeDagPath(); - MString pathString = proxyDagPath.fullPathName() - + Ufe::PathString::pathSegmentSeparator().c_str() + _PrimSegmentString[0]; - MObjectArray ancestorDisplayLayers - = displayLayerManager.getAncestorLayersInclusive(pathString, &status); - for (unsigned int i = 0; i < ancestorDisplayLayers.length() && displayLayerVisibility; - i++) { - MFnDependencyNode displayLayerNodeFn(ancestorDisplayLayers[i]); - MPlug layerEnabled = displayLayerNodeFn.findPlug("enabled"); - MPlug layerVisible = displayLayerNodeFn.findPlug("visibility"); - MPlug layerHidesOnPlayback = displayLayerNodeFn.findPlug("hideOnPlayback"); - displayLayerVisibility &= layerEnabled.asBool() ? layerVisible.asBool() : true; - hideOnPlayback |= layerHidesOnPlayback.asBool(); + // Display layer features are currently implemented only for non-instanced geometry + if (refThis.GetInstancerId().IsEmpty()) { + // Get all the display layers the object is affected by. If any of those layers + // are invisible, the object is invisible. + MFnDisplayLayerManager displayLayerManager( + MFnDisplayLayerManager::currentDisplayLayerManager()); + MStatus status; + auto* const param = static_cast(_delegate->GetRenderParam()); + ProxyRenderDelegate& drawScene = param->GetDrawScene(); + MDagPath proxyDagPath = drawScene.GetProxyShapeDagPath(); + MString pathString = proxyDagPath.fullPathName() + + Ufe::PathString::pathSegmentSeparator().c_str() + _PrimSegmentString[0]; + MObjectArray ancestorDisplayLayers + = displayLayerManager.getAncestorLayersInclusive(pathString, &status); + for (unsigned int i = 0; i < ancestorDisplayLayers.length() && displayLayerVisibility; + i++) { + MFnDependencyNode displayLayerNodeFn(ancestorDisplayLayers[i]); + MPlug layerEnabled = displayLayerNodeFn.findPlug("enabled"); + MPlug layerVisible = displayLayerNodeFn.findPlug("visibility"); + MPlug layerHidesOnPlayback = displayLayerNodeFn.findPlug("hideOnPlayback"); + MPlug layerDisplayType = displayLayerNodeFn.findPlug("displayType"); + displayLayerVisibility &= layerEnabled.asBool() ? layerVisible.asBool() : true; + hideOnPlayback |= layerHidesOnPlayback.asBool(); + if (_displayType == kNormal) { + _displayType = (DisplayType)layerDisplayType.asShort(); + } + } } // Update "hide on playback" status diff --git a/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.h b/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.h index e53fe218eb..b5989a558d 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.h +++ b/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.h @@ -172,6 +172,13 @@ class MayaUsdRPrim void(const TfToken& name, const VtValue& value, const HdInterpolation interpolation)>; using ErasePrimvarInfoFunc = std::function; + enum DisplayType + { + kNormal = 0, + kTemplate = 1, + kReference = 2 + }; + void _CommitMVertexBuffer(MHWRender::MVertexBuffer* const, void*) const; void _UpdateTransform( @@ -201,7 +208,7 @@ class MayaUsdRPrim HdSceneDelegate* delegate, HdDirtyBits const* dirtyBits, TfToken const& reprToken, - SdfPath const& id, + HdRprim const& refThis, ReprVector const& reprs, TfToken const& renderTag); @@ -259,6 +266,9 @@ class MayaUsdRPrim //! HideOnPlayback status of the Rprim bool _hideOnPlayback { false }; + //! Display type of the Rprim + DisplayType _displayType { kNormal }; + //! The string representation of the runtime only path to this object MStringArray _PrimSegmentString; }; diff --git a/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp b/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp index fd2238d01d..3261b3263c 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp @@ -1008,7 +1008,7 @@ void HdVP2Mesh::Sync( const TfToken& renderTag = delegate->GetRenderTag(id); #endif - _SyncSharedData(_sharedData, delegate, dirtyBits, reprToken, id, _reprs, renderTag); + _SyncSharedData(_sharedData, delegate, dirtyBits, reprToken, *this, _reprs, renderTag); *dirtyBits = HdChangeTracker::Clean; @@ -1456,12 +1456,16 @@ void HdVP2Mesh::_UpdateDrawItem( const bool usingShadedSelectedInstanceItem = false; #endif - // We don't need to update the dedicated selection highlight item when there - // is no selection highlight change and the mesh is not selected. Draw item - // has its own dirty bits, so update will be done when it shows in viewport. - const bool isDedicatedSelectionHighlightItem + const bool isDedicatedHighlightItem = drawItem->MatchesUsage(HdVP2DrawItem::kSelectionHighlight); - if (isDedicatedSelectionHighlightItem && ((itemDirtyBits & DirtySelectionHighlight) == 0) + const bool isHighlightItem = drawItem->ContainsUsage(HdVP2DrawItem::kSelectionHighlight); + const bool inTemplateMode = _displayType == MayaUsdRPrim::kTemplate; + const bool inPureSelectionHighlightMode = isDedicatedHighlightItem && !inTemplateMode; + + // We don't need to update the selection-highlight-only item when there is no selection + // highlight change and the mesh is not selected. Render item stores its own + // dirty bits, so the proper update will be done when it shows in the viewport. + if (inPureSelectionHighlightMode && ((itemDirtyBits & DirtySelectionHighlight) == 0) && (_selectionStatus == kUnselected)) { return; } @@ -1722,7 +1726,7 @@ void HdVP2Mesh::_UpdateDrawItem( unsigned char modeActive = invalid; unsigned char modeLead = invalid; - if (!drawItem->ContainsUsage(HdVP2DrawItem::kSelectionHighlight)) { + if (!isHighlightItem) { stateToCommit._instanceColorParam = kDiffuseColorStr; if (!usingShadedSelectedInstanceItem) { if (isShadedSelectedInstanceItem) { @@ -1749,7 +1753,7 @@ void HdVP2Mesh::_UpdateDrawItem( modeDormant = _selectionStatus == kFullyLead ? lead : active; stateToCommit._instanceColorParam = kSolidColorStr; } else { - modeDormant = isDedicatedSelectionHighlightItem ? invalid : dormant; + modeDormant = inPureSelectionHighlightMode ? invalid : dormant; modeActive = active; modeLead = lead; stateToCommit._instanceColorParam = kSolidColorStr; @@ -1950,12 +1954,16 @@ void HdVP2Mesh::_UpdateDrawItem( } else { // Non-instanced Rprims. - if ((itemDirtyBits & DirtySelectionHighlight) - && drawItem->ContainsUsage(HdVP2DrawItem::kSelectionHighlight)) { - const MColor& color - = (_selectionStatus != kUnselected ? drawScene.GetSelectionHighlightColor( - _selectionStatus == kFullyLead ? TfToken() : HdPrimTypeTokens->mesh) - : drawScene.GetWireframeColor()); + if ((itemDirtyBits & DirtySelectionHighlight) && isHighlightItem) { + MColor color; + if (inTemplateMode) { + color = drawScene.GetTemplateColor(_selectionStatus != kUnselected); + } else { + color + = (_selectionStatus != kUnselected ? drawScene.GetSelectionHighlightColor( + _selectionStatus == kFullyLead ? TfToken() : HdPrimTypeTokens->mesh) + : drawScene.GetWireframeColor()); + } MHWRender::MShaderInstance* shader = _delegate->Get3dSolidShader(color); if (shader != nullptr && shader != drawItemData._shader) { @@ -1975,7 +1983,7 @@ void HdVP2Mesh::_UpdateDrawItem( bool enable = drawItem->GetVisible() && !_points(_meshSharedData->_primvarInfo).empty() && !instancerWithNoInstances; - if (isDedicatedSelectionHighlightItem) { + if (inPureSelectionHighlightMode) { enable = enable && (_selectionStatus != kUnselected); } else if (isPointSnappingItem) { enable = enable && (_selectionStatus == kUnselected); @@ -1983,6 +1991,10 @@ void HdVP2Mesh::_UpdateDrawItem( enable = enable && !range.IsEmpty(); } + if (inTemplateMode) { + enable = enable && isHighlightItem; + } + enable = enable && drawScene.DrawRenderTag(_meshSharedData->_renderTag); if (drawItemData._enabled != enable) { @@ -1996,26 +2008,40 @@ void HdVP2Mesh::_UpdateDrawItem( & (HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyNormals | HdChangeTracker::DirtyPrimvar | HdChangeTracker::DirtyTopology)); -#ifdef MAYA_NEW_POINT_SNAPPING_SUPPORT - if (!isBBoxItem && !isDedicatedSelectionHighlightItem + // Some items may require selection mask overrides + if (!isDedicatedHighlightItem && !isPointSnappingItem && (itemDirtyBits & (DirtySelectionHighlight | DirtySelectionMode))) { + bool dynamicSelectionMaskItem = false; MSelectionMask selectionMask(MSelectionMask::kSelectMeshes); - bool shadedUnselectedInstances = !isShadedSelectedInstanceItem - && !isDedicatedSelectionHighlightItem && !GetInstancerId().IsEmpty(); - if (_selectionStatus == kUnselected || drawScene.SnapToSelectedObjects() - || shadedUnselectedInstances) { - selectionMask.addMask(MSelectionMask::kSelectPointsForGravity); +#ifdef MAYA_NEW_POINT_SNAPPING_SUPPORT + if (!isBBoxItem) { + dynamicSelectionMaskItem = true; + bool shadedUnselectedInstances + = !isShadedSelectedInstanceItem && !GetInstancerId().IsEmpty(); + if (_selectionStatus == kUnselected || drawScene.SnapToSelectedObjects() + || shadedUnselectedInstances) { + selectionMask.addMask(MSelectionMask::kSelectPointsForGravity); + } + // Only unselected Rprims can be used for point snapping. + if (_selectionStatus == kUnselected && !shadedUnselectedInstances) { + selectionMask.addMask(MSelectionMask::kSelectPointsForGravity); + } } - // Only unselected Rprims can be used for point snapping. - if (_selectionStatus == kUnselected && !shadedUnselectedInstances) { - selectionMask.addMask(MSelectionMask::kSelectPointsForGravity); +#endif + if (isHighlightItem) { + dynamicSelectionMaskItem = true; + // In template mode, items should have no selection + if (inTemplateMode) { + selectionMask = MSelectionMask(); + } } - // The function is thread-safe, thus called in place to keep simple. - renderItem->setSelectionMask(selectionMask); + if (dynamicSelectionMaskItem) { + // The function is thread-safe, thus called in place to keep simple. + renderItem->setSelectionMask(selectionMask); + } } -#endif // Capture buffers we need MHWRender::MIndexBuffer* indexBuffer = drawItemData._indexBuffer.get(); diff --git a/lib/mayaUsd/render/vp2RenderDelegate/points.cpp b/lib/mayaUsd/render/vp2RenderDelegate/points.cpp index f24a8899ed..2281896116 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/points.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/points.cpp @@ -198,7 +198,7 @@ void HdVP2Points::Sync( const TfToken& renderTag = delegate->GetRenderTag(id); #endif - _SyncSharedData(_sharedData, delegate, dirtyBits, reprToken, id, _reprs, renderTag); + _SyncSharedData(_sharedData, delegate, dirtyBits, reprToken, *this, _reprs, renderTag); *dirtyBits = HdChangeTracker::Clean; @@ -262,12 +262,12 @@ void HdVP2Points::_UpdateDrawItem( HdVP2DrawItem* drawItem, HdPointsReprDesc const& desc) { - MHWRender::MRenderItem* renderItem = drawItem->GetRenderItem(); - if (ARCH_UNLIKELY(!renderItem)) { + if (drawItem->GetRenderItems().empty()) { return; } - HdDirtyBits itemDirtyBits = drawItem->GetDirtyBits(); + MHWRender::MRenderItem* renderItem = drawItem->GetRenderItem(); + HdDirtyBits itemDirtyBits = drawItem->GetDirtyBits(); MayaUsdCommitState stateToCommit(drawItem->GetRenderItemData()); HdVP2DrawItem::RenderItemData& drawItemData = stateToCommit._renderItemData; @@ -290,6 +290,8 @@ void HdVP2Points::_UpdateDrawItem( // doesn't need to extract index data from topology. Points use non-indexed // draw. const bool isBoundingBoxItem = (drawMode == MHWRender::MGeometry::kBoundingBox); + const bool isHighlightItem = drawItem->ContainsUsage(HdVP2DrawItem::kSelectionHighlight); + const bool inTemplateMode = _displayType == MayaUsdRPrim::kTemplate; if (desc.geomStyle == HdPointsGeomStylePoints) { // Prepare normals buffer. @@ -391,6 +393,7 @@ void HdVP2Points::_UpdateDrawItem( if (material) { MHWRender::MShaderInstance* shader = material->GetPointShader(); + drawItemData._shaderIsFallback = (shader == nullptr); if (shader != nullptr && shader != drawItemData._shader) { drawItemData._shader = shader; stateToCommit._shader = shader; @@ -409,6 +412,8 @@ void HdVP2Points::_UpdateDrawItem( drawItemData._primitiveStride = primitiveStride; stateToCommit._primitiveStride = &drawItemData._primitiveStride; } + } else { + drawItemData._shaderIsFallback = true; } } @@ -468,7 +473,7 @@ void HdVP2Points::_UpdateDrawItem( // Use fallback shader if there is no material binding or we failed to create a shader // instance from the material. - if (!stateToCommit._shader) { + if (drawItemData._shaderIsFallback) { MHWRender::MShaderInstance* shader = nullptr; MHWRender::MGeometry::Primitive primitiveType = MHWRender::MGeometry::kPoints; int primitiveStride = 0; @@ -617,7 +622,7 @@ void HdVP2Points::_UpdateDrawItem( // If the item is used for both regular draw and selection highlight, // it needs to display both wireframe color and selection highlight // with one color vertex buffer. - if (drawItem->ContainsUsage(HdVP2DrawItem::kSelectionHighlight)) { + if (isHighlightItem) { const MColor colors[] = { drawScene.GetWireframeColor(), drawScene.GetSelectionHighlightColor(HdPrimTypeTokens->points), @@ -669,20 +674,25 @@ void HdVP2Points::_UpdateDrawItem( } else { // Non-instanced Rprims. if (itemDirtyBits & (DirtySelectionHighlight | HdChangeTracker::DirtyDisplayStyle)) { - if (drawItem->ContainsUsage(HdVP2DrawItem::kRegular) - && drawItem->ContainsUsage(HdVP2DrawItem::kSelectionHighlight)) { + if (drawItem->ContainsUsage(HdVP2DrawItem::kRegular) && isHighlightItem) { MHWRender::MShaderInstance* shader = nullptr; auto primitiveType = MHWRender::MGeometry::kPoints; int primitiveStride = 0; - const MColor& color - = (_selectionStatus != kUnselected ? drawScene.GetSelectionHighlightColor( - _selectionStatus == kFullyLead ? TfToken() : HdPrimTypeTokens->points) - : drawScene.GetWireframeColor()); + MColor color; + if (inTemplateMode) { + color = drawScene.GetTemplateColor(_selectionStatus != kUnselected); + } else { + color + = (_selectionStatus != kUnselected ? drawScene.GetSelectionHighlightColor( + _selectionStatus == kFullyLead ? TfToken() + : HdPrimTypeTokens->points) + : drawScene.GetWireframeColor()); + } if (desc.geomStyle == HdPointsGeomStylePoints) { - if (_selectionStatus != kUnselected) { + if (_selectionStatus != kUnselected || inTemplateMode) { shader = _delegate->GetPointsFallbackShader(color); } } else { @@ -734,19 +744,26 @@ void HdVP2Points::_UpdateDrawItem( | HdChangeTracker::DirtyPrimvar | HdChangeTracker::DirtyTopology | DirtySelectionHighlight)); -#ifdef MAYA_NEW_POINT_SNAPPING_SUPPORT - if ((itemDirtyBits & DirtySelectionHighlight) && !isBoundingBoxItem) { + // update selection mask if dirty + if (itemDirtyBits & DirtySelectionHighlight) { MSelectionMask selectionMask(MSelectionMask::kSelectParticleShapes); - // Only unselected Rprims can be used for point snapping. - if (_selectionStatus == kUnselected) { - selectionMask.addMask(MSelectionMask::kSelectPointsForGravity); +#ifdef MAYA_NEW_POINT_SNAPPING_SUPPORT + if (!isBoundingBoxItem) { + // Only unselected Rprims can be used for point snapping. + if (_selectionStatus == kUnselected) { + selectionMask.addMask(MSelectionMask::kSelectPointsForGravity); + } + } +#endif + // In template mode, items should have no selection + if (inTemplateMode) { + selectionMask = MSelectionMask(); } // The function is thread-safe, thus called in place to keep simple. renderItem->setSelectionMask(selectionMask); } -#endif // Reset dirty bits because we've prepared commit state for this draw item. drawItem->ResetDirtyBits(); @@ -966,11 +983,13 @@ void HdVP2Points::_InitRepr(TfToken const& reprToken, HdDirtyBits* dirtyBits) switch (desc.geomStyle) { case HdPointsGeomStylePoints: - renderItem = _CreateFatPointsRenderItem(renderItemName); - drawItem->AddUsage(HdVP2DrawItem::kSelectionHighlight); + if (reprToken == HdReprTokens->smoothHull) { + renderItem = _CreateFatPointsRenderItem(renderItemName); + drawItem->AddUsage(HdVP2DrawItem::kSelectionHighlight); #ifdef HAS_DEFAULT_MATERIAL_SUPPORT_API - renderItem->setDefaultMaterialHandling(MRenderItem::SkipWhenDefaultMaterialActive); + renderItem->setDefaultMaterialHandling(MRenderItem::SkipWhenDefaultMaterialActive); #endif + } break; default: TF_WARN("Unsupported geomStyle"); break; } diff --git a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp index e42380e24f..a9c56e1191 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp @@ -819,7 +819,7 @@ void ProxyRenderDelegate::_DirtyUsdSubtree(const UsdPrim& prim) HdChangeTracker& changeTracker = _renderIndex->GetChangeTracker(); constexpr HdDirtyBits dirtyBits = HdChangeTracker::DirtyVisibility - | MayaUsdRPrim::DirtyDisplayMode | MayaUsdRPrim::DirtySelectionHighlight; + | HdChangeTracker::DirtyDisplayStyle | MayaUsdRPrim::DirtySelectionHighlight; if (prim.IsA()) { auto indexPath = _sceneDelegate->ConvertCachePathToIndexPath(prim.GetPath()); @@ -986,16 +986,32 @@ void ProxyRenderDelegate::_Execute(const MHWRender::MFrameContext& frameContext) // if there are no repr's to update then don't even call sync. if (reprSelector != HdReprSelector()) { + HdDirtyBits dirtyBits = HdChangeTracker::Clean; + + // check to see if representation mode changed if (_defaultCollection->GetReprSelector() != reprSelector) { _defaultCollection->SetReprSelector(reprSelector); _taskController->SetCollection(*_defaultCollection); + dirtyBits |= MayaUsdRPrim::DirtyDisplayMode; + } + +#if MAYA_API_VERSION >= 20230200 + // check to see if the color space changed + MString colorTransformId; + frameContext.viewTransformName(colorTransformId); + if (colorTransformId != _colorTransformId) { + _colorTransformId = colorTransformId; + dirtyBits |= MayaUsdRPrim::DirtySelectionHighlight; + } +#endif + if (dirtyBits != HdChangeTracker::Clean) { // Mark everything "dirty" so that sync is called on everything // If there are multiple views up with different viewport modes then // this is slow. auto& rprims = _renderIndex->GetRprimIds(); for (auto path : rprims) { - changeTracker.MarkRprimDirty(path, MayaUsdRPrim::DirtyDisplayMode); + changeTracker.MarkRprimDirty(path, dirtyBits); } } @@ -1048,11 +1064,14 @@ void ProxyRenderDelegate::update(MSubSceneContainer& container, const MFrameCont // render param's. auto* param = reinterpret_cast(_renderDelegate->GetRenderParam()); param->BeginUpdate(container, _sceneDelegate->GetTime()); + _currentFrameContext = &frameContext; if (_Populate()) { _UpdateSceneDelegate(); _Execute(frameContext); } + + _currentFrameContext = nullptr; param->EndUpdate(); } @@ -1752,6 +1771,51 @@ GfVec3f ProxyRenderDelegate::GetDefaultColor(const TfToken& className) return colorCache->first; } +MColor ProxyRenderDelegate::GetTemplateColor(bool active) +{ + MColorCache& colorCache = active ? _activeTemplateColorCache : _dormantTemplateColorCache; + + // Check the cache. It is safe since colorCache.second is atomic + if (colorCache.second == _frameCounter) { + return colorCache.first; + } + + // Enter the mutex and check the cache again + std::lock_guard mutexGuard(_mayaCommandEngineMutex); + if (colorCache.second == _frameCounter) { + return colorCache.first; + } + + // Construct the query command string. + MString queryCommand; + queryCommand = "displayRGBColor -q \""; + queryCommand += active ? "templateActive" : "templateDormant"; + queryCommand += "\""; + + // Query and return the template color. + MDoubleArray colorResult; + MGlobal::executeCommand(queryCommand, colorResult); + + if (colorResult.length() == 3) { + colorCache.first = MColor(colorResult[0], colorResult[1], colorResult[2]); +#if MAYA_API_VERSION >= 20230200 + if (active && _currentFrameContext) { + colorCache.first = _currentFrameContext->applyViewTransform( + colorCache.first, MFrameContext::kInverse); + } +#endif + } else { + TF_WARN("Failed to obtain template color."); + + // In case of any failure, return the default color + colorCache.first = MColor(0.5f, 0.5f, 0.5f); + } + + // Update the cache and return + colorCache.second = _frameCounter; + return colorCache.first; +} + //! \brief MColor ProxyRenderDelegate::GetSelectionHighlightColor(const TfToken& className) { diff --git a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h index 32d0ef8eb9..76c3d2c2a5 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h +++ b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h @@ -201,6 +201,9 @@ class ProxyRenderDelegate MAYAUSD_CORE_PUBLIC MColor GetSelectionHighlightColor(const TfToken& className = TfToken()); + MAYAUSD_CORE_PUBLIC + MColor GetTemplateColor(bool active); + MAYAUSD_CORE_PUBLIC const HdSelection::PrimSelectionState* GetLeadSelectionState(const SdfPath& path) const; @@ -310,6 +313,7 @@ class ProxyRenderDelegate //!< really need it, but there doesn't seem to be a way to get //!< synchronization running without it) std::unique_ptr _sceneDelegate; //!< USD scene delegate + const MHWRender::MFrameContext* _currentFrameContext = nullptr; bool _isPopulated { false @@ -340,6 +344,9 @@ class ProxyRenderDelegate std::mutex _mayaCommandEngineMutex; uint64_t _frameCounter { 0 }; + // The name of the currently used color space + MString _colorTransformId; + typedef std::pair> MColorCache; typedef std::pair> GfVec3fCache; @@ -347,6 +354,8 @@ class ProxyRenderDelegate MColorCache _activeCurveColorCache { MColor(), 0 }; MColorCache _activePointsColorCache { MColor(), 0 }; MColorCache _leadColorCache { MColor(), 0 }; + MColorCache _activeTemplateColorCache { MColor(), 0 }; + MColorCache _dormantTemplateColorCache { MColor(), 0 }; GfVec3fCache _dormantCurveColorCache { GfVec3f(), 0 }; GfVec3fCache _dormantPointsColorCache { GfVec3f(), 0 };