Beispiel #1
0
void getConnectedChildPlugs(const char *attrName, MFnDependencyNode& depFn, bool dest, MPlugArray& thisNodePlugs, MPlugArray& otherSidePlugs)
{
    MPlug p = depFn.findPlug(attrName);
    if (p.isCompound() && !p.isArray())
    {
        getConnectedChildPlugs(p, dest, thisNodePlugs, otherSidePlugs);
        return;
    }
    if (p.isArray())
    {
        for (uint i = 0; i < p.numElements(); i++)
        {
            if (p[i].numConnectedChildren() == 0)
                continue;
            if (!p[i].isCompound())
                getConnectedChildPlugs(p[i], dest, thisNodePlugs, otherSidePlugs);
            else
            {
                if (getAttributeNameFromPlug(p) == MString("colorEntryList"))
                {
                    getConnectedChildPlugs(p[i].child(1), dest, thisNodePlugs, otherSidePlugs);
                }
            }
        }
    }
}
    //---------------------------------------------------
    bool DagHelper::connectToList ( const MPlug& source, const MObject& destination, const MString& destinationAttribute, int* _index )
    {
        MStatus status;
        MFnDependencyNode destFn ( destination );
        MPlug dest = destFn.findPlug ( destinationAttribute, &status );

        if ( status != MStatus::kSuccess ) return false;

        if ( !dest.isArray() ) return false;

        int index = ( _index != NULL ) ? *_index : -1;

        if ( index < 0 )
        {
            index = getNextAvailableIndex ( dest, ( int ) dest.evaluateNumElements() );

            if ( _index != NULL ) *_index = index;
        }

        MPlug d = dest.elementByLogicalIndex ( index );

        MDGModifier modifier;
        modifier.connect ( source, d );
        status = modifier.doIt();
        return status == MStatus::kSuccess;
    }
Beispiel #3
0
// --------------------------------------------------------------------------------------------
void polyModifierCmd::collectNodeState()
// --------------------------------------------------------------------------------------------
{
	MStatus status;

	// Collect node state information on the given polyMeshShape
	//
	// - HasHistory (Construction History exists)
	// - HasTweaks
	// - HasRecordHistory (Construction History is turned on)
	//
	fDagPath.extendToShape();
	MObject meshNodeShape = fDagPath.node();

	MFnDependencyNode depNodeFn;
	depNodeFn.setObject( meshNodeShape );

	MPlug inMeshPlug = depNodeFn.findPlug( "inMesh" );
	fHasHistory = inMeshPlug.isConnected();

	// Tweaks exist only if the multi "pnts" attribute contains plugs
	// which contain non-zero tweak values. Use false, until proven true
	// search algorithm.
	//
	fHasTweaks = false;
	MPlug tweakPlug = depNodeFn.findPlug( "pnts" );
	if( !tweakPlug.isNull() )
	{
		// ASSERT: tweakPlug should be an array plug!
		//
		MAssert( (tweakPlug.isArray()),
				 "tweakPlug.isArray() -- tweakPlug is not an array plug" );

		MPlug tweak;
		MFloatVector tweakData;
		int i;
		int numElements = tweakPlug.numElements();

		for( i = 0; i < numElements; i++ )
		{
			tweak = tweakPlug.elementByPhysicalIndex( i, &status );
			if( status == MS::kSuccess && !tweak.isNull() )
			{
				getFloat3PlugValue( tweak, tweakData );
				if( 0 != tweakData.x ||
					0 != tweakData.y ||
					0 != tweakData.z )
				{
					fHasTweaks = true;
					break;
				}
			}
		}
	}

	int result;
	MGlobal::executeCommand( "constructionHistory -q -tgl", result );
	fHasRecordHistory = (0 != result);
}
 // -------------------------------------------
 MPlug AnimationHelper::getTargetedPlug ( MPlug parentPlug, int index )
 {
     if ( index >= 0 && parentPlug.isCompound() )
     {
         return parentPlug.child ( index );
     }
     else if ( index >= 0 && parentPlug.isArray() )
     {
         return parentPlug.elementByLogicalIndex ( index );
     }
     else return parentPlug;
 }
Beispiel #5
0
void getDirectConnectedPlugs(const char *attrName, MFnDependencyNode& depFn, bool dest, MPlugArray& thisNodePlugs, MPlugArray& otherSidePlugs)
{
	MPlug thisPlug = depFn.findPlug(attrName);
	if (!thisPlug.isArray())
	{
		if (thisPlug.isConnected())
		{
			thisNodePlugs.append(thisPlug);
			otherSidePlugs.append(getDirectConnectedPlug(thisPlug, dest));
		}
		return;
	}
	for (uint i = 0; i < thisPlug.numElements(); i++)
	{
		if (thisPlug.isCompound())
		{
			// we only support simple compounds like colorListEntry
			if (MString(attrName) == MString("colorEntryList"))
			{
				MPlug element = thisPlug[i];
				if (element.child(0).isConnected())
				{
					MPlug connectedPlug = element.child(0);
					thisNodePlugs.append(connectedPlug);
					otherSidePlugs.append(getDirectConnectedPlug(connectedPlug, dest));
				}
				if (element.child(1).isConnected())
				{
					MPlug connectedPlug = element.child(1);
					thisNodePlugs.append(connectedPlug);
					otherSidePlugs.append(getDirectConnectedPlug(connectedPlug, dest));
				}
			}
		}
		else{
			if (!thisPlug[i].isConnected())
			{
				continue;
			}
			MPlug connectedPlug = thisPlug[i];
			thisNodePlugs.append(connectedPlug);
			otherSidePlugs.append(getDirectConnectedPlug(connectedPlug, dest));
		}
	}

}
Beispiel #6
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::undoTweakProcessing()
// --------------------------------------------------------------------------------------------
{
	MStatus status = MS::kSuccess;

	if( fHasTweaks )
	{
		MFnDependencyNode depNodeFn;

		MObject	meshNodeShape;
		MPlug	meshTweakPlug;
		MPlug	tweak;
		MObject	tweakData;

		meshNodeShape = fDagPath.node();
		depNodeFn.setObject( meshNodeShape );
		meshTweakPlug = depNodeFn.findPlug( "pnts" );

		MStatusAssert( (meshTweakPlug.isArray()),
					   "meshTweakPlug.isArray() -- meshTweakPlug is not an array plug" );

		unsigned i;
		unsigned numElements = fTweakIndexArray.length();

		for( i = 0; i < numElements; i++ )
		{
			tweak = meshTweakPlug.elementByLogicalIndex( fTweakIndexArray[i] );
			getFloat3asMObject( fTweakVectorArray[i], tweakData );
			tweak.setValue( tweakData );
		}

		// In the case of no history, the duplicate node shape will be disconnected on undo
		// so, there is no need to undo the tweak processing on it.
		//
	}

	return status;
}
Beispiel #7
0
PXR_NAMESPACE_OPEN_SCOPE



