- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Examples

# conditionTest.cpp

    //-
    // ==========================================================================
    // Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
    //
    // Use of this software is subject to the terms of the Autodesk
    // license agreement provided at the time of installation or download,
    // or which otherwise accompanies this software in either electronic
    // or hard copy form.
    // ==========================================================================
    //+

    #include <stdio.h>

    #define OPENMAYA_EXPORT

    #include <maya/MIOStream.h>
    #include <maya/MGlobal.h>
    #include <maya/MString.h>
    #include <maya/MStringArray.h>
    #include <maya/MConditionMessage.h>
    #include <maya/MFnPlugin.h>

    #include <maya/MPxCommand.h>
    #include <maya/MSyntax.h>
    #include <maya/MArgDatabase.h>

    //
    // Definitions
    //

    // Message flag
    //
    #define kMessageFlag        "m"
    #define kMessageFlagLong    "message"

    //
    // Declarations
    //

    // Callback function for messages
    //
    static void conditionChangedCB(bool state, void * data);

    // Array of callback ids.
    //
    typedef MCallbackId* MCallbackIdPtr;
    static MCallbackIdPtr callbackId = NULL;

    // Array of condition names.
    //
    static MStringArray conditionNames;

    //
    // Command class declaration
    //
    class conditionTest : public MPxCommand
    {
    public:
        conditionTest();
        virtual                 ~conditionTest();

        MStatus                 doIt( const MArgList& args );

        static MSyntax          newSyntax();
        static void*            creator();

    private:
        MStatus                 parseArgs( const MArgList& args );

        bool                    addMessage;
        bool                    delMessage;

        MStringArray            conditions;
    };

    //
    // Command class implementation
    //

    // Constructor
    //
    conditionTest::conditionTest()
    :   addMessage(false)
    ,   delMessage(false)
    {
        conditions.clear();
    }

    // Destructor
    //
    conditionTest::~conditionTest()
    {
        // Do nothing
    }

    // creator
    //
    void* conditionTest::creator()
    {
        return (void *) (new conditionTest);
    }

    // newSyntax
    //
    MSyntax conditionTest::newSyntax()
    {
        MSyntax syntax;

        syntax.addFlag(kMessageFlag, kMessageFlagLong, MSyntax::kBoolean);
        syntax.setObjectType(MSyntax::kStringObjects);

        return syntax;
    }

    // parseArgs
    //
    MStatus conditionTest::parseArgs(const MArgList& args)
    {
        MStatus         status;
        MArgDatabase    argData(syntax(), args);

        if (argData.isFlagSet(kMessageFlag))
        {
            bool flag;

            status = argData.getFlagArgument(kMessageFlag, 0, flag);
            if (!status)
            {
                status.perror("could not parse message flag");
                return status;
            }

            if (flag)
            {
                addMessage = true;
            }
            else
            {
                delMessage = true;
            }
        }

        status = argData.getObjects(conditions);
        if (!status)
        {
            status.perror("could not parse condition names");
        }

        // If there are no conditions specified, operate on all of them
        //
        if (conditions.length() == 0)
        {
            // conditionNames is set in initializePlugin to all the
            // currently available condition names.
            //
            conditions = conditionNames;
        }

        return status;
    }

    // doIt
    //
    MStatus conditionTest::doIt(const MArgList& args)
    {
        MStatus status;

        status = parseArgs(args);
        if (!status)
        {
            return status;
        }

        // Allocate an array of indices.  conditions[n] is a user provided
        // condition name.  Look it up in the static conditionNames array
        // and set indices[n] to the index of the entry in conditionNames.
        //
        // This maps the user specified conditions to the global conditions
        // so we can track callback adds and removes globally.
        //
        int * indices = new int [conditions.length()];

        int i, j;

        for (i = 0; i < (int)conditions.length(); ++i)
        {
            // Initialize the entry to "not found".
            //
            indices[i] = -1;

            // Search condition names for a match.
            //
            for (j = 0; j < (int)conditionNames.length(); ++j)
            {
                if (conditions[i] == conditionNames[j])
                {
                    // Found a match.  Store the index and stop looking for
                    //
                    indices[i] = j;
                    break;
                }
            }
        }

        for (i = 0; i < (int)conditions.length(); ++i)
        {
            j = indices[i];
            if (j == -1)
            {
                MGlobal::displayWarning(conditions[i] +
                                        MString("is not a valid condition name\n"));
                break;
            }

            if (addMessage && callbackId[j] == 0)
            {
                callbackId[j] = MConditionMessage::addConditionCallback(
                    conditions[i],
                    conditionChangedCB,
                    (void*)(size_t)j,
                    &status);

                if (!status)
                {
                    status.perror("failed to add callback for " + conditions[i]);
                    callbackId[j] = 0;
                }
            }
            else if (delMessage && callbackId[j] != 0)
            {
                status = MMessage::removeCallback(callbackId[j]);

                if (!status)
                {
                    status.perror("failed to remove callback for " + conditions[i]);
                }

                callbackId[j] = 0;
            }
        }

        // Ok, we've made all the necessary changes.  Now show the status.
        //

        MGlobal::displayInfo("Condition Name        State  Msgs On\n");
        MGlobal::displayInfo("--------------------  -----  -------\n");

        char tmpStr[128];
        bool state, msgs;

        for (i = 0; i < (int)conditions.length(); ++i)
        {
            j = indices[i];
            if (j == -1)
            {
                continue;
            }

            state = MConditionMessage::getConditionState(conditions[i], &status);
            if (!status)
            {
                status.perror("failed to get status for " + conditions[i]);
                state = false;
            }

            msgs = (callbackId[j] != 0);

            sprintf(tmpStr, "%-20s  %-5s  %s\n",
                    conditions[i].asChar(),
                    state ? "true" : "false",
                    msgs  ? "yes"  : "no");

            MGlobal::displayInfo(tmpStr);
        }

        // Free up the indices we allocated.
        //
        delete [] indices;

        return status;
    }

    //
    // Plug-in functions
    //

    MStatus initializePlugin( MObject obj )
    {
        MStatus   status;
        MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");

        status = MConditionMessage::getConditionNames(conditionNames);
        if (!status)
        {
            return status;
        }

        cout<<"conditionTest: "<<conditionNames.length()<<" conditions are defined."<<endl;

        callbackId = new MCallbackId [conditionNames.length()];

        if (!callbackId)
        {
            return MStatus(MS::kInsufficientMemory);
        }

        for (unsigned int i = 0; i < conditionNames.length(); ++i)
        {
            callbackId[i] = 0;
        }

        // Register the command so we can actually do some work
        //
        status = plugin.registerCommand("conditionTest",
                                        conditionTest::creator,
                                        conditionTest::newSyntax);

        if (!status)
        {
            status.perror("registerCommand");
        }

        return status;
    }

    MStatus uninitializePlugin( MObject obj)
    {
        MStatus   status;
        MFnPlugin plugin( obj );

        // Loop through all the ids and remove the callbacks
        //
        int i;
        int len = conditionNames.length();

        for (i = 0; i < len; ++i)
        {
            if (callbackId[i] != 0)
            {
                MGlobal::displayWarning("Removing callback for " +
                                        conditionNames[i] +
                                        "\n");
                MMessage::removeCallback(callbackId[i]);
                callbackId[i] = 0;
            }
        }

        conditionNames.clear();

        delete [] callbackId;

        // Deregister the command
        //
        status = plugin.deregisterCommand("conditionTest");

        if (!status)
        {
            status.perror("deregisterCommand");
        }

        return status;
    }

    //
    // Callback function
    //

    static void conditionChangedCB(bool state, void * data)
    {
        int i = (int)(size_t)data;

        if (i > 0 && i < (MIntPtrSz)conditionNames.length())
        {
            MGlobal::displayInfo("condition " +
                                 conditionNames[i] +
                                 " changed to " +
                                 (state ? "true\n" : "false\n"));
        }
        else
        {
            MGlobal::displayWarning("BOGUS client data in conditionChangedCB!\n");
        }
    }