#include <maya/MIOStream.h>
#include <maya/MString.h> 
#include <maya/MArgList.h> 
#include <maya/MFnPlugin.h> 
#include <maya/MPxCommand.h> 
#include <maya/MSyntax.h> 
#include <maya/MArgDatabase.h> 
#include <maya/MMessage.h> 
#include <maya/MLockMessage.h> 
#include <maya/MObject.h> 
#include <maya/MSelectionList.h> 
#include <maya/MFn.h> 
#include <maya/MItSelectionList.h> 
#include <maya/MFnDependencyNode.h> 
#include <maya/MStringArray.h> 
#include <maya/MString.h>
#include <maya/MGlobal.h> 
#include <maya/MDagPath.h> 
#include <maya/MCallbackIdArray.h>
#define MEL_COMMAND_NAME  "lockEvent"
#define VENDOR_TAG        "Autodesk"
#define PLUGIN_VERSION    "1.0"
#define checkStdError(stat,msg)     \
    if ( MS::kSuccess != stat ) {   \
            cerr << msg;            \
            return MS::kFailure;    \
    }
#define kClearCBLong      "-clearCB" 
#define kClearCB          "-ccb" 
#define kClearCBDV        false
#define kOverrideLong     "-override"
#define kOverride         "-o"
#define kOverrideDV       false  
#define kAttachLong       "-attach"
#define kAttach           "-a"
#define kAttachDV         0
#define MLM               MLockMessage
{
public: 
    lockEvent( ); 
    virtual ~lockEvent( ); 
    
    static void*   creator( ); 
    
    static bool    clearCallbackIds();
private: 
    unsigned int fAttach;
    bool fOverrideFlag, fOverrideVal, fClearCB; 
}; 
static bool overrideMode = false; 
                      void *clientData, MLM::LockDAGEvent,
                      bool &decision ); 
                   void *clientData, MLM::LockEvent, 
                   bool &decision ); 
                   void *clientData, MLM::LockPlugEvent, 
                   bool &decision ); 
                        void *clientData, MLM::LockPlugEvent, 
                        bool &decision ); 