/* static */
bool 
PxrUsdMayaTranslatorMesh::Create(
        const UsdGeomMesh& mesh,
        MObject parentNode,
        const PxrUsdMayaPrimReaderArgs& args,
        PxrUsdMayaPrimReaderContext* context)
{
    if (!mesh) {
        return false;
    }

    const UsdPrim& prim = mesh.GetPrim();

    MStatus status;

    // Create node (transform)
    MObject mayaNodeTransformObj;
    if (!PxrUsdMayaTranslatorUtil::CreateTransformNode(prim,
                                                          parentNode,
                                                          args,
                                                          context,
                                                          &status,
                                                          &mayaNodeTransformObj)) {
        return false;
    }

    VtArray<GfVec3f> points;
    VtArray<GfVec3f> normals;
    VtArray<int>     faceVertexCounts;
    VtArray<int>     faceVertexIndices;
    
    UsdAttribute fvc = mesh.GetFaceVertexCountsAttr();
    if (fvc.ValueMightBeTimeVarying()){
        // at some point, it would be great, instead of failing, to create a usd/hydra proxy node
        // for the mesh, perhaps?  For now, better to give a more specific error
        MGlobal::displayError(
            TfStringPrintf("<%s> is a topologically varying Mesh (animated faceVertexCounts). Skipping...", 
                prim.GetPath().GetText()).c_str());
        return false;
    } else {
        // for any non-topo-varying mesh, sampling at zero will get us the right answer
        fvc.Get(&faceVertexCounts, 0);
    }

    UsdAttribute fvi = mesh.GetFaceVertexIndicesAttr();
    if (fvi.ValueMightBeTimeVarying()){
        // at some point, it would be great, instead of failing, to create a usd/hydra proxy node
        // for the mesh, perhaps?  For now, better to give a more specific error
        MGlobal::displayError(
            TfStringPrintf("<%s> is a topologically varying Mesh (animated faceVertexIndices). Skipping...", 
                prim.GetPath().GetText()).c_str());
        return false;
    } else {
        // for any non-topo-varying mesh, sampling at zero will get us the right answer
        fvi.Get(&faceVertexIndices, 0);
    }
        
    // Sanity Checks. If the vertex arrays are empty, skip this mesh
    if (faceVertexCounts.size() == 0 || faceVertexIndices.size() == 0) {
        MGlobal::displayError(
            TfStringPrintf("FaceVertex arrays are empty [Count:%zu Indices:%zu] on Mesh <%s>. Skipping...", 
                faceVertexCounts.size(), faceVertexIndices.size(), 
                prim.GetPath().GetText()).c_str());
        return false; // invalid mesh, so exit
    }

    // Gather points and normals
    // If args.GetReadAnimData() is TRUE,
    // pick the first avaiable sample or default
    UsdTimeCode pointsTimeSample=UsdTimeCode::EarliestTime();
    UsdTimeCode normalsTimeSample=UsdTimeCode::EarliestTime();
    std::vector<double> pointsTimeSamples;
    size_t pointsNumTimeSamples = 0;
    if (args.GetReadAnimData()) {
        PxrUsdMayaTranslatorUtil::GetTimeSamples(mesh.GetPointsAttr(), args,
                &pointsTimeSamples);
        pointsNumTimeSamples = pointsTimeSamples.size();
        if (pointsNumTimeSamples>0) {
            pointsTimeSample = pointsTimeSamples[0];
        }
    	std::vector<double> normalsTimeSamples;
        PxrUsdMayaTranslatorUtil::GetTimeSamples(mesh.GetNormalsAttr(), args,
                &normalsTimeSamples);
        if (normalsTimeSamples.size()) {
            normalsTimeSample = normalsTimeSamples[0];
        }
    }
    mesh.GetPointsAttr().Get(&points, pointsTimeSample);
    mesh.GetNormalsAttr().Get(&normals, normalsTimeSample);
    
    if (points.size() == 0) {
        MGlobal::displayError(
            TfStringPrintf("Points arrays is empty on Mesh <%s>. Skipping...", 
                prim.GetPath().GetText()).c_str());
        return false; // invalid mesh, so exit
    }


    // == Convert data
    size_t mayaNumVertices = points.size();
    MPointArray mayaPoints(mayaNumVertices);
    for (size_t i=0; i < mayaNumVertices; i++) {
        mayaPoints.set( i, points[i][0], points[i][1], points[i][2] );
    }

    MIntArray polygonCounts( faceVertexCounts.cdata(),  faceVertexCounts.size() );
    MIntArray polygonConnects( faceVertexIndices.cdata(), faceVertexIndices.size() );

    // == Create Mesh Shape Node
    MFnMesh meshFn;
    MObject meshObj = meshFn.create(mayaPoints.length(), 
                           polygonCounts.length(), 
                           mayaPoints, 
                           polygonCounts, 
                           polygonConnects,
                           mayaNodeTransformObj,
                           &status
                           );
                           
    if (status != MS::kSuccess) {
        return false;
    }

    // Since we are "decollapsing", we will create a xform and a shape node for each USD prim
    std::string usdPrimName(prim.GetName().GetText());
    std::string shapeName(usdPrimName); shapeName += "Shape";
    // Set mesh name and register
    meshFn.setName(MString(shapeName.c_str()), false, &status);
    if (context) {
        std::string usdPrimPath(prim.GetPath().GetText());
        std::string shapePath(usdPrimPath);
        shapePath += "/";
        shapePath += shapeName;
        context->RegisterNewMayaNode( shapePath, meshObj ); // used for undo/redo
    }

    // If a material is bound, create (or reuse if already present) and assign it
    // If no binding is present, assign the mesh to the default shader    
    const TfToken& shadingMode = args.GetShadingMode();
    PxrUsdMayaTranslatorMaterial::AssignMaterial(shadingMode, mesh, meshObj,
            context);
    
    // Mesh is a shape, so read Gprim properties
    PxrUsdMayaTranslatorGprim::Read(mesh, meshObj, context);

    // Set normals if supplied
    MIntArray normalsFaceIds;
    if (normals.size() == static_cast<size_t>(meshFn.numFaceVertices())) {

        for (size_t i=0; i < polygonCounts.length(); i++) {
            for (int j=0; j < polygonCounts[i]; j++) {
                normalsFaceIds.append(i);
            }
        }
        if (normalsFaceIds.length() == static_cast<size_t>(meshFn.numFaceVertices())) {
            MVectorArray mayaNormals(normals.size());
            for (size_t i=0; i < normals.size(); i++) {
                mayaNormals.set( MVector(normals[i][0], normals[i][1], normals[i][2]), i);
            }
            if (meshFn.setFaceVertexNormals(mayaNormals, normalsFaceIds, polygonConnects) != MS::kSuccess) {
            }
        }
     }

    // Determine if PolyMesh or SubdivMesh
    TfToken subdScheme = PxrUsdMayaMeshUtil::setSubdivScheme(mesh, meshFn, args.GetDefaultMeshScheme());

    // If we are dealing with polys, check if there are normals
    // If we are dealing with SubdivMesh, read additional attributes and SubdivMesh properties
    if (subdScheme == UsdGeomTokens->none) {
        if (normals.size() == static_cast<size_t>(meshFn.numFaceVertices())) {
            PxrUsdMayaMeshUtil::setEmitNormals(mesh, meshFn, UsdGeomTokens->none);
        }
    } else {
        PxrUsdMayaMeshUtil::setSubdivInterpBoundary(mesh, meshFn, UsdGeomTokens->edgeAndCorner);
        PxrUsdMayaMeshUtil::setSubdivFVLinearInterpolation(mesh, meshFn);
        _AssignSubDivTagsToMesh(mesh, meshObj, meshFn);
    }
 
    // Set Holes
    VtArray<int> holeIndices;
    mesh.GetHoleIndicesAttr().Get(&holeIndices);   // not animatable
    if ( holeIndices.size() != 0 ) {
        MUintArray mayaHoleIndices;
        mayaHoleIndices.setLength( holeIndices.size() );
        for (size_t i=0; i < holeIndices.size(); i++) {
            mayaHoleIndices[i] = holeIndices[i];
        }
        if (meshFn.setInvisibleFaces(mayaHoleIndices) == MS::kFailure) {
            MGlobal::displayError(TfStringPrintf("Unable to set Invisible Faces on <%s>", 
                            meshFn.fullPathName().asChar()).c_str());
        }
    }

    // GETTING PRIMVARS
    std::vector<UsdGeomPrimvar> primvars = mesh.GetPrimvars();
    TF_FOR_ALL(iter, primvars) {
        const UsdGeomPrimvar& primvar = *iter;
        const TfToken& name = primvar.GetBaseName();
        const SdfValueTypeName& typeName = primvar.GetTypeName();

        // If the primvar is called either displayColor or displayOpacity check
        // if it was really authored from the user.  It may not have been
        // authored by the user, for example if it was generated by shader
        // values and not an authored colorset/entity.
        // If it was not really authored, we skip the primvar.
        if (name == PxrUsdMayaMeshColorSetTokens->DisplayColorColorSetName || 
                name == PxrUsdMayaMeshColorSetTokens->DisplayOpacityColorSetName) {
            if (!PxrUsdMayaRoundTripUtil::IsAttributeUserAuthored(primvar)) {
                continue;
            }
        }

        // XXX: Maya stores UVs in MFloatArrays and color set data in MColors
        // which store floats, so we currently only import primvars holding
        // float-typed arrays. Should we still consider other precisions
        // (double, half, ...) and/or numeric types (int)?
        if (typeName == SdfValueTypeNames->Float2Array) {
            // We assume that Float2Array primvars are UV sets.
            if (!_AssignUVSetPrimvarToMesh(primvar, meshFn)) {
                MGlobal::displayWarning(
                    TfStringPrintf("Unable to retrieve and assign data for UV set <%s> on mesh <%s>", 
                                   name.GetText(),
                                   mesh.GetPrim().GetPath().GetText()).c_str());
            }
        } else if (typeName == SdfValueTypeNames->FloatArray   || 
                   typeName == SdfValueTypeNames->Float3Array  || 
                   typeName == SdfValueTypeNames->Color3fArray ||
                   typeName == SdfValueTypeNames->Float4Array  || 
                   typeName == SdfValueTypeNames->Color4fArray) {
            if (!_AssignColorSetPrimvarToMesh(mesh, primvar, meshFn)) {
                MGlobal::displayWarning(
                    TfStringPrintf("Unable to retrieve and assign data for color set <%s> on mesh <%s>",
                                   name.GetText(),
                                   mesh.GetPrim().GetPath().GetText()).c_str());
            }
        }
    }

    // We only vizualize the colorset by default if it is "displayColor".  
    MStringArray colorSetNames;
    if (meshFn.getColorSetNames(colorSetNames)==MS::kSuccess) {
        for (unsigned int i=0; i < colorSetNames.length(); i++) {
            const MString colorSetName = colorSetNames[i];
            if (std::string(colorSetName.asChar()) 
                    == PxrUsdMayaMeshColorSetTokens->DisplayColorColorSetName.GetString()) {
                MFnMesh::MColorRepresentation csRep=
                    meshFn.getColorRepresentation(colorSetName);
                if (csRep==MFnMesh::kRGB || csRep==MFnMesh::kRGBA) {

                    // both of these are needed to show the colorset.
                    MPlug plg=meshFn.findPlug("displayColors");
                    if ( !plg.isNull() ) {
                        plg.setBool(true);
                    }
                    meshFn.setCurrentColorSetName(colorSetName);
                }
                break;
            }
        }
    }
    
    // == Animate points ==
    //   Use blendShapeDeformer so that all the points for a frame are contained in a single node
    //
    if (pointsNumTimeSamples > 0) {
        MPointArray mayaPoints(mayaNumVertices);
        MObject meshAnimObj;

        MFnBlendShapeDeformer blendFn;
        MObject blendObj = blendFn.create(meshObj);
        if (context) {
            context->RegisterNewMayaNode( blendFn.name().asChar(), blendObj ); // used for undo/redo
        }

        for (unsigned int ti=0; ti < pointsNumTimeSamples; ++ti) {
             mesh.GetPointsAttr().Get(&points, pointsTimeSamples[ti]);

            for (unsigned int i=0; i < mayaNumVertices; i++) {
                mayaPoints.set( i, points[i][0], points[i][1], points[i][2] );
            }

            // == Create Mesh Shape Node
            MFnMesh meshFn;
            if ( meshAnimObj.isNull() ) {
                meshAnimObj = meshFn.create(mayaPoints.length(), 
                                       polygonCounts.length(), 
                                       mayaPoints, 
                                       polygonCounts, 
                                       polygonConnects,
                                       mayaNodeTransformObj,
                                       &status
                                       );
                if (status != MS::kSuccess) {
                    continue;
                }
            }
            else {
                // Reuse the already created mesh by copying it and then setting the points
                meshAnimObj = meshFn.copy(meshAnimObj, mayaNodeTransformObj, &status);
                meshFn.setPoints(mayaPoints);
            }

            // Set normals if supplied
            //
            // NOTE: This normal information is not propagated through the blendShapes, only the controlPoints.
            //
             mesh.GetNormalsAttr().Get(&normals, pointsTimeSamples[ti]);
             if (normals.size() == static_cast<size_t>(meshFn.numFaceVertices()) &&
                normalsFaceIds.length() == static_cast<size_t>(meshFn.numFaceVertices())) {

                MVectorArray mayaNormals(normals.size());
                for (size_t i=0; i < normals.size(); i++) {
                    mayaNormals.set( MVector(normals[i][0], normals[i][1], normals[i][2]), i);
                }
                if (meshFn.setFaceVertexNormals(mayaNormals, normalsFaceIds, polygonConnects) != MS::kSuccess) {
                }
             }

            // Add as target and set as an intermediate object
            blendFn.addTarget(meshObj, ti, meshAnimObj, 1.0);
            meshFn.setIntermediateObject(true);
            if (context) {
                context->RegisterNewMayaNode( meshFn.fullPathName().asChar(), meshAnimObj ); // used for undo/redo
            }
        }

        // Animate the weights so that mesh0 has a weight of 1 at frame 0, etc.
        MFnAnimCurve animFn;

        // Construct the time array to be used for all the keys
        MTimeArray timeArray;
        timeArray.setLength(pointsNumTimeSamples);
        for (unsigned int ti=0; ti < pointsNumTimeSamples; ++ti) {
            timeArray.set( MTime(pointsTimeSamples[ti]), ti);
        }

        // Key/Animate the weights
        MPlug plgAry = blendFn.findPlug( "weight" );
        if ( !plgAry.isNull() && plgAry.isArray() ) {
            for (unsigned int ti=0; ti < pointsNumTimeSamples; ++ti) {
                MPlug plg = plgAry.elementByLogicalIndex(ti, &status);
                MDoubleArray valueArray(pointsNumTimeSamples, 0.0);
                valueArray[ti] = 1.0; // Set the time value where this mesh's weight should be 1.0
                MObject animObj = animFn.create(plg, NULL, &status);
                animFn.addKeys(&timeArray, &valueArray);
                if (context) {
                    context->RegisterNewMayaNode(animFn.name().asChar(), animObj ); // used for undo/redo
                }
            }
        }
    }

    return true;
}
Beispiel #8
0
void liqRibData::addAdditionalSurfaceParameters( MObject node )
{
  LIQDEBUGPRINTF("-> scanning for additional rman surface attributes \n");
  MStatus status = MS::kSuccess;
  unsigned i;

  // work out how many elements there would be in a facevarying array if a mesh or subD
  // faceVaryingCount is a private data member
  if ( ( type() == MRT_Mesh ) || ( type() == MRT_Subdivision ) ) {
    faceVaryingCount = 0;
    MFnMesh fnMesh( node );
    for ( uint pOn = 0; pOn < fnMesh.numPolygons(); pOn++ ) {
      faceVaryingCount += fnMesh.polygonVertexCount( pOn );
    }
  }

  // find how many additional
  MFnDependencyNode nodeFn( node );

  // find the attributes
  MStringArray floatAttributesFound  = findAttributesByPrefix( "rmanF", nodeFn );
  MStringArray pointAttributesFound  = findAttributesByPrefix( "rmanP", nodeFn );
  MStringArray vectorAttributesFound = findAttributesByPrefix( "rmanV", nodeFn );
  MStringArray normalAttributesFound = findAttributesByPrefix( "rmanN", nodeFn );
  MStringArray colorAttributesFound  = findAttributesByPrefix( "rmanC", nodeFn );
  MStringArray stringAttributesFound = findAttributesByPrefix( "rmanS", nodeFn );


  if ( floatAttributesFound.length() > 0 ) {
    for ( i = 0; i < floatAttributesFound.length(); i++ ) {
      liqTokenPointer tokenPointerPair;
      MString cutString = floatAttributesFound[i].substring(5, floatAttributesFound[i].length());
      MPlug fPlug = nodeFn.findPlug( floatAttributesFound[i] );
      MObject plugObj;
      status = fPlug.getValue( plugObj );
      if ( plugObj.apiType() == MFn::kDoubleArrayData ) {
        MFnDoubleArrayData  fnDoubleArrayData( plugObj );
        MDoubleArray doubleArrayData = fnDoubleArrayData.array( &status );
        tokenPointerPair.set( cutString.asChar(),
                              rFloat,
                              ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false,
                              true,
                              false,
                              doubleArrayData.length() );
        for( unsigned int kk = 0; kk < doubleArrayData.length(); kk++ ) {
          tokenPointerPair.setTokenFloat( kk, doubleArrayData[kk] );
        }
        if ( ( type() == MRT_NuCurve ) && ( cutString == MString( "width" ) ) ) {
          tokenPointerPair.setDetailType( rVarying);
        } else if ( ( ( type() == MRT_Mesh ) || ( type() == MRT_Subdivision ) ) && ( doubleArrayData.length() == faceVaryingCount ) ) {
          tokenPointerPair.setDetailType( rFaceVarying);
        } else {
          tokenPointerPair.setDetailType( rVertex );
        }
      } else {

        if( fPlug.isArray() ) {

          int nbElts = fPlug.evaluateNumElements();
          float floatValue;
          tokenPointerPair.set( cutString.asChar(),
                                rFloat,
                                ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false,
                                false,
                                true, // philippe :passed as uArray, otherwise it will think it is a single float
                                nbElts );
          MPlug elementPlug;
          for( unsigned int kk = 0; kk < nbElts; kk++ ) {
            elementPlug = fPlug.elementByPhysicalIndex(kk);
            elementPlug.getValue( floatValue );
            tokenPointerPair.setTokenFloat( kk, floatValue );
          }
          tokenPointerPair.setDetailType( rConstant );

        } else {

          float floatValue;
          tokenPointerPair.set( cutString.asChar(),
                                rFloat,
                                ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false,
                                false,
                                false,
                                0 );
          fPlug.getValue( floatValue );
          tokenPointerPair.setTokenFloat( 0, floatValue );
          tokenPointerPair.setDetailType( rConstant );

        }

      }
      tokenPointerArray.push_back( tokenPointerPair );
    }
  }

  if ( pointAttributesFound.length() > 0 ) {
    for ( i = 0; i < pointAttributesFound.length(); i++ ) {
      liqTokenPointer tokenPointerPair;
      MString cutString = pointAttributesFound[i].substring(5, pointAttributesFound[i].length());
      MPlug pPlug = nodeFn.findPlug( pointAttributesFound[i] );
      MObject plugObj;
      status = pPlug.getValue( plugObj );
      if ( plugObj.apiType() == MFn::kPointArrayData ) {
        MFnPointArrayData  fnPointArrayData( plugObj );
        MPointArray pointArrayData = fnPointArrayData.array( &status );
        tokenPointerPair.set( cutString.asChar(),
                              rPoint,
                              ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false,
                              true,
                              false,
                              pointArrayData.length() );
        if ( type() == MRT_Nurbs || type() == MRT_NuCurve ) {
          for ( int kk = 0; kk < pointArrayData.length(); kk++ ) {
            tokenPointerPair.setTokenFloat( kk, pointArrayData[kk].x, pointArrayData[kk].y, pointArrayData[kk].z, pointArrayData[kk].w );
          }
        } else {
          for ( int kk = 0; kk < pointArrayData.length(); kk++ ) {
            tokenPointerPair.setTokenFloat( kk, pointArrayData[kk].x, pointArrayData[kk].y, pointArrayData[kk].z );
          }
        }
        tokenPointerPair.setDetailType( rVertex );
      } else {
        // Hmmmm float ? double ?
        float x, y, z;
        tokenPointerPair.set(
                cutString.asChar(),
                rPoint,
                ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false,
                false,
                false,
                0 );
        // Hmmm should check as for arrays if we are in nurbs mode : 4 values
        pPlug.child(0).getValue( x );
        pPlug.child(1).getValue( y );
        pPlug.child(2).getValue( z );
        tokenPointerPair.setTokenFloat( 0, x, y, z );
        tokenPointerPair.setDetailType( rConstant );
      }
      tokenPointerArray.push_back( tokenPointerPair );
    }
  }
  parseVectorAttributes( nodeFn, vectorAttributesFound, rVector );
  parseVectorAttributes( nodeFn, normalAttributesFound, rNormal );
  parseVectorAttributes( nodeFn, colorAttributesFound,  rColor  );

  if ( stringAttributesFound.length() > 0 ) {
    for ( i = 0; i < stringAttributesFound.length(); i++ ) {
      liqTokenPointer tokenPointerPair;
      MString cutString = stringAttributesFound[i].substring(5, stringAttributesFound[i].length());
      MPlug sPlug = nodeFn.findPlug( stringAttributesFound[i] );
      MObject plugObj;
      status = sPlug.getValue( plugObj );
      tokenPointerPair.set(
        cutString.asChar(),
        rString,
        ( type() == MRT_Nurbs || type() == MRT_NuCurve ) ? true : false,
        false,
        false,
        0 );
      MString stringVal;
      sPlug.getValue( stringVal );
      tokenPointerPair.setTokenString( 0, stringVal.asChar(), stringVal.length() );
      tokenPointerPair.setDetailType( rConstant );
      tokenPointerArray.push_back( tokenPointerPair );
    }
  }
}
Beispiel #9
0
// returns 0 if static, 1 if sampled, and 2 if a curve
int util::getSampledType(const MPlug& iPlug)
{
    MPlugArray conns;

    iPlug.connectedTo(conns, true, false);

    // it's possible that only some element of an array plug or
    // some component of a compound plus is connected
    if (conns.length() == 0)
    {
        if (iPlug.isArray())
        {
            unsigned int numConnectedElements = iPlug.numConnectedElements();
            for (unsigned int e = 0; e < numConnectedElements; e++)
            {
                int retVal = getSampledType(iPlug.connectionByPhysicalIndex(e));
                if (retVal > 0)
                    return retVal;
            }
        }
        else if (iPlug.isCompound() && iPlug.numConnectedChildren() > 0)
        {
            unsigned int numChildren = iPlug.numChildren();
            for (unsigned int c = 0; c < numChildren; c++)
            {
                int retVal = getSampledType(iPlug.child(c));
                if (retVal > 0)
                    return retVal;
            }
        }
        return 0;
    }

    MObject ob;
    MFnDependencyNode nodeFn;
    for (unsigned i = 0; i < conns.length(); i++)
    {
        ob = conns[i].node();
        MFn::Type type = ob.apiType();

        switch (type)
        {
            case MFn::kAnimCurveTimeToAngular:
            case MFn::kAnimCurveTimeToDistance:
            case MFn::kAnimCurveTimeToTime:
            case MFn::kAnimCurveTimeToUnitless:
            {
                nodeFn.setObject(ob);
                MPlug incoming = nodeFn.findPlug("i", true);

                // sampled
                if (incoming.isConnected())
                    return 1;

                // curve
                else
                    return 2;
            }
            break;

            case MFn::kMute:
            {
                nodeFn.setObject(ob);
                MPlug mutePlug = nodeFn.findPlug("mute", true);

                // static
                if (mutePlug.asBool())
                    return 0;
                // curve
                else
                   return 2;
            }
            break;

            default:
            break;
        }
    }

    return 1;
}
Beispiel #10
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::processTweaks( modifyPolyData& data )
// --------------------------------------------------------------------------------------------
{
	MStatus status = MS::kSuccess;

	// Clear tweak undo information (to be rebuilt)
	//
	fTweakIndexArray.clear();
	fTweakVectorArray.clear();

	// Extract the tweaks and place them into a polyTweak node. This polyTweak node
	// will be placed ahead of the modifier node to maintain the order of operations.
	// Special care must be taken into recreating the tweaks:
	//
	//		1) Copy tweak info (including connections!)
	//		2) Remove tweak info from both meshNode and a duplicate meshNode (if applicable)
	//		3) Cache tweak info for undo operations
	//
	//if( fHasTweaks && fHasHistory && !speedupTweakProcessing())
	if( fHasTweaks && fHasHistory )
	{
		// Declare our function sets
		//
		MFnDependencyNode depNodeFn;

		// Declare our attributes and plugs
		//
		MPlug	meshTweakPlug;
		MPlug	upstreamTweakPlug;
		MObject tweakNodeTweakAttr;

		// Declare our tweak processing variables
		//
		MPlug				tweak;
		MPlug				tweakChild;
		MObject				tweakData;
		MObjectArray		tweakDataArray;
		MFloatVector		tweakVector;

		MIntArray			tweakSrcConnectionCountArray;
		MPlugArray			tweakSrcConnectionPlugArray;
		MIntArray			tweakDstConnectionCountArray;
		MPlugArray			tweakDstConnectionPlugArray;

		MPlugArray			tempPlugArray;

		unsigned i;
		unsigned j;
		unsigned k;

		// Create the tweak node and get its attributes
		//
		data.tweakNode = fDGModifier.MDGModifier::createNode( "polyTweak" );
		depNodeFn.setObject( data.tweakNode );
		data.tweakNodeSrcAttr = depNodeFn.attribute( "output" );
		data.tweakNodeDestAttr = depNodeFn.attribute( "inputPolymesh" );
		tweakNodeTweakAttr = depNodeFn.attribute( "tweak" );

		depNodeFn.setObject( data.meshNodeShape );
		meshTweakPlug = depNodeFn.findPlug( "pnts" );

		// ASSERT: meshTweakPlug should be an array plug!
		//
		MStatusAssert( (meshTweakPlug.isArray()),
					   "meshTweakPlug.isArray() -- meshTweakPlug is not an array plug" );
		unsigned numElements = meshTweakPlug.numElements();

		// Gather meshTweakPlug data
		//
		for( i = 0; i < numElements; i++ )
		{
			// MPlug::numElements() only returns the number of physical elements
			// in the array plug. Thus we must use elementByPhysical index when using
			// the index i.
			//
			tweak = meshTweakPlug.elementByPhysicalIndex(i);

			// If the method fails, the element is NULL. Only append the index
			// if it is a valid plug.
			//
			if( !tweak.isNull() )
			{
				// Cache the logical index of this element plug
				//
				unsigned logicalIndex = tweak.logicalIndex();

				// Collect tweak data and cache the indices and float vectors
				//
				tweak.getValue( tweakData );
				tweakDataArray.append( tweakData );
				getFloat3PlugValue( tweak, tweakVector );
				fTweakIndexArray.append( logicalIndex );
				fTweakVectorArray.append( tweakVector );

				// Collect tweak connection data
				//
				// Parse down to the deepest level of the plug tree and check
				// for connections - look at the child nodes of the element plugs.
				// If any connections are found, record the connection and disconnect
				// it.
				//

				// ASSERT: The element plug should be compound!
				//
				MStatusAssert( (tweak.isCompound()),
							   "tweak.isCompound() -- Element tweak plug is not compound" );

				unsigned numChildren = tweak.numChildren();
				for( j = 0; j < numChildren; j++ )
				{
					tweakChild = tweak.child(j);
					if( tweakChild.isConnected() )
					{
						// Get all connections with this plug as source, if they exist
						//
						tempPlugArray.clear();
						if( tweakChild.connectedTo( tempPlugArray, false, true ) )
						{
							unsigned numSrcConnections = tempPlugArray.length();
							tweakSrcConnectionCountArray.append( numSrcConnections );

							for( k = 0; k < numSrcConnections; k++ )
							{
								tweakSrcConnectionPlugArray.append( tempPlugArray[k] );
								fDGModifier.disconnect( tweakChild, tempPlugArray[k] );
							}
						}
						else
						{
							tweakSrcConnectionCountArray.append(0);
						}

						// Get the connection with this plug as destination, if it exists
						//
						tempPlugArray.clear();
						if( tweakChild.connectedTo( tempPlugArray, true, false ) )
						{
							// ASSERT: tweakChild should only have one connection as destination!
							//
							MStatusAssert( (tempPlugArray.length() == 1),
										   "tempPlugArray.length() == 1 -- 0 or >1 connections on tweakChild" );

							tweakDstConnectionCountArray.append(1);
							tweakDstConnectionPlugArray.append( tempPlugArray[0] );
							fDGModifier.disconnect( tempPlugArray[0], tweakChild );
						}
						else
						{
							tweakDstConnectionCountArray.append(0);
						}
					}
					else
					{
						tweakSrcConnectionCountArray.append(0);
						tweakDstConnectionCountArray.append(0);
					}
				}
			}
		}

		// Apply meshTweakPlug data to our polyTweak node
		//
		MPlug polyTweakPlug( data.tweakNode, tweakNodeTweakAttr );
		unsigned numTweaks = fTweakIndexArray.length();
		int srcOffset = 0;
		int dstOffset = 0;
		
		
		//Progress initialisieren
		progressBar progress("Processing Tweaks", numTweaks);
		

		for( i = 0; i < numTweaks; i++ )
		{
			// Apply tweak data
			//
			tweak = polyTweakPlug.elementByLogicalIndex( fTweakIndexArray[i] );
			tweak.setValue( tweakDataArray[i] );

			// ASSERT: Element plug should be compound!
			//
			MStatusAssert( (tweak.isCompound()),
						   "tweak.isCompound() -- Element plug, 'tweak', is not compound" );

			unsigned numChildren = tweak.numChildren();
			for( j = 0; j < numChildren; j++ )
			{
				tweakChild = tweak.child(j);

				// Apply tweak source connection data
				//
				if( 0 < tweakSrcConnectionCountArray[i*numChildren + j] )
				{
					for( k = 0;
						 k < (unsigned) tweakSrcConnectionCountArray[i*numChildren + j];
						 k++ )
					{
						fDGModifier.connect( tweakChild,
											 tweakSrcConnectionPlugArray[srcOffset] );
						srcOffset++;
					}
				}
						
				// Apply tweak destination connection data
				//
				if( 0 < tweakDstConnectionCountArray[i*numChildren + j] )
				{
					fDGModifier.connect( tweakDstConnectionPlugArray[dstOffset],
										 tweakChild );
					dstOffset++;
				}
			}

			if(i%50 == 0)
			{	
				progress.set(i);
			}
		}

		


		// Now, set the tweak values on the meshNode(s) to zero (History dependent)
		//
		MFnNumericData numDataFn;
		MObject nullVector;

		// Create a NULL vector (0,0,0) using MFnNumericData to pass into the plug
		//
		numDataFn.create( MFnNumericData::k3Float );
		numDataFn.setData( 0, 0, 0 );
		nullVector = numDataFn.object();

		for( i = 0; i < numTweaks; i++ )
		{
			// Access using logical indices since they are the only plugs guaranteed
			// to hold tweak data.
			//
			tweak = meshTweakPlug.elementByLogicalIndex( fTweakIndexArray[i] );
			tweak.setValue( nullVector );
		}

		// Only have to clear the tweaks off the duplicate mesh if we do not have history
		// and we want history.
		//
		if( !fHasHistory && fHasRecordHistory )
		{
			depNodeFn.setObject( data.upstreamNodeShape );
			upstreamTweakPlug = depNodeFn.findPlug( "pnts" );

			if( !upstreamTweakPlug.isNull() )
			{
				for( i = 0; i < numTweaks; i++ )
				{
					tweak = meshTweakPlug.elementByLogicalIndex( fTweakIndexArray[i] );
					tweak.setValue( nullVector );
				}
			}
		}
	}
	else
		fHasTweaks = false;

	return status;
}
Beispiel #11
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::cacheMeshTweaks()
// --------------------------------------------------------------------------------------------
{
	MStatus status = MS::kSuccess;

	// Clear tweak undo information (to be rebuilt)
	//
	fTweakIndexArray.clear();
	fTweakVectorArray.clear();

	// Extract the tweaks and store them in our local tweak cache members
	//
	if( fHasTweaks )
	{
		// Declare our function sets
		//
		MFnDependencyNode depNodeFn;

		MObject meshNode = fDagPath.node();
		MPlug	meshTweakPlug;

		// Declare our tweak processing variables
		//
		MPlug				tweak;
		MPlug				tweakChild;
		MObject				tweakData;
		MObjectArray		tweakDataArray;
		MFloatVector		tweakVector;

		MPlugArray			tempPlugArray;

		unsigned i;

		depNodeFn.setObject( meshNode );
		meshTweakPlug = depNodeFn.findPlug( "pnts" );

		// ASSERT: meshTweakPlug should be an array plug!
		//
		MStatusAssert( (meshTweakPlug.isArray()),
					   "meshTweakPlug.isArray() -- meshTweakPlug is not an array plug" );
		unsigned numElements = meshTweakPlug.numElements();

		// Gather meshTweakPlug data
		//
		for( i = 0; i < numElements; i++ )
		{
			// MPlug::numElements() only returns the number of physical elements
			// in the array plug. Thus we must use elementByPhysical index when using
			// the index i.
			//
			tweak = meshTweakPlug.elementByPhysicalIndex(i);

			// If the method fails, the element is NULL. Only append the index
			// if it is a valid plug.
			//
			if( !tweak.isNull() )
			{
				// Cache the logical index of this element plug
				//
				unsigned logicalIndex = tweak.logicalIndex();

				// Collect tweak data and cache the indices and float vectors
				//
				getFloat3PlugValue( tweak, tweakVector );
				fTweakIndexArray.append( logicalIndex );
				fTweakVectorArray.append( tweakVector );
			}
		}
	}

	return status;
}
Beispiel #12
0
/* static */
bool
PxrUsdMayaTranslatorCurves::Create(
        const UsdGeomCurves& curves,
        MObject parentNode,
        const PxrUsdMayaPrimReaderArgs& args,
        PxrUsdMayaPrimReaderContext* context)
{
    if (not curves) {
        return false;
    }

    const UsdPrim& prim = curves.GetPrim();

    MStatus status;

    // Create node (transform)
    MObject mayaNodeTransformObj;
    if (not PxrUsdMayaTranslatorUtil::CreateTransformNode(prim,
                                                          parentNode,
                                                          args,
                                                          context,
                                                          &status,
                                                          &mayaNodeTransformObj)) {
        return false;
    }

    VtArray<GfVec3f> points;
    VtArray<int>     curveOrder;
    VtArray<int>     curveVertexCounts;
    VtArray<float>   curveWidths;
    VtArray<GfVec2d> curveRanges;
    VtArray<double>  curveKnots;

    // LIMITATION:  xxx REVISIT xxx
    //   Non-animated Attrs
    //   Assuming that a number of these USD attributes are assumed to not be animated
    //   Some we may want to expose as animatable later.
    //
    curves.GetCurveVertexCountsAttr().Get(&curveVertexCounts); // not animatable

    // XXX:
    // Only supporting single curve for now.
    // Sanity Checks
    if (curveVertexCounts.size() == 0) {
        MGlobal::displayError(
            TfStringPrintf("VertexCount arrays is empty on NURBS curves <%s>. Skipping...", 
                            prim.GetPath().GetText()).c_str());
        return false; // No verts for the curve, so exit
    } else if (curveVertexCounts.size() > 1) {
        MGlobal::displayWarning(
            TfStringPrintf("Multiple curves in <%s>. Reading first one...", 
                            prim.GetPath().GetText()).c_str());
    }

    int curveIndex = 0;
    curves.GetWidthsAttr().Get(&curveWidths); // not animatable

    // Gather points. If args.GetReadAnimData() is TRUE,
    // pick the first avaiable sample or default
    UsdTimeCode pointsTimeSample=UsdTimeCode::EarliestTime();
    std::vector<double> pointsTimeSamples;
    size_t numTimeSamples = 0;
    if (args.GetReadAnimData()) {
        curves.GetPointsAttr().GetTimeSamples(&pointsTimeSamples);
        numTimeSamples = pointsTimeSamples.size();
        if (numTimeSamples>0) {
            pointsTimeSample = pointsTimeSamples[0];
        }
    }
    curves.GetPointsAttr().Get(&points, pointsTimeSample);
    
    if (points.size() == 0) {
        MGlobal::displayError(
            TfStringPrintf("Points arrays is empty on NURBS curves <%s>. Skipping...", 
                            prim.GetPath().GetText()).c_str());
        return false; // invalid nurbscurves, so exit
    }

    if (UsdGeomNurbsCurves nurbsSchema = UsdGeomNurbsCurves(prim)) {
        nurbsSchema.GetOrderAttr().Get(&curveOrder);   // not animatable
        nurbsSchema.GetKnotsAttr().Get(&curveKnots);   // not animatable
        nurbsSchema.GetRangesAttr().Get(&curveRanges); // not animatable
    } else {

        // Handle basis curves originally modelled in Maya as nurbs.

        curveOrder.resize(1);
        UsdGeomBasisCurves basisSchema = UsdGeomBasisCurves(prim);
        TfToken typeToken;
        basisSchema.GetTypeAttr().Get(&typeToken);
        if (typeToken == UsdGeomTokens->linear) {
            curveOrder[0] = 2;
            curveKnots.resize(points.size());
            for (size_t i=0; i < curveKnots.size(); ++i) {
                curveKnots[i] = i;
            }
        } else {
            curveOrder[0] = 4;

            // Strip off extra end points; assuming this is non-periodic.
            VtArray<GfVec3f> tmpPts(points.size() - 2);
            std::copy(points.begin() + 1, points.end() - 1, tmpPts.begin());
            points.swap(tmpPts);

            // Cubic curves in Maya have numSpans + 2*3 - 1, and for geometry
            // that came in as basis curves, we have numCV's - 3 spans.  See the
            // MFnNurbsCurve documentation and the nurbs curve export
            // implementation in mojitoplugmaya for more details.
            curveKnots.resize(points.size() -3 + 5);
            int knotIdx = 0;
            for (size_t i=0; i < curveKnots.size(); ++i) {
                if (i < 3) {
                    curveKnots[i] = 0.0;
                } else {
                    if (i <= curveKnots.size() - 3) {
                        ++knotIdx;
                    }
                    curveKnots[i] = double(knotIdx);
                } 
            }
        }
    }

    // == Convert data
    size_t mayaNumVertices = points.size();
    MPointArray mayaPoints(mayaNumVertices);
    for (size_t i=0; i < mayaNumVertices; i++) {
        mayaPoints.set( i, points[i][0], points[i][1], points[i][2] );
    }

    double *knots=curveKnots.data();
    MDoubleArray mayaKnots( knots, curveKnots.size());

    int mayaDegree = curveOrder[curveIndex] - 1;

    MFnNurbsCurve::Form mayaCurveForm = MFnNurbsCurve::kOpen; // HARDCODED
    bool mayaCurveCreate2D = false;
    bool mayaCurveCreateRational = true;

    // == Create NurbsCurve Shape Node
    MFnNurbsCurve curveFn;
    MObject curveObj = curveFn.create(mayaPoints, 
                                     mayaKnots,
                                     mayaDegree,
                                     mayaCurveForm,
                                     mayaCurveCreate2D,
                                     mayaCurveCreateRational,
                                     mayaNodeTransformObj,
                                     &status
                                     );
     if (status != MS::kSuccess) {
         return false;
     }
    MString nodeName( prim.GetName().GetText() );
    nodeName += "Shape";
    curveFn.setName(nodeName, false, &status);

    std::string nodePath( prim.GetPath().GetText() );
    nodePath += "/";
    nodePath += nodeName.asChar();
    if (context) {
        context->RegisterNewMayaNode( nodePath, curveObj ); // used for undo/redo
    }

    // == Animate points ==
    //   Use blendShapeDeformer so that all the points for a frame are contained in a single node
    //   Almost identical code as used with MayaMeshReader.cpp
    //
    if (numTimeSamples > 0) {
        MPointArray mayaPoints(mayaNumVertices);
        MObject curveAnimObj;

        MFnBlendShapeDeformer blendFn;
        MObject blendObj = blendFn.create(curveObj);
        if (context) {
            context->RegisterNewMayaNode(blendFn.name().asChar(), blendObj ); // used for undo/redo
        }
        
        for (unsigned int ti=0; ti < numTimeSamples; ++ti) {
             curves.GetPointsAttr().Get(&points, pointsTimeSamples[ti]);

            for (unsigned int i=0; i < mayaNumVertices; i++) {
                mayaPoints.set( i, points[i][0], points[i][1], points[i][2] );
            }

            // == Create NurbsCurve Shape Node
            MFnNurbsCurve curveFn;
            if ( curveAnimObj.isNull() ) {
                curveAnimObj = curveFn.create(mayaPoints, 
                                     mayaKnots,
                                     mayaDegree,
                                     mayaCurveForm,
                                     mayaCurveCreate2D,
                                     mayaCurveCreateRational,
                                     mayaNodeTransformObj,
                                     &status
                                     );
                if (status != MS::kSuccess) {
                    continue;
                }
            }
            else {
                // Reuse the already created curve by copying it and then setting the points
                curveAnimObj = curveFn.copy(curveAnimObj, mayaNodeTransformObj, &status);
                curveFn.setCVs(mayaPoints);
            }
            blendFn.addTarget(curveObj, ti, curveAnimObj, 1.0);
            curveFn.setIntermediateObject(true);
            if (context) {
                context->RegisterNewMayaNode( curveFn.fullPathName().asChar(), curveAnimObj ); // used for undo/redo
            }
        }

        // Animate the weights so that curve0 has a weight of 1 at frame 0, etc.
        MFnAnimCurve animFn;

        // Construct the time array to be used for all the keys
        MTimeArray timeArray;
        timeArray.setLength(numTimeSamples);
        for (unsigned int ti=0; ti < numTimeSamples; ++ti) {
            timeArray.set( MTime(pointsTimeSamples[ti]), ti);
        }

        // Key/Animate the weights
        MPlug plgAry = blendFn.findPlug( "weight" );
        if ( !plgAry.isNull() && plgAry.isArray() ) {
            for (unsigned int ti=0; ti < numTimeSamples; ++ti) {
                MPlug plg = plgAry.elementByLogicalIndex(ti, &status);
                MDoubleArray valueArray(numTimeSamples, 0.0);
                valueArray[ti] = 1.0; // Set the time value where this curve's weight should be 1.0
                MObject animObj = animFn.create(plg, NULL, &status);
                animFn.addKeys(&timeArray, &valueArray);
                if (context) {
                    context->RegisterNewMayaNode(animFn.name().asChar(), animObj ); // used for undo/redo
                }
            }
        }
    }

    return true;
}
void ShadingNetworkExporter::createShader(const MObject& node)
{
    MStatus status;
    MFnDependencyNode depNodeFn(node);

    const OSLShaderInfo *shaderInfo =
        ShadingNodeRegistry::getShaderInfo(depNodeFn.typeName());

    if(!shaderInfo)
    {
        std::cout << "Skipping unsupported shader: " << depNodeFn.typeName() << "\n";
        return;
    }

    if(m_shadersExported.count(depNodeFn.name()) != 0)
    {
        std::cout << "Skipping already exported shader: " << depNodeFn.name() << "\n";
        return;
    }

    m_shadersExported.insert(depNodeFn.name());

    asr::ParamArray shaderParams;

    for(int i = 0, e = shaderInfo->paramInfo.size(); i < e; ++i)
    {
        const OSLParamInfo& paramInfo = shaderInfo->paramInfo[i];

        // Skip output attributes.
        if(paramInfo.isOutput)
        {
            std::cout << "Skipping output attribute: " << "\n";
            std::cout << paramInfo << std::endl;
            continue;
        }

        if(!paramInfo.validDefault)
        {
            std::cout << "Skipping attribute without valid default: " << "\n";
            std::cout << paramInfo << std::endl;
            continue;
        }

        if(paramInfo.isArray)
        {
            std::cout << "Skipping array attribute: " << "\n";
            std::cout << paramInfo << std::endl;
            continue;
        }

        MPlug plug = depNodeFn.findPlug(paramInfo.mayaAttributeName, &status);
        if(!status)
        {
            std::cout << "Skipping unknown attribute: "
                        << paramInfo.mayaAttributeName << std::endl;
            continue;
        }

        if(plug.isConnected())
        {
            MObject srcNode;
            if(AttributeUtils::get(plug, srcNode))
                createShader(srcNode);

            continue;
        }

        if(plug.isCompound() && plug.numConnectedChildren() != 0)
        {
            std::cout << "Skipping connected compound attribute: " << plug.name() << "\n";
            continue;
        }

        if(plug.isArray() && plug.numConnectedElements() != 0)
        {
            std::cout << "Skipping connected array attribute: " << plug.name() << "\n";
            continue;
        }

        processAttribute(plug, paramInfo, shaderParams);
    }

    m_shaderGroup->add_shader(
        shaderInfo->shaderType.asChar(),
        shaderInfo->shaderName.asChar(),
        depNodeFn.name().asChar(),
        shaderParams);
}
void ShadingNetworkExporter::addConnections(const MObject& node)
{
    MStatus status;
    MFnDependencyNode depNodeFn(node);

    const OSLShaderInfo *shaderInfo =
        ShadingNodeRegistry::getShaderInfo(depNodeFn.typeName());

    if(!shaderInfo)
    {
        std::cout << "Skipping unsupported shader: " << depNodeFn.typeName() << "\n";
        return;
    }

    if(m_shadersExported.count(depNodeFn.name()) != 0)
    {
        std::cout << "Skipping already exported shader: " << depNodeFn.name() << "\n";
        return;
    }

    m_shadersExported.insert(depNodeFn.name());

    for(int i = 0, e = shaderInfo->paramInfo.size(); i < e; ++i)
    {
        const OSLParamInfo& paramInfo = shaderInfo->paramInfo[i];

        // Skip output attributes.
        if(paramInfo.isOutput)
            continue;

        MPlug plug = depNodeFn.findPlug(paramInfo.mayaAttributeName, &status);
        if(!status)
        {
            std::cout << "Skipping unknown attribute: "
                        << paramInfo.mayaAttributeName << std::endl;
            continue;
        }

        if(plug.isConnected())
        {
            MPlug srcPlug;
            if(AttributeUtils::getPlugConnectedTo(plug, srcPlug))
            {
                MFnDependencyNode srcDepNodeFn(srcPlug.node());

                const OSLShaderInfo *srcShaderInfo =
                    ShadingNodeRegistry::getShaderInfo(srcDepNodeFn.typeName());

                if(!srcShaderInfo)
                    continue;

                if(const OSLParamInfo *srcParamInfo = srcShaderInfo->findParam(srcPlug.name()))
                {
                    m_shaderGroup->add_connection(
                        srcDepNodeFn.name().asChar(),
                        srcParamInfo->paramName.asChar(),
                        depNodeFn.name().asChar(),
                        paramInfo.paramName.asChar());
                }

                addConnections(srcPlug.node());
            }
        }

        if(plug.isCompound() && plug.numConnectedChildren() != 0)
        {
            // ???
        }

        if(plug.isArray() && plug.numConnectedElements() != 0)
        {
            // ???
        }
    }
}
bool FxAttributeFiller::FillPlug( DXCCEffectPath& parameter, MPlug& plug )
{
	HRESULT hr= S_OK;
	LPDXCCRESOURCE pResource= NULL;
	LPDIRECT3DBASETEXTURE9 pTexture= NULL;
	D3DXPARAMETER_DESC desc= parameter.End->Description;
	float NumericVals[16]= {0.0f};
	MString StringVal;
	LPCSTR StringValStr= "";

	bool RestoreFound= false;
	LPCVOID pRestoreData= NULL;
	size_t RestoreSize= 0;
	CComPtr<IDXCCPropertyCollection> pCollection;
	DXCCPROPERTY_KEY key= 0;

	if(Restore)
	{
		if( DXCC_SUCCEEDED( Restore->GetPath( parameter.End->LongPathName, &pCollection, &key) ) )
		{
			pCollection->GetPropertyValueAsData(key, &pRestoreData);
			DXCCPROPERTY_DESC desc= pCollection->GetPropertyDesc(key);

			if(desc == DXCCPD_STRING)
			{
				StringVal= (LPCSTR)pRestoreData;
				StringValStr= (LPCSTR)pRestoreData;

				RestoreFound= true;
			}
			else
			{
				size_t RestoreSize= DXCCPropertySize( desc, pRestoreData );
				memcpy( NumericVals, pRestoreData, RestoreSize);

				RestoreFound= true;
			}
		}
	}



	if((desc.Type == D3DXPT_BOOL)
	||(desc.Type == D3DXPT_INT)
	||(desc.Type == D3DXPT_FLOAT))
	{

		if(!RestoreFound)
		{

			if(plug.isArray())
			{
				hr=  Shader->Effect->GetFloatArray(parameter.End->Handle, NumericVals, 16);
					if(DXCC_FAILED(hr))
						DXCC_GOTO_EXIT(e_Exit, TRUE);
			}
			else
			{
				hr=  Shader->Effect->GetFloat(parameter.End->Handle, NumericVals);
				if(DXCC_FAILED(hr))
					DXCC_GOTO_EXIT(e_Exit, TRUE);
			}
		}

		if(plug.isArray())
		{
			int count= desc.Rows * desc.Columns;
			for(int i= 0; i < count; i++)
			{
				MPlug subPlug= plug.elementByLogicalIndex(i);
				DXCHECK_MSTATUS(subPlug.setValue( NumericVals[i] ));
			}
		}
		else
		{
			DXCHECK_MSTATUS(plug.setValue( NumericVals[0] ));
		}
	}
	else if((desc.Type == D3DXPT_TEXTURE)
	||(desc.Type == D3DXPT_TEXTURE1D)
	||(desc.Type == D3DXPT_TEXTURE2D)
	||(desc.Type == D3DXPT_TEXTURE3D)
	||(desc.Type == D3DXPT_TEXTURECUBE))
	{

		if(!RestoreFound)
		{
			hr=  Shader->Effect->GetTexture(parameter.End->Handle, &pTexture);
			if(DXCC_SUCCEEDED(hr) && pTexture != NULL)
			{
				hr= g_PreviewPipeline.AccessManager()->FindResourceByPointer(
						(LPUNKNOWN)pTexture, 
						NULL, 
						&pResource);
				if(DXCC_SUCCEEDED(hr))
				{
					StringVal= pResource->GetResourcePath();
				}
			}
			else
			{
				D3DXHANDLE hResourceAddy= Shader->Effect->GetAnnotationByName( parameter.End->Handle, "SasResourceAddress");
				if(hResourceAddy)
				{
					LPCSTR resourceAddressStr= NULL;
					Shader->Effect->GetString(hResourceAddy, &resourceAddressStr); 

					StringVal= resourceAddressStr;
				}
			}
		}

		DXCHECK_MSTATUS(plug.setValue( StringVal ));
	}
	else if(desc.Type == D3DXPT_STRING)
	{
		if(!RestoreFound)
		{
			hr=  Shader->Effect->GetString(parameter.End->Handle, &StringValStr);
			StringVal= StringValStr;
		}

		DXCHECK_MSTATUS(plug.setValue( StringVal ));
	}
	else
	{
		DXCC_STATUS_EXIT(hr, E_FAIL, e_Exit, TRUE);
	}

e_Exit:
	DXCC_RELEASE(pResource);
	DXCC_RELEASE(pTexture);

	return DXCC_SUCCEEDED(hr);
}