//---------------------------------------------------
    // get the first empty item in the named array plug
    unsigned DagHelper::getFirstEmptyElementId ( const MPlug& parent )
    {
        unsigned num_element = 1;

        if ( parent.numElements() > num_element ) num_element = parent.numElements();

        for ( unsigned i = 0; i< num_element; i++ )
        {
            if ( !parent.elementByLogicalIndex ( i ).isConnected() ) return i;
        }

        return parent.numElements() +1;
    }
Exemple #2
0
// --------------------------------------------------------------------------------------------
void		polyModifierCmd::deleteTweaks()
// --------------------------------------------------------------------------------------------
{
		
	
	// Now, set the tweak values on the meshNode(s) to zero (History dependent)
		//
		MStatus stat;
		MFnNumericData numDataFn;
		MObject nullVector;

		// Create a NULL vector (0,0,0) using MFnNumericData to pass into the plug
		//

		MFnDependencyNode depTmpFn(fDagPath.node(),&stat);
		//stat.perror("");

		MPlug meshTweakPlug = depTmpFn.findPlug("pnts");

		numDataFn.create( MFnNumericData::k3Float );
		numDataFn.setData( 0, 0, 0 );
		nullVector = numDataFn.object();
		unsigned numTweaks = meshTweakPlug.numElements();
		MPlug tweak;
		for(unsigned  i = 0; i < numTweaks; i++ )
		{
			// Access using logical indices since they are the only plugs guaranteed
			// to hold tweak data.
			//
			tweak = meshTweakPlug.elementByPhysicalIndex(i);
			tweak.setValue( nullVector );
		}

}
Exemple #3
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);
                }
            }
        }
    }
}
Exemple #4
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);
}
void SurfaceAttach::inUVs(MFnDependencyNode &fn) {
    MPlug inUVPlug = fn.findPlug("inUV");
    const std::uint32_t numElements = inUVPlug.numElements();

    this->uInputs.resize((size_t)(numElements));
    this->vInputs.resize((size_t)(numElements));

    for (std::uint32_t i=0; i < numElements; i++){
        MPlug uvPlug = inUVPlug.elementByLogicalIndex(i);
        this->uInputs[i] = uvPlug.child(0).asDouble();
        this->vInputs[i] = uvPlug.child(1).asDouble();
    }
}
Exemple #6
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));
		}
	}

}
Exemple #7
0
int physicalIndex(MPlug& p)
{
	MPlug parent = p;
	while (parent.isChild())
		parent = parent.parent();
	
	if (!parent.isElement())
		return -1;

	if (!parent.array())
		return - 1;
	
	MPlug arrayPlug = parent.array();

	for (uint i = 0; i < arrayPlug.numElements(); i++)
		if (arrayPlug[i].logicalIndex() == parent.logicalIndex())
			return i;

	return -1;
}
    // -------------------------------------------
    bool AnimationHelper::isPhysicsAnimation ( const MObject& o )
    {
        if ( o.hasFn ( MFn::kChoice ) )
        {
            MFnDependencyNode n ( o );
            MPlug p = n.findPlug ( "input" );
            uint choiceCount = p.numElements();

            for ( uint i = 0; i < choiceCount; ++i )
            {
                MPlug child = p.elementByPhysicalIndex ( i );
                MObject connection = DagHelper::getSourceNodeConnectedTo ( child );

                if ( !connection.isNull() && connection != o )
                    if ( isPhysicsAnimation ( connection ) ) return true;
            }
        }

        else if ( o.hasFn ( MFn::kRigidSolver ) || o.hasFn ( MFn::kRigid ) ) return true;

        return false;
    }
    //---------------------------------------------------
    //
    // Find a node connected to a node's array attribute
    //
    bool DagHelper::getPlugArrayConnectedTo ( const MObject& node, const MString& attribute, MPlug& connectedPlug )
    {
        MStatus status;
        MFnDependencyNode dgFn ( node );
        MPlug plug = dgFn.findPlug ( attribute, &status );

        if ( status != MS::kSuccess )
        {
            MGlobal::displayWarning ( MString ( "couldn't find plug on attribute " ) +
                                      attribute + MString ( " on object " ) + dgFn.name() );
            return false;
        }

        if ( plug.numElements() < 1 )
        {
            MGlobal::displayWarning ( MString ( "plug array doesn't have any connection on attribute " ) +
                                      attribute + MString ( " on object " ) + dgFn.name() );
            return false;
        }

        MPlug firstElementPlug = plug.connectionByPhysicalIndex ( 0 );

        // Get the connection - there can be at most one input to a plug
        //
        MPlugArray connections;
        firstElementPlug.connectedTo ( connections, true, true );

        if ( connections.length() == 0 )
        {
            MGlobal::displayWarning ( MString ( "plug connected to an empty array on attribute " ) +
                                      attribute + MString ( " on object " ) + dgFn.name() );
            return false;
        }

        connectedPlug = connections[0];

        return true;
    }