lockEvent::lockEvent( ) : 
    fOverrideFlag(kOverrideDV), 
    fOverrideVal(false),
    fAttach(kAttachDV)
{
}
lockEvent::~lockEvent( ) 
{
}
{
    MCallbackId id = 0; 
    switch (fAttach) { 
    case 1: { 
        if ( status ) { 
            
            
            
            id = MLM::setNodeLockQueryCallback( node, lockDecision, 
                                                NULL, &status );
        }
    }   break;
    case 2: { 
        if ( status ) { 
            
            
            
            id = MLM::setNodeLockDAGQueryCallback( path, lockDagDecision, 
                                                   NULL, &status ); 
        }
    }   break;
    case 3: { 
        
        
        if ( status && plugName.
length() > 0 ) { 
 
            plugName[0].split( '.', attrName ); 
            
            MPlug plug = depNode.findPlug( attrName[1], &status ); 
 
            if ( status ) { 
                
                
                
                id = MLM::setPlugLockQueryCallback( plug, plugDecision, 
                                                    NULL,&status );
            }
        } else { 
        }
    } break;    
    case 4: {
        if ( status ) { 
            
            
            
            id = MLM::setPlugLockQueryCallback( node, nodePlugDecision, 
                                                NULL, &status ); 
        }
    } break; 
    default: 
    };  
    
    
    
    
    
    
    
    
    if ( !status || !id ) { 
        msg = "Unable to add callback for node "; 
        msg += fnNode.name(); 
    } else { 
        
        
        
        cerr << "Callback attached to " << fnNode.name();   
        cerr << "; attachment type = " << fAttach << endl;  
        callbackIds.
append( (
int)
id ); 
    }
    return id; 
}
{
    int result = 0;
    
    
    
    if ( !parseArgs( args ) ) { 
    }
    if ( fAttach ) { 
            MCallbackId id = installCallback( iter ); 
            if ( id ) { 
                result ++; 
            } else { 
            }
        }
    } else if ( fOverrideFlag ) { 
        
        overrideMode = fOverrideVal; 
    } else if ( fClearCB ) { 
        clearCallbackIds(); 
        result++; 
    }    
    clearResult(); 
    
    
    
    
    setResult( result ); 
    return status; 
}
void *lockEvent::creator( )
{
    return new lockEvent; 
}
{
    
    fAttach = kAttachDV; 
    fOverrideFlag = kOverrideDV; 
    fClearCB = kClearCBDV; 
    
    if ( argData.isFlagSet( kClearCB ) ) { 
        fClearCB = !kClearCBDV; 
    }   
    if ( argData.isFlagSet( kOverride ) ) { 
        bool tmp;
        status = argData.getFlagArgument( kOverride, 0, tmp ); 
        if ( !status ) { 
            return status;
        }
        fOverrideFlag = !kOverrideDV; 
        fOverrideVal = tmp; 
    }
    if ( argData.isFlagSet( kAttach ) ) { 
        unsigned int tmp;
        status = argData.getFlagArgument( kAttach, 0, tmp ); 
        if ( !status ) { 
            return status;
        }
        fAttach = tmp; 
    } 
    if ( fAttach ) { 
        status = argData.getObjects( theList ); 
        if ( theList.length() == 0 ) { 
            MString msg = 
"You must specify a node/plug to attach to!"; 
 
        }
    }
    
    
    if ( status && fAttach && fOverrideFlag ) { 
        MString msg = 
"You specified too many flags!" ;
 
    } 
    
    
    
    return status; 
}
{
    
    
    syntax.
addFlag( kClearCB, kClearCBLong ); 
    
    return syntax; 
}
                       void *clientData, MLM::LockPlugEvent event, 
                       bool &decision )
{ 
    msg = "nodePlugDecision called"; 
    
    
    
    switch (event) { 
    case MLM::kPlugLockAttr: 
        eventString = "kPlugLockAttr"; 
        break; 
    case MLM::kPlugUnlockAttr: 
        eventString = "kPlugUnlockAttr";
        break; 
    case MLM::kPlugAttrValChange:
        eventString = "kPlugAttrValChange"; 
        break;
    case MLM::kPlugRemoveAttr: 
        eventString = "kPlugRemoveAttr"; 
        break; 
    case MLM::kPlugRenameAttr:
        eventString = "kPlugRenameAttr";
        break;
    case MLM::kPlugConnect: 
        eventString = "kPlugConnect"; 
        break;
    case MLM::kPlugDisconnect: 
        eventString = "kPlugDisconnect"; 
        break; 
    default:
        eventString = "kLastPlug"; 
        break;
    }; 
            
    cerr << msg << "; event = " << eventString; 
    cerr << "; override = " << overrideMode << endl; 
    decision = !overrideMode; 
}   
                   void *clientData, MLM::LockPlugEvent event, 
                   bool &decision )
{ 
    msg = "plugDecision called";
    switch (event) { 
    case MLM::kPlugLockAttr: 
        eventString = "kPlugLockAttr"; 
        break; 
    case MLM::kPlugUnlockAttr: 
        eventString = "kPlugUnlockAttr";
        break; 
    case MLM::kPlugAttrValChange:
        eventString = "kPlugAttrValChange"; 
        break;
    case MLM::kPlugRemoveAttr: 
        eventString = "kPlugRemoveAttr"; 
        break; 
    case MLM::kPlugRenameAttr:
        eventString = "kPlugRenameAttr";
        break;
    case MLM::kPlugConnect: 
        eventString = "kPlugConnect"; 
        break;
    case MLM::kPlugDisconnect: 
        eventString = "kPlugDisconnect"; 
        break; 
    default:
        eventString = "kInvalidPlug"; 
        break;
    }; 
            
    cerr << msg << "; event = " << eventString; 
    cerr << "; override = " << overrideMode << endl; 
    
    decision = !overrideMode;  
}   
    
                      void *clientData, MLM::LockDAGEvent event, 
                      bool &decision )
{
    cerr << "lockDagDecision called ";
    switch (event) { 
    case MLM::kGroup: 
        eventString = "kGroup"; 
        break; 
    case MLM::kUnGroup:
        eventString = "kUnGroup";
        break;
    case MLM::kReparent: 
        eventString = "kReparent"; 
        break;
    case MLM::kChildReorder: 
        eventString = "kChildReorder"; 
        break;
    case MLM::kCreateNodeInstance: 
        eventString = "kCreateNodeInstance"; 
        break;
    case MLM::kCreateChildInstance:
        eventString = "kCreateChildInstance"; 
        break;
    case MLM::kCreateParentInstance:
        eventString = "kCreateParentInstance"; 
        break;
    case MLM::kInvalidDAG: 
    default: 
        eventString = "kInvalid";   
    }; 
        
    cerr << "on " << eventString << " event"; 
    cerr << "; overrideMode = " << overrideMode << endl; 
    decision = !overrideMode; 
}
                   void *clientData, MLM::LockEvent event,
                   bool &decision )
{
    cerr << "lockDecision called "; 
    
    switch ( event ) { 
    case MLM::kDelete: 
        eventString = "kDelete"; 
        break;
    case MLM::kRename: 
        eventString = "kRename"; 
        break;
    case MLM::kLockNode: 
        eventString = "kLockNode"; 
        break; 
    case MLM::kUnlockNode: 
        eventString = "kUnlockNode"; 
        break; 
    case MLM::kAddAttr: 
        eventString = "kAddAttr"; 
        break;
    case MLM::kRemoveAttr: 
        eventString = "kRemoveAttr"; 
        break;
    case MLM::kRenameAttr: 
        eventString = "kRemoveAttr"; 
        break; 
    case MLM::kUnlockAttr: 
        eventString = "kUnlockAttr"; 
        break;
    case MLM::kLockAttr: 
        eventString = "kLockAttr"; 
        break;
    case MLM::kInvalid: 
    default: 
        eventString = "kInvalid"; 
    }; 
    cerr << "on " << eventString << " event";
    cerr << "; overrideMode = " << overrideMode << endl; 
    decision = !overrideMode; 
}
bool lockEvent::clearCallbackIds( ) 
{
    unsigned int idCount = callbackIds.
length(); 
 
    for ( unsigned int i = 0; i < idCount; i ++ ) { 
        cerr << "callback #" << i << "; id = " << (unsigned)callbackIds[i] << endl; 
    } 
    return true; 
}
{
    
    MFnPlugin plugin( obj, VENDOR_TAG, PLUGIN_VERSION, 
"Any" ); 
 
    status = plugin.registerCommand( MEL_COMMAND_NAME, 
                                     lockEvent::creator, 
                                     lockEvent::newSyntax ); 
    return status; 
}
{
    
    status = plugin.deregisterCommand( MEL_COMMAND_NAME ); 
    if ( status ) { 
        lockEvent::clearCallbackIds(); 
    }
    return status; 
}