From cc0cbcb86fa58b4beb22b443c279b65482d0e9af Mon Sep 17 00:00:00 2001 From: David Lanier Date: Thu, 22 Feb 2024 14:40:39 +0100 Subject: [PATCH 1/6] HYDRA-746 : Avoid a crash when mayaHydra is not loaded and update this example with the proper name and fixes from the footprint node --- .../flowViewportAPIMayaLocator/CMakeLists.txt | 5 +- ...r.cpp => mhFlowViewportAPIMayaLocator.cpp} | 309 ++++++++---------- .../mhFlowViewportAPIMayaLocatorStrings.h | 38 +++ .../render/mayaToHydra/testFlowViewportAPI.py | 52 +-- 4 files changed, 207 insertions(+), 197 deletions(-) rename lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/{flowViewportAPIMayaLocator.cpp => mhFlowViewportAPIMayaLocator.cpp} (72%) create mode 100644 lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocatorStrings.h diff --git a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/CMakeLists.txt b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/CMakeLists.txt index 1f93f3e196..fa73c81d34 100644 --- a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/CMakeLists.txt +++ b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/CMakeLists.txt @@ -1,4 +1,4 @@ -set(TARGET_NAME flowViewportAPIMayaLocator) +set(TARGET_NAME mayaHydraFlowViewportAPIMayaLocator) add_library(${TARGET_NAME} SHARED) @@ -7,11 +7,12 @@ add_library(${TARGET_NAME} SHARED) # ----------------------------------------------------------------------------- target_sources(${TARGET_NAME} PRIVATE - flowViewportAPIMayaLocator.cpp + mhFlowViewportAPIMayaLocator.cpp ) set(HEADERS PRIVATE + mhFlowViewportAPIMayaLocatorStrings.h ) # ----------------------------------------------------------------------------- diff --git a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/flowViewportAPIMayaLocator.cpp b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocator.cpp similarity index 72% rename from lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/flowViewportAPIMayaLocator.cpp rename to lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocator.cpp index d5cf868ab9..e005eedccc 100644 --- a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/flowViewportAPIMayaLocator.cpp +++ b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocator.cpp @@ -14,6 +14,9 @@ // limitations under the License. // +//Local headers +#include "mhFlowViewportAPIMayaLocatorStrings.h" + //Flow viewport headers #include #include @@ -38,22 +41,26 @@ #include #include #include - +#include +#include //We use a locator node to deal with creating and filtering hydra primitives as an example. //But you could use another kind of maya plugin. /*To create an instance of this node in maya, please use the following MEL command : -createNode("FlowViewportAPIMayaLocator") +createNode("MhFlowViewportAPIMayaLocator") */ PXR_NAMESPACE_USING_DIRECTIVE ///Maya Locator node subclass to create filtering and data producer scene indices example, to be used with the flow viewport API. -class FlowViewportAPIMayaLocator : public MPxLocatorNode +class MhFlowViewportAPIMayaLocator : public MPxLocatorNode { public: - ~FlowViewportAPIMayaLocator() override; + ~MhFlowViewportAPIMayaLocator() override; + + //Is called when the MObject has been constructed and is valid + void postConstructor() override; MStatus compute( const MPlug& plug, MDataBlock& data ) override; @@ -63,8 +70,8 @@ class FlowViewportAPIMayaLocator : public MPxLocatorNode MStatus preEvaluation(const MDGContext& context, const MEvaluationNode& evaluationNode) override; void getCacheSetup(const MEvaluationNode& evalNode, MNodeCacheDisablingInfo& disablingInfo, MNodeCacheSetupInfo& cacheSetupInfo, MObjectArray& monitoredAttributes) const override; - void SetCubeGridParametersFromAttributes(); - void SetupFlowViewportInterfaces(); + void setCubeGridParametersFromAttributes(); + void setupFlowViewportInterfaces(); //static members static void* creator(); @@ -96,68 +103,22 @@ class FlowViewportAPIMayaLocator : public MPxLocatorNode /// _hydraViewportInformationClient is the viewport information example for a Hydra viewport. std::shared_ptr _hydraViewportInformationClient; ///To be used in hydra viewport API to pass the Maya node's MObject for setting callbacks for filtering and data producer scene indices - MObject _thisMObject; - ///To check if the MObject of this node has changed - MObject _oldMObject; + MObjectHandle _thisMObject; ///To hold the attributeChangedCallback Id to be able to react when the 3D grid creation parameters attributes from this node change. MCallbackId _cbAttributeChangedId = 0; ///To hold the afterOpenCallback Id to be able to react when a File Open has happened. MCallbackId _cbAfterOpenId = 0; - ///To hold the transformAttributeChangedCallback Id to be able to react when the transform matrix has changed. - MCallbackId _cbParentAttributeChangedId; private: - // Private Constructor - FlowViewportAPIMayaLocator(); - /// Init flag to be able to do things only once for this node - bool _init = false; + /// Private Constructor + MhFlowViewportAPIMayaLocator() {} + + ///Update the MObject of this node + void _UpdateThisMObject(); }; namespace { - //Get node inverse transform matrix (needed by instancing in a dataProducerSceneIndex) - MStatus GetNodeInverseTransform(MObject& mObj, GfMatrix4d& outInvTransform) - { - outInvTransform = outInvTransform.SetIdentity(); - - MStatus stat; - - //Try directly if the mObj is a transform node - MObject nodeToGetTransform = mObj; - if ( ! mObj.hasFn(MFn::kTransform)){ - //Try with the parent dag path from that node - MDagPath dagPath = MDagPath::getAPathTo(mObj, &stat); - CHECK_MSTATUS(stat); - dagPath.pop(); - nodeToGetTransform = dagPath.node(); - if ( ! nodeToGetTransform.hasFn(MFn::kTransform)){ - return MStatus::kInvalidParameter;//Stopping here - } - } - - MFnTransform transform(nodeToGetTransform, &stat); - CHECK_MSTATUS(stat); - if (MStatus::kSuccess != stat){ - return MStatus::kFailure; - } - - MMatrix transformMatrix = transform.transformationMatrix(&stat); - CHECK_MSTATUS(stat); - if (MStatus::kSuccess != stat){ - return MStatus::kFailure; - } - - MMatrix invTransform = transformMatrix.inverse(); - memcpy(outInvTransform.GetArray(), invTransform[0], sizeof(double) * 16);//convert from MMatrix to GfMatrix4d - - return MStatus::kSuccess; - } - - //Callback when an attribute of this Maya node changes - void transformAttributeChangedCallback(MNodeMessage::AttributeMessage msg, MPlug& plug, MPlug & otherPlug, void* dataProducerSceneIndexData) - { - } - //Callback when an attribute of this Maya node changes void attributeChangedCallback(MNodeMessage::AttributeMessage msg, MPlug& plug, MPlug & otherPlug, void* dataProducerSceneIndexData) { @@ -165,7 +126,7 @@ namespace return; } - FlowViewportAPIMayaLocator* flowViewportAPIMayaLocator = reinterpret_cast(dataProducerSceneIndexData); + MhFlowViewportAPIMayaLocator* flowViewportAPIMayaLocator = reinterpret_cast(dataProducerSceneIndexData); MPlug parentPlug = plug.parent(); if (plug == flowViewportAPIMayaLocator->mDummyInput || plug == flowViewportAPIMayaLocator->mDummyOutput){ @@ -263,47 +224,44 @@ namespace return; } - FlowViewportAPIMayaLocator* flowViewportAPIMayaLocator = reinterpret_cast(clientData); - flowViewportAPIMayaLocator->SetCubeGridParametersFromAttributes(); - flowViewportAPIMayaLocator->SetupFlowViewportInterfaces(); + MhFlowViewportAPIMayaLocator* flowViewportAPIMayaLocator = reinterpret_cast(clientData); + flowViewportAPIMayaLocator->setCubeGridParametersFromAttributes(); + flowViewportAPIMayaLocator->setupFlowViewportInterfaces(); + } + + // Register all strings used by the plugin C++ code + static MStatus registerMStringResources() + { + MStringResource::registerString(rMayaHydraNotLoadedStringError); + return MS::kSuccess; } }//end of anonymous namespace //Initialization of static members -MTypeId FlowViewportAPIMayaLocator::id( 0x90517 ); -MString FlowViewportAPIMayaLocator::nodeClassification("hydraAPIExample/geometry/FlowViewportAPIMayaLocator"); - -MObject FlowViewportAPIMayaLocator::mNumCubeLevelsX; -MObject FlowViewportAPIMayaLocator::mNumCubeLevelsY; -MObject FlowViewportAPIMayaLocator::mNumCubeLevelsZ; -MObject FlowViewportAPIMayaLocator::mCubeHalfSize; -MObject FlowViewportAPIMayaLocator::mCubeInitalTransform; -MObject FlowViewportAPIMayaLocator::mCubeColor; -MObject FlowViewportAPIMayaLocator::mCubeOpacity; -MObject FlowViewportAPIMayaLocator::mCubesUseInstancing; -MObject FlowViewportAPIMayaLocator::mCubesDeltaTrans; -MObject FlowViewportAPIMayaLocator::mDummyInput; -MObject FlowViewportAPIMayaLocator::mDummyOutput; - -//Macro to create input attribute for the maya node -#define MAKE_INPUT(attr) \ - CHECK_MSTATUS(attr.setKeyable(true) ); \ - CHECK_MSTATUS(attr.setStorable(true) ); \ - CHECK_MSTATUS(attr.setReadable(true) ); \ - CHECK_MSTATUS(attr.setWritable(true) ); \ - CHECK_MSTATUS(attr.setAffectsAppearance(true) ); - -//Macro to create output attribute for the maya node -#define MAKE_OUTPUT(attr) \ -CHECK_MSTATUS ( attr.setKeyable(false) ); \ -CHECK_MSTATUS ( attr.setStorable(false) ); \ -CHECK_MSTATUS ( attr.setReadable(true) ); \ -CHECK_MSTATUS ( attr.setWritable(false) ); +MTypeId MhFlowViewportAPIMayaLocator::id( 0x58000086 ); +MString MhFlowViewportAPIMayaLocator::nodeClassification("hydraAPIExample/geometry/MhFlowViewportAPIMayaLocator"); + +MObject MhFlowViewportAPIMayaLocator::mNumCubeLevelsX; +MObject MhFlowViewportAPIMayaLocator::mNumCubeLevelsY; +MObject MhFlowViewportAPIMayaLocator::mNumCubeLevelsZ; +MObject MhFlowViewportAPIMayaLocator::mCubeHalfSize; +MObject MhFlowViewportAPIMayaLocator::mCubeInitalTransform; +MObject MhFlowViewportAPIMayaLocator::mCubeColor; +MObject MhFlowViewportAPIMayaLocator::mCubeOpacity; +MObject MhFlowViewportAPIMayaLocator::mCubesUseInstancing; +MObject MhFlowViewportAPIMayaLocator::mCubesDeltaTrans; +MObject MhFlowViewportAPIMayaLocator::mDummyInput; +MObject MhFlowViewportAPIMayaLocator::mDummyOutput; + +void MhFlowViewportAPIMayaLocator::postConstructor() +{ + //The MObject has been constructed and is valid + MObject currentMObj = thisMObject(); + //Add the callback when an attribute of this node changes + _cbAttributeChangedId = MNodeMessage::addAttributeChangedCallback(currentMObj, attributeChangedCallback, ((void*)this)); -FlowViewportAPIMayaLocator::FlowViewportAPIMayaLocator() -{ //Get the flow viewport API hydra interfaces int majorVersion = 0; int minorVersion = 0; @@ -336,10 +294,11 @@ FlowViewportAPIMayaLocator::FlowViewportAPIMayaLocator() FvpViewportAPITokens->allRenderers, //We could set only Storm by using "GL" or only Arnold by using "Arnold" or both with "GL, Arnold" nullptr);//DCC node will be filled later + setCubeGridParametersFromAttributes(); } //This is called only when our node is destroyed and the undo queue flushed. -FlowViewportAPIMayaLocator::~FlowViewportAPIMayaLocator() +MhFlowViewportAPIMayaLocator::~MhFlowViewportAPIMayaLocator() { //Remove the callbacks if (_cbAttributeChangedId){ @@ -352,11 +311,6 @@ FlowViewportAPIMayaLocator::~FlowViewportAPIMayaLocator() _cbAfterOpenId = 0; } - if (_cbParentAttributeChangedId){ - CHECK_MSTATUS(MSceneMessage::removeCallback(_cbParentAttributeChangedId)); - _cbParentAttributeChangedId = 0; - } - //The DataProducerSceneIndexExample in its destructor removes itself by calling DataProducerSceneIndexExample::RemoveDataProducerSceneIndex() //Unregister filtering scene index client @@ -368,34 +322,38 @@ FlowViewportAPIMayaLocator::~FlowViewportAPIMayaLocator() informationInterface.UnregisterInformationClient(_hydraViewportInformationClient); } -void FlowViewportAPIMayaLocator::SetCubeGridParametersFromAttributes() +void MhFlowViewportAPIMayaLocator::setCubeGridParametersFromAttributes() { - const MObject mObj = thisMObject(); + MObject mObj = _thisMObject.object(); if (mObj.isNull()){ - return; + _UpdateThisMObject(); + mObj = _thisMObject.object(); + if(mObj.isNull()){ + return; + } } - GetAttributeValue(_cubeGridParams._numLevelsX, mObj, FlowViewportAPIMayaLocator::mNumCubeLevelsX); - GetAttributeValue(_cubeGridParams._numLevelsY, mObj, FlowViewportAPIMayaLocator::mNumCubeLevelsY); - GetAttributeValue(_cubeGridParams._numLevelsZ, mObj, FlowViewportAPIMayaLocator::mNumCubeLevelsZ); + GetAttributeValue(_cubeGridParams._numLevelsX, mObj, MhFlowViewportAPIMayaLocator::mNumCubeLevelsX); + GetAttributeValue(_cubeGridParams._numLevelsY, mObj, MhFlowViewportAPIMayaLocator::mNumCubeLevelsY); + GetAttributeValue(_cubeGridParams._numLevelsZ, mObj, MhFlowViewportAPIMayaLocator::mNumCubeLevelsZ); - GetAttributeValue(_cubeGridParams._halfSize, mObj, FlowViewportAPIMayaLocator::mCubeHalfSize); + GetAttributeValue(_cubeGridParams._halfSize, mObj, MhFlowViewportAPIMayaLocator::mCubeHalfSize); MMatrix mat; - GetMatrixAttributeValue(mat, mObj, FlowViewportAPIMayaLocator::mCubeInitalTransform); + GetMatrixAttributeValue(mat, mObj, MhFlowViewportAPIMayaLocator::mCubeInitalTransform); memcpy(_cubeGridParams._initalTransform.GetArray(), mat[0], sizeof(double) * 16);//convert from MMatrix to GfMatrix4d double3 color; - GetDouble3AttributeValue(color, mObj, FlowViewportAPIMayaLocator::mCubeColor); + GetDouble3AttributeValue(color, mObj, MhFlowViewportAPIMayaLocator::mCubeColor); _cubeGridParams._color.data()[0] = color[0];//Implicit conversion from double to float _cubeGridParams._color.data()[1] = color[1]; _cubeGridParams._color.data()[2] = color[2]; - GetAttributeValue(_cubeGridParams._opacity, mObj, FlowViewportAPIMayaLocator::mCubeOpacity); - GetAttributeValue(_cubeGridParams._useInstancing, mObj, FlowViewportAPIMayaLocator::mCubesUseInstancing); + GetAttributeValue(_cubeGridParams._opacity, mObj, MhFlowViewportAPIMayaLocator::mCubeOpacity); + GetAttributeValue(_cubeGridParams._useInstancing, mObj, MhFlowViewportAPIMayaLocator::mCubesUseInstancing); double3 deltaTrans; - GetDouble3AttributeValue(deltaTrans, mObj, FlowViewportAPIMayaLocator::mCubesDeltaTrans); + GetDouble3AttributeValue(deltaTrans, mObj, MhFlowViewportAPIMayaLocator::mCubesDeltaTrans); _cubeGridParams._deltaTrans.data()[0] = deltaTrans[0];//Implicit conversion from double to float _cubeGridParams._deltaTrans.data()[1] = deltaTrans[1]; _cubeGridParams._deltaTrans.data()[2] = deltaTrans[2]; @@ -403,29 +361,30 @@ void FlowViewportAPIMayaLocator::SetCubeGridParametersFromAttributes() _hydraViewportDataProducerSceneIndexExample.setCubeGridParams(_cubeGridParams); } -void FlowViewportAPIMayaLocator::SetupFlowViewportInterfaces() +void MhFlowViewportAPIMayaLocator::_UpdateThisMObject() { - if (_thisMObject.isNull()){ - MObject currentMObj = thisMObject(); - if (_oldMObject.isNull() || _oldMObject != currentMObj){ - _thisMObject = currentMObj; - _oldMObject = _thisMObject; - } - - if(_thisMObject.isNull()){ - return; - } + if (_thisMObject.isValid()){ + return; } + _thisMObject = thisMObject(); +} + +void MhFlowViewportAPIMayaLocator::setupFlowViewportInterfaces() +{ + _UpdateThisMObject(); + //Set the maya node as a parent for this data producer scene index so that when the node is hidden/deleted/moved it gets applied to the prims produced - GfMatrix4d nodeInvTransform; - GetNodeInverseTransform(_thisMObject, nodeInvTransform); - _hydraViewportDataProducerSceneIndexExample.setContainerNode(&_thisMObject); + MObject obj = _thisMObject.object(); + if (obj.isNull()){ + perror("ERROR : _thisMObject.object() is null, using the maya node to move/hide the prims won't be supported"); + } + + _hydraViewportDataProducerSceneIndexExample.setContainerNode(&obj); _hydraViewportDataProducerSceneIndexExample.addDataProducerSceneIndex(); //Register a filtering scene index client Fvp::FilteringSceneIndexInterface& filteringSceneIndexInterface = Fvp::FilteringSceneIndexInterface::get(); - //Store the MObject* of the maya node in various classes _hydraViewportFilteringSceneIndexClientExample->setDccNode(&_thisMObject); @@ -437,49 +396,23 @@ void FlowViewportAPIMayaLocator::SetupFlowViewportInterfaces() } } -MStatus FlowViewportAPIMayaLocator::compute( const MPlug& plug, MDataBlock& dataBlock) +MStatus MhFlowViewportAPIMayaLocator::compute( const MPlug& plug, MDataBlock& dataBlock) { - //Do it only once per call to this function per node - - if( ! _init){ - SetCubeGridParametersFromAttributes(); - - MObject currentMObj = thisMObject(); - //Add the callback when an attribute of this node changes - _cbAttributeChangedId = MNodeMessage::addAttributeChangedCallback(currentMObj, attributeChangedCallback, ((void*)this)); - - //Also monitor parent DAG node to be able to update the scene index if the parent transform is modified - MStatus stat; - MDagPath parentDagPath = MDagPath::getAPathTo(currentMObj, &stat); - CHECK_MSTATUS(stat); - parentDagPath.pop(); - MObject parentObj = parentDagPath.node(); - _cbParentAttributeChangedId = MNodeMessage::addAttributeChangedCallback(parentObj, transformAttributeChangedCallback, this); - - _init = true; + //The MObject can change if the node gets deleted and deletion being undone + if (! _thisMObject.isValid()){ + setupFlowViewportInterfaces(); } - - //The MObject can change if the node gets deleted and deletion being undone, so always update it in our records - MObject currentMObj = thisMObject(); - if (_oldMObject.isNull() || _oldMObject != currentMObj){ - - _thisMObject = currentMObj; - _oldMObject = _thisMObject; - - SetupFlowViewportInterfaces(); - } - return MS::kSuccess; } -bool FlowViewportAPIMayaLocator::isBounded() const +bool MhFlowViewportAPIMayaLocator::isBounded() const { return true; } //We return as a bounding box the bounding box of the data producer hydra data -MBoundingBox FlowViewportAPIMayaLocator::boundingBox() const +MBoundingBox MhFlowViewportAPIMayaLocator::boundingBox() const { float corner1X, corner1Y, corner1Z, corner2X, corner2Y, corner2Z; _hydraViewportDataProducerSceneIndexExample.getPrimsBoundingBox(corner1X, corner1Y, corner1Z, corner2X, corner2Y, corner2Z); @@ -487,23 +420,37 @@ MBoundingBox FlowViewportAPIMayaLocator::boundingBox() const } // Called before this node is evaluated by Evaluation Manager -MStatus FlowViewportAPIMayaLocator::preEvaluation( +MStatus MhFlowViewportAPIMayaLocator::preEvaluation( const MDGContext& context, const MEvaluationNode& evaluationNode) { return MStatus::kSuccess; } -void FlowViewportAPIMayaLocator::getCacheSetup(const MEvaluationNode& evalNode, MNodeCacheDisablingInfo& disablingInfo, MNodeCacheSetupInfo& cacheSetupInfo, MObjectArray& monitoredAttributes) const +void MhFlowViewportAPIMayaLocator::getCacheSetup(const MEvaluationNode& evalNode, MNodeCacheDisablingInfo& disablingInfo, MNodeCacheSetupInfo& cacheSetupInfo, MObjectArray& monitoredAttributes) const { MPxLocatorNode::getCacheSetup(evalNode, disablingInfo, cacheSetupInfo, monitoredAttributes); assert(!disablingInfo.getCacheDisabled()); cacheSetupInfo.setPreference(MNodeCacheSetupInfo::kWantToCacheByDefault, true); } -void* FlowViewportAPIMayaLocator::creator() +void* MhFlowViewportAPIMayaLocator::creator() { - return new FlowViewportAPIMayaLocator; + int isMayaHydraLoaded = false; + // Validate that the mayaHydra plugin is loaded. + MGlobal::executeCommand( "pluginInfo -query -loaded mayaHydra", isMayaHydraLoaded ); + if( ! isMayaHydraLoaded){ + MStatus status; + MString errorString = MStringResource::getString(rMayaHydraNotLoadedStringError, status); + if (! status){ + status.perror("Cannot retrieve the rMayaHydraNotLoadedStringError string, but you need to load mayaHydra before creating this node"); + }else{ + MGlobal::displayError(errorString); + } + return nullptr; + } + + return new MhFlowViewportAPIMayaLocator; } //--------------------------------------------------------------------------- @@ -511,7 +458,22 @@ void* FlowViewportAPIMayaLocator::creator() // Plugin Registration //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -MStatus FlowViewportAPIMayaLocator::initialize() +//Macro to create input attribute for the maya node +#define MAKE_INPUT(attr) \ + CHECK_MSTATUS(attr.setKeyable(true) ); \ + CHECK_MSTATUS(attr.setStorable(true) ); \ + CHECK_MSTATUS(attr.setReadable(true) ); \ + CHECK_MSTATUS(attr.setWritable(true) ); \ + CHECK_MSTATUS(attr.setAffectsAppearance(true) ); + +//Macro to create output attribute for the maya node +#define MAKE_OUTPUT(attr) \ + CHECK_MSTATUS ( attr.setKeyable(false) ); \ + CHECK_MSTATUS ( attr.setStorable(false) ); \ + CHECK_MSTATUS ( attr.setReadable(true) ); \ + CHECK_MSTATUS ( attr.setWritable(false) ); + +MStatus MhFlowViewportAPIMayaLocator::initialize() { MStatus status; @@ -577,7 +539,6 @@ MStatus FlowViewportAPIMayaLocator::initialize() CHECK_MSTATUS ( addAttribute(mDummyOutput)); CHECK_MSTATUS ( attributeAffects(mDummyInput, mDummyOutput)); - return status; } @@ -588,13 +549,21 @@ MStatus initializePlugin( MObject obj ) static const char * pluginVersion = "1.0"; MFnPlugin plugin( obj, PLUGIN_COMPANY, pluginVersion, "Any"); + // This is done first, so the strings are available. + status = plugin.registerUIStrings(registerMStringResources, "mayaHydraFootPrintNodeInitStrings"); + if (status != MS::kSuccess) + { + status.perror("registerUIStrings"); + return status; + } + status = plugin.registerNode( - "FlowViewportAPIMayaLocator", - FlowViewportAPIMayaLocator::id, - &FlowViewportAPIMayaLocator::creator, - &FlowViewportAPIMayaLocator::initialize, + kMhFlowViewportAPIMayaLocatorNodePluginId, + MhFlowViewportAPIMayaLocator::id, + &MhFlowViewportAPIMayaLocator::creator, + &MhFlowViewportAPIMayaLocator::initialize, MPxNode::kLocatorNode, - &FlowViewportAPIMayaLocator::nodeClassification); + &MhFlowViewportAPIMayaLocator::nodeClassification); if (!status) { status.perror("registerNode"); return status; @@ -608,7 +577,7 @@ MStatus uninitializePlugin( MObject obj) MStatus status; MFnPlugin plugin( obj ); - status = plugin.deregisterNode( FlowViewportAPIMayaLocator::id ); + status = plugin.deregisterNode( MhFlowViewportAPIMayaLocator::id ); if (!status) { status.perror("deregisterNode"); return status; diff --git a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocatorStrings.h b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocatorStrings.h new file mode 100644 index 0000000000..036e2e8241 --- /dev/null +++ b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocatorStrings.h @@ -0,0 +1,38 @@ +// +// Copyright 2024 Autodesk, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef _MAYAHYDRA_FLOW_VIEWPORT_API_MAYA_LOCATOR_STRINGS_ +#define _MAYAHYDRA_FLOW_VIEWPORT_API_MAYA_LOCATOR_STRINGS_ + +//////////////////////////////////////////////////////////////////////////////// +// +// MhFlowViewportAPIMayaLocator Node hydra plugin localization strings +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +// MStringResourceIds contain plug-in id, unique resource id for +// each string and the default value for the string. + +#define kMhFlowViewportAPIMayaLocatorNodePluginId "MhFlowViewportAPIMayaLocator" + +// If a MStringResourceId is added to this list, please register in registerMStringRes() +// in mhFlowViewportAPIMayaLocator.cpp + +#define rMayaHydraNotLoadedStringError MStringResourceId( kMhFlowViewportAPIMayaLocatorNodePluginId, "rMayaHydraNotLoadedStringError", "You need to load the mayaHydra plugin before creating this node.") + +#endif //_MAYAHYDRA_FLOW_VIEWPORT_API_MAYA_LOCATOR_STRINGS_ \ No newline at end of file diff --git a/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py b/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py index f0a38ac2b9..83254b0f96 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py +++ b/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py @@ -44,14 +44,14 @@ def setupScene(self): #Test adding primitives def test_AddingPrimitives(self): self.setupScene() - with PluginLoaded('flowViewportAPIMayaLocator'): + with PluginLoaded('mayaHydraFlowViewportAPIMayaLocator'): #Create a maya sphere sphereNode, sphereShape = cmds.polySphere() cmds.refresh() - #Create a FlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index - flowViewportNodeName = cmds.createNode("FlowViewportAPIMayaLocator") + #Create a MhFlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName = cmds.createNode("MhFlowViewportAPIMayaLocator") self.assertFalse(flowViewportNodeName == None) #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute cmds.setAttr(flowViewportNodeName + '.dummyInput', 2)#setting this will set dirty the dummyOutput attribute @@ -61,7 +61,7 @@ def test_AddingPrimitives(self): self.assertSnapshotClose("add_NodeCreated.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) #Move the transform node, the added prims (cube grid) should move as well - # Get the transform node of the FlowViewportAPIMayaLocator + # Get the transform node of the MhFlowViewportAPIMayaLocator transformNode = cmds.listRelatives(flowViewportNodeName, parent=True)[0] self.assertFalse(transformNode == None) #Select the transform node @@ -71,11 +71,11 @@ def test_AddingPrimitives(self): cmds.refresh() self.assertSnapshotClose("add_NodeMoved.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - #Hide the transform node, this should hide the FlowViewportAPIMayaLocator node and the added prims as well. + #Hide the transform node, this should hide the MhFlowViewportAPIMayaLocator node and the added prims as well. cmds.hide(transformNode) self.assertSnapshotClose("add_NodeHidden.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - #Unhide the transform node, this should unhide the FlowViewportAPIMayaLocator node and the added prims as well. + #Unhide the transform node, this should unhide the MhFlowViewportAPIMayaLocator node and the added prims as well. cmds.showHidden(transformNode) self.assertSnapshotClose("add_NodeUnhidden.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) @@ -111,17 +111,18 @@ def test_AddingPrimitives(self): #Finish by a File New command cmds.file(new=True, force=True) + """ #Test filtering primitives def test_FilteringPrimitives(self): self.setupScene() - with PluginLoaded('flowViewportAPIMayaLocator'): + with PluginLoaded('mayaHydraFlowViewportAPIMayaLocator'): #Create a maya sphere sphereNode, sphereShape = cmds.polySphere() cmds.refresh() - #Create a FlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index - flowViewportNodeName = cmds.createNode("FlowViewportAPIMayaLocator") + #Create a MhFlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName = cmds.createNode("MhFlowViewportAPIMayaLocator") self.assertFalse(flowViewportNodeName == None) #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute cmds.setAttr(flowViewportNodeName + '.dummyInput', 3)#setting this will set dirty the dummyOutput attribute @@ -131,7 +132,7 @@ def test_FilteringPrimitives(self): self.assertSnapshotClose("filter_NodeCreated.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) #Move the transform node, the added prims (cube grid) should move as well - # Get the transform node of the FlowViewportAPIMayaLocator + # Get the transform node of the MhFlowViewportAPIMayaLocator transformNode = cmds.listRelatives(flowViewportNodeName, parent=True)[0] self.assertFalse(transformNode == None) #Select the transform node @@ -157,11 +158,11 @@ def test_FilteringPrimitives(self): cmds.refresh() self.assertSnapshotClose("filter_SphereFilteredAgain.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - #Hide the transform node, this should hide the FlowViewportAPIMayaLocator shape node and disable the filtering as well. + #Hide the transform node, this should hide the MhFlowViewportAPIMayaLocator shape node and disable the filtering as well. cmds.hide(transformNode) self.assertSnapshotClose("filter_NodeHidden.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - #Unhide the transform node, this should unhide the FlowViewportAPIMayaLocator node and enable the filtering as well. + #Unhide the transform node, this should unhide the MhFlowViewportAPIMayaLocator node and enable the filtering as well. cmds.showHidden(transformNode) self.assertSnapshotClose("filter_NodeUnhidden.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) @@ -200,10 +201,10 @@ def test_FilteringPrimitives(self): #Test Cube grids parameters def test_CubeGrid(self): self.setupScene() - with PluginLoaded('flowViewportAPIMayaLocator'): + with PluginLoaded('mayaHydraFlowViewportAPIMayaLocator'): - #Create a FlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index - flowViewportNodeName = cmds.createNode("FlowViewportAPIMayaLocator") + #Create a MhFlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName = cmds.createNode("MhFlowViewportAPIMayaLocator") self.assertFalse(flowViewportNodeName == None) #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute @@ -256,10 +257,10 @@ def test_CubeGrid(self): #Test multiple nodes def test_MultipleNodes(self): self.setupScene() - with PluginLoaded('flowViewportAPIMayaLocator'): + with PluginLoaded('mayaHydraFlowViewportAPIMayaLocator'): - #Create a FlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index - flowViewportNodeName1 = cmds.createNode("FlowViewportAPIMayaLocator", n="nodeShape1") + #Create a MhFlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName1 = cmds.createNode("MhFlowViewportAPIMayaLocator", n="nodeShape1") self.assertFalse(flowViewportNodeName1 == None) #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute @@ -284,7 +285,7 @@ def test_MultipleNodes(self): cmds.refresh() #Move the transform node, the added prims (cube grid) should move as well - # Get the transform node of the FlowViewportAPIMayaLocator + # Get the transform node of the MhFlowViewportAPIMayaLocator transformNode1 = cmds.listRelatives(flowViewportNodeName1, parent=True)[0] self.assertFalse(transformNode1 == None) #Select the transform node @@ -293,8 +294,8 @@ def test_MultipleNodes(self): cmds.move(-10, 0, 0) cmds.refresh() - #Create a FlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index - flowViewportNodeName2 = cmds.createNode("FlowViewportAPIMayaLocator", n="nodeShape2") + #Create a MhFlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName2 = cmds.createNode("MhFlowViewportAPIMayaLocator", n="nodeShape2") self.assertFalse(flowViewportNodeName2 == None) #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute @@ -319,7 +320,7 @@ def test_MultipleNodes(self): cmds.refresh() #Move the transform node, the added prims (cube grid) should move as well - # Get the transform node of the FlowViewportAPIMayaLocator + # Get the transform node of the MhFlowViewportAPIMayaLocator transformNode2 = cmds.listRelatives(flowViewportNodeName2, parent=True)[0] self.assertFalse(transformNode2 == None) #Select the transform node @@ -365,7 +366,7 @@ def test_MultipleNodes(self): #Test multiple viewports def test_MultipleViewports(self): - with PluginLoaded('flowViewportAPIMayaLocator'): + with PluginLoaded('mayaHydraFlowViewportAPIMayaLocator'): #switch to 4 views mel.eval('FourViewLayout') #Set focus on persp view @@ -386,8 +387,8 @@ def test_MultipleViewports(self): cmds.move(15, 0, 0) cmds.refresh() - #Create a FlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index - flowViewportNodeName1 = cmds.createNode("FlowViewportAPIMayaLocator", n="nodeShape1") + #Create a MhFlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName1 = cmds.createNode("MhFlowViewportAPIMayaLocator", n="nodeShape1") self.assertFalse(flowViewportNodeName1 == None) #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute @@ -445,5 +446,6 @@ def test_MultipleViewports(self): #Finish by a File New command cmds.file(new=True, force=True) + """ if __name__ == '__main__': fixturesUtils.runTests(globals()) From 01e98346855a2d19f4f0fcdad57e65a37833b32c Mon Sep 17 00:00:00 2001 From: David Lanier Date: Thu, 22 Feb 2024 15:00:18 +0100 Subject: [PATCH 2/6] Name change --- .../flowViewportAPIExamples/CMakeLists.txt | 2 +- .../CMakeLists.txt | 6 +- .../mhFlowViewportAPILocator.cpp} | 100 +++++++++--------- .../mhFlowViewportAPILocatorStrings.h} | 8 +- .../render/mayaToHydra/testFlowViewportAPI.py | 50 ++++----- 5 files changed, 83 insertions(+), 83 deletions(-) rename lib/mayaHydra/flowViewportAPIExamples/{flowViewportAPIMayaLocator => flowViewportAPILocator}/CMakeLists.txt (96%) rename lib/mayaHydra/flowViewportAPIExamples/{flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocator.cpp => flowViewportAPILocator/mhFlowViewportAPILocator.cpp} (88%) rename lib/mayaHydra/flowViewportAPIExamples/{flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocatorStrings.h => flowViewportAPILocator/mhFlowViewportAPILocatorStrings.h} (79%) diff --git a/lib/mayaHydra/flowViewportAPIExamples/CMakeLists.txt b/lib/mayaHydra/flowViewportAPIExamples/CMakeLists.txt index f05a524afd..6acc46c69a 100644 --- a/lib/mayaHydra/flowViewportAPIExamples/CMakeLists.txt +++ b/lib/mayaHydra/flowViewportAPIExamples/CMakeLists.txt @@ -1 +1 @@ -add_subdirectory(flowViewportAPIMayaLocator) +add_subdirectory(flowViewportAPILocator) diff --git a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/CMakeLists.txt b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/CMakeLists.txt similarity index 96% rename from lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/CMakeLists.txt rename to lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/CMakeLists.txt index fa73c81d34..9ae5be0a80 100644 --- a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/CMakeLists.txt +++ b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/CMakeLists.txt @@ -1,4 +1,4 @@ -set(TARGET_NAME mayaHydraFlowViewportAPIMayaLocator) +set(TARGET_NAME mayaHydraFlowViewportAPILocator) add_library(${TARGET_NAME} SHARED) @@ -7,12 +7,12 @@ add_library(${TARGET_NAME} SHARED) # ----------------------------------------------------------------------------- target_sources(${TARGET_NAME} PRIVATE - mhFlowViewportAPIMayaLocator.cpp + mhFlowViewportAPILocator.cpp ) set(HEADERS PRIVATE - mhFlowViewportAPIMayaLocatorStrings.h + mhFlowViewportAPILocatorStrings.h ) # ----------------------------------------------------------------------------- diff --git a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocator.cpp b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocator.cpp similarity index 88% rename from lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocator.cpp rename to lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocator.cpp index e005eedccc..32cf6ad622 100644 --- a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocator.cpp +++ b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocator.cpp @@ -15,7 +15,7 @@ // //Local headers -#include "mhFlowViewportAPIMayaLocatorStrings.h" +#include "MhFlowViewportAPILocatorStrings.h" //Flow viewport headers #include @@ -48,16 +48,16 @@ //But you could use another kind of maya plugin. /*To create an instance of this node in maya, please use the following MEL command : -createNode("MhFlowViewportAPIMayaLocator") +createNode("MhFlowViewportAPILocator") */ PXR_NAMESPACE_USING_DIRECTIVE ///Maya Locator node subclass to create filtering and data producer scene indices example, to be used with the flow viewport API. -class MhFlowViewportAPIMayaLocator : public MPxLocatorNode +class MhFlowViewportAPILocator : public MPxLocatorNode { public: - ~MhFlowViewportAPIMayaLocator() override; + ~MhFlowViewportAPILocator() override; //Is called when the MObject has been constructed and is valid void postConstructor() override; @@ -111,7 +111,7 @@ class MhFlowViewportAPIMayaLocator : public MPxLocatorNode private: /// Private Constructor - MhFlowViewportAPIMayaLocator() {} + MhFlowViewportAPILocator() {} ///Update the MObject of this node void _UpdateThisMObject(); @@ -126,7 +126,7 @@ namespace return; } - MhFlowViewportAPIMayaLocator* flowViewportAPIMayaLocator = reinterpret_cast(dataProducerSceneIndexData); + MhFlowViewportAPILocator* flowViewportAPIMayaLocator = reinterpret_cast(dataProducerSceneIndexData); MPlug parentPlug = plug.parent(); if (plug == flowViewportAPIMayaLocator->mDummyInput || plug == flowViewportAPIMayaLocator->mDummyOutput){ @@ -224,7 +224,7 @@ namespace return; } - MhFlowViewportAPIMayaLocator* flowViewportAPIMayaLocator = reinterpret_cast(clientData); + MhFlowViewportAPILocator* flowViewportAPIMayaLocator = reinterpret_cast(clientData); flowViewportAPIMayaLocator->setCubeGridParametersFromAttributes(); flowViewportAPIMayaLocator->setupFlowViewportInterfaces(); } @@ -239,22 +239,22 @@ namespace }//end of anonymous namespace //Initialization of static members -MTypeId MhFlowViewportAPIMayaLocator::id( 0x58000086 ); -MString MhFlowViewportAPIMayaLocator::nodeClassification("hydraAPIExample/geometry/MhFlowViewportAPIMayaLocator"); - -MObject MhFlowViewportAPIMayaLocator::mNumCubeLevelsX; -MObject MhFlowViewportAPIMayaLocator::mNumCubeLevelsY; -MObject MhFlowViewportAPIMayaLocator::mNumCubeLevelsZ; -MObject MhFlowViewportAPIMayaLocator::mCubeHalfSize; -MObject MhFlowViewportAPIMayaLocator::mCubeInitalTransform; -MObject MhFlowViewportAPIMayaLocator::mCubeColor; -MObject MhFlowViewportAPIMayaLocator::mCubeOpacity; -MObject MhFlowViewportAPIMayaLocator::mCubesUseInstancing; -MObject MhFlowViewportAPIMayaLocator::mCubesDeltaTrans; -MObject MhFlowViewportAPIMayaLocator::mDummyInput; -MObject MhFlowViewportAPIMayaLocator::mDummyOutput; - -void MhFlowViewportAPIMayaLocator::postConstructor() +MTypeId MhFlowViewportAPILocator::id( 0x58000086 ); +MString MhFlowViewportAPILocator::nodeClassification("hydraAPIExample/geometry/MhFlowViewportAPILocator"); + +MObject MhFlowViewportAPILocator::mNumCubeLevelsX; +MObject MhFlowViewportAPILocator::mNumCubeLevelsY; +MObject MhFlowViewportAPILocator::mNumCubeLevelsZ; +MObject MhFlowViewportAPILocator::mCubeHalfSize; +MObject MhFlowViewportAPILocator::mCubeInitalTransform; +MObject MhFlowViewportAPILocator::mCubeColor; +MObject MhFlowViewportAPILocator::mCubeOpacity; +MObject MhFlowViewportAPILocator::mCubesUseInstancing; +MObject MhFlowViewportAPILocator::mCubesDeltaTrans; +MObject MhFlowViewportAPILocator::mDummyInput; +MObject MhFlowViewportAPILocator::mDummyOutput; + +void MhFlowViewportAPILocator::postConstructor() { //The MObject has been constructed and is valid MObject currentMObj = thisMObject(); @@ -298,7 +298,7 @@ void MhFlowViewportAPIMayaLocator::postConstructor() } //This is called only when our node is destroyed and the undo queue flushed. -MhFlowViewportAPIMayaLocator::~MhFlowViewportAPIMayaLocator() +MhFlowViewportAPILocator::~MhFlowViewportAPILocator() { //Remove the callbacks if (_cbAttributeChangedId){ @@ -322,7 +322,7 @@ MhFlowViewportAPIMayaLocator::~MhFlowViewportAPIMayaLocator() informationInterface.UnregisterInformationClient(_hydraViewportInformationClient); } -void MhFlowViewportAPIMayaLocator::setCubeGridParametersFromAttributes() +void MhFlowViewportAPILocator::setCubeGridParametersFromAttributes() { MObject mObj = _thisMObject.object(); if (mObj.isNull()){ @@ -333,27 +333,27 @@ void MhFlowViewportAPIMayaLocator::setCubeGridParametersFromAttributes() } } - GetAttributeValue(_cubeGridParams._numLevelsX, mObj, MhFlowViewportAPIMayaLocator::mNumCubeLevelsX); - GetAttributeValue(_cubeGridParams._numLevelsY, mObj, MhFlowViewportAPIMayaLocator::mNumCubeLevelsY); - GetAttributeValue(_cubeGridParams._numLevelsZ, mObj, MhFlowViewportAPIMayaLocator::mNumCubeLevelsZ); + GetAttributeValue(_cubeGridParams._numLevelsX, mObj, MhFlowViewportAPILocator::mNumCubeLevelsX); + GetAttributeValue(_cubeGridParams._numLevelsY, mObj, MhFlowViewportAPILocator::mNumCubeLevelsY); + GetAttributeValue(_cubeGridParams._numLevelsZ, mObj, MhFlowViewportAPILocator::mNumCubeLevelsZ); - GetAttributeValue(_cubeGridParams._halfSize, mObj, MhFlowViewportAPIMayaLocator::mCubeHalfSize); + GetAttributeValue(_cubeGridParams._halfSize, mObj, MhFlowViewportAPILocator::mCubeHalfSize); MMatrix mat; - GetMatrixAttributeValue(mat, mObj, MhFlowViewportAPIMayaLocator::mCubeInitalTransform); + GetMatrixAttributeValue(mat, mObj, MhFlowViewportAPILocator::mCubeInitalTransform); memcpy(_cubeGridParams._initalTransform.GetArray(), mat[0], sizeof(double) * 16);//convert from MMatrix to GfMatrix4d double3 color; - GetDouble3AttributeValue(color, mObj, MhFlowViewportAPIMayaLocator::mCubeColor); + GetDouble3AttributeValue(color, mObj, MhFlowViewportAPILocator::mCubeColor); _cubeGridParams._color.data()[0] = color[0];//Implicit conversion from double to float _cubeGridParams._color.data()[1] = color[1]; _cubeGridParams._color.data()[2] = color[2]; - GetAttributeValue(_cubeGridParams._opacity, mObj, MhFlowViewportAPIMayaLocator::mCubeOpacity); - GetAttributeValue(_cubeGridParams._useInstancing, mObj, MhFlowViewportAPIMayaLocator::mCubesUseInstancing); + GetAttributeValue(_cubeGridParams._opacity, mObj, MhFlowViewportAPILocator::mCubeOpacity); + GetAttributeValue(_cubeGridParams._useInstancing, mObj, MhFlowViewportAPILocator::mCubesUseInstancing); double3 deltaTrans; - GetDouble3AttributeValue(deltaTrans, mObj, MhFlowViewportAPIMayaLocator::mCubesDeltaTrans); + GetDouble3AttributeValue(deltaTrans, mObj, MhFlowViewportAPILocator::mCubesDeltaTrans); _cubeGridParams._deltaTrans.data()[0] = deltaTrans[0];//Implicit conversion from double to float _cubeGridParams._deltaTrans.data()[1] = deltaTrans[1]; _cubeGridParams._deltaTrans.data()[2] = deltaTrans[2]; @@ -361,7 +361,7 @@ void MhFlowViewportAPIMayaLocator::setCubeGridParametersFromAttributes() _hydraViewportDataProducerSceneIndexExample.setCubeGridParams(_cubeGridParams); } -void MhFlowViewportAPIMayaLocator::_UpdateThisMObject() +void MhFlowViewportAPILocator::_UpdateThisMObject() { if (_thisMObject.isValid()){ return; @@ -370,7 +370,7 @@ void MhFlowViewportAPIMayaLocator::_UpdateThisMObject() _thisMObject = thisMObject(); } -void MhFlowViewportAPIMayaLocator::setupFlowViewportInterfaces() +void MhFlowViewportAPILocator::setupFlowViewportInterfaces() { _UpdateThisMObject(); @@ -396,7 +396,7 @@ void MhFlowViewportAPIMayaLocator::setupFlowViewportInterfaces() } } -MStatus MhFlowViewportAPIMayaLocator::compute( const MPlug& plug, MDataBlock& dataBlock) +MStatus MhFlowViewportAPILocator::compute( const MPlug& plug, MDataBlock& dataBlock) { //The MObject can change if the node gets deleted and deletion being undone if (! _thisMObject.isValid()){ @@ -406,13 +406,13 @@ MStatus MhFlowViewportAPIMayaLocator::compute( const MPlug& plug, MDataBlock& da return MS::kSuccess; } -bool MhFlowViewportAPIMayaLocator::isBounded() const +bool MhFlowViewportAPILocator::isBounded() const { return true; } //We return as a bounding box the bounding box of the data producer hydra data -MBoundingBox MhFlowViewportAPIMayaLocator::boundingBox() const +MBoundingBox MhFlowViewportAPILocator::boundingBox() const { float corner1X, corner1Y, corner1Z, corner2X, corner2Y, corner2Z; _hydraViewportDataProducerSceneIndexExample.getPrimsBoundingBox(corner1X, corner1Y, corner1Z, corner2X, corner2Y, corner2Z); @@ -420,21 +420,21 @@ MBoundingBox MhFlowViewportAPIMayaLocator::boundingBox() const } // Called before this node is evaluated by Evaluation Manager -MStatus MhFlowViewportAPIMayaLocator::preEvaluation( +MStatus MhFlowViewportAPILocator::preEvaluation( const MDGContext& context, const MEvaluationNode& evaluationNode) { return MStatus::kSuccess; } -void MhFlowViewportAPIMayaLocator::getCacheSetup(const MEvaluationNode& evalNode, MNodeCacheDisablingInfo& disablingInfo, MNodeCacheSetupInfo& cacheSetupInfo, MObjectArray& monitoredAttributes) const +void MhFlowViewportAPILocator::getCacheSetup(const MEvaluationNode& evalNode, MNodeCacheDisablingInfo& disablingInfo, MNodeCacheSetupInfo& cacheSetupInfo, MObjectArray& monitoredAttributes) const { MPxLocatorNode::getCacheSetup(evalNode, disablingInfo, cacheSetupInfo, monitoredAttributes); assert(!disablingInfo.getCacheDisabled()); cacheSetupInfo.setPreference(MNodeCacheSetupInfo::kWantToCacheByDefault, true); } -void* MhFlowViewportAPIMayaLocator::creator() +void* MhFlowViewportAPILocator::creator() { int isMayaHydraLoaded = false; // Validate that the mayaHydra plugin is loaded. @@ -450,7 +450,7 @@ void* MhFlowViewportAPIMayaLocator::creator() return nullptr; } - return new MhFlowViewportAPIMayaLocator; + return new MhFlowViewportAPILocator; } //--------------------------------------------------------------------------- @@ -473,7 +473,7 @@ void* MhFlowViewportAPIMayaLocator::creator() CHECK_MSTATUS ( attr.setReadable(true) ); \ CHECK_MSTATUS ( attr.setWritable(false) ); -MStatus MhFlowViewportAPIMayaLocator::initialize() +MStatus MhFlowViewportAPILocator::initialize() { MStatus status; @@ -558,12 +558,12 @@ MStatus initializePlugin( MObject obj ) } status = plugin.registerNode( - kMhFlowViewportAPIMayaLocatorNodePluginId, - MhFlowViewportAPIMayaLocator::id, - &MhFlowViewportAPIMayaLocator::creator, - &MhFlowViewportAPIMayaLocator::initialize, + kMhFlowViewportAPILocatorNodePluginId, + MhFlowViewportAPILocator::id, + &MhFlowViewportAPILocator::creator, + &MhFlowViewportAPILocator::initialize, MPxNode::kLocatorNode, - &MhFlowViewportAPIMayaLocator::nodeClassification); + &MhFlowViewportAPILocator::nodeClassification); if (!status) { status.perror("registerNode"); return status; @@ -577,7 +577,7 @@ MStatus uninitializePlugin( MObject obj) MStatus status; MFnPlugin plugin( obj ); - status = plugin.deregisterNode( MhFlowViewportAPIMayaLocator::id ); + status = plugin.deregisterNode( MhFlowViewportAPILocator::id ); if (!status) { status.perror("deregisterNode"); return status; diff --git a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocatorStrings.h b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocatorStrings.h similarity index 79% rename from lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocatorStrings.h rename to lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocatorStrings.h index 036e2e8241..6a8f1c1450 100644 --- a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPIMayaLocator/mhFlowViewportAPIMayaLocatorStrings.h +++ b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocatorStrings.h @@ -19,7 +19,7 @@ //////////////////////////////////////////////////////////////////////////////// // -// MhFlowViewportAPIMayaLocator Node hydra plugin localization strings +// MhFlowViewportAPILocator Node hydra plugin localization strings // //////////////////////////////////////////////////////////////////////////////// @@ -28,11 +28,11 @@ // MStringResourceIds contain plug-in id, unique resource id for // each string and the default value for the string. -#define kMhFlowViewportAPIMayaLocatorNodePluginId "MhFlowViewportAPIMayaLocator" +#define kMhFlowViewportAPILocatorNodePluginId "MhFlowViewportAPILocator" // If a MStringResourceId is added to this list, please register in registerMStringRes() -// in mhFlowViewportAPIMayaLocator.cpp +// in MhFlowViewportAPILocator.cpp -#define rMayaHydraNotLoadedStringError MStringResourceId( kMhFlowViewportAPIMayaLocatorNodePluginId, "rMayaHydraNotLoadedStringError", "You need to load the mayaHydra plugin before creating this node.") +#define rMayaHydraNotLoadedStringError MStringResourceId( kMhFlowViewportAPILocatorNodePluginId, "rMayaHydraNotLoadedStringError", "You need to load the mayaHydra plugin before creating this node.") #endif //_MAYAHYDRA_FLOW_VIEWPORT_API_MAYA_LOCATOR_STRINGS_ \ No newline at end of file diff --git a/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py b/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py index 83254b0f96..363697e85a 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py +++ b/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py @@ -44,14 +44,14 @@ def setupScene(self): #Test adding primitives def test_AddingPrimitives(self): self.setupScene() - with PluginLoaded('mayaHydraFlowViewportAPIMayaLocator'): + with PluginLoaded('mayaHydraFlowViewportAPILocator'): #Create a maya sphere sphereNode, sphereShape = cmds.polySphere() cmds.refresh() - #Create a MhFlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index - flowViewportNodeName = cmds.createNode("MhFlowViewportAPIMayaLocator") + #Create a MhFlowViewportAPILocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName = cmds.createNode("MhFlowViewportAPILocator") self.assertFalse(flowViewportNodeName == None) #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute cmds.setAttr(flowViewportNodeName + '.dummyInput', 2)#setting this will set dirty the dummyOutput attribute @@ -61,7 +61,7 @@ def test_AddingPrimitives(self): self.assertSnapshotClose("add_NodeCreated.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) #Move the transform node, the added prims (cube grid) should move as well - # Get the transform node of the MhFlowViewportAPIMayaLocator + # Get the transform node of the MhFlowViewportAPILocator transformNode = cmds.listRelatives(flowViewportNodeName, parent=True)[0] self.assertFalse(transformNode == None) #Select the transform node @@ -71,11 +71,11 @@ def test_AddingPrimitives(self): cmds.refresh() self.assertSnapshotClose("add_NodeMoved.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - #Hide the transform node, this should hide the MhFlowViewportAPIMayaLocator node and the added prims as well. + #Hide the transform node, this should hide the MhFlowViewportAPILocator node and the added prims as well. cmds.hide(transformNode) self.assertSnapshotClose("add_NodeHidden.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - #Unhide the transform node, this should unhide the MhFlowViewportAPIMayaLocator node and the added prims as well. + #Unhide the transform node, this should unhide the MhFlowViewportAPILocator node and the added prims as well. cmds.showHidden(transformNode) self.assertSnapshotClose("add_NodeUnhidden.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) @@ -115,14 +115,14 @@ def test_AddingPrimitives(self): #Test filtering primitives def test_FilteringPrimitives(self): self.setupScene() - with PluginLoaded('mayaHydraFlowViewportAPIMayaLocator'): + with PluginLoaded('mayaHydraFlowViewportAPILocator'): #Create a maya sphere sphereNode, sphereShape = cmds.polySphere() cmds.refresh() - #Create a MhFlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index - flowViewportNodeName = cmds.createNode("MhFlowViewportAPIMayaLocator") + #Create a MhFlowViewportAPILocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName = cmds.createNode("MhFlowViewportAPILocator") self.assertFalse(flowViewportNodeName == None) #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute cmds.setAttr(flowViewportNodeName + '.dummyInput', 3)#setting this will set dirty the dummyOutput attribute @@ -132,7 +132,7 @@ def test_FilteringPrimitives(self): self.assertSnapshotClose("filter_NodeCreated.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) #Move the transform node, the added prims (cube grid) should move as well - # Get the transform node of the MhFlowViewportAPIMayaLocator + # Get the transform node of the MhFlowViewportAPILocator transformNode = cmds.listRelatives(flowViewportNodeName, parent=True)[0] self.assertFalse(transformNode == None) #Select the transform node @@ -158,11 +158,11 @@ def test_FilteringPrimitives(self): cmds.refresh() self.assertSnapshotClose("filter_SphereFilteredAgain.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - #Hide the transform node, this should hide the MhFlowViewportAPIMayaLocator shape node and disable the filtering as well. + #Hide the transform node, this should hide the MhFlowViewportAPILocator shape node and disable the filtering as well. cmds.hide(transformNode) self.assertSnapshotClose("filter_NodeHidden.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - #Unhide the transform node, this should unhide the MhFlowViewportAPIMayaLocator node and enable the filtering as well. + #Unhide the transform node, this should unhide the MhFlowViewportAPILocator node and enable the filtering as well. cmds.showHidden(transformNode) self.assertSnapshotClose("filter_NodeUnhidden.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) @@ -201,10 +201,10 @@ def test_FilteringPrimitives(self): #Test Cube grids parameters def test_CubeGrid(self): self.setupScene() - with PluginLoaded('mayaHydraFlowViewportAPIMayaLocator'): + with PluginLoaded('mayaHydraFlowViewportAPILocator'): - #Create a MhFlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index - flowViewportNodeName = cmds.createNode("MhFlowViewportAPIMayaLocator") + #Create a MhFlowViewportAPILocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName = cmds.createNode("MhFlowViewportAPILocator") self.assertFalse(flowViewportNodeName == None) #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute @@ -257,10 +257,10 @@ def test_CubeGrid(self): #Test multiple nodes def test_MultipleNodes(self): self.setupScene() - with PluginLoaded('mayaHydraFlowViewportAPIMayaLocator'): + with PluginLoaded('mayaHydraFlowViewportAPILocator'): - #Create a MhFlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index - flowViewportNodeName1 = cmds.createNode("MhFlowViewportAPIMayaLocator", n="nodeShape1") + #Create a MhFlowViewportAPILocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName1 = cmds.createNode("MhFlowViewportAPILocator", n="nodeShape1") self.assertFalse(flowViewportNodeName1 == None) #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute @@ -285,7 +285,7 @@ def test_MultipleNodes(self): cmds.refresh() #Move the transform node, the added prims (cube grid) should move as well - # Get the transform node of the MhFlowViewportAPIMayaLocator + # Get the transform node of the MhFlowViewportAPILocator transformNode1 = cmds.listRelatives(flowViewportNodeName1, parent=True)[0] self.assertFalse(transformNode1 == None) #Select the transform node @@ -294,8 +294,8 @@ def test_MultipleNodes(self): cmds.move(-10, 0, 0) cmds.refresh() - #Create a MhFlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index - flowViewportNodeName2 = cmds.createNode("MhFlowViewportAPIMayaLocator", n="nodeShape2") + #Create a MhFlowViewportAPILocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName2 = cmds.createNode("MhFlowViewportAPILocator", n="nodeShape2") self.assertFalse(flowViewportNodeName2 == None) #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute @@ -320,7 +320,7 @@ def test_MultipleNodes(self): cmds.refresh() #Move the transform node, the added prims (cube grid) should move as well - # Get the transform node of the MhFlowViewportAPIMayaLocator + # Get the transform node of the MhFlowViewportAPILocator transformNode2 = cmds.listRelatives(flowViewportNodeName2, parent=True)[0] self.assertFalse(transformNode2 == None) #Select the transform node @@ -366,7 +366,7 @@ def test_MultipleNodes(self): #Test multiple viewports def test_MultipleViewports(self): - with PluginLoaded('mayaHydraFlowViewportAPIMayaLocator'): + with PluginLoaded('mayaHydraFlowViewportAPILocator'): #switch to 4 views mel.eval('FourViewLayout') #Set focus on persp view @@ -387,8 +387,8 @@ def test_MultipleViewports(self): cmds.move(15, 0, 0) cmds.refresh() - #Create a MhFlowViewportAPIMayaLocator node which adds a dataProducerSceneIndex and a Filtering scene index - flowViewportNodeName1 = cmds.createNode("MhFlowViewportAPIMayaLocator", n="nodeShape1") + #Create a MhFlowViewportAPILocator node which adds a dataProducerSceneIndex and a Filtering scene index + flowViewportNodeName1 = cmds.createNode("MhFlowViewportAPILocator", n="nodeShape1") self.assertFalse(flowViewportNodeName1 == None) #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute From 7a81de970ea3e315072f03608f2df18a057b5e51 Mon Sep 17 00:00:00 2001 From: David Lanier Date: Thu, 22 Feb 2024 17:25:46 +0100 Subject: [PATCH 3/6] HYDRA-746 : rename classes and files and avoid crashing when maya hydra is not loaded --- .../flowViewportAPILocator/CMakeLists.txt | 1 - .../mhFlowViewportAPILocator.cpp | 60 ++++++------------- .../mhFlowViewportAPILocatorStrings.h | 38 ------------ 3 files changed, 18 insertions(+), 81 deletions(-) delete mode 100644 lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocatorStrings.h diff --git a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/CMakeLists.txt b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/CMakeLists.txt index 9ae5be0a80..fe55272271 100644 --- a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/CMakeLists.txt +++ b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/CMakeLists.txt @@ -12,7 +12,6 @@ target_sources(${TARGET_NAME} set(HEADERS PRIVATE - mhFlowViewportAPILocatorStrings.h ) # ----------------------------------------------------------------------------- diff --git a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocator.cpp b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocator.cpp index 32cf6ad622..35adc947cb 100644 --- a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocator.cpp +++ b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocator.cpp @@ -14,9 +14,6 @@ // limitations under the License. // -//Local headers -#include "MhFlowViewportAPILocatorStrings.h" - //Flow viewport headers #include #include @@ -59,7 +56,6 @@ class MhFlowViewportAPILocator : public MPxLocatorNode public: ~MhFlowViewportAPILocator() override; - //Is called when the MObject has been constructed and is valid void postConstructor() override; MStatus compute( const MPlug& plug, MDataBlock& data ) override; @@ -228,14 +224,6 @@ namespace flowViewportAPIMayaLocator->setCubeGridParametersFromAttributes(); flowViewportAPIMayaLocator->setupFlowViewportInterfaces(); } - - // Register all strings used by the plugin C++ code - static MStatus registerMStringResources() - { - MStringResource::registerString(rMayaHydraNotLoadedStringError); - return MS::kSuccess; - } - }//end of anonymous namespace //Initialization of static members @@ -256,12 +244,6 @@ MObject MhFlowViewportAPILocator::mDummyOutput; void MhFlowViewportAPILocator::postConstructor() { - //The MObject has been constructed and is valid - MObject currentMObj = thisMObject(); - - //Add the callback when an attribute of this node changes - _cbAttributeChangedId = MNodeMessage::addAttributeChangedCallback(currentMObj, attributeChangedCallback, ((void*)this)); - //Get the flow viewport API hydra interfaces int majorVersion = 0; int minorVersion = 0; @@ -324,13 +306,9 @@ MhFlowViewportAPILocator::~MhFlowViewportAPILocator() void MhFlowViewportAPILocator::setCubeGridParametersFromAttributes() { - MObject mObj = _thisMObject.object(); + MObject mObj = thisMObject(); if (mObj.isNull()){ - _UpdateThisMObject(); - mObj = _thisMObject.object(); - if(mObj.isNull()){ - return; - } + return; } GetAttributeValue(_cubeGridParams._numLevelsX, mObj, MhFlowViewportAPILocator::mNumCubeLevelsX); @@ -373,13 +351,23 @@ void MhFlowViewportAPILocator::_UpdateThisMObject() void MhFlowViewportAPILocator::setupFlowViewportInterfaces() { _UpdateThisMObject(); - + //Set the maya node as a parent for this data producer scene index so that when the node is hidden/deleted/moved it gets applied to the prims produced MObject obj = _thisMObject.object(); if (obj.isNull()){ perror("ERROR : _thisMObject.object() is null, using the maya node to move/hide the prims won't be supported"); + return; + } + + //Remove any existing callback + if (_cbAttributeChangedId){ + CHECK_MSTATUS(MMessage::removeCallback(_cbAttributeChangedId)); + _cbAttributeChangedId = 0; } + //Add the callback when an attribute of this node changes + _cbAttributeChangedId = MNodeMessage::addAttributeChangedCallback(obj, attributeChangedCallback, ((void*)this)); + _hydraViewportDataProducerSceneIndexExample.setContainerNode(&obj); _hydraViewportDataProducerSceneIndexExample.addDataProducerSceneIndex(); @@ -387,7 +375,7 @@ void MhFlowViewportAPILocator::setupFlowViewportInterfaces() Fvp::FilteringSceneIndexInterface& filteringSceneIndexInterface = Fvp::FilteringSceneIndexInterface::get(); //Store the MObject* of the maya node in various classes - _hydraViewportFilteringSceneIndexClientExample->setDccNode(&_thisMObject); + _hydraViewportFilteringSceneIndexClientExample->setDccNode(&obj); //Register this filtering scene index client, so it can append custom filtering scene indices to Hydra viewport scene indices const bool bResult = filteringSceneIndexInterface.registerFilteringSceneIndexClient(_hydraViewportFilteringSceneIndexClientExample); @@ -436,17 +424,13 @@ void MhFlowViewportAPILocator::getCacheSetup(const MEvaluationNode& evalNode, MN void* MhFlowViewportAPILocator::creator() { + static const MString errorMsg ("You need to load the mayaHydra plugin before creating this node"); + int isMayaHydraLoaded = false; // Validate that the mayaHydra plugin is loaded. MGlobal::executeCommand( "pluginInfo -query -loaded mayaHydra", isMayaHydraLoaded ); if( ! isMayaHydraLoaded){ - MStatus status; - MString errorString = MStringResource::getString(rMayaHydraNotLoadedStringError, status); - if (! status){ - status.perror("Cannot retrieve the rMayaHydraNotLoadedStringError string, but you need to load mayaHydra before creating this node"); - }else{ - MGlobal::displayError(errorString); - } + MGlobal::displayError(errorMsg); return nullptr; } @@ -549,16 +533,8 @@ MStatus initializePlugin( MObject obj ) static const char * pluginVersion = "1.0"; MFnPlugin plugin( obj, PLUGIN_COMPANY, pluginVersion, "Any"); - // This is done first, so the strings are available. - status = plugin.registerUIStrings(registerMStringResources, "mayaHydraFootPrintNodeInitStrings"); - if (status != MS::kSuccess) - { - status.perror("registerUIStrings"); - return status; - } - status = plugin.registerNode( - kMhFlowViewportAPILocatorNodePluginId, + "MhFlowViewportAPILocator", MhFlowViewportAPILocator::id, &MhFlowViewportAPILocator::creator, &MhFlowViewportAPILocator::initialize, diff --git a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocatorStrings.h b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocatorStrings.h deleted file mode 100644 index 6a8f1c1450..0000000000 --- a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocatorStrings.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright 2024 Autodesk, Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#ifndef _MAYAHYDRA_FLOW_VIEWPORT_API_MAYA_LOCATOR_STRINGS_ -#define _MAYAHYDRA_FLOW_VIEWPORT_API_MAYA_LOCATOR_STRINGS_ - -//////////////////////////////////////////////////////////////////////////////// -// -// MhFlowViewportAPILocator Node hydra plugin localization strings -// -//////////////////////////////////////////////////////////////////////////////// - -#include -#include -// MStringResourceIds contain plug-in id, unique resource id for -// each string and the default value for the string. - -#define kMhFlowViewportAPILocatorNodePluginId "MhFlowViewportAPILocator" - -// If a MStringResourceId is added to this list, please register in registerMStringRes() -// in MhFlowViewportAPILocator.cpp - -#define rMayaHydraNotLoadedStringError MStringResourceId( kMhFlowViewportAPILocatorNodePluginId, "rMayaHydraNotLoadedStringError", "You need to load the mayaHydra plugin before creating this node.") - -#endif //_MAYAHYDRA_FLOW_VIEWPORT_API_MAYA_LOCATOR_STRINGS_ \ No newline at end of file From 12e9546f9f1e6f5a36820de80976d5bbb5231a7f Mon Sep 17 00:00:00 2001 From: David Lanier Date: Mon, 4 Mar 2024 17:59:03 +0100 Subject: [PATCH 4/6] HYDRA-746 : Apply Pierre's changes to this example --- .../mhFlowViewportAPILocator.cpp | 175 +++++++++--------- .../render/mayaToHydra/testFlowViewportAPI.py | 75 ++------ 2 files changed, 101 insertions(+), 149 deletions(-) diff --git a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocator.cpp b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocator.cpp index 35adc947cb..a0bacb4833 100644 --- a/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocator.cpp +++ b/lib/mayaHydra/flowViewportAPIExamples/flowViewportAPILocator/mhFlowViewportAPILocator.cpp @@ -40,6 +40,8 @@ #include #include #include +#include +#include //We use a locator node to deal with creating and filtering hydra primitives as an example. //But you could use another kind of maya plugin. @@ -48,6 +50,11 @@ createNode("MhFlowViewportAPILocator") */ +namespace { +void nodeAddedToModel(MObject& node, void* clientData); +void nodeRemovedFromModel(MObject& node, void* clientData); +} + PXR_NAMESPACE_USING_DIRECTIVE ///Maya Locator node subclass to create filtering and data producer scene indices example, to be used with the flow viewport API. @@ -67,7 +74,6 @@ class MhFlowViewportAPILocator : public MPxLocatorNode void getCacheSetup(const MEvaluationNode& evalNode, MNodeCacheDisablingInfo& disablingInfo, MNodeCacheSetupInfo& cacheSetupInfo, MObjectArray& monitoredAttributes) const override; void setCubeGridParametersFromAttributes(); - void setupFlowViewportInterfaces(); //static members static void* creator(); @@ -85,14 +91,18 @@ class MhFlowViewportAPILocator : public MPxLocatorNode static MObject mCubeOpacity; static MObject mCubesUseInstancing; static MObject mCubesDeltaTrans; - static MObject mDummyInput;//Dummy input to trigger a call to compute - static MObject mDummyOutput;//Dummy output to trigger a call to compute ///3D Grid of cube mesh primitives creation parameters for the data producer scene index Fvp::DataProducerSceneIndexExample::CubeGridCreationParams _cubeGridParams; ///_hydraViewportDataProducerSceneIndexExample is what will inject the 3D grid of Hydra cube mesh primitives into the viewport Fvp::DataProducerSceneIndexExample _hydraViewportDataProducerSceneIndexExample; + // Callback when the footprint node is added to the model (create / + // undo-delete) + void addedToModelCb(); + // Callback when the footprint node is removed from model (delete) + void removedFromModelCb(); + protected: /// _hydraViewportFilteringSceneIndexClientExample is the filtering scene index example for a Hydra viewport scene index. std::shared_ptr _hydraViewportFilteringSceneIndexClientExample; @@ -101,16 +111,17 @@ class MhFlowViewportAPILocator : public MPxLocatorNode ///To be used in hydra viewport API to pass the Maya node's MObject for setting callbacks for filtering and data producer scene indices MObjectHandle _thisMObject; ///To hold the attributeChangedCallback Id to be able to react when the 3D grid creation parameters attributes from this node change. - MCallbackId _cbAttributeChangedId = 0; + MCallbackId _cbAttributeChangedId {0}; ///To hold the afterOpenCallback Id to be able to react when a File Open has happened. - MCallbackId _cbAfterOpenId = 0; - + MCallbackId _cbAfterOpenId {0}; + /// to hold the nodeAddedToModel callback id + MCallbackId _nodeAddedToModelCbId{0}; + /// to hold the nodeRemovedFromModel callback id + MCallbackId _nodeRemovedFromModelCbId{0}; + private: /// Private Constructor MhFlowViewportAPILocator() {} - - ///Update the MObject of this node - void _UpdateThisMObject(); }; namespace @@ -125,10 +136,6 @@ namespace MhFlowViewportAPILocator* flowViewportAPIMayaLocator = reinterpret_cast(dataProducerSceneIndexData); MPlug parentPlug = plug.parent(); - if (plug == flowViewportAPIMayaLocator->mDummyInput || plug == flowViewportAPIMayaLocator->mDummyOutput){ - return; //These attributes are not related to the cubes grid - } - if (plug == flowViewportAPIMayaLocator->mNumCubeLevelsX){ flowViewportAPIMayaLocator->_cubeGridParams._numLevelsX = plug.asInt(); }else @@ -222,8 +229,29 @@ namespace MhFlowViewportAPILocator* flowViewportAPIMayaLocator = reinterpret_cast(clientData); flowViewportAPIMayaLocator->setCubeGridParametersFromAttributes(); - flowViewportAPIMayaLocator->setupFlowViewportInterfaces(); + flowViewportAPIMayaLocator->addedToModelCb(); } + + void nodeAddedToModel(MObject& node, void* /* clientData */) + { + auto fpNode = reinterpret_cast(MFnDagNode(node).userNode()); + if (!TF_VERIFY(fpNode)) { + return; + } + + fpNode->addedToModelCb(); + } + + void nodeRemovedFromModel(MObject& node, void* /* clientData */) + { + auto fpNode = reinterpret_cast(MFnDagNode(node).userNode()); + if (!TF_VERIFY(fpNode)) { + return; + } + + fpNode->removedFromModelCb(); + } + }//end of anonymous namespace //Initialization of static members @@ -239,8 +267,6 @@ MObject MhFlowViewportAPILocator::mCubeColor; MObject MhFlowViewportAPILocator::mCubeOpacity; MObject MhFlowViewportAPILocator::mCubesUseInstancing; MObject MhFlowViewportAPILocator::mCubesDeltaTrans; -MObject MhFlowViewportAPILocator::mDummyInput; -MObject MhFlowViewportAPILocator::mDummyOutput; void MhFlowViewportAPILocator::postConstructor() { @@ -277,20 +303,20 @@ void MhFlowViewportAPILocator::postConstructor() nullptr);//DCC node will be filled later setCubeGridParametersFromAttributes(); + + MObject obj = thisMObject(); + _nodeAddedToModelCbId = MModelMessage::addNodeAddedToModelCallback(obj, nodeAddedToModel); + _nodeRemovedFromModelCbId = MModelMessage::addNodeRemovedFromModelCallback(obj, nodeRemovedFromModel); } //This is called only when our node is destroyed and the undo queue flushed. MhFlowViewportAPILocator::~MhFlowViewportAPILocator() { //Remove the callbacks - if (_cbAttributeChangedId){ - CHECK_MSTATUS(MMessage::removeCallback(_cbAttributeChangedId)); - _cbAttributeChangedId = 0; - } - - if (_cbAfterOpenId){ - CHECK_MSTATUS(MSceneMessage::removeCallback(_cbAfterOpenId)); - _cbAfterOpenId = 0; + for(auto cbId : {_cbAfterOpenId, _cbAttributeChangedId, _nodeAddedToModelCbId, _nodeRemovedFromModelCbId}) { + if (cbId) { + CHECK_MSTATUS(MMessage::removeCallback(cbId)); + } } //The DataProducerSceneIndexExample in its destructor removes itself by calling DataProducerSceneIndexExample::RemoveDataProducerSceneIndex() @@ -339,58 +365,8 @@ void MhFlowViewportAPILocator::setCubeGridParametersFromAttributes() _hydraViewportDataProducerSceneIndexExample.setCubeGridParams(_cubeGridParams); } -void MhFlowViewportAPILocator::_UpdateThisMObject() -{ - if (_thisMObject.isValid()){ - return; - } - - _thisMObject = thisMObject(); -} - -void MhFlowViewportAPILocator::setupFlowViewportInterfaces() -{ - _UpdateThisMObject(); - - //Set the maya node as a parent for this data producer scene index so that when the node is hidden/deleted/moved it gets applied to the prims produced - MObject obj = _thisMObject.object(); - if (obj.isNull()){ - perror("ERROR : _thisMObject.object() is null, using the maya node to move/hide the prims won't be supported"); - return; - } - - //Remove any existing callback - if (_cbAttributeChangedId){ - CHECK_MSTATUS(MMessage::removeCallback(_cbAttributeChangedId)); - _cbAttributeChangedId = 0; - } - - //Add the callback when an attribute of this node changes - _cbAttributeChangedId = MNodeMessage::addAttributeChangedCallback(obj, attributeChangedCallback, ((void*)this)); - - _hydraViewportDataProducerSceneIndexExample.setContainerNode(&obj); - _hydraViewportDataProducerSceneIndexExample.addDataProducerSceneIndex(); - - //Register a filtering scene index client - Fvp::FilteringSceneIndexInterface& filteringSceneIndexInterface = Fvp::FilteringSceneIndexInterface::get(); - - //Store the MObject* of the maya node in various classes - _hydraViewportFilteringSceneIndexClientExample->setDccNode(&obj); - - //Register this filtering scene index client, so it can append custom filtering scene indices to Hydra viewport scene indices - const bool bResult = filteringSceneIndexInterface.registerFilteringSceneIndexClient(_hydraViewportFilteringSceneIndexClientExample); - if(! bResult){ - perror("ERROR : filteringSceneIndexInterface.registerFilteringSceneIndexClient returned false"); - } -} - MStatus MhFlowViewportAPILocator::compute( const MPlug& plug, MDataBlock& dataBlock) { - //The MObject can change if the node gets deleted and deletion being undone - if (! _thisMObject.isValid()){ - setupFlowViewportInterfaces(); - } - return MS::kSuccess; } @@ -437,6 +413,43 @@ void* MhFlowViewportAPILocator::creator() return new MhFlowViewportAPILocator; } +void MhFlowViewportAPILocator::addedToModelCb() +{ + static const SdfPath noPrefix = SdfPath::AbsoluteRootPath(); + + //Add the callback when an attribute of this node changes + MObject obj = thisMObject(); + _cbAttributeChangedId = MNodeMessage::addAttributeChangedCallback(obj, attributeChangedCallback, ((void*)this)); + + _hydraViewportDataProducerSceneIndexExample.setContainerNode(&obj); + _hydraViewportDataProducerSceneIndexExample.addDataProducerSceneIndex(); + + //Store the MObject* of the maya node in various classes + _hydraViewportFilteringSceneIndexClientExample->setDccNode(&obj); + + //Register this filtering scene index client, so it can append custom filtering scene indices to Hydra viewport scene indices + Fvp::FilteringSceneIndexInterface& filteringSceneIndexInterface = Fvp::FilteringSceneIndexInterface::get(); + const bool bResult = filteringSceneIndexInterface.registerFilteringSceneIndexClient(_hydraViewportFilteringSceneIndexClientExample); + if(! bResult){ + perror("ERROR : filteringSceneIndexInterface.registerFilteringSceneIndexClient returned false"); + } +} + +void MhFlowViewportAPILocator::removedFromModelCb() +{ + //Remove the callback + if (_cbAttributeChangedId){ + CHECK_MSTATUS(MMessage::removeCallback(_cbAttributeChangedId)); + _cbAttributeChangedId = 0; + } + + //Remove the data producer scene index. + _hydraViewportDataProducerSceneIndexExample.removeDataProducerSceneIndex(); + + Fvp::FilteringSceneIndexInterface& filteringSceneIndexInterface = Fvp::FilteringSceneIndexInterface::get(); + filteringSceneIndexInterface.unregisterFilteringSceneIndexClient(_hydraViewportFilteringSceneIndexClientExample); +} + //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Plugin Registration @@ -500,16 +513,6 @@ MStatus MhFlowViewportAPILocator::initialize() MAKE_INPUT(nAttr); CHECK_MSTATUS ( nAttr.setDefault(5.0, 5.0, 5.0) ); - //Create dummy output attribute to trigger a call to the compute function on demand. as it's in the compute fonction that we add our scene indices - mDummyInput = nAttr.create("dummyInput", "dI", MFnNumericData::kInt, 1.0, &status); - MAKE_INPUT(nAttr); - CHECK_MSTATUS ( nAttr.setDefault(1) ); - - //Create dummy output attribute to trigger a call to the compute function on demand. as it's in the compute fonction that we add our scene indices - mDummyOutput = nAttr.create("dummyOutput", "dO", MFnNumericData::kInt, 1.0, &status); - MAKE_OUTPUT(nAttr); - CHECK_MSTATUS ( nAttr.setDefault(1) ); - CHECK_MSTATUS ( addAttribute(mNumCubeLevelsX)); CHECK_MSTATUS ( addAttribute(mNumCubeLevelsY)); CHECK_MSTATUS ( addAttribute(mNumCubeLevelsZ)); @@ -519,10 +522,6 @@ MStatus MhFlowViewportAPILocator::initialize() CHECK_MSTATUS ( addAttribute(mCubeOpacity)); CHECK_MSTATUS ( addAttribute(mCubesUseInstancing)); CHECK_MSTATUS ( addAttribute(mCubesDeltaTrans)); - CHECK_MSTATUS ( addAttribute(mDummyInput)); - CHECK_MSTATUS ( addAttribute(mDummyOutput)); - - CHECK_MSTATUS ( attributeAffects(mDummyInput, mDummyOutput)); return status; } diff --git a/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py b/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py index 363697e85a..f07dbec139 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py +++ b/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py @@ -52,10 +52,6 @@ def test_AddingPrimitives(self): #Create a MhFlowViewportAPILocator node which adds a dataProducerSceneIndex and a Filtering scene index flowViewportNodeName = cmds.createNode("MhFlowViewportAPILocator") - self.assertFalse(flowViewportNodeName == None) - #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute - cmds.setAttr(flowViewportNodeName + '.dummyInput', 2)#setting this will set dirty the dummyOutput attribute - cmds.getAttr(flowViewportNodeName + '.dummyOutput')#getting this value will trigger a call to compute cmds.refresh() #Original images are located for example in maya-hydra\test\lib\mayaUsd\render\mayaToHydra\FlowViewportAPITest self.assertSnapshotClose("add_NodeCreated.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) @@ -63,11 +59,8 @@ def test_AddingPrimitives(self): #Move the transform node, the added prims (cube grid) should move as well # Get the transform node of the MhFlowViewportAPILocator transformNode = cmds.listRelatives(flowViewportNodeName, parent=True)[0] - self.assertFalse(transformNode == None) - #Select the transform node - cmds.select(transformNode) - # Move the selected node - cmds.move(10, 5, -5) + self.assertIsNotNone(transformNode) + cmds.move(10, 5, -5, transformNode) cmds.refresh() self.assertSnapshotClose("add_NodeMoved.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) @@ -96,9 +89,7 @@ def test_AddingPrimitives(self): self.assertSnapshotClose("add_NodeDeletedUndoAgain.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) #Move transform node again to see if it still updates the added prims transform - cmds.select(transformNode) - # Move the selected node - cmds.move(-20, -5, 0) + cmds.move(-20, -5, 0, transformNode) cmds.refresh() self.assertSnapshotClose("add_NodeMovedAfterDeletionAndUndo.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) @@ -111,7 +102,6 @@ def test_AddingPrimitives(self): #Finish by a File New command cmds.file(new=True, force=True) - """ #Test filtering primitives def test_FilteringPrimitives(self): self.setupScene() @@ -123,10 +113,6 @@ def test_FilteringPrimitives(self): #Create a MhFlowViewportAPILocator node which adds a dataProducerSceneIndex and a Filtering scene index flowViewportNodeName = cmds.createNode("MhFlowViewportAPILocator") - self.assertFalse(flowViewportNodeName == None) - #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute - cmds.setAttr(flowViewportNodeName + '.dummyInput', 3)#setting this will set dirty the dummyOutput attribute - cmds.getAttr(flowViewportNodeName + '.dummyOutput')#getting this value will trigger a call to compute cmds.refresh() #Original images are located for example in maya-hydra\test\lib\mayaUsd\render\mayaToHydra\FlowViewportAPITest self.assertSnapshotClose("filter_NodeCreated.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) @@ -134,11 +120,8 @@ def test_FilteringPrimitives(self): #Move the transform node, the added prims (cube grid) should move as well # Get the transform node of the MhFlowViewportAPILocator transformNode = cmds.listRelatives(flowViewportNodeName, parent=True)[0] - self.assertFalse(transformNode == None) - #Select the transform node - cmds.select(transformNode) - # Move the selected node - cmds.move(15, 0, 0) + self.assertIsNotNone(transformNode) + cmds.move(15, 0, 0, transformNode) cmds.refresh() self.assertSnapshotClose("filter_NodeMoved.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) @@ -205,11 +188,6 @@ def test_CubeGrid(self): #Create a MhFlowViewportAPILocator node which adds a dataProducerSceneIndex and a Filtering scene index flowViewportNodeName = cmds.createNode("MhFlowViewportAPILocator") - self.assertFalse(flowViewportNodeName == None) - - #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute - cmds.setAttr(flowViewportNodeName + '.dummyInput', 2)#setting this will set dirty the dummyOutput attribute - cmds.getAttr(flowViewportNodeName + '.dummyOutput')#getting this value will trigger a call to compute self.assertSnapshotClose("cubeGrid_BeforeModifs.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) #Get the matrix and set a rotation of 70 degress around Y axis. @@ -261,11 +239,6 @@ def test_MultipleNodes(self): #Create a MhFlowViewportAPILocator node which adds a dataProducerSceneIndex and a Filtering scene index flowViewportNodeName1 = cmds.createNode("MhFlowViewportAPILocator", n="nodeShape1") - self.assertFalse(flowViewportNodeName1 == None) - - #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute - cmds.setAttr(flowViewportNodeName1 + '.dummyInput', 2)#setting this will set dirty the dummyOutput attribute - cmds.getAttr(flowViewportNodeName1 + '.dummyOutput')#getting this value will trigger a call to compute #Get the matrix and set a rotation of 70 degress around Y axis. matrix = cmds.getAttr(flowViewportNodeName1 + '.cubeInitalTransform') @@ -287,20 +260,12 @@ def test_MultipleNodes(self): #Move the transform node, the added prims (cube grid) should move as well # Get the transform node of the MhFlowViewportAPILocator transformNode1 = cmds.listRelatives(flowViewportNodeName1, parent=True)[0] - self.assertFalse(transformNode1 == None) - #Select the transform node - cmds.select(transformNode1) - # Move the selected node - cmds.move(-10, 0, 0) + self.assertIsNotNone(transformNode1) + cmds.move(-10, 0, 0, transformNode1) cmds.refresh() #Create a MhFlowViewportAPILocator node which adds a dataProducerSceneIndex and a Filtering scene index flowViewportNodeName2 = cmds.createNode("MhFlowViewportAPILocator", n="nodeShape2") - self.assertFalse(flowViewportNodeName2 == None) - - #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute - cmds.setAttr(flowViewportNodeName2 + '.dummyInput', 3)#setting this will set dirty the dummyOutput attribute - cmds.getAttr(flowViewportNodeName2 + '.dummyOutput')#getting this value will trigger a call to compute #Get the matrix and set a rotation of 70 degress around Y axis. matrix = cmds.getAttr(flowViewportNodeName2 + '.cubeInitalTransform') @@ -322,11 +287,8 @@ def test_MultipleNodes(self): #Move the transform node, the added prims (cube grid) should move as well # Get the transform node of the MhFlowViewportAPILocator transformNode2 = cmds.listRelatives(flowViewportNodeName2, parent=True)[0] - self.assertFalse(transformNode2 == None) - #Select the transform node - cmds.select(transformNode2) - # Move the selected node - cmds.move(-30, 0, -30) + self.assertIsNotNone(transformNode2) + cmds.move(-30, 0, -30, transformNode2) cmds.refresh() self.assertSnapshotClose("multipleNodes_BeforeModifs.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) @@ -336,10 +298,9 @@ def test_MultipleNodes(self): cmds.setAttr(flowViewportNodeName2 + '.cubeOpacity', 0.1) # Apply transform on node #2 - cmds.select(transformNode2) - cmds.move(-30, 0, 0) - cmds.rotate(-30, 45, 0) - cmds.scale(2, 1, 1) + cmds.move(-30, 0, 0, transformNode2) + cmds.rotate(-30, 45, 0, transformNode2) + cmds.scale(2, 1, 1, transformNode2) cmds.refresh() self.assertSnapshotClose("multipleNodes_AfterModifs.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) @@ -381,19 +342,11 @@ def test_MultipleViewports(self): #Create a maya sphere sphereNode, sphereShape = cmds.polySphere() - #Select the transform node - cmds.select(sphereNode) - # Move the selected node - cmds.move(15, 0, 0) + cmds.move(15, 0, 0, sphereNode) cmds.refresh() #Create a MhFlowViewportAPILocator node which adds a dataProducerSceneIndex and a Filtering scene index flowViewportNodeName1 = cmds.createNode("MhFlowViewportAPILocator", n="nodeShape1") - self.assertFalse(flowViewportNodeName1 == None) - - #When the node above is created, its compute method is not called automatically, so work around to trigger a call to compute - cmds.setAttr(flowViewportNodeName1 + '.dummyInput', 2)#setting this will set dirty the dummyOutput attribute - cmds.getAttr(flowViewportNodeName1 + '.dummyOutput')#getting this value will trigger a call to compute #Modify the cube grid parameters cmds.setAttr(flowViewportNodeName1 + '.numCubesX', 3) @@ -446,6 +399,6 @@ def test_MultipleViewports(self): #Finish by a File New command cmds.file(new=True, force=True) - """ + if __name__ == '__main__': fixturesUtils.runTests(globals()) From 534f01b93efcbf843ab1134499cf26006b38d588 Mon Sep 17 00:00:00 2001 From: David Lanier Date: Tue, 5 Mar 2024 14:23:03 +0100 Subject: [PATCH 5/6] Fix tests. --- .../fvpDataProducerSceneIndexDataBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataBase.cpp b/lib/flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataBase.cpp index dde4c93c8b..87bb796045 100644 --- a/lib/flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataBase.cpp +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpDataProducerSceneIndexDataBase.cpp @@ -112,7 +112,6 @@ void DataProducerSceneIndexDataBase::_CreateSceneIndexChainForDataProducerSceneI HdSceneIndexBaseRefPtr DataProducerSceneIndexDataBase::_CreateUsdStageSceneIndexChain(HdSceneIndexBaseRefPtr const & inputStageSceneIndex) { _CreateSceneIndexChainForDataProducerSceneIndexWithDCCNode(inputStageSceneIndex); - UpdateHydraTransformFromParentPath();//Update the transform, this is useful when deleting the node and undoing it return _lastSceneIndexChain; } @@ -136,6 +135,7 @@ void DataProducerSceneIndexDataBase::_CreateSceneIndexChainForDataProducerSceneI { _rootOverridesSceneIndex = UsdImagingRootOverridesSceneIndex::New(inputSceneIndex); _lastSceneIndexChain = _rootOverridesSceneIndex; + UpdateHydraTransformFromParentPath();//Update the transform, this is useful when deleting the node and undoing it } void DataProducerSceneIndexDataBase::_CreateSceneIndexChainForDataProducerSceneIndexWithoutDCCNode(HdSceneIndexBaseRefPtr const & inputSceneIndex) From 260ca026d81c2b5f70047003b98c99ed212402b7 Mon Sep 17 00:00:00 2001 From: David Lanier Date: Wed, 6 Mar 2024 09:14:57 +0100 Subject: [PATCH 6/6] Use TearDown in tests. --- .../render/mayaToHydra/testFlowViewportAPI.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py b/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py index f07dbec139..b05d9845f5 100644 --- a/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py +++ b/test/lib/mayaUsd/render/mayaToHydra/testFlowViewportAPI.py @@ -41,6 +41,10 @@ class TestFlowViewportAPI(mtohUtils.MtohTestCase): #Subclassing mtohUtils.MtohTe def setupScene(self): self.setHdStormRenderer() + def tearDown(self): + #is called after each test : finish by a File New command to check that it's not crashing when cleaning up everything' + cmds.file(new=True, force=True) + #Test adding primitives def test_AddingPrimitives(self): self.setupScene() @@ -99,9 +103,6 @@ def test_AddingPrimitives(self): self.setHdStormRenderer() self.assertSnapshotClose("add_VP2AndThenBackToStorm.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - #Finish by a File New command - cmds.file(new=True, force=True) - #Test filtering primitives def test_FilteringPrimitives(self): self.setupScene() @@ -177,9 +178,6 @@ def test_FilteringPrimitives(self): cmds.setAttr(sphereShape + '.subdivisionsAxis', 30) #Unfilter the prim cmds.refresh() self.assertSnapshotClose("filter_VP2AndThenBackToStorm_MovedSphereUnFiltered.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - - #Finish by a File New command - cmds.file(new=True, force=True) #Test Cube grids parameters def test_CubeGrid(self): @@ -229,9 +227,6 @@ def test_CubeGrid(self): self.setHdStormRenderer() self.assertSnapshotClose("cubeGrid_VP2AndThenBackToStorm.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - #Finish by a File New command - cmds.file(new=True, force=True) - #Test multiple nodes def test_MultipleNodes(self): self.setupScene() @@ -322,9 +317,6 @@ def test_MultipleNodes(self): self.setHdStormRenderer() self.assertSnapshotClose("multipleNodes_VP2AndThenBackToStorm.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - #Finish by a File New command - cmds.file(new=True, force=True) - #Test multiple viewports def test_MultipleViewports(self): with PluginLoaded('mayaHydraFlowViewportAPILocator'): @@ -396,9 +388,6 @@ def test_MultipleViewports(self): cmds.setFocus ('modelPanel2') self.setHdStormRenderer() self.assertSnapshotClose("multipleViewports_VP2AndThenBackToStorm_modPan2.png", self.IMAGE_DIFF_FAIL_THRESHOLD, self.IMAGE_DIFF_FAIL_PERCENT) - - #Finish by a File New command - cmds.file(new=True, force=True) if __name__ == '__main__': fixturesUtils.runTests(globals())