|
/* |
|
|
|
>>> from maya.api import OpenMaya as om |
|
>>> mod = om.MDagModifier() |
|
>>> parent = mod.createNode("transform") |
|
>>> rigid = mod.createNode("destroyMePlease", parent=parent) |
|
>>> mod.doIt() |
|
>>> mod.undoIt() |
|
# ~destructor not called |
|
>>> |
|
>>> del mod |
|
# still not called |
|
>>> |
|
>>> cmds.flushUndo() |
|
# still not called |
|
>>> |
|
>>> cmds.file(new=True, force=True) |
|
# still not called |
|
>>> |
|
>>> cmds.unloadPlugin("destroyMePlease") |
|
# RuntimeError: Plug-in, "destroyMePlease", cannot be unloaded because it is still in use # |
|
|
|
*/ |
|
|
|
#include <string.h> |
|
#include <assert.h> |
|
|
|
#include <maya/MPxLocatorNode.h> |
|
#include <maya/MFnPlugin.h> |
|
|
|
#include <maya/MBoundingBox.h> |
|
#include <maya/MTypeId.h> |
|
#include <maya/MPlug.h> |
|
#include <maya/MVector.h> |
|
#include <maya/MMatrix.h> |
|
#include <maya/MDataBlock.h> |
|
#include <maya/MStreamUtils.h> |
|
#include <maya/MNodeMessage.h> |
|
#include <maya/MDGModifier.h> |
|
#include <maya/MCallbackIdArray.h> |
|
|
|
#define Print MStreamUtils::stdErrorStream |
|
|
|
class destroyMePlease : public MPxLocatorNode { |
|
public: |
|
destroyMePlease(); |
|
~destroyMePlease() override; |
|
|
|
MStatus compute(const MPlug& plug, MDataBlock& data) override; |
|
void postConstructor() override; |
|
|
|
static void* creator() { return new destroyMePlease(); } |
|
static MStatus initialize(); |
|
|
|
static void onPreRemoval(MObject&, void*); |
|
static void onAboutToDelete(MObject&, MDGModifier&, void*); |
|
static void onDestroyed(void*); |
|
|
|
public: |
|
static MTypeId id; |
|
static MString drawDbClassification; |
|
MCallbackIdArray callbackIds; |
|
}; |
|
|
|
|
|
MTypeId destroyMePlease::id(0x80012); |
|
MString destroyMePlease::drawDbClassification("drawdb/geometry/destroyMePlease"); |
|
|
|
|
|
destroyMePlease::destroyMePlease() { |
|
// Called during MDagModifier::createNode.. |
|
// ..before MDagModifier::doIt() |
|
Print() << "Destroy me please..\n"; |
|
} |
|
|
|
destroyMePlease::~destroyMePlease() { |
|
// Called after MDagModifier goes out of Python scope |
|
Print() << "I'm being destroyed, yaaaay!\n"; |
|
} |
|
|
|
MStatus destroyMePlease::initialize() { |
|
return MS::kSuccess; |
|
} |
|
|
|
|
|
/* Called on delete, and on redoing delete, but not from undoing its creation */ |
|
void destroyMePlease::onPreRemoval(MObject&, void*) { |
|
Print() << "addNodePreRemovalCallback()\n"; |
|
} |
|
|
|
|
|
/* Also called on delete, but not from undoing its creation */ |
|
void destroyMePlease::onAboutToDelete(MObject&, MDGModifier&, void*) { |
|
Print() << "addNodeAboutToDeleteCallback()\n"; |
|
} |
|
|
|
|
|
/* Called after ~destroyMePlease */ |
|
void destroyMePlease::onDestroyed(void*) { |
|
Print() << "addNodeDestroyedCallback()\n"; |
|
} |
|
|
|
|
|
void destroyMePlease::postConstructor() { |
|
MStatus status { MS::kFailure }; |
|
|
|
MObject tempobj { this->thisMObject() }; |
|
|
|
callbackIds.append(MNodeMessage::addNodePreRemovalCallback(tempobj, onPreRemoval, nullptr, &status)); |
|
assert(status == MS::kSuccess); |
|
|
|
callbackIds.append(MNodeMessage::addNodeAboutToDeleteCallback(tempobj, onAboutToDelete, nullptr, &status)); |
|
assert(status == MS::kSuccess); |
|
|
|
callbackIds.append(MNodeMessage::addNodeDestroyedCallback(tempobj, onDestroyed, nullptr, &status)); |
|
assert(status == MS::kSuccess); |
|
|
|
} |
|
|
|
|
|
MStatus destroyMePlease::compute(const MPlug& plug, MDataBlock& datablock) { |
|
return MS::kUnknownParameter; |
|
} |
|
|
|
|
|
MStatus initializePlugin(MObject obj) { |
|
MStatus status; |
|
MFnPlugin plugin(obj, PLUGIN_COMPANY, "3.0", "Any"); |
|
|
|
plugin.registerNode("destroyMePlease", |
|
destroyMePlease::id, |
|
destroyMePlease::creator, |
|
destroyMePlease::initialize, |
|
MPxNode::kLocatorNode, |
|
&destroyMePlease::drawDbClassification); |
|
|
|
Print() << "==============\n"; |
|
Print() << "Initialising\n"; |
|
|
|
return status; |
|
} |
|
|
|
|
|
MStatus uninitializePlugin(MObject obj) { |
|
MStatus status; |
|
MFnPlugin plugin(obj); |
|
|
|
plugin.deregisterNode(destroyMePlease::id); |
|
|
|
Print() << "Deinitialising.\n"; |
|
Print() << "==============\n"; |
|
|
|
return status; |
|
} |
Hi! I know it has been a while. But for this situation, you can use the DGMessage::addNodeRemovedCallback. This one is triggered on "undos". Please note that at that stage the node's path won't be valid but the rest is ok.
Sorry for the delay