Last active
February 10, 2025 13:56
-
-
Save mottosso/e02a2d58482eae3e36be9d9cbd3040d1 to your computer and use it in GitHub Desktop.
Revisions
-
mottosso revised this gist
Feb 10, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -63,6 +63,6 @@ Your simplest option is to replace any devkit example with this source and build cd c:\maya_devkit\plug-ins\simpleSimulationNode $env:DEVKIT_LOCATION="c:\maya_devkit" cmake . -G Ninja cmake --build . # [2/2] Linking CXX shared library simpleSimulationNode.mll ``` -
mottosso created this gist
Feb 4, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,68 @@ ### dirtyNode The node has 3 attributes. - `shapeType` - `outputMesh` - `state` The affect each other, like so. ```cpp shapeType -> outputMesh -> state ``` Reading from `state` should compute `outputMesh` which depend on `shapeType`. But `state` is not dirtied when `shapeType` changes. Why? <br> ### Usage ```py import os import sys from maya import cmds fname = "c:/maya_devkit/plug-ins/simpleSimulationNode/simpleSimulationNode.mll" # or .so on Linux cmds.loadPlugin(fname) node = cmds.createNode("dirtyNode") # Suceeds assert cmds.getAttr(node + ".state") == 1 cmds.setAttr(node + ".shapeType", 2) # Fails assert cmds.getAttr(node + ".state") == 2 # I can force `outputMesh` to be dirty, and cause `simulation` to be dirty cmds.setAttr(node + ".outputMesh", 0) # Should not be writable # Succeeds, but should be 2 assert cmds.getAttr(node + ".state") == 0 # Succeeds cmds.setAttr(node + ".outputMesh", 2) # Should not be writable assert cmds.getAttr(node + ".state") == 2 ``` <br> ### Build Your simplest option is to replace any devkit example with this source and build from there. 1. Copy/paste the contents of `dirtynode.cpp` into `simpleSimulationNode.cpp` 1. Launch a Visual Studio 2019+ environment 2. Call the below. ```bash cd c:\maya_devkit\plug-ins\simpleSimulationNode $env:DEVKIT_LOCATION="c:\maya_devkit" cmake . -G Ninja cmake --build # [2/2] Linking CXX shared library simpleSimulationNode.mll ``` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,146 @@ #include <maya/MPxNode.h> #include <maya/MFnNumericAttribute.h> #include <maya/MString.h> #include <maya/MTypeId.h> #include <maya/MPlug.h> #include <maya/MDataBlock.h> #include <maya/MGlobal.h> #include <maya/MDataHandle.h> #include <maya/MFnPlugin.h> class dirtyNode final : public MPxNode { public: MStatus compute(const MPlug& plug, MDataBlock& data) override; static void* creator() { return new dirtyNode(); } static MStatus initialize(); public: // Attributes static MObject aShapeType; static MObject aOutputMesh; static MObject aState; public: static MTypeId id; static MString nodeName; }; MTypeId dirtyNode::id = { 0x00081165 }; MString dirtyNode::nodeName = { "dirtyNode" }; MObject dirtyNode::aShapeType; MObject dirtyNode::aOutputMesh; MObject dirtyNode::aState; MStatus dirtyNode::initialize() { MFnNumericAttribute nAttr; MStatus status; aShapeType = nAttr.create("shapeType", "shty", MFnNumericData::kInt); nAttr.setDefault(1); nAttr.setKeyable(false); nAttr.setWritable(true); // Mark as user-provided (not computed) nAttr.setReadable(true); nAttr.setStorable(true); nAttr.setChannelBox(true); aOutputMesh = nAttr.create("outputMesh", "oume", MFnNumericData::kInt); nAttr.setKeyable(false); nAttr.setChannelBox(true); nAttr.setWritable(false); // Mark as computed (non-writable) nAttr.setStorable(false); // Don't store this computed value nAttr.setReadable(true); aState = nAttr.create("state", "stat", MFnNumericData::kInt); nAttr.setWritable(false); nAttr.setStorable(false); nAttr.setReadable(true); status = addAttribute(aShapeType); status = addAttribute(aOutputMesh); status = addAttribute(aState); status = attributeAffects(aShapeType, aOutputMesh); status = attributeAffects(aOutputMesh, aState); return MS::kSuccess; } MStatus dirtyNode::compute(const MPlug& plug, MDataBlock& data) { MStatus status; if (plug == aOutputMesh) { MDataHandle shapeTypeHandle = data.inputValue(aShapeType, &status); CHECK_MSTATUS_AND_RETURN_IT(status); int shapeType = shapeTypeHandle.asInt(); // Compute outputMesh based on shapeType MDataHandle outputMeshHandle = data.outputValue(aOutputMesh, &status); CHECK_MSTATUS_AND_RETURN_IT(status); outputMeshHandle.setInt(shapeType); // Or more complex logic outputMeshHandle.setClean(); MGlobal::displayInfo("Computed aOutputMesh"); return MS::kSuccess; } else if (plug == aState) { // Get outputMesh value MDataHandle outputMeshHandle = data.inputValue(aOutputMesh, &status); CHECK_MSTATUS_AND_RETURN_IT(status); int outputMesh = outputMeshHandle.asInt(); // Compute currentStatus based on outputMesh and initialStatus MDataHandle stateHandle = data.outputValue(aState, &status); CHECK_MSTATUS_AND_RETURN_IT(status); stateHandle.setInt(outputMesh); stateHandle.setClean(); MGlobal::displayInfo("Computed aState"); return MS::kSuccess; } // Let Maya handle it return MS::kUnknownParameter; } MStatus initializePlugin(MObject obj) { MStatus status; MFnPlugin plugin(obj, PLUGIN_COMPANY, "1.0", "Any"); status = plugin.registerNode( dirtyNode::nodeName, dirtyNode::id, dirtyNode::creator, dirtyNode::initialize ); if (!status) { status.perror("registerNode"); return status; } return status; } MStatus uninitializePlugin(MObject obj) { MStatus status; MFnPlugin plugin(obj); status = plugin.deregisterNode(dirtyNode::id); if (!status) { status.perror("deregisterNode"); return status; } return status; }