1

I'm trying to write a Maya plugin using the C++ API that will identify meshes in the selection, (compute something), delete them and then insert a new mesh into the scene.

I'm gathering the selected meshes by the same manner as the objExporter plug-in example. I'm using a MDagModifier to delete the mesh nodes and attempt to undo these changes. But the undoIt is not working...

Here's my simplified code:

#include <maya/MArgList.h>
#include <maya/MObject.h>
#include <maya/MGlobal.h>
#include <maya/MPxCommand.h>
#include <maya/MDagModifier.h>

class LibiglBoolean : public MPxCommand
{
  private:
    MDagModifier dgModifier;
  public:
    LibiglBoolean() {};
    virtual MStatus doIt(const MArgList& argList);
    virtual MStatus redoIt();
    virtual MStatus undoIt();
    virtual bool isUndoable() const;
    static void* creator();
};

and

#include "LibiglBoolean.h"
#include <maya/MDagPath.h>
#include <maya/MFnDagNode.h>
#include <maya/MFnPlugin.h>
#include <maya/MItDag.h>
#include <maya/MItSelectionList.h>
#include <maya/MSelectionList.h>

void* LibiglBoolean::creator() { return new LibiglBoolean; }

MStatus LibiglBoolean::doIt(const MArgList& /*argList*/) 
{
  return redoIt();
}

MStatus LibiglBoolean::redoIt()
{
  MSelectionList slist;
  MGlobal::getActiveSelectionList(slist);
  MItSelectionList iter(slist);
  for(MItDag dagIterator(MItDag::kDepthFirst, MFn::kInvalid);
    !iter.isDone(); 
    iter.next())
  {
    MDagPath objectPath;
    iter.getDagPath( objectPath );
    dagIterator.reset(objectPath.node());

    // DAG iteration beginning at at selected node
    for ( ; !dagIterator.isDone(); dagIterator.next() )
    {
      MDagPath dagPath;
      dagIterator.getPath(dagPath);
      // skip over intermediate objects
      MFnDagNode dagNode(dagPath);
      if(dagNode.isIntermediateObject()) 
      {
        continue;
      }else if((dagPath.hasFn(MFn::kMesh)) && (dagPath.hasFn(MFn::kTransform)))
      {
        continue;
      }else if( dagPath.hasFn(MFn::kMesh))
      {
        dgModifier.deleteNode(dagPath.node());
      }
    }
  }
  dgModifier.doIt();
  return MS::kSuccess;
}

MStatus LibiglBoolean::undoIt()
{
  return dgModifier.undoIt();
}

bool LibiglBoolean::isUndoable() const
{
  return true;
}

MStatus initializePlugin(MObject obj)
{
  MFnPlugin plugin(obj, "Name", "1.0", "Any");
  return plugin.registerCommand("LibiglBoolean", LibiglBoolean::creator);
}

MStatus uninitializePlugin(MObject obj) 
{
  MFnPlugin plugin(obj);
  return plugin.deregisterCommand("LibiglBoolean");
}

(I'd like to stick to the C++ API and avoid the MEL/Python interfaces).

How can I undo the deleteNode actions properly?

Alec Jacobson
  • 6,032
  • 5
  • 51
  • 88
  • I may have made other mistakes, so I'll leave the question for now, but it seems that undo _does_ work if I issue the command in the MEL prompt: `LibiglBoolean` rather than how I was previously using the Python prompt: `import maya.cmds as cmds; cmds.LibiglBoolean()`. So is the Python call not undoable in the same way? – Alec Jacobson May 16 '16 at 21:00
  • Most of the code in your redoIt method should be moved to the doIt method, before the call to redoIt. dgModifier only needs to record the changes that it needs to make once, and the only thing your redoIt method should be doing is calling dgModifier's doIt method. – TheBeardyMan May 18 '16 at 08:57
  • As long as you don't need the MArgList it does not matter weather to call doIt() from redoIt() or vice versa. Only if doIt() involves heavy calculation, it makes sense to store the result and recall only the execution but not the calculation on redoIt() – thewhiteambit Jul 02 '18 at 16:22

0 Answers0