Maya API How-To #21

Back · Previous · Next Maya

How do I find the file texture, and the image filepath, assigned to a material?

The textures for a material are assigned through dependency node connections. Typically the primary color connection (if any) is through the ".color" attribute. Different materials will have different channels, however, but the means for obtaining a texture connection are the same.

Given:

MStatus status;

// The material node.
MObject material;

// The attribute to which may be connected a texture.
const MString COLOR_ATTR( "color" );

// The attribute on Maya's "file" node which stores the
// path to the assigned texture image.
const MString TEXTURE_NAME( "fileTextureName" );

We find the incoming texture thusly:

  MFnDependencyNode fnDependNode( material );
  MPlug plug = fnDependNode.findPlug( COLOR_ATTR, &status );
  if ( status == MS::kSuccess )
  {
    // If you're looping through arbitrary attributes here, you could
    // add a check to ensure that the queried plug represents a
    // (double3) attribute, and perhaps even MFnAttribute::isUsedAsColor().

    // Is plug connected?
    MPlugArray cc;

    // Do not simply check for return value here; this returns TRUE if the
    // the plug is _either_ the source or destination for a connection,
    // even though we've specified only destination.
    plug.connectedTo( cc, true /* asDst */, false );
    if ( cc.length() > 0 )
    {
      // As a destination there can be only one source.
      MObject src = cc[0];

      // Is it a file texture?
      if ( src.hasFn( MFn::kFileTexture ) )
      {
        MFnDependencyNode fnFile( src );
        MPlug ftnPlug = fnFile.findPlug( TEXTURE_NAME, &status );
        if ( status == MS::kSuccess )
        {
          MString fileTextureName;
          ftnPlug.getValue( fileTextureName );
        }
      }

      // Not a file node? Add support for other nodes here.
      else
      {
        assert( false && "Unsupported texture node." );
      }
    }
    else
    {
      // The plug is not connected. Just read its color values.
      double r, g, b;
      plug.getChild(0).getValue( r );
      plug.getChild(1).getValue( g );
      plug.getChild(2).getValue( b );
    }
  }

The file texture name will likely be returned as a full path - but it's not always that straight-forward. Maya has all sorts of little internal tricks to resolve the actual location for a file texture, and uses one or more double slash "//" separators (in place of a single slash) as a hint to derive a path for the image relative to the current project. You may need to do some more massaging of this path to determine the actual file.

In Maya v5 Alias introduced a handy means of extracting the image itself - that is, the pixel data - from the 'file' node:

MImage::readFromTextureNode( const MObject& fileTextureObject );

And in Maya 6, they added a method to the MRenderUtil class to return the full path to the texture image resolved by a file node (Hallelujah!):

  MRenderUtil:: exactFileTextureName ( const MObject& fileNode,
                                       MString& texturePath,
                                       MStatus* ReturnStatus );

Related How-To's

19 Sep 2004