M Zeinstra
M Zeinstra

Reputation: 1981

Maya API - Get mesh from material

I'm currently working on a custom viewport plugin for Maya. At the moment, I'm trying to parse materials from Maya to my own custom framework materials.

I've created a callback that is called when a lambert shader is added (see code snippet below). I feel like this callback is called before even initializing the (just) added Lambert shader, but that's beside the point.

MCallbackId lambert_added_id = MDGMessage::addNodeAddedCallback(
    LambertAddedCallback,  // The callback function
    "lambert", // The type of object that triggers the callback
    m_material_parser.get(), // Client data
    &status // Return status
);

The return status is MStatus::kSuccess. Whenever I add a Lambert shader, this callback is triggered.

Although my question is.. How do I get the mesh node that this material is added to? I've tried to get the connections of the lambert shader, but there are none (see code snippet below).

void LambertAddedCallback(MObject& node, void* client_data)
{
    assert(node.apiType() == MFn::Type::kLambert);

    MFnLambertShader fn_lambert(node);

    MGlobal::displayInfo(node.apiTypeStr() + MString(" added!"));

    {
        MString str = fn_lambert.parentNamespace();
        MGlobal::displayInfo((str + " = parentNameSpace").asChar());
    }

    {
        MPlugArray plug_array;
        fn_lambert.getConnections(plug_array);
        auto num = plug_array.length();
        MGlobal::displayInfo("Pluggies: ");
        for (int i = 0; i < plug_array.length(); ++i)
        {
            MGlobal::displayInfo(plug_array[i].name().asChar());
        }
    }
}

The callback prints:

 = parentNamespace

Nothing else is printed, which means that there is no parentNamespace and not plugs connected to it..? I know that when you add a lambert shader to a mesh, it is applied as a surface shader in a shader group., but I can't find that relation in the callback.

So, my question to you is: Can I get the mesh that this Lambert shader is bound to (and how)?

Upvotes: 0

Views: 882

Answers (1)

Klaudikus
Klaudikus

Reputation: 392

The only way I know of is to traverse the dependency graph. The shape is not directly connected to the shader, it goes through a kShadingEngine node so you need to zig-zag the graph. The shading engine is downstream from the material, while the node is upstream from the shading engine.

Here's an example using the Python api:

def get_shading_engine_from_material(m_object):

    shading_engine = None
    iterator = OpenMaya.MItDependencyGraph(m_object, OpenMaya.MFn.kShadingEngine,
                                           OpenMaya.MItDependencyGraph.kDownstream,
                                           OpenMaya.MItDependencyGraph.kDepthFirst,
                                           OpenMaya.MItDependencyGraph.kPlugLevel)


    if not iterator.isDone():
        obj = iterator.currentNode()
        if not obj.isNull():
           return obj

def get_node_from_material(m_object):

    shading_engine = get_shading_engine_from_material(m_object)
    if shading_engine is None:
        return None


    iterator = OpenMaya.MItDependencyGraph(shader, OpenMaya.MFn.kMesh,
                                           OpenMaya.MItDependencyGraph.kUpstream,
                                           OpenMaya.MItDependencyGraph.kDepthFirst,
                                           OpenMaya.MItDependencyGraph.kNodeLevel)
    if not iterator.isDone():
        obj = iterator.currentNode()
        if not obj.isNull():
           return obj

shape = get_node_from_material(mat)
assert shape.apiType() == OpenMaya.MFn.kMesh

Upvotes: 2

Related Questions