Example #1
0
MStatus disconnectAllPlugsTo(MPlug & dstPlug)
{
    MStatus status = MS::kSuccess;
    MPlugArray array;
    dstPlug.connectedTo(array, true, false, &status);
    unsigned int arrayLength = array.length();

    for (unsigned int i = 0; i < arrayLength; i++)
    {
        MPlug srcPlug = array[i];
        if (status == MS::kSuccess)
        {
            MDGModifier modifier;
            status = modifier.disconnect(srcPlug, dstPlug);
            status = modifier.doIt();
            if (status != MS::kSuccess)
            {
                MString theError("Disconnect ");
                theError += srcPlug.name();
                theError += MString(" -> ");
                theError += dstPlug.name();
                theError += MString(" failed, status = ");
                theError += status.errorString();
                MGlobal::displayError(theError);
                return status;
            }
        }
    }
    return MS::kSuccess;
}
MStatus liqLightNodeBehavior::connectNodeToNode( MObject &sourceNode, MObject &destinationNode, bool force )
{
    //CM_TRACE_FUNC("liqLightNodeBehavior::connectNodeToNode("<<sourceNode.apiTypeStr()<<","<< destinationNode.apiTypeStr()<<","<<force<<")");

    MStatus result = MS::kFailure;
    MFnDependencyNode src(sourceNode);

    if (src.typeName() == "liquidLight")
    {
        // if we are dragging from a liquidLight
        // than we want to see what we are dragging onto
        if( true )//destinationNode.hasFn(MFn::kLight))
        {
            /* if the user is dragging onto a light
            then make the connection from the worldMesh
            to the dirtyShader plug on the slopeShader */

            MFnDependencyNode dest(destinationNode);
            MPlug srcPlug = src.findPlug("assignedObjects");
            MPlug destPlug = dest.findPlug("liquidLightShaderNode");

            if ( destPlug.isNull() )
            {
                /* the attribute does not exist yet : create it ! */
                //cout <<"need to create liquidLightShaderNode attribute on "<<dest.name()<<"..."<<endl;
                MString mel = "addAttr -at message -ln liquidLightShaderNode " + dest.name() +";";
                result = MGlobal::executeCommand(mel);
                if ( result == MS::kSuccess )
                {
                    //cout <<"attribute liquidLightShaderNode successfully created"<<endl;
                    result = MS::kFailure;
                    destPlug = dest.findPlug("liquidLightShaderNode");
                }
            }

            if(!srcPlug.isNull() && !destPlug.isNull())
            {
                MString boolean = (force)? "true":"false";
                MString cmd = "connectAttr ";
                //cmd += "-force " + boolean + " ";
                cmd += srcPlug.name() + " ";
                cmd += destPlug.name();
                result = MGlobal::executeCommand(cmd);
            }
        }
    }
    //if ( result == MS::kSuccess ) cout <<"connection successfull"<<endl;
    //else cout <<"connection failed !"<<endl;
    return result;
}
Example #3
0
void findConnectedNodeTypes(uint nodeId, MObject thisObject, MObjectArray& connectedElements, MPlugArray& completeList, bool upstream)
{

	MGlobal::displayInfo(MString("thisNode: ") + getObjectName(thisObject));

	MString name = getObjectName(thisObject);

	MFnDependencyNode depFn(thisObject);
	if(depFn.typeId().id() == nodeId)
	{
		connectedElements.append(thisObject);
		MGlobal::displayInfo(MString("found object with correct id: ") + depFn.name());
		return;
	}

	bool downstream = !upstream;

	MPlugArray plugArray;
	depFn.getConnections(plugArray);

	int numc = plugArray.length();

	for( uint plugId = 0; plugId < plugArray.length(); plugId++)
	{
		MPlug plug = plugArray[plugId];
		if( isPlugInList(plug, completeList))
			continue;

		completeList.append(plug);

		MString pn = plug.name();
		if( upstream && plug.isDestination())
			continue;
		if( downstream && plug.isSource())
			continue;
		
		MPlugArray otherSidePlugs;
		bool asDest = plug.isDestination();
		bool asSrc = plug.isSource();
		MGlobal::displayInfo(MString("findConnectedNodeTypes: checking plug ") + plug.name());
		plug.connectedTo(otherSidePlugs, asDest, asSrc);
		for( uint cplugId = 0; cplugId < otherSidePlugs.length(); cplugId++)
		{
			findConnectedNodeTypes(nodeId, otherSidePlugs[cplugId].node(), connectedElements, completeList, upstream);
		}		
	}

}
void liquidIPR_AttributeChangedCallback( MNodeMessage::AttributeMessage msg, 
	MPlug & plug, MPlug & otherPlug, void *userData )
{
	MGlobal::displayInfo( "liquidIPR_AttributeChangedCallback(msg, "+ plug.name()+","+otherPlug.name()+", userData)");
	//liquidMessage2(messageInfo, "msg=%0x", msg);

	static std::size_t iHowMantThreadEnters = 0;
	iHowMantThreadEnters++;
	//liquidMessage2(messageInfo, "HowMantThreadEnters=%d", iHowMantThreadEnters);

	if ( msg & MNodeMessage::kConnectionMade ) {
		MGlobal::displayInfo("Connection made ");
	}
	else if ( msg & MNodeMessage::kConnectionBroken ) {
		MGlobal::displayInfo("Connection broken ");
	}
	else if ( msg & MNodeMessage::kAttributeEval ) {
		MGlobal::displayInfo("kAttributeEval");
	}
	else if ( msg & MNodeMessage::kAttributeSet ) {
		MGlobal::displayInfo("kAttributeSet");

		//liqRibTranslator::getInstancePtr()->IPRRenderBegin();

		//if( canExport() )
		{
			liquid::RendererMgr::getInstancePtr()->getRenderer()
				->IPR_AttributeChangedCallback(msg, plug, otherPlug, userData);
		}

		//liqRibTranslator::getInstancePtr()->IPRRenderEnd();
	}
	else {
		liquidMessage2(messageInfo, "else: msg=%0x", msg);
	}

// 	cout << plug.info();
// 	if ( msg & MNodeMessage::kOtherPlugSet ) {
// 		if ( msg & MNodeMessage::kIncomingDirection ) {
// 				cout << "  <--  " << otherPlug.info();
// 		} else {
// 				cout << "  -->  " << otherPlug.info();
// 		}
// 	}
// 	cout << endl;
	--iHowMantThreadEnters;

}
Example #5
0
static bool
_GetMetadataUnchecked(
    const MFnDependencyNode& node,
    const TfToken& key,
    VtValue* value)
{
    VtValue fallback = SdfSchema::GetInstance().GetFallback(key);
    if (fallback.IsEmpty()) {
        return false;
    }

    std::string mayaAttrName = _GetMayaAttrNameForMetadataKey(key);
    MPlug plug = node.findPlug(mayaAttrName.c_str());
    if (plug.isNull()) {
        return false;
    }

    TfType ty = fallback.GetType();
    VtValue result = UsdMayaWriteUtil::GetVtValue(plug, ty, TfToken());
    if (result.IsEmpty()) {
        TF_RUNTIME_ERROR(
                "Cannot convert plug '%s' into metadata '%s' (%s)",
                plug.name().asChar(),
                key.GetText(),
                ty.GetTypeName().c_str());
        return false;
    }

    *value = result;
    return true;
}
Example #6
0
// The compute() method does the actual work of the node using the inputs
// of the node to generate its output.
//
// Compute takes two parameters: plug and data.
// - Plug is the the data value that needs to be recomputed
// - Data provides handles to all of the nodes attributes, only these
//   handles should be used when performing computations.
//
MStatus affects::compute( const MPlug& plug, MDataBlock& data )
{
    MStatus status;
    MObject thisNode = thisMObject();
    MFnDependencyNode fnThisNode( thisNode );
    fprintf(stderr,"affects::compute(), plug being computed is \"%s\"\n",
            plug.name().asChar());

    if ( plug.partialName() == "B" ) {
        // Plug "B" is being computed. Assign it the value on plug "A"
        // if "A" exists.
        //
        MPlug pA = fnThisNode.findPlug( "A", &status );
        if ( MStatus::kSuccess == status ) {
            fprintf(stderr,"\t\t... found dynamic attribute \"A\", copying its value to \"B\"\n");
            MDataHandle inputData = data.inputValue( pA, &status );
            CHECK_MSTATUS( status );
            int value = inputData.asInt();

            MDataHandle outputHandle = data.outputValue( plug );
            outputHandle.set( value );
            data.setClean(plug);
        }
    } else {
        return MS::kUnknownParameter;
    }
    return( MS::kSuccess );
}
Example #7
0
void ShadingNode::getConnectedInputObjects(MObjectArray& objectArray)
{
	MStatus stat;
	MFnDependencyNode depFn(this->mobject);
	MStringArray aliasArray;
	depFn.getAliasList(aliasArray);
	MObjectArray objectList;
	MPlugArray connections;
	depFn.getConnections(connections);

	for (uint connId = 0; connId < connections.length(); connId++)
	{
		MPlug p = connections[connId];
		if (!p.isDestination())
			continue;
		
		// a connection can be a direct connection or a child connection e.g. colorR, colorG...
		// but in a shader description file only the main attribute is listed so we go up until we have the main plug
		MPlug mainPlug = p;
		while (mainPlug.isChild())
			mainPlug = mainPlug.parent();
		if (mainPlug.isElement())
			mainPlug = mainPlug.array();
		MStringArray stringArray;
		// name contains node.attributeName, so we have to get rid of the nodeName
		mainPlug.name().split('.', stringArray);
		MString plugName = stringArray[stringArray.length() - 1];
		if (!this->isAttributeValid(plugName))
			continue;
		getConnectedInNodes(p, objectList);
		makeUniqueArray(objectList);
	}
	objectArray = objectList;
}
Example #8
0
UsdAttribute
PxrUsdMayaWriteUtil::GetOrCreateUsdAttr(
    const MPlug& plg,
    const UsdPrim& usdPrim,
    const std::string &attrName,
    bool custom)
{
    MObject attrObj(plg.attribute());

    TfToken usdAttrName(attrName);
    if (usdAttrName.IsEmpty()) {
        printf("Invalid attrName '%s' for %s\n",
               attrName.c_str(),
               plg.name().asChar());
        return UsdAttribute();
    }

    // See if usdAttr already exists.  If so, return.
    UsdAttribute usdAttr = usdPrim.GetAttribute(usdAttrName);
    if (usdAttr) {
        return usdAttr;
    }

    SdfValueTypeName attrType = PxrUsdMayaWriteUtil::GetUsdTypeName(plg);

    // ---------------------
    // CreateAttribute on USD Prim if specified above
    if (attrType) {
        usdAttr = usdPrim.CreateAttribute(usdAttrName, attrType, custom);
    }
    else {
        // Skipping.  Unsupported type.
    }
    return usdAttr;
}
Example #9
0
MObject getConnectedInNode(const MObject& thisObject, const char *attrName)
{
    MObject result = MObject::kNullObj;
    MString indexStr, base;
    int index = -1;
    if (getArrayIndex(attrName, indexStr, base))
    {
        index = indexStr.asInt();
        attrName = base.asChar();
    }
    MFnDependencyNode depFn(thisObject);
    MPlug inPlug = depFn.findPlug(attrName);
    if (index > -1)
        inPlug = inPlug[index];
    MString plugname = inPlug.name();

    if (!inPlug.isConnected())
        return result;

    MPlugArray connectedPlugs;
    inPlug.connectedTo(connectedPlugs, true, false);
    if (connectedPlugs.length() == 0)
        return result;

    return connectedPlugs[0].node();
}
Example #10
0
MStatus btSPHMgrNode::compute(const MPlug &plug, MDataBlock &data)
{
	_LogFunctionCall("btSPHMgrNode::compute("<< plug.name().asChar()<< ")");

	MStatus status;	
	
	return MS::kSuccess;
}
MStatus liqLightNodeBehavior::connectNodeToAttr( MObject &sourceNode, MPlug &destinationPlug, bool force )
{
    //CM_TRACE_FUNC("liqLightNodeBehavior::connectNodeToAttr("<<sourceNode.apiTypeStr()<<","<< destinationPlug.name()<<","<<force<<")");

    MStatus result = MS::kFailure;
    MFnDependencyNode src(sourceNode);

    /*
    if we are dragging from a liquidLight
    to a light then connect the assignedObjects
    plug to the plug being passed in
    */

    if(destinationPlug.node().hasFn(MFn::kLight))
    {
        if(src.typeName() == "liquidLight")
        {
            MPlug srcPlug = src.findPlug("assignedObjects");

            MObject dstNode = destinationPlug.node();
            MFnDependencyNode dst( dstNode );
            MPlug dstPlug = dst.findPlug("liquidLightShaderNode");

            if(!srcPlug.isNull() && !destinationPlug.isNull() && destinationPlug == dstPlug )
            {
                //MString boolean = (force)? "true":"false";
                MString cmd = "connectAttr ";
                //cmd += "-force " + boolean + " ";
                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;
}
Example #12
0
	// Break connections to this blendshape
	void BlendShape::breakConnections()
	{
		MStatus stat;
		MDagModifier dagModifier;
		// Clear the stored connections
		m_weightConnections.clear();
		// Save node connections and break them
		MPlug weightsPlug = m_pBlendShapeFn->findPlug("weight",true);
		for (int i=0; i<weightsPlug.evaluateNumElements(); i++)
		{
			MPlug wPlug = weightsPlug.elementByPhysicalIndex(i);
			MPlugArray srcConnections;
			MPlugArray dstConnections;
			wPlug.connectedTo(srcConnections,false,true);
			wPlug.connectedTo(dstConnections,true,false);
			weightConnections wcon;
			for (int j=0; j<srcConnections.length(); j++)
			{
				wcon.srcConnections.append(srcConnections[j]);
				dagModifier.disconnect(wPlug,srcConnections[j]);
				dagModifier.doIt();
			}
			for (int j=0; j<dstConnections.length(); j++)
			{
				wcon.dstConnections.append(dstConnections[j]);
				stat = dagModifier.disconnect(dstConnections[j],wPlug);
				if (MS::kSuccess != stat)
				{
					std::cout << "Error trying to disconnect plug " << wPlug.name().asChar() << " and plug " << dstConnections[j].name().asChar() << "\n";
					std::cout << stat.errorString().asChar() << "\n";
					std::cout.flush();
				}
				stat = dagModifier.doIt();
				if (MS::kSuccess != stat)
				{
					std::cout << "Error trying to disconnect plug " << wPlug.name().asChar() << " and plug " << dstConnections[j].name().asChar() << "\n";
					std::cout << stat.errorString().asChar() << "\n";
					std::cout.flush();
				}
			}
			m_weightConnections.push_back(wcon);
		}
	}
Example #13
0
/**
 *	Check if this node has animations connected (AnimCurves or MotionPaths)
 *	and indicate the type of the animation found (if any)
 */
bool Transform::hasAnimation(MObject &obj, MFn::Type &type)
{
	MFnDependencyNode dn(obj);
	MPlugArray conns;
	dn.getConnections(conns);
	for(int i=0; i<conns.length(); i++){
		MPlug conn = conns[i];
		if( conn.name() == dn.name() + ".translateX" ||
			conn.name() == dn.name() + ".translateY" ||
			conn.name() == dn.name() + ".translateZ" ||
			conn.name() == dn.name() + ".rotateX" ||
			conn.name() == dn.name() + ".rotateY" ||
			conn.name() == dn.name() + ".rotateZ" ||
			conn.name() == dn.name() + ".scaleX" ||
			conn.name() == dn.name() + ".scaleY" ||
			conn.name() == dn.name() + ".scaleZ" ){

			MPlugArray connectedTo;
			// Get all connections having this node as destination
			conn.connectedTo(connectedTo, true, false);
#ifdef GENERIC_EXPORTER
			if ( connectedTo.length() > 0 ) {
				return true;
			}
#else
			for(int j=0; j<connectedTo.length(); j++){
				MPlug origin = connectedTo[j];
				MObject origin_node = origin.node();
				if(origin_node.hasFn(MFn::kAnimCurve)){
					type = MFn::kAnimCurve;
					return true;
				}
				else if(origin_node.hasFn(MFn::kMotionPath)){
					type = MFn::kMotionPath;
					return true;
				}
			}
#endif
		}
	}
	type = MFn::kInvalid;
	return false;
}
Example #14
0
/* static */
UsdAttribute PxrUsdMayaWriteUtil::GetOrCreateUsdRiAttribute(
        const MPlug& attrPlug,
        const UsdPrim& usdPrim,
        const std::string& attrName,
        const std::string& nameSpace,
        const bool translateMayaDoubleToUsdSinglePrecision)
{
    UsdAttribute usdAttr;

    if (!usdPrim) {
        return usdAttr;
    }

    MObject attrObj(attrPlug.attribute());

    TfToken riAttrNameToken(attrName);
    if (riAttrNameToken.IsEmpty()) {
        MGlobal::displayError(
            TfStringPrintf("Invalid UsdRi attribute name '%s' for Maya plug '%s'",
                           attrName.c_str(),
                           attrPlug.name().asChar()).c_str());
        return usdAttr;
    }

    UsdRiStatements riStatements(usdPrim);
    if (!riStatements) {
        return usdAttr;
    }

    // See if a UsdRi attribute with this name already exists. If so, return it.
    // XXX: There isn't currently API for looking for a specific UsdRi attribute
    // by name, so we have to get them all and then see if one matches.
    const std::vector<UsdProperty>& riAttrs = riStatements.GetRiAttributes(nameSpace);
    TF_FOR_ALL(iter, riAttrs) {
        if (iter->GetBaseName() == riAttrNameToken) {
            // Re-get the attribute from the prim so we can return it as a
            // UsdAttribute rather than a UsdProperty.
            return usdPrim.GetAttribute(iter->GetName());
        }
    }

    const SdfValueTypeName& typeName =
        PxrUsdMayaWriteUtil::GetUsdTypeName(attrPlug,
                                            translateMayaDoubleToUsdSinglePrecision);
    if (typeName) {
        usdAttr = riStatements.CreateRiAttribute(riAttrNameToken,
                                                 typeName.GetType(),
                                                 nameSpace);
    }

    return usdAttr;
}
void liquidIPR_NodeDirtyPlugCallback( MObject& node,MPlug& plug,void* userData )
{
	MFnDependencyNode nodeFn(node);
	MGlobal::displayInfo( "liquidIPR_NodeDirtyPlugCallback( " + nodeFn.name()+","+plug.name()+", userData)");


	liqRibTranslator::getInstancePtr()->IPRRenderBegin();

	liquid::RendererMgr::getInstancePtr()->getRenderer()
		->IPR_NodeDirtyPlugCallback(node, plug, userData);

	liqRibTranslator::getInstancePtr()->IPRRenderEnd();
}
Example #16
0
bool getOtherSidePlugName(MString& plugName, MObject& thisObject, MString& otherSidePlugName)
{
	MStatus stat;
	MFnDependencyNode depFn(thisObject, &stat);	if( stat != MStatus::kSuccess) return false;
	MPlug plug = depFn.findPlug(plugName, &stat);	if( stat != MStatus::kSuccess) return false;
	MPlugArray plugArray;
	plug.connectedTo(plugArray, 1, 0, &stat);if( stat != MStatus::kSuccess) return false;
	if( plugArray.length() == 0)
		return false;
	MPlug otherSidePlug = plugArray[0];
	otherSidePlugName = otherSidePlug.name();
	return true;
}
Example #17
0
bool LuxRenderer::isLightMesh(mtlu_MayaObject *obj)
{
	MStatus stat;
	MObject result = MObject::kNullObj;
	MFnDependencyNode depFn(obj->mobject, &stat);	if( stat != MStatus::kSuccess) return false;
	MPlug plug = depFn.findPlug("message", &stat);	if( stat != MStatus::kSuccess) return false;
	MPlugArray plugArray;
	plug.connectedTo(plugArray, 0, 1, &stat);if( stat != MStatus::kSuccess) return false;
	if( plugArray.length() == 0)
		return false;
	for( uint i = 0; i < plugArray.length(); i++)
	{
		MPlug otherSidePlug = plugArray[i];
		logger.debug(MString("Checking message connection: ") + otherSidePlug.name());
		if( !pystring::endswith(otherSidePlug.name().asChar(), "mtlu_areaLight_geo"))
			continue;
		result = otherSidePlug.node();
		if( result.hasFn(MFn::kLight))
			return true;
	}
	return false;
}
Example #18
0
bool getConnectedFileTexturePath(MString& plugName, MString& nodeName, MString& value, MObject& outFileNode)
{
	MStatus stat;
	MObject obj = objectFromName(nodeName);
	if( obj == MObject::kNullObj)
		return false;

	MFnDependencyNode depFn(obj);
	MPlug plug = depFn.findPlug(plugName, &stat);
	if( !stat )
		return false;
	
	//MGlobal::displayInfo(MString("is plug connected: ") + plug.name());
	if( !plug.isConnected())
	{
		//MGlobal::displayInfo(MString("plug is NOT connected: ") + plug.name());
		return false;
	}
	MPlugArray parray;
	plug.connectedTo(parray, true, false, &stat);
	if( !stat )
		return false;

	if( parray.length() == 0 )
		return false;

	MPlug destPlug = parray[0];
	MObject fileNode = destPlug.node();
	std::cout << "filenode: " << getObjectName(fileNode).asChar() << " plug name " << destPlug.name() << "\n";
	
	if( !fileNode.hasFn(MFn::kFileTexture) )
	{
		std::cout << "node is not from type fileTexture.\n";
		return false;
	}

	MFnDependencyNode fileDepFn(fileNode);
	MPlug ftn = fileDepFn.findPlug("fileTextureName", &stat);

	if(!stat)
	{
		std::cout << "fileTextureName not found at fileTexNode.\n";
		return false;
	}
	
	MString fileTextureName = ftn.asString();
	std::cout << "fileTextureName value: " << fileTextureName.asChar() <<"\n";
	value = fileTextureName;
	outFileNode = fileNode;
	return true;
}
void ClassParameterHandler::currentClass( const MPlug &plug, MString &className, int &classVersion, MString &searchPathEnvVar )
{
	MObject attribute = plug.attribute();
	MFnTypedAttribute fnTAttr( attribute );
	if ( !fnTAttr.hasObj( attribute ) || fnTAttr.attrType() != MFnData::kStringArray )
	{
		// compatibility for the deprecated compound plug behaviour
		className = plug.child( 0 ).asString();
		classVersion = plug.child( 1 ).asInt();
		searchPathEnvVar = plug.child( 2 ).asString();
		return;
	}
	
	MFnStringArrayData fnSAD( plug.asMObject() );
	if ( fnSAD.length() == 0 )
	{
		className = "";
		classVersion = 0;
		searchPathEnvVar = "";
		return;
	}
	
	if ( fnSAD.length() != 3 )
	{
		throw( IECore::InvalidArgumentException( ( plug.name() + " has more than 3 values. Expected name, version, searchPath only." ).asChar() ) );
	}

	MStringArray storedClassInfo = fnSAD.array();
	if ( !storedClassInfo[1].isInt() )
	{
		throw( IECore::InvalidArgumentException( ( "Second value of " + plug.name() + " must represent an integer" ).asChar() ) );
	}
	
	className = storedClassInfo[0];
	classVersion = storedClassInfo[1].asInt();
	searchPathEnvVar = storedClassInfo[2];
}
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;
}
Example #21
0
// get direct connections and primary children connections for such plugs like color, vector, point
void getConnectedInNodes(MPlug& plug, MObjectArray& nodeList)
{
    MPlugArray connectedPlugs;
    plug.connectedTo(connectedPlugs, true, false);
    MString plugname = plug.name();
    int numConnections = connectedPlugs.length();

    for (int i = 0; i <  numConnections; i++)
    {
        MString otherSidePlug = connectedPlugs[i].name();
        MObject plugObject = connectedPlugs[i].node();
        if (plugObject != MObject::kNullObj)
            nodeList.append(plugObject);
    }
}
Example #22
0
/* static */
UsdGeomPrimvar PxrUsdMayaWriteUtil::GetOrCreatePrimvar(
        const MPlug& attrPlug,
        UsdGeomImageable& imageable,
        const std::string& primvarName,
        const TfToken& interpolation,
        const int elementSize,
        const bool custom,
        const bool translateMayaDoubleToUsdSinglePrecision)
{
    UsdGeomPrimvar primvar;

    if (!imageable) {
        return primvar;
    }

    MObject attrObj(attrPlug.attribute());

    TfToken primvarNameToken(primvarName);
    if (primvarNameToken.IsEmpty()) {
        MGlobal::displayError(
            TfStringPrintf("Invalid primvar name '%s' for Maya plug '%s'",
                           primvarName.c_str(),
                           attrPlug.name().asChar()).c_str());
        return primvar;
    }

    // See if the primvar already exists. If so, return it.
    primvar = imageable.GetPrimvar(primvarNameToken);
    if (primvar) {
        return primvar;
    }

    const SdfValueTypeName& typeName =
        PxrUsdMayaWriteUtil::GetUsdTypeName(attrPlug,
                                            translateMayaDoubleToUsdSinglePrecision);
    if (typeName) {
        primvar = imageable.CreatePrimvar(primvarNameToken,
                                          typeName,
                                          interpolation,
                                          elementSize,
                                          custom);
    }

    return primvar;
}
Example #23
0
MObject getOtherSideNode(MString& plugName, MObject& thisObject, MString& otherSidePlugName)
{
	MStatus stat;
	MObject result = MObject::kNullObj;
	MFnDependencyNode depFn(thisObject, &stat);	if( stat != MStatus::kSuccess) return result;
	MPlug plug = depFn.findPlug(plugName, &stat);	if( stat != MStatus::kSuccess)return result;
	if( !plug.isConnected() )
		return result;
	MPlugArray plugArray;
	plug.connectedTo(plugArray, 1, 0, &stat);if( stat != MStatus::kSuccess) return result;
	if( plugArray.length() == 0)
		return result;
	MPlug otherSidePlug = plugArray[0];
	result = otherSidePlug.node();
	otherSidePlugName = otherSidePlug.name();
	otherSidePlugName = otherSidePlug.partialName(false, false, false, false, false, true);
	return result;
}
Example #24
0
// This function is a utility that can be used to extract vector values from
// plugs.
//
MVector vectorPlugValue(const MPlug& plug) {
	if (plug.numChildren() == 3)
	{
		double x,y,z;
		MPlug rx = plug.child(0);
		MPlug ry = plug.child(1);
		MPlug rz = plug.child(2);
		rx.getValue(x);
		ry.getValue(y);
		rz.getValue(z);
		MVector result(x,y,z);
		return result;
	}
	else {
		MGlobal::displayError("Expected 3 children for plug "+MString(plug.name()));
		MVector result(0,0,0);
		return result;
	}
}
Example #25
0
// check if the node or any of its parents has a animated visibility
bool  MayaObject::isVisiblityAnimated()
{
	MStatus stat = MStatus::kSuccess;
	bool visibility = true;
	MDagPath dp = this->dagPath;
	while (stat == MStatus::kSuccess)
	{
		MFnDependencyNode depFn(dp.node());
		MPlug vplug = depFn.findPlug("visibility");
		if(vplug.isConnected())
		{
			Logging::debug(MString("Object: ") + vplug.name() + " has animated visibility");
			return true;
		}
		stat = dp.pop();
	}

	return false;	
}
Example #26
0
bool isConnected(const char *attrName, MFnDependencyNode& depFn, bool dest, bool primaryChild = false)
{
    MStatus stat;
    MPlugArray pa;
    depFn.getConnections(pa);
    std::vector<std::string> stringParts;
    pystring::split(attrName, stringParts, ".");
    MString attName = attrName;
    if (stringParts.size() > 1)
        attName = stringParts.back().c_str();
    if (pystring::endswith(attrName, "]"))
    {
        int found = attName.rindex('[');
        if (found >= 0)
            attName = attName.substring(0, found-1);
    }

    for (uint pId = 0; pId < pa.length(); pId++)
    {
        if (dest)
        {
            if (!pa[pId].isDestination())
                continue;
        }
        else
        {
            if (!pa[pId].isSource())
                continue;
        }
        MPlug plug = pa[pId];
        if (primaryChild)
            while (plug.isChild())
                plug = plug.parent();
        MString plugName = plug.name();
        if (plug.isElement())
            plug = plug.array();
        MString attNameFromPlug = getAttributeNameFromPlug(plug);
        if ((attNameFromPlug == attName))
            return true;
    }
    return false;
}
Example #27
0
MObject getOtherSideNode(const MString& plugName, MObject& thisObject, MStringArray& otherSidePlugNames)
{
    MStatus stat;
    MObject result = MObject::kNullObj;
    MFnDependencyNode depFn(thisObject, &stat);
    if (stat != MStatus::kSuccess) return result;
    MPlug plug = depFn.findPlug(plugName, &stat);
    if (stat != MStatus::kSuccess)return result;
    if (!plug.isConnected())
    {
        int numChildConnects = plug.numConnectedChildren();
        if (numChildConnects == 0)
            return result;
        else
        {
            for (int i = 0; i < numChildConnects; i++)
            {
                MPlug child = plug.child(i);
                MString otherSidePlugName;
                MObject childObj = getOtherSideNode(child.partialName(false), thisObject, otherSidePlugName);
                if (childObj != MObject::kNullObj)
                {
                    otherSidePlugNames.append(otherSidePlugName);
                    result = childObj;
                } else
                    otherSidePlugNames.append(MString(""));
            }
        }
    }
    else
    {
        MPlugArray plugArray;
        plug.connectedTo(plugArray, 1, 0, &stat);
        if (stat != MStatus::kSuccess) return result;
        if (plugArray.length() == 0)
            return result;
        MPlug otherSidePlug = plugArray[0];
        result = otherSidePlug.node();
        otherSidePlugNames.append(otherSidePlug.name());
    }
    return result;
}
Example #28
0
/* static */
UsdAttribute
PxrUsdMayaWriteUtil::GetOrCreateUsdAttr(
        const MPlug& attrPlug,
        const UsdPrim& usdPrim,
        const std::string& attrName,
        const bool custom,
        const bool translateMayaDoubleToUsdSinglePrecision)
{
    UsdAttribute usdAttr;

    if (!usdPrim) {
        return usdAttr;
    }

    MObject attrObj(attrPlug.attribute());

    TfToken usdAttrNameToken(attrName);
    if (usdAttrNameToken.IsEmpty()) {
        MGlobal::displayError(
            TfStringPrintf("Invalid USD attribute name '%s' for Maya plug '%s'",
                           attrName.c_str(),
                           attrPlug.name().asChar()).c_str());
        return usdAttr;
    }

    // See if the USD attribute already exists. If so, return it.
    usdAttr = usdPrim.GetAttribute(usdAttrNameToken);
    if (usdAttr) {
        return usdAttr;
    }

    const SdfValueTypeName& typeName =
        PxrUsdMayaWriteUtil::GetUsdTypeName(attrPlug,
                                            translateMayaDoubleToUsdSinglePrecision);
    if (typeName) {
        usdAttr = usdPrim.CreateAttribute(usdAttrNameToken, typeName, custom);
    }

    return usdAttr;
}
bool ToMayaSkinClusterConverter::doConversion( IECore::ConstObjectPtr from, MObject &to, IECore::ConstCompoundObjectPtr operands ) const
{
    MStatus s;

    IECore::ConstSmoothSkinningDataPtr skinningData = IECore::runTimeCast<const IECore::SmoothSkinningData>( from );
    assert( skinningData );

    const std::vector<std::string> &influenceNames = skinningData->influenceNames()->readable();
    const std::vector<Imath::M44f> &influencePoseData  = skinningData->influencePose()->readable();
    const std::vector<int> &pointIndexOffsets  = skinningData->pointIndexOffsets()->readable();
    const std::vector<int> &pointInfluenceCounts = skinningData->pointInfluenceCounts()->readable();
    const std::vector<int> &pointInfluenceIndices = skinningData->pointInfluenceIndices()->readable();
    const std::vector<float> &pointInfluenceWeights = skinningData->pointInfluenceWeights()->readable();

    MFnDependencyNode fnSkinClusterNode( to, &s );
    MFnSkinCluster fnSkinCluster( to, &s );
    if ( s != MS::kSuccess )
    {
        /// \todo: optional parameter to allow custom node types and checks for the necessary attributes
        /// \todo: create a new skinCluster if we want a kSkinClusterFilter and this isn't one
        throw IECore::Exception( ( boost::format( "ToMayaSkinClusterConverter: \"%s\" is not a valid skinCluster" ) % fnSkinClusterNode.name() ).str() );
    }

    const unsigned origNumInfluences = influenceNames.size();
    unsigned numInfluences = origNumInfluences;
    std::vector<bool> ignoreInfluence( origNumInfluences, false );
    std::vector<int> indexMap( origNumInfluences, -1 );
    const bool ignoreMissingInfluences = m_ignoreMissingInfluencesParameter->getTypedValue();
    const bool ignoreBindPose = m_ignoreBindPoseParameter->getTypedValue();

    // gather the influence objects
    MObject mObj;
    MDagPath path;
    MSelectionList influenceList;
    MDagPathArray influencePaths;
    for ( unsigned i=0, index=0; i < origNumInfluences; i++ )
    {
        MString influenceName( influenceNames[i].c_str() );
        s = influenceList.add( influenceName );
        if ( !s )
        {
            if ( ignoreMissingInfluences )
            {
                ignoreInfluence[i] = true;
                MGlobal::displayWarning( MString( "ToMayaSkinClusterConverter: \"" + influenceName + "\" is not a valid influence" ) );
                continue;
            }

            throw IECore::Exception( ( boost::format( "ToMayaSkinClusterConverter: \"%s\" is not a valid influence" ) % influenceName ).str() );
        }

        influenceList.getDependNode( index, mObj );
        MFnIkJoint fnInfluence( mObj, &s );
        if ( !s )
        {
            if ( ignoreMissingInfluences )
            {
                ignoreInfluence[i] = true;
                influenceList.remove( index );
                MGlobal::displayWarning( MString( "ToMayaSkinClusterConverter: \"" + influenceName + "\" is not a valid influence" ) );
                continue;
            }

            throw IECore::Exception( ( boost::format( "ToMayaSkinClusterConverter: \"%s\" is not a valid influence" ) % influenceName ).str() );
        }

        fnInfluence.getPath( path );
        influencePaths.append( path );
        indexMap[i] = index;
        index++;
    }

    MPlugArray connectedPlugs;

    bool existingBindPose = true;
    MPlug bindPlug = fnSkinClusterNode.findPlug( "bindPose", true, &s );
    if ( !bindPlug.connectedTo( connectedPlugs, true, false ) )
    {
        existingBindPose = false;
        if ( !ignoreBindPose )
        {
            throw IECore::Exception( ( boost::format( "ToMayaSkinClusterConverter: \"%s\" does not have a valid bindPose" ) % fnSkinClusterNode.name() ).str() );
        }
    }

    MPlug bindPoseMatrixArrayPlug;
    MPlug bindPoseMemberArrayPlug;
    if ( existingBindPose )
    {
        MFnDependencyNode fnBindPose( connectedPlugs[0].node() );
        if ( fnBindPose.typeName() != "dagPose" )
        {
            throw IECore::Exception( ( boost::format( "ToMayaSkinClusterConverter: \"%s\" is not a valid bindPose" ) % fnBindPose.name() ).str() );
        }

        bindPoseMatrixArrayPlug = fnBindPose.findPlug( "worldMatrix", true, &s );
        bindPoseMemberArrayPlug = fnBindPose.findPlug( "members", true, &s );
    }

    /// \todo: optional parameter to reset the skinCluster's geomMatrix plug

    // break existing influence connections to the skinCluster
    MDGModifier dgModifier;
    MMatrixArray ignoredPreMatrices;
    MPlug matrixArrayPlug = fnSkinClusterNode.findPlug( "matrix", true, &s );
    MPlug bindPreMatrixArrayPlug = fnSkinClusterNode.findPlug( "bindPreMatrix", true, &s );
    for ( unsigned i=0; i < matrixArrayPlug.numConnectedElements(); i++ )
    {
        MPlug matrixPlug = matrixArrayPlug.connectionByPhysicalIndex( i, &s );
        matrixPlug.connectedTo( connectedPlugs, true, false );
        if ( !connectedPlugs.length() )
        {
            continue;
        }

        MFnIkJoint fnInfluence( connectedPlugs[0].node() );
        fnInfluence.getPath( path );
        if ( ignoreMissingInfluences && !influenceList.hasItem( path ) )
        {
            MPlug preMatrixPlug = bindPreMatrixArrayPlug.elementByLogicalIndex( i );
            preMatrixPlug.getValue( mObj );
            MFnMatrixData matFn( mObj );
            ignoredPreMatrices.append( matFn.matrix() );
            ignoreInfluence.push_back( false );
            indexMap.push_back( influenceList.length() );
            influenceList.add( connectedPlugs[0].node() );
            numInfluences++;
        }
        dgModifier.disconnect( connectedPlugs[0], matrixPlug );
    }
    MPlug lockArrayPlug = fnSkinClusterNode.findPlug( "lockWeights", true, &s );
    for ( unsigned i=0; i < lockArrayPlug.numConnectedElements(); i++ )
    {
        MPlug lockPlug = lockArrayPlug.connectionByPhysicalIndex( i, &s );
        lockPlug.connectedTo( connectedPlugs, true, false );
        if ( connectedPlugs.length() )
        {
            dgModifier.disconnect( connectedPlugs[0], lockPlug );
        }
    }
    MPlug paintPlug = fnSkinClusterNode.findPlug( "paintTrans", true, &s );
    paintPlug.connectedTo( connectedPlugs, true, false );
    if ( connectedPlugs.length() )
    {
        dgModifier.disconnect( connectedPlugs[0], paintPlug );
    }

    // break existing influence connections to the bind pose
    if ( existingBindPose )
    {
        for ( unsigned i=0; i < bindPoseMatrixArrayPlug.numConnectedElements(); i++ )
        {
            MPlug matrixPlug = bindPoseMatrixArrayPlug.connectionByPhysicalIndex( i, &s );
            matrixPlug.connectedTo( connectedPlugs, true, false );
            if ( connectedPlugs.length() )
            {
                dgModifier.disconnect( connectedPlugs[0], matrixPlug );
            }
        }
        for ( unsigned i=0; i < bindPoseMemberArrayPlug.numConnectedElements(); i++ )
        {
            MPlug memberPlug = bindPoseMemberArrayPlug.connectionByPhysicalIndex( i, &s );
            memberPlug.connectedTo( connectedPlugs, true, false );
            if ( connectedPlugs.length() )
            {
                dgModifier.disconnect( connectedPlugs[0], memberPlug );
            }
        }
    }

    if ( !dgModifier.doIt() )
    {
        dgModifier.undoIt();
        throw IECore::Exception( "ToMayaSkinClusterConverter: Unable to break the influence connections" );
    }

    // make connections from influences to skinCluster and bindPose
    for ( unsigned i=0; i < numInfluences; i++ )
    {
        if ( ignoreInfluence[i] )
        {
            continue;
        }

        int index = indexMap[i];
        s = influenceList.getDependNode( index, mObj );
        MFnIkJoint fnInfluence( mObj, &s );
        MPlug influenceMatrixPlug = fnInfluence.findPlug( "worldMatrix", true, &s ).elementByLogicalIndex( 0, &s );
        MPlug influenceMessagePlug = fnInfluence.findPlug( "message", true, &s );
        MPlug influenceBindPosePlug = fnInfluence.findPlug( "bindPose", true, &s );
        MPlug influenceLockPlug = fnInfluence.findPlug( "lockInfluenceWeights", true, &s );
        if ( !s )
        {
            // add the lockInfluenceWeights attribute if it doesn't exist
            MFnNumericAttribute nAttr;
            MObject attribute = nAttr.create( "lockInfluenceWeights", "liw", MFnNumericData::kBoolean, false );
            fnInfluence.addAttribute( attribute );
            influenceLockPlug = fnInfluence.findPlug( "lockInfluenceWeights", true, &s );
        }

        // connect influence to the skinCluster
        MPlug matrixPlug = matrixArrayPlug.elementByLogicalIndex( index );
        MPlug lockPlug = lockArrayPlug.elementByLogicalIndex( index );
        dgModifier.connect( influenceMatrixPlug, matrixPlug );
        dgModifier.connect( influenceLockPlug, lockPlug );

        // connect influence to the bindPose
        if ( !ignoreBindPose )
        {
            MPlug bindPoseMatrixPlug = bindPoseMatrixArrayPlug.elementByLogicalIndex( index );
            MPlug memberPlug = bindPoseMemberArrayPlug.elementByLogicalIndex( index );
            dgModifier.connect( influenceMessagePlug, bindPoseMatrixPlug );
            dgModifier.connect( influenceBindPosePlug, memberPlug );
        }
    }
    unsigned firstIndex = find( ignoreInfluence.begin(), ignoreInfluence.end(), false ) - ignoreInfluence.begin();
    influenceList.getDependNode( firstIndex, mObj );
    MFnDependencyNode fnInfluence( mObj );
    MPlug influenceMessagePlug = fnInfluence.findPlug( "message", true, &s );
    dgModifier.connect( influenceMessagePlug, paintPlug );
    if ( !dgModifier.doIt() )
    {
        dgModifier.undoIt();
        throw IECore::Exception( "ToMayaSkinClusterConverter: Unable to create the influence connections" );
    }

    // use influencePoseData as bindPreMatrix
    for ( unsigned i=0; i < numInfluences; i++ )
    {
        if ( ignoreInfluence[i] )
        {
            continue;
        }

        MMatrix preMatrix = ( i < origNumInfluences ) ? IECore::convert<MMatrix>( influencePoseData[i] ) : ignoredPreMatrices[i-origNumInfluences];
        MPlug preMatrixPlug = bindPreMatrixArrayPlug.elementByLogicalIndex( indexMap[i], &s );
        s = preMatrixPlug.getValue( mObj );
        if ( s )
        {
            MFnMatrixData matFn( mObj );
            matFn.set( preMatrix );
            mObj = matFn.object();
        }
        else
        {
            MFnMatrixData matFn;
            mObj = matFn.create( preMatrix );
        }

        preMatrixPlug.setValue( mObj );
    }

    // remove unneeded bindPreMatrix children
    unsigned existingElements = bindPreMatrixArrayPlug.numElements();
    for ( unsigned i=influenceList.length(); i < existingElements; i++ )
    {
        MPlug preMatrixPlug = bindPreMatrixArrayPlug.elementByLogicalIndex( i, &s );
        /// \todo: surely there is a way to accomplish this in c++...
        MGlobal::executeCommand( ( boost::format( "removeMultiInstance %s" ) % preMatrixPlug.name() ).str().c_str() );
    }

    // get the geometry
    MObjectArray outputGeoObjs;
    if ( !fnSkinCluster.getOutputGeometry( outputGeoObjs ) )
    {
        throw IECore::Exception( ( boost::format( "ToMayaSkinClusterConverter: skinCluster \"%s\" does not have any output geometry!" ) % fnSkinCluster.name() ).str() );
    }
    MFnDagNode dagFn( outputGeoObjs[0] );
    MDagPath geoPath;
    dagFn.getPath( geoPath );

    // loop through all the points of the geometry and set the weights
    MItGeometry geoIt( outputGeoObjs[0] );
    MPlug weightListArrayPlug = fnSkinClusterNode.findPlug( "weightList", true, &s );
    for ( unsigned pIndex=0; !geoIt.isDone(); geoIt.next(), pIndex++ )
    {
        MPlug pointWeightsPlug = weightListArrayPlug.elementByLogicalIndex( pIndex, &s ).child( 0 );

        // remove existing influence weight plugs
        MIntArray existingInfluenceIndices;
        pointWeightsPlug.getExistingArrayAttributeIndices( existingInfluenceIndices );
        for( unsigned i=0; i < existingInfluenceIndices.length(); i++ )
        {
            MPlug influenceWeightPlug = pointWeightsPlug.elementByLogicalIndex( existingInfluenceIndices[i], &s );
            MGlobal::executeCommand( ( boost::format( "removeMultiInstance -break 1 %s" ) % influenceWeightPlug.name() ).str().c_str() );
        }

        // add new influence weight plugs
        int firstIndex = pointIndexOffsets[pIndex];
        for( int i=0; i < pointInfluenceCounts[pIndex]; i++ )
        {
            int influenceIndex = pointInfluenceIndices[ firstIndex + i ];
            if ( ignoreInfluence[ influenceIndex ] )
            {
                continue;
            }

            int skinClusterInfluenceIndex = fnSkinCluster.indexForInfluenceObject( influencePaths[ indexMap[ influenceIndex ] ] );
            MPlug influenceWeightPlug = pointWeightsPlug.elementByLogicalIndex( skinClusterInfluenceIndex, &s );
            influenceWeightPlug.setValue( pointInfluenceWeights[ firstIndex + i ] );
        }
    }

    return true;
}
bool
PxrUsdTranslators_InstancerWriter::writeInstancerAttrs(
        const UsdTimeCode& usdTime,
        const UsdGeomPointInstancer& instancer)
{
    MStatus status = MS::kSuccess;
    MFnDagNode dagNode(GetDagPath(), &status);
    CHECK_MSTATUS_AND_RETURN(status, false);

    // Note: In this function, we don't read instances using the provided
    // MFnInstancer API. One reason is that it breaks up prototypes into their
    // constituent shapes, and there's no way to figure out which hierarchy
    // they came from. Another reason is that it only provides computed matrices
    // and not separate position, rotation, scale attrs.

    const SdfPath prototypesGroupPath =
            instancer.GetPrim().GetPath().AppendChild(_tokens->Prototypes);

    // At the default time, setup all the prototype instances.
    if (usdTime.IsDefault()) {
        const MPlug inputHierarchy = dagNode.findPlug("inputHierarchy", true,
                &status);
        CHECK_MSTATUS_AND_RETURN(status, false);

        // Note that the "Prototypes" prim needs to be a model group to ensure
        // contiguous model hierarchy.
        const UsdPrim prototypesGroupPrim = GetUsdStage()->DefinePrim(
                prototypesGroupPath);
        UsdModelAPI(prototypesGroupPrim).SetKind(KindTokens->group);
        _modelPaths.push_back(prototypesGroupPath);

        UsdRelationship prototypesRel = instancer.CreatePrototypesRel();

        const unsigned int numElements = inputHierarchy.numElements();
        for (unsigned int i = 0; i < numElements; ++i) {
            const MPlug plug = inputHierarchy[i];
            const MPlug source(UsdMayaUtil::GetConnected(plug));
            if (source.isNull()) {
                TF_WARN("Cannot read prototype: the source plug %s was null",
                        plug.name().asChar());
                return false;
            }

            MFnDagNode sourceNode(source.node(), &status);
            CHECK_MSTATUS_AND_RETURN(status, false);

            MDagPath prototypeDagPath;
            sourceNode.getPath(prototypeDagPath);

            // Prototype names are guaranteed unique by virtue of having a
            // unique numerical suffix _# indicating the prototype index.
            const TfToken prototypeName(
                    TfStringPrintf("%s_%d", sourceNode.name().asChar(), i));
            const SdfPath prototypeUsdPath = prototypesGroupPrim.GetPath()
                    .AppendChild(prototypeName);
            UsdPrim prototypePrim = GetUsdStage()->DefinePrim(
                    prototypeUsdPath);
            _modelPaths.push_back(prototypeUsdPath);

            // Try to be conservative and only create an intermediary xformOp
            // with the instancerTranslate if we can ensure that we don't need
            // to compensate for the translation on the prototype root.
            //
            // XXX: instancerTranslate does not behave well when added to a
            // reference that has an existing transform on the far side of the
            // reference. However, its behavior at least matches the
            // behavior in UsdMayaTranslatorModelAssembly. If we fix the
            // behavior there, we need to make sure that this is also
            // fixed to match.
            bool instancerTranslateAnimated = false;
            if (_NeedsExtraInstancerTranslate(
                    prototypeDagPath, &instancerTranslateAnimated)) {
                UsdGeomXformable xformable(prototypePrim);
                UsdGeomXformOp newOp = xformable.AddTranslateOp(
                        UsdGeomXformOp::PrecisionDouble,
                        _tokens->instancerTranslate);
                _instancerTranslateOps.push_back(
                        {prototypeDagPath, newOp, instancerTranslateAnimated});
            }

            // Two notes:
            // (1) We don't un-instance here, because it's OK for the prototype
            // to just be a reference to an instance master if the prototype
            // participates in Maya native instancing.
            // (2) The prototype root must be visible to match Maya's behavior,
            // which always vis'es the prototype root, even if it is marked
            // hidden.
            _writeJobCtx.CreatePrimWriterHierarchy(
                    prototypeDagPath,
                    prototypeUsdPath,
                    /*forceUninstance*/ false,
                    /*exportRootVisibility*/ false,
                    &_prototypeWriters);
            prototypesRel.AddTarget(prototypeUsdPath);
        }

        _numPrototypes = numElements;
    }

    // If there aren't any prototypes, fail and don't export on subsequent
    // time-sampled exports.
    if (_numPrototypes == 0) {
        return false;
    }

    // Actual write of prototypes (@ both default time and animated time).
    for (UsdMayaPrimWriterSharedPtr& writer : _prototypeWriters) {
        writer->Write(usdTime);

        if (usdTime.IsDefault()) {
            // Prototype roots should have kind component or derived.
            // Calling Write() above may have populated kinds, so don't stomp
            // over existing component-derived kinds.
            // (Note that ModelKindWriter's fix-up stage might change this.)
            if (writer->GetUsdPath().GetParentPath() == prototypesGroupPath) {
                if (const UsdPrim writerPrim = writer->GetUsdPrim()) {
                    UsdModelAPI primModelAPI(writerPrim);
                    TfToken kind;
                    primModelAPI.GetKind(&kind);
                    if (!KindRegistry::IsA(kind, KindTokens->component)) {
                        primModelAPI.SetKind(KindTokens->component);
                    }
                }
            }
        }
    }

    // Write the instancerTranslate xformOp for all prims that need it.
    // (This should happen @ default time or animated time depending on whether
    // the xform is animated.)
    for (const _TranslateOpData& opData : _instancerTranslateOps) {
        if (opData.isAnimated != usdTime.IsDefault()) {
            GfVec3d origin;
            if (_GetTransformedOriginInLocalSpace(opData.mayaPath, &origin)) {
                UsdGeomXformOp translateOp = opData.op;
                _SetAttribute(translateOp.GetAttr(), -origin, usdTime);
            }
        }
    }

    // Grab the inputPoints data from the source plug.
    // (This attribute's value must come from a source plug; it isn't
    // directly writeable. Thus reading it directly may not give the right
    // value depending on Maya's execution behavior.)
    MPlug inputPointsDest = dagNode.findPlug("inputPoints", true, &status);
    CHECK_MSTATUS_AND_RETURN(status, false);

    MPlug inputPointsSrc = UsdMayaUtil::GetConnected(inputPointsDest);
    if (inputPointsSrc.isNull()) {
        TF_WARN("inputPoints not connected on instancer '%s'",
                GetDagPath().fullPathName().asChar());
        return false;
    }

    auto holder = UsdMayaUtil::GetPlugDataHandle(inputPointsSrc);
    if (!holder) {
        TF_WARN("Unable to read inputPoints data handle for instancer '%s'",
                GetDagPath().fullPathName().asChar());
        return false;
    }

    MFnArrayAttrsData inputPointsData(holder->GetDataHandle().data(),
            &status);
    CHECK_MSTATUS_AND_RETURN(status, false);

    if (!UsdMayaWriteUtil::WriteArrayAttrsToInstancer(
            inputPointsData, instancer, _numPrototypes, usdTime,
            _GetSparseValueWriter())) {
        return false;
    }

    // Load the completed point instancer to compute and set its extent.
    instancer.GetPrim().GetStage()->Load(instancer.GetPath());
    VtArray<GfVec3f> extent(2);
    if (instancer.ComputeExtentAtTime(&extent, usdTime, usdTime)) {
        _SetAttribute(instancer.CreateExtentAttr(), &extent, usdTime);
    }

    return true;
}