3

I'm updating my command to use MDGModifier::commandToExecute instead of MGlobal::executeCommand in order to provide the undo mechanism. The problem is that my sequence of commands depends on values returned from previous commands, and since MDGModifier saves all commands instead of executing them, I'm lost about how to do it... Example:

MStringArray commandResult; 
MGlobal::executeCommand("polyCube", commandResult);
MGlobal::executeCommand( "polyTriangulate " + commandResult[0]);

Since MDGModifier::commandToExecute doesn't give me a return value(commandResult), what would I pass to the second command? I suppose this is simple enough that people already figured it out. Any help is greatly appreciated! Thanks.

  • What exactly are you trying to do? I think you're trying to do too much at once. You should consider writing your main method in MEL or Python, then only fill in the blanks with commands implemented in C++. – Andreas Haferburg Apr 01 '13 at 16:36

1 Answers1

1

You can use more than one instance of MDGModifier in your command. In your command's doIt, whenever a sub-command has a dependency on the name of a DG node created by an earlier sub-command, schedule the creation of the DG node on the first MDGModifier, call the first MDGModifier's doIt, then schedule the second sub-command on the second MDGModifier using the DG node's now known name, and call the second MDGModifier's doIt. Your command's redoIt simply calls doIt on both MDGModifiers in the same order, and your command's undoIt calls undoIt on both MDGModifiers, but in reverse order.

In the example that you give, your first sub-command is a polyCube, which creates multiple DG nodes, so scheduling the polyCube comamnd using MDGModifier::commandToExecute is the simplest way to achieve that in an undoable manner. But unlike MDGModifer::createNode or MDagModifier::createNode, it doesn't give you any MObject referring to the created node, and you need one to get the name. To get such a MObject, you need to add a callback using MDGMessage::addNodeAddedCallback before calling the MDGModfier's doIt, and remove it afterwards.

WARNING: NOT TESTED!

class MyCommand: public MPxCommand
{
    ...

    MDGModifier             m_modifier1;
    MDGModifier             m_modifier2;

    static void NodeAdded( MObject& node, void* clientData )
    {
        if ( node.hasFn( MFn::kMesh ) )
        {
            *static_cast< MObject* >( clientData ) = node;
        }
    }

    MStatus doIt( const MArgList& args )
    {
        MObject                 node;
        MFnDependencyNode       nodeFn;
        MCallbackId             nodeAddedId;

        nodeAddedId = MDGMessage::addNodeAddedCallback( NodeAdded, &node );
        m_modifier1.commandToExecute( "polyCube" );
        m_modifier1.doIt();
        MMessage::removeCallback( nodeAddedId );
        nodeFn.setObject( node );
        m_modifier2.commandToExecute( "polyTriangulate " + nodeFn.name() );
        m_modifier2.doIt();
        return MStatus::kSuccess;
    }

    MStatus redoIt()
    {
        m_modifier1.doIt();
        m_modifier2.doIt();
        return MStatus::kSuccess;
    }

    MStatus undoIt()
    {
        m_modifier2.undoIt();
        m_modifier1.undoIt();
        return MStatus::kSuccess;
    }

    ...
};
TheBeardyMan
  • 829
  • 10
  • 28
  • Thanks, this is exactly what I was looking for. In the mean time, I have discovered that if you call MGlobal::executeCommand with a true as the last argument, it will generate the undo for you, plus it will give you back the result you need. In addition, it also lumps all the commands issued inside your custom command into one undoable operation, which is exactly what I wanted... makes me wonder why even bother with the MDGModifier class... – Robert Trussardi Jun 13 '13 at 16:48
  • Just happen to run into this myself, this solution works great. You actually don't need two modifiers either as you can chain operations following the `doIt()` calls. Also the API now allows you to pass in the object filter at callback registration. – Serguei Kalentchouk Feb 21 '16 at 09:00