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

# slopeShaderBehavior.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 <slopeShaderBehavior.h>
    #include <maya/MGlobal.h>
    #include <maya/MPlugArray.h>
    #include <maya/MFnDagNode.h>
    #include <maya/MObjectArray.h>

    slopeShaderBehavior::slopeShaderBehavior()
    //
    //  Description:
    //      Constructor
    //
    {
    }

    slopeShaderBehavior::~slopeShaderBehavior()
    //
    //  Description:
    //      Destructor
    //
    {
    }

    void *slopeShaderBehavior::creator()
    //
    //  Description:
    //      Returns a new instance of this class
    //
    {
        return new slopeShaderBehavior;
    }

    bool slopeShaderBehavior::shouldBeUsedFor( MObject &sourceNode, MObject &destinationNode,
                                               MPlug &sourcePlug, MPlug &destinationPlug)
    //
    //  Description:
    //      Overloaded function from MPxDragAndDropBehavior
    //  this method will return true if it is going to handle the connection
    //  between the two nodes given.
    //
    {
        bool result = false;

        if(sourceNode.hasFn(MFn::kLambert))
        {
            //if the source node was a lambert
            //than we will check the downstream connections to see
            //if a slope shader is assigned to it.
            //
            MObject shaderNode;
            MFnDependencyNode src(sourceNode);
            MPlugArray connections;

            src.getConnections(connections);
            for(unsigned i = 0; i < connections.length(); i++)
            {
                //check the incoming connections to this plug
                //
                MPlugArray connectedPlugs;
                connections[i].connectedTo(connectedPlugs, true, false);
                for(unsigned j = 0; j < connectedPlugs.length(); j++)
                {
                    //if the incoming node is a slope shader than
                    //set shaderNode equal to it and break out of the inner
                    //loop
                    //
                    if(MFnDependencyNode(connectedPlugs[j].node()).typeName() == "slopeShader")
                    {
                        shaderNode = connectedPlugs[j].node();
                        break;
                    }
                }

                //if the shaderNode is not null
                //than we have found a slopeShader
                //
                if(!shaderNode.isNull())
                {
                    //if the destination node is a mesh than we will take
                    //care of this connection so set the result to true
                    //and break out of the outer loop
                    //
                    if(destinationNode.hasFn(MFn::kMesh))
                        result = true;

                    break;
                }
            }
        }
        if(MFnDependencyNode(sourceNode).typeName() == "slopeShader")
        //if the sourceNode is a slope shader than check what we
        //are dropping on to
        //
        {
            if(destinationNode.hasFn(MFn::kLambert))
                result = true;
            else if(destinationNode.hasFn(MFn::kMesh))
                result = true;
        }

        return result;
    }

    MStatus slopeShaderBehavior::connectNodeToNode( MObject &sourceNode, MObject &destinationNode, bool force )
    //
    //  Description:
    //      Overloaded function from MPxDragAndDropBehavior
    //  this method will handle the connection between the slopeShader and the shader it is
    //  assigned to as well as any meshes that it is assigned to.
    //
    {
        MStatus result = MS::kFailure;
        MFnDependencyNode src(sourceNode);

        //if we are dragging from a lambert
        //we want to check what we are dragging
        //onto.
        if(sourceNode.hasFn(MFn::kLambert))
        {
            MObject shaderNode;
            MPlugArray connections;
            MObjectArray shaderNodes;
            shaderNodes.clear();

            //if the source node was a lambert
            //than we will check the downstream connections to see
            //if a slope shader is assigned to it.
            //
            src.getConnections(connections);
            unsigned i;
            for(i = 0; i < connections.length(); i++)
            {
                //check the incoming connections to this plug
                //
                MPlugArray connectedPlugs;
                connections[i].connectedTo(connectedPlugs, true, false);
                for(unsigned j = 0; j < connectedPlugs.length(); j++)
                {
                    //if the incoming node is a slope shader than
                    //append the node to the shaderNodes array
                    //
                    MObject currentnode = connectedPlugs[j].node();
                    if(MFnDependencyNode(currentnode).typeName() == "slopeShader")
                    {
                        shaderNodes.append(currentnode);
                    }
                }
            }

            //if we found a shading node
            //than check the destination node
            //type to see if it is a mesh
            //
            if(shaderNodes.length() > 0)
            {
                MFnDependencyNode dest(destinationNode);
                if(destinationNode.hasFn(MFn::kMesh))
                {
                    //if the node is a mesh than for each slopeShader
                    //connect the worldMesh attribute to the dirtyShaderPlug
                    //attribute to force an evaluation of the node when the mesh
                    //changes
                    //
                    for(i = 0; i < shaderNodes.length(); i++)
                    {
                        MPlug srcPlug = dest.findPlug("worldMesh");
                        MPlug destPlug = MFnDependencyNode(shaderNodes[i]).findPlug("dirtyShaderPlug");

                        if(!srcPlug.isNull() && !destPlug.isNull())
                        {
                            MString cmd = "connectAttr -na ";
                            cmd += srcPlug.name() + " ";
                            cmd += destPlug.name();
                            MGlobal::executeCommand(cmd);
                        }
                    }

                    //get the shading engine so we can assign the shader
                    //to the mesh after doing the connection
                    //
                    MObject shadingEngine = findShadingEngine(sourceNode);

                    //if there is a valid shading engine than make
                    //the connection
                    //
                    if(!shadingEngine.isNull())
                    {
                        MString cmd = "sets -edit -forceElement ";
                        cmd += MFnDependencyNode(shadingEngine).name() + " ";
                        cmd += MFnDagNode(destinationNode).partialPathName();
                        result = MGlobal::executeCommand(cmd);
                    }
                }
            }
        }
        else if(src.typeName() == "slopeShader")
        //if we are dragging from a slope shader
        //than we want to see what we are dragging onto
        //
        {
            if(destinationNode.hasFn(MFn::kMesh))
            {
                //if the user is dragging onto a mesh
                //than make the connection from the worldMesh
                //to the dirtyShader plug on the slopeShader
                //
                MFnDependencyNode dest(destinationNode);
                MPlug srcPlug = dest.findPlug("worldMesh");
                MPlug destPlug = src.findPlug("dirtyShaderPlug");
                if(!srcPlug.isNull() && !destPlug.isNull())
                {
                    MString cmd = "connectAttr -na ";
                    cmd += srcPlug.name() + " ";
                    cmd += destPlug.name();
                    result = MGlobal::executeCommand(cmd);
                }
            }
        }

        return result;
    }

    MStatus slopeShaderBehavior::connectNodeToAttr( MObject &sourceNode, MPlug &destinationPlug, bool force )
    //
    //  Description:
    //      Overloaded function from MPxDragAndDropBehavior
    //  this method will assign the correct output from the slope shader
    //  onto the given attribute.
    //
    {
        MStatus result = MS::kFailure;
        MFnDependencyNode src(sourceNode);

        //if we are dragging from a slopeShader
        //to a shader than connect the outColor
        //plug to the plug being passed in
        //
        if(destinationPlug.node().hasFn(MFn::kLambert)) {
            if(src.typeName() == "slopeShader")
            {
                MPlug srcPlug = src.findPlug("outColor");
                if(!srcPlug.isNull() && !destinationPlug.isNull())
                {
                    MString cmd = "connectAttr ";
                    cmd += srcPlug.name() + " ";
                    cmd += destinationPlug.name();
                    result = MGlobal::executeCommand(cmd);
                }
            }
        } else {
            //in all of the other cases we do not need the plug just the node
            //that it is on
            //
            MObject destinationNode = destinationPlug.node();
            result = connectNodeToNode(sourceNode, destinationNode, force);
        }

        return result;
    }

    MObject slopeShaderBehavior::findShadingEngine(MObject &node)
    //
    //  Description:
    //      Given the material MObject this method will
    //  return the shading group that it is assigned to.
    //  if there is no shading group associated with
    //  the material than a null MObject is apssed back.
    //
    {
        MFnDependencyNode nodeFn(node);
        MPlug srcPlug = nodeFn.findPlug("outColor");
        MPlugArray nodeConnections;
        srcPlug.connectedTo(nodeConnections, false, true);
        //loop through the connections
        //and find the shading engine node that
        //it is connected to
        //
        for(unsigned i = 0; i < nodeConnections.length(); i++)
        {
            if(nodeConnections[i].node().hasFn(MFn::kShadingEngine))
                return nodeConnections[i].node();
        }

        //no shading engine associated so return a
        //null MObject
        //
        return MObject();
    }