Exemple #10
0
int tm_polygon::removeTweaks_Func( MSelectionList &selectionList)
{
   MStatus status;
   MObject object;
   status = selectionList.getDependNode( 0, object);
   if(!status)
   {
      MGlobal::displayError("***### tm_polygon: Can't find object.");
      return 0;
   }
   MFnMesh mesh( object, &status);
   if(!status)
   {
      MGlobal::displayError("***### tm_polygon: Can't find mesh.");
      return 0;
   }

   int pntsCount = 0;
   MPlug pntsPlug = mesh.findPlug( "pnts" );
   if( !pntsPlug.isNull() )
   {
      MPlug tweakPlug;
      MObject nullVector_object;
      MFnNumericData numDataFn( nullVector_object );
//      numDataFn.setData3Double( 0.0, 0.0, 0.0 );
      numDataFn.setData( 0.0, 0.0, 0.0 );
      pntsCount = pntsPlug.numElements();
      for( int i = 0; i < pntsCount; i++ )
      {
         tweakPlug = pntsPlug.elementByPhysicalIndex( (unsigned int)i, &status );
         if( status == MS::kSuccess && !tweakPlug.isNull() )
            tweakPlug.setValue( nullVector_object );
      }
   }
   return pntsCount;
}
Exemple #11
0
void MG_vectorGL::draw( M3dView & view, const MDagPath & path, 
							 M3dView::DisplayStyle dispStyle,
							 M3dView::DisplayStatus status )
{ 
   
	MPlug drawItP (thisMObject(),drawIt);
	bool drawItV;
	drawItP.getValue(drawItV);
	
	
	MPlug arrowSizeP (thisMObject(),arrowSize);
	double arrowSizeV;
	arrowSizeP.getValue(arrowSizeV);
	
	MPlug upVecP (thisMObject(),upVec);
	MVector upVecV;
	upVecP.child(0).getValue(upVecV.x);
	upVecP.child(1).getValue(upVecV.y);
	upVecP.child(2).getValue(upVecV.z);
	
	MPlug vecsP (thisMObject(),vecs);
	MPlug startPointP (thisMObject(),startPoint);

	 
	int elemVecs   =  vecsP.numElements();
	int elemPoints =  startPointP.numElements();
	
	if ( drawItV == 0 )
	{
	  return ;
	  
	}
	
	if (elemVecs != elemPoints )
	{
	  return;
	  
	}
	
	
	// Draw it 
	view.beginGL();
	glPushAttrib( GL_ALL_ATTRIB_BITS );
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glLineWidth(2);
	if(status == M3dView::kLead)
		glColor4f(0.0,1.0,0.0,1.0f);
	else
		glColor4f(1.0,1.0,0.0,1.0f);
	
	for ( unsigned int i = 0 ; i < elemVecs ; i++ )
	{
	   vecsP.selectAncestorLogicalIndex( i , vecs);
	   startPointP.selectAncestorLogicalIndex( i , startPoint);

	
	   MVector currentVec ;
	   MPoint currentPoint;
	  
	  vecsP.child(0).getValue(currentVec.x);
	  vecsP.child(1).getValue(currentVec.y);
	  vecsP.child(2).getValue(currentVec.z);
	  
	  startPointP.child(0).getValue(currentPoint.x);
	  startPointP.child(1).getValue(currentPoint.y);
	  startPointP.child(2).getValue(currentPoint.z);
	    
	  drawArrow(currentVec , upVecV , arrowSizeV , currentPoint);
	  

	}


	glDisable(GL_BLEND);
	glPopAttrib();



}
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;
}
MStatus	CmpMeshModifierCmd::transferTweaks( const MDagPath &shapePath,
										    MObject &tweakNode, 
											MDagModifier &dagMod )
{
	// Get the tweaks from the mesh shape and apply them to the 
	// to the tweak node
	MFnDagNode shapeNodeFn( shapePath );
	MPlug srcTweaksPlug = shapeNodeFn.findPlug( "pnts" );
	
	MFnDependencyNode tweakNodeFn( tweakNode );
	MPlug dstTweaksPlug = tweakNodeFn.findPlug( "tweak" );
		
	//MGlobal::displayInfo( MString( "storing tweaks from " ) + shapePath.fullPathName() + "\n" );
	
	MPlugArray plugs;
	MPlug srcTweakPlug;
	MPlug dstTweakPlug;
	MObject dataObj;
	MFloatVector tweak;
	unsigned int nTweaks = srcTweaksPlug.numElements();
	unsigned int i, j, ci, logicalIndex;
	for( i=0; i < nTweaks; i++ )
	{
		srcTweakPlug = srcTweaksPlug.elementByPhysicalIndex( i );
		if( !srcTweakPlug.isNull() )
		{
			logicalIndex = srcTweakPlug.logicalIndex();
			
			// Set tweak node tweak element
			srcTweakPlug.getValue( dataObj );			
			MFnNumericData numDataFn( dataObj );
			numDataFn.getData( tweak[0], tweak[1], tweak[2] );
			
			dagMod.commandToExecute( MString( "setAttr " ) + tweakNodeFn.name() + ".tweak[" + logicalIndex + "] " + 
									 tweak[0] + " " + tweak[1] + " " + tweak[2] );

			// Handle transfer of incoming and outgoing connections to "pnts" elements
			dstTweakPlug = dstTweaksPlug.elementByLogicalIndex(logicalIndex);

			if( srcTweakPlug.isConnected() )
			{
				// As source, transfer source to tweak node tweak
				srcTweakPlug.connectedTo( plugs, false, true );
				for( j=0; j < plugs.length(); j++ )
				{
					dagMod.disconnect( srcTweakPlug, plugs[j] );
					dagMod.connect( dstTweakPlug, plugs[j] );
				}
				
				// As destination, transfer destination to tweak node tweak
				srcTweakPlug.connectedTo( plugs, true, false );
				if( plugs.length() == 1 ) // There can only be one input connection
				{
					dagMod.disconnect( plugs[0], srcTweakPlug );
					dagMod.connect( plugs[0], dstTweakPlug );
				}	
			}
			else // Check children
			{
				MPlug srcTweakChildPlug;
				MPlug dstTweakChildPlug;
				
				for( ci=0; ci < srcTweakPlug.numChildren(); ci++ )
				{
					srcTweakChildPlug = srcTweakPlug.child(ci);
					dstTweakChildPlug = dstTweakPlug.child(ci);
					if( srcTweakChildPlug.isConnected() )
					{
						// As souce, transfer source to tweak node tweak
						srcTweakChildPlug.connectedTo( plugs, false, true );
						for( j=0; j < plugs.length(); j++ )
						{
							dagMod.disconnect( srcTweakChildPlug, plugs[j] );
							dagMod.connect( dstTweakChildPlug, plugs[j] );
						}
						
						// As destination, transfer destination to tweak node tweak
						srcTweakChildPlug.connectedTo( plugs, true, false );
						if( plugs.length() == 1 ) // There can only be one input connection
						{
							dagMod.disconnect( plugs[0], srcTweakChildPlug );
							dagMod.connect( plugs[0], dstTweakChildPlug );
						}
					}	
				}				
			}
									
			// With the tweak values and any connections now transferred to
			// the tweak node's tweak element, this source element can be reset
			dagMod.commandToExecute( MString( "setAttr " ) + shapePath.fullPathName() + ".pnts[" + logicalIndex + "] 0 0 0" );									
			
			//MGlobal::displayInfo( MString(" tweak: ") + tweakIndices[i] + ": " + tweaks[i].x + ", " + tweaks[i].y + ", " + tweaks[i].z + "\n" );
		}
	}

	return MS::kSuccess;
}
MStatus CmpMeshModifierCmd::doIt( const MDagPath &dagPath, const MTypeId &meshModType )
{
	MStatus stat;
	
	meshShapePath = dagPath;
	if( !meshShapePath.isValid() )
	{
		displayError( "Invalid mesh shape path: " + meshShapePath.fullPathName() );
		return MS::kFailure;
	}
	
	meshModifierNodeType = meshModType;
	
	//
	// Get the current state of the history
	//
	MFnDagNode origShapeNodeFn( meshShapePath );
	
	// Determine if the mesh has history
	MPlug inMeshOrigPlug = origShapeNodeFn.findPlug( "inMesh" );
	hasHistory = inMeshOrigPlug.isConnected();
	
	// Determine if the mesh has tweaks
	hasInternalTweaks = false;
	MPlug tweaksPlug = origShapeNodeFn.findPlug( "pnts" );
	if( !tweaksPlug.isNull() )
	{
		MObject obj;
		MPlug tweakPlug;
		MFloatVector tweak;
		unsigned int i;
		unsigned int nTweaks = tweaksPlug.numElements();
		for( i=0; i < nTweaks; i++ )
		{
			tweakPlug = tweaksPlug.elementByPhysicalIndex( i, &stat );
			if( stat && !tweakPlug.isNull() )
			{
				tweakPlug.getValue( obj );
				MFnNumericData numDataFn( obj );
				numDataFn.getData( tweak[0], tweak[1], tweak[2] );
				
				if( tweak[0] != 0.0f || tweak[1] != 0.0f || tweak[2] != 0.0f )
				{
					hasInternalTweaks = true;
					break;
				}
			}
		}
	}
	
	int res;
	MGlobal::executeCommand( "constructionHistory -query -toggle", res );
	genHistory = res != 0;
	
	//MGlobal::displayInfo( MString("resulting: ") + hasHistory + " " + hasInternalTweaks + " " + genHistory + "\n" );
	
	// When there is no existing history
	// cache the mesh data for later undoing
	//
	if( !hasHistory )
	{
		MPlug meshPlug = origShapeNodeFn.findPlug( hasInternalTweaks ? "cachedInMesh" : "outMesh" );
		meshPlug.getValue( origMeshData );
	}
	
	// Create the modifier node
	MObject modNode = dagMods[0].MDGModifier::createNode( meshModifierNodeType, &stat );
	// Create tweak node
	MObject tweakNode = dagMods[0].MDGModifier::createNode( "polyTweak", &stat );
	// Execute DAG modifier to ensure that the nodes actually exist
	dagMods[0].doIt(); 
	
	// Check that the inMesh and outMesh attributes exist in the modifier node
	MFnDependencyNode nodeFn( modNode );
	if( nodeFn.attribute( "inMesh" ).isNull() || nodeFn.attribute( "outMesh" ).isNull() )
	{
		displayError( "Invalid modifier node. It doesn't have inMesh and/or outMesh attributes" );
		return MS::kFailure;
	}

	// Let the derived command class initialize the modifier node
	initModifierNode( modNode, dagMods[1] );
	MFnDependencyNode modNodeFn( modNode );
		
	// Get plug that is the start of the new stream
	MPlug newStreamInMeshPlug = modNodeFn.findPlug( "inMesh" );
		
	// Get the plug connecting into original shape's inMesh
	MPlugArray inPlugs;
	inMeshOrigPlug.connectedTo( inPlugs, true, false );
	MPlug oldStreamOutMeshPlug;
	// N.B. For meshes without construction history
	// there won't be incoming connection
	if( inPlugs.length() )
	{
		oldStreamOutMeshPlug = inPlugs[0];		
		
		// Disconnect the connection into the mesh shape's inMesh attribute.
		// The outMesh of the modifier node will later connect into this.
		dagMods[1].disconnect( oldStreamOutMeshPlug, inMeshOrigPlug );
	}
		
	if( hasInternalTweaks )
	{
		// Transfer tweaks from the mesh shape to the tweak node
		transferTweaks( meshShapePath, tweakNode, dagMods[1] );
		
		MFnDependencyNode tweakNodeFn( tweakNode );
		newStreamInMeshPlug = tweakNodeFn.findPlug( "inputPolymesh" );
		
		// Connect output of tweak node into modifier node		
		MPlug inMeshModPlug = modNodeFn.findPlug( "inMesh" );
		MPlug outMeshTweakPlug = tweakNodeFn.findPlug( "output" );
		dagMods[1].connect( outMeshTweakPlug, inMeshModPlug );
	}

	dagMods[1].doIt();
	
	copyTransform = MObject::kNullObj;
	
	// Generate history for shape that doesn't have one
	if( !hasHistory ) //&& genHistory )
	{		
		// Duplicate the mesh shape node
		copyTransform = origShapeNodeFn.duplicate();
		MFnDagNode copyTransformFn( copyTransform );
		
		MObject copyShapeNode = copyTransformFn.child(0);
		MFnDagNode copyShapeNodeFn( copyShapeNode );
		
		//MGlobal::displayInfo( MString("copy: transform: ") + copyTransformFn.fullPathName() + " shape name: " + copyShapeNodeFn.fullPathName() + "\n" );
				
		// Set it to be an intermediate object
		dagMods[2].commandToExecute( "setAttr " + copyShapeNodeFn.fullPathName() + ".intermediateObject true" );
		
		// Set output plug of old stream to be the outMesh of the duplicated shape
		oldStreamOutMeshPlug = copyShapeNodeFn.findPlug( "outMesh" );
				
		// Rename the duplicate
		dagMods[2].renameNode( copyShapeNode, copyShapeNodeFn.name() + "Orig" );
		
		// Reparent the shape
		MObject origTransform = meshShapePath.transform();
		dagMods[2].reparentNode( copyShapeNode, origTransform );
		
		// Remove the now orphaned transform
		// N.B. calling deleteNode( transformCopy ) causes the shape node to
		// also be deleted, even though it has been reparented to the original mesh.
		// As such, the MEL command "delete" was used instead.
		//
		// The deleteNode() method does some
		// preparation work before it enqueues itself in the MDagModifier list
		// of operations, namely, it looks at it's parents and children and
		// deletes them as well if they are the only parent/child of the node
		// scheduled to be deleted.
		dagMods[2].commandToExecute( "delete " + copyTransformFn.fullPathName() );
	}	
	
	if( !oldStreamOutMeshPlug.isNull() )
		// Connect output mesh of the previous stream the input of the new stream
		dagMods[2].connect( oldStreamOutMeshPlug, newStreamInMeshPlug );
		
	// Connect output of the mesh modifier node to the input of the original mesh shape
	MPlug outMeshModPlug = modNodeFn.findPlug( "outMesh" );
	dagMods[2].connect( outMeshModPlug, inMeshOrigPlug );
	
	if( !hasHistory && !genHistory )
		// Collapse the history
		dagMods[2].commandToExecute( MString("delete -constructionHistory ") + meshShapePath.fullPathName() );
	
	dagMods[2].doIt();
	
	return MS::kSuccess;
}
Exemple #15
0
	// Load material data
	MStatus Material::load(MFnDependencyNode* pShader,MStringArray& uvsets,ParamList& params)
	{
		MStatus stat;
		clear();
		//read material name, adding the requested prefix
		MString tmpStr = params.matPrefix;
		if (tmpStr != "")
			tmpStr += "/";
		tmpStr += pShader->name();
		MStringArray tmpStrArray;
		tmpStr.split(':',tmpStrArray);
		m_name = "";
		for (int i=0; i<tmpStrArray.length(); i++)
		{
			m_name += tmpStrArray[i];
			if (i < tmpStrArray.length()-1)
				m_name += "_";
		}

		//check if we want to export with lighting off option
		m_lightingOff = params.lightingOff;

		// GET MATERIAL DATA

		// Check material type
		if (pShader->object().hasFn(MFn::kPhong))
		{
			stat = loadPhong(pShader);
		}
		else if (pShader->object().hasFn(MFn::kBlinn))
		{
			stat = loadBlinn(pShader);
		}
		else if (pShader->object().hasFn(MFn::kLambert))
		{
			stat = loadLambert(pShader);
		}
		else if (pShader->object().hasFn(MFn::kPluginHwShaderNode))
		{
			stat = loadCgFxShader(pShader);
		}
		else
		{
			stat = loadSurfaceShader(pShader);
		}

		// Get textures data
		MPlugArray colorSrcPlugs;
		MPlugArray texSrcPlugs;
		MPlugArray placetexSrcPlugs;
		if (m_isTextured)
		{
			// Translate multiple textures if material is multitextured
			if (m_isMultiTextured)
			{
				// Get layered texture node
				MFnDependencyNode* pLayeredTexNode = NULL;
				if (m_type == MT_SURFACE_SHADER)
					pShader->findPlug("outColor").connectedTo(colorSrcPlugs,true,false);
				else
					pShader->findPlug("color").connectedTo(colorSrcPlugs,true,false);
				for (int i=0; i<colorSrcPlugs.length(); i++)
				{
					if (colorSrcPlugs[i].node().hasFn(MFn::kLayeredTexture))
					{
						pLayeredTexNode = new MFnDependencyNode(colorSrcPlugs[i].node());
						continue;
					}
				}

				// Get inputs to layered texture
				MPlug inputsPlug = pLayeredTexNode->findPlug("inputs");

				// Scan inputs and export textures
				for (int i=inputsPlug.numElements()-1; i>=0; i--)
				{
					MFnDependencyNode* pTextureNode = NULL;
					// Search for a connected texture
					inputsPlug[i].child(0).connectedTo(colorSrcPlugs,true,false);
					for (int j=0; j<colorSrcPlugs.length(); j++)
					{
						if (colorSrcPlugs[j].node().hasFn(MFn::kFileTexture))
						{
							pTextureNode = new MFnDependencyNode(colorSrcPlugs[j].node());
							continue;
						}
					}

					// Translate the texture if it was found
					if (pTextureNode)
					{
						// Get blend mode
						TexOpType opType;
						short bm;
						inputsPlug[i].child(2).getValue(bm);
						switch(bm)
						{				
						case 0:
							opType = TOT_REPLACE;
							break;
						case 1:
							opType = TOT_ALPHABLEND;
							break;				
						case 4:
							opType = TOT_ADD;
							break;
						case 6:
							opType = TOT_MODULATE;
							break;
						default:
							opType = TOT_MODULATE;
						}

						stat = loadTexture(pTextureNode,opType,uvsets,params);
						delete pTextureNode;
						if (MS::kSuccess != stat)
						{
							std::cout << "Error loading layered texture\n";
							std::cout.flush();
							delete pLayeredTexNode;
							return MS::kFailure;
						}
					}
				}
				if (pLayeredTexNode)
					delete pLayeredTexNode;
			}
			// Else translate the single texture
			else
			{
				// Get texture node
				MFnDependencyNode* pTextureNode = NULL;
				if (m_type == MT_SURFACE_SHADER)
					pShader->findPlug("outColor").connectedTo(colorSrcPlugs,true,false);
				else
					pShader->findPlug("color").connectedTo(colorSrcPlugs,true,false);
				for (int i=0; i<colorSrcPlugs.length(); i++)
				{
					if (colorSrcPlugs[i].node().hasFn(MFn::kFileTexture))
					{
						pTextureNode = new MFnDependencyNode(colorSrcPlugs[i].node());
						continue;
					}
				}
				if (pTextureNode)
				{
					TexOpType opType = TOT_MODULATE;
					stat = loadTexture(pTextureNode,opType,uvsets,params);
					delete pTextureNode;
					if (MS::kSuccess != stat)
					{
						std::cout << "Error loading texture\n";
						std::cout.flush();
						return MS::kFailure;
					}
				}
			}
		}

		return MS::kSuccess;
	}
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;
}
Exemple #17
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;
}
Exemple #18
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;
}