Search code examples
c++eventscallbackmessagemaya

Event in Maya Api to capture currentTime / frame change



I am currently developing a Maya plugin. How can I set-up a callback that gets fired each time the frame number / current time is changed in the scene ?
I had a look at the MSceneMessage Class, but it doesn't seem to contain what I am looking for.
Thanks.


Solution

  • You can use MEventMessage to setup a callback every time frame/current time changes. Code speaks louder than words, so here's some code with comments interspersed to illustrate how to set this up: (TLDR for the impatient first, full code excerpt will follow in the next section)

    TLDR:

    A code summary for the impatient:

        // ...
    
        // Our callback Id array to 
        // store the Ids of all our callbacks
        // for later removal    
        MCallbackIdArray myCallbackIds;
    
        // This is where the actual adding callback happens
        // We register our callback to the "timeChanged" event
        MCallbackId callbackId = MEventMessage::addEventCallback("timeChanged",  (MMessage::MBasicFunction) MySampleCmd::userCB);
    
        // ...
    
        if(myCallbackIds.length() != 0)
            // Make sure we remove all the callbacks we added
            stat = MEventMessage::removeCallbacks(myCallbackIds);
    

    Full(ish) code with comments:

    MySampleCommand.h

    class MySampleCmd : public MPxCommand {
    public:
                    MySampleCmd();
        virtual     ~MySampleCmd();
    
        // Our callback - implemented as a static method
        static      void userCB(void* clientData);
    
        MStatus     doIt( const MArgList& );
        MStatus     redoIt();
        MStatus     undoIt();   
        bool        isUndoable() const;
        static      void* creator();
    
    public:
    
        // Our callback Id array to 
        // store the Ids of all our callbacks
        // for later removal
        MCallbackIdArray myCallbackIds;
    };
    

    MySampleCommand.cpp (Excerpt)

    // Constructor
    MySampleCmd::MySampleCmd() {
    
        // Clearing our callback Id array
        // for housekeeping    
        myCallbackIds.clear();
    }
    
    // Destructor
    MySampleCmd::~MySampleCmd() {
    
        // Make sure we remove all the callbacks we added
        // Failing to do so will result in fatal error    
        if(myCallbackIds.length() != 0)
    
            // Remove the MEventMessage callback
            MEventMessage::removeCallbacks(myCallbackIds);
    }
    
    MStatus MySampleCmd::redoIt() {
    
        // This is where the actual adding callback happens
        // We register our callback to the "timeChanged" event
        MCallbackId callbackId = MEventMessage::addEventCallback("timeChanged",  (MMessage::MBasicFunction) MySampleCmd::userCB);
    
        // Append the newly added callback's ID to our list of callback ids
        // for future removal
        myCallbackIds.append(callbackId);
        return MS::kSuccess;
    }
    
    MStatus MySampleCmd::undoIt() {
        MStatus stat;
        if(myCallbackIds.length() != 0)
            // Make sure we remove all the callbacks we added
            stat = MEventMessage::removeCallbacks(myCallbackIds);
        return stat;
    }
    
    // Our callback function
    void SafeSelect::userCB(void* clientData) {
        MGlobal::displayInfo( "Callback userCB called!\n" );
        return;
    }