//- // ========================================================================== // Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors. All // rights reserved. // // The coded instructions, statements, computer programs, and/or related // material (collectively the "Data") in these files contain unpublished // information proprietary to Autodesk, Inc. ("Autodesk") and/or its // licensors, which is protected by U.S. and Canadian federal copyright // law and by international treaties. // // The Data is provided for use exclusively by You. You have the right // to use, modify, and incorporate this Data into other products for // purposes authorized by the Autodesk software license agreement, // without fee. // // The copyright notices in the Software and this entire statement, // including the above license grant, this restriction and the // following disclaimer, must be included in all copies of the // Software, in whole or in part, and all derivative works of // the Software, unless such copies or derivative works are solely // in the form of machine-executable object code generated by a // source language processor. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. // AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED // WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF // NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR // PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR // TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS // BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, // DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK // AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY // OR PROBABILITY OF SUCH DAMAGES. // // ========================================================================== //+ // MEL Command: nodeCreatedCB // // Description: // A simple plugin to register a mel proc to be called whenever a node is // created. Registered Mel procedures should be declared to take a single // string argument (the name of the added node). // // Warning: mel procedures registered with this method will be called // whenever a node is added to the DG. This may cause problems // in certain cases. For example: each time a reference is // reloaded, each of its nodes is re-added to the DG. // // Flags: // -register/-r string: registers a mel callback. There is no limit // to the number of callbacks that can be registered. // // -unregister/-u string: unregister the specified callback. // // -filter/-f string: by default all registered callbacks will be called // whenever any node is created. Using the filter flag // you can indicate that callbacks should only be // called when certain node types are created. // To determine the type of a particular node see the // 'objectType' and 'nodeType' commands. // // Note: only one filter can be in affect at a time, // and it will be applied to all registered callbacks. // // -fullDagPath/-fdp: if this flag is specified when registering a // callback, any dag node names passed into the mel // procedure will include the full dag path. // // Note: // The -register, -unregister, and -filter flags are mutually exclusive, // only one should be used per command invocation. // // Important: // Do not delete the node in your callback. // // Example Usage: // // // Appends the suffix '_ply' to all created mesh nodes // // // global proc myCB( string $node ) // { // print("calling polyCB " + $node + "\n"); // string $type = `objectType $node`; // if ( $type == "mesh" ) { // rename $node ($node+"_ply"); // } // } // // nodeCreatedCB -register "myCB"; // #include #include #include #include #include #include #include #include #include #define kRegisterFlagLong "-register" #define kRegisterFlag "-r" #define kUnregisterFlagLong "-unregister" #define kUnregisterFlag "-u" #define kFilterFlagLong "-filter" #define kFilterFlag "-f" #define kFullDagPathFlagLong "-fullDagPath" #define kFullDagPathFlag "-fdp" // The id of the API callback. The API callback must be removed when this // plug-in is unloaded. // MCallbackId nodeCreatedCB::sId; // The array of all registered Mel procedures. // MStringArray nodeCreatedCB::sMelProcs; // Flags to indicate whether or not a mel procedure should be passed the // short or long names of dag nodes. // MIntArray nodeCreatedCB::sFullDagPath; MStatus nodeCreatedCB::doIt( const MArgList& args ) // // Description: // implements the MEL nodeCreatedCB command. // { MStatus stat = MS::kSuccess; MArgDatabase argData( syntax(), args ); // Parse command flags. // if ( argData.isFlagSet( kRegisterFlag ) ) { // Register a new procedure. // MString proc; argData.getFlagArgument( kRegisterFlag, 0, proc ); stat = registerMelProc( proc, argData.isFlagSet( kFullDagPathFlag ) ); } else if ( argData.isFlagSet( kUnregisterFlag ) ) { // Unregister a procedure. // MString proc; argData.getFlagArgument( kUnregisterFlag, 0, proc ); stat = unregisterMelProc( proc ); } else if ( argData.isFlagSet( kFilterFlag ) ) { // Change the filter being applied. // MString filter; argData.getFlagArgument( kFilterFlag, 0, filter ); stat = changeFilter( filter ); } if ( stat.error() ) { MGlobal::displayError( stat.errorString() ); } return stat; } MStatus nodeCreatedCB::registerMelProc( MString melProc, bool fullDagPath ) // // Register a Mel procedure to be called whenever a node is added. // { MStatus stat = MS::kSuccess; if ( melProc.length() == 0 ) { // Basic error checking. An empty string is not a valid mel procedure // name // stat = MS::kFailure; stat.perror("invalid mel callback: " + melProc); return stat; } nodeCreatedCB::sMelProcs.append( melProc ); nodeCreatedCB::sFullDagPath.append( fullDagPath ); return stat; } MStatus nodeCreatedCB::unregisterMelProc( MString melProc ) // // Unregister a Mel procedure. // { MStatus stat = MS::kFailure; int numProcs = nodeCreatedCB::sMelProcs.length(); for ( int i = 0; i < numProcs; i++ ) { // Search the array of registered callbacks for melProc and // remove it. If melProc exists more than once, only one instance // of it will be removed. // if ( nodeCreatedCB::sMelProcs[i] == melProc ) { nodeCreatedCB::sMelProcs.remove(i); nodeCreatedCB::sFullDagPath.remove(i); stat = MS::kSuccess; break; } } if ( !stat ) { // Report an error if melProc was not found. // stat.perror(melProc + " is not a registered callback."); } return stat; } MStatus nodeCreatedCB::changeFilter( MString filter ) // // Change the node type filter. // { MStatus stat = MS::kSuccess; // We don't want to add sCallbackFunc more than once as that will cause // all registered Mel procs to be called multiple times. So we first // remove, then re-add the callback. // MDGMessage::removeCallback( nodeCreatedCB::sId ); nodeCreatedCB::sId = MDGMessage::addNodeAddedCallback( nodeCreatedCB::sCallbackFunc, filter ); return stat; } void nodeCreatedCB::sCallbackFunc( MObject& node, void* clientData ) // // The API callback called whenever a node is added. This function handles // calling all registered MEL callbacks and passing them the appropriate // node name argument. // { int numProcs = nodeCreatedCB::sMelProcs.length(); for ( int i = 0; i < numProcs; i++ ) { MString melCmd = nodeCreatedCB::sMelProcs[i]; MString nodeName; if ( nodeCreatedCB::sFullDagPath[i] && node.hasFn( MFn::kDagNode ) ) { MFnDagNode dagObj( node ); nodeName = dagObj.fullPathName(); } else { MFnDependencyNode dn( node ); nodeName = dn.name(); } melCmd += " \"" + nodeName + "\""; MGlobal::executeCommand( melCmd ); } } MSyntax nodeCreatedCB::newSyntax() // // Create the syntax object for the nodeCreateCB command. // { MSyntax syntax; syntax.addFlag( kRegisterFlag, kRegisterFlagLong, MSyntax::kString ); syntax.addFlag( kUnregisterFlag, kUnregisterFlagLong, MSyntax::kString ); syntax.addFlag( kFilterFlag, kFilterFlagLong, MSyntax::kString ); syntax.addFlag( kFullDagPathFlag, kFullDagPathFlagLong ); return syntax; } void* nodeCreatedCB::creator() { return new nodeCreatedCB; } MStatus initializePlugin( MObject obj ) { MFnPlugin plugin( obj, PLUGIN_COMPANY, "6.0" ); MStatus stat; stat = plugin.registerCommand( "nodeCreatedCB", nodeCreatedCB::creator, nodeCreatedCB::newSyntax ); if ( !stat ) stat.perror("registerCommand"); // add the API callback. // nodeCreatedCB::sId = MDGMessage::addNodeAddedCallback( nodeCreatedCB::sCallbackFunc ); return stat; } MStatus uninitializePlugin( MObject obj ) { MFnPlugin plugin( obj ); MStatus stat; stat = plugin.deregisterCommand( "nodeCreatedCB" ); if ( !stat ) stat.perror("deregisterCommand"); // Remove the API callback, necessary to prevent crashes. // MDGMessage::removeCallback( nodeCreatedCB::sId ); nodeCreatedCB::sMelProcs.clear(); nodeCreatedCB::sFullDagPath.clear(); return stat; }