MStatus	liqAttachPrefAttribute::redoIt()
{
  MFnTypedAttribute tAttr;
  MStatus status;

  for ( unsigned i( 0 ); i < objectNames.length(); i++ ) 
  {
    MSelectionList		nodeList;
    nodeList.add( objectNames[i] );
    MObject depNodeObj;
    nodeList.getDependNode( 0, depNodeObj );
    MDagPath dagNode;
    nodeList.getDagPath( 0, dagNode );
    MFnDependencyNode depNode( depNodeObj );
    MObject prefAttr;
    MString attrName, varName;

    // make sure the renderer description is up to date
    liqglo.liquidRenderer.setRenderer();

    // build the name of the attribute
    varName = ( ( exportN && depNodeObj.hasFn( MFn::kMesh ) )? "N":"P" );
    attrName = "rman";
    attrName += varName;
    attrName += ( ( liqglo.liquidRenderer.requires__PREF )? "__":"" );
    attrName += varName + "ref";

    // create the attribute
    prefAttr = tAttr.create( attrName, attrName, MFnData::kPointArray );


    if ( depNodeObj.hasFn( MFn::kNurbsSurface ) ) 
    {
      MFnNurbsSurface nodeFn( depNodeObj );
      MPointArray nodePArray;
      MItSurfaceCV cvs( dagNode, MObject::kNullObj, liqglo.liquidRenderer.requires_SWAPPED_UVS == false, &status );

      while( !cvs.isDone() ) 
      {
        while( !cvs.isRowDone() ) 
        {
          MPoint pt = (worldSpace)? cvs.position( MSpace::kWorld ) : cvs.position( MSpace::kObject );
          nodePArray.append( pt );
          cvs.next();
        }
        cvs.nextRow();
      }

      nodeFn.addAttribute( prefAttr );
      MFnPointArrayData pArrayData;

      MObject prefDefault = pArrayData.create( nodePArray );
      MPlug nodePlug( depNodeObj, prefAttr );
      nodePlug.setValue( prefDefault );
    } 
    else if ( depNodeObj.hasFn( MFn::kNurbsCurve ) ) 
    {
      // Carsten: added support for PREF on nurbs curves
      //
      MFnNurbsCurve nodeFn( depNodeObj );
      MPointArray nodePArray;
      nodeFn.getCVs( nodePArray );

      nodeFn.addAttribute( prefAttr );
      MFnPointArrayData pArrayData;

      MObject prefDefault = pArrayData.create( nodePArray );
      MPlug nodePlug( depNodeObj, prefAttr );
      nodePlug.setValue( prefDefault );
    } 
    else if ( depNodeObj.hasFn( MFn::kMesh ) ) 
    {
      MFnMesh nodeFn( depNodeObj );
      // Moritz: modified this line to dim nodePArray -- otherwise
      // nodePArray.set() in the wile loop below throws an exception
      // which was why __Pref didn't work
      MPointArray nodePArray( MFnMesh( depNodeObj ).numVertices() );
      unsigned count;

      nodeFn.addAttribute( prefAttr );

      if ( exportN ) 
      {
        // export Nref
        unsigned vertex;
        unsigned normal;
        unsigned face = 0;
        unsigned faceVertex = 0;
        unsigned int numNormals = nodeFn.numNormals();
        unsigned int numPoints  = nodeFn.numVertices();
        MFloatVectorArray normals;
        MVectorArray normalAttArray;
        nodeFn.getNormals( normals );

        if ( numNormals > numPoints ) 
        {
          // if we get more than 1 normal per vertex,
          // force the arraysize to the full facevarying size
          unsigned faceVaryingCount( 0 );
          for ( unsigned pOn( 0 ); pOn < nodeFn.numPolygons(); pOn++ ) 
            faceVaryingCount += nodeFn.polygonVertexCount( pOn );
          
          normalAttArray.setLength( faceVaryingCount );
        } 
        else 
          normalAttArray.setLength(normals.length());
        
        for ( MItMeshPolygon polyIt ( depNodeObj ); polyIt.isDone() == false; polyIt.next() ) 
        {
          count = polyIt.polygonVertexCount();
          while ( count > 0 ) 
          {
            --count;
            normal = polyIt.normalIndex( count );
            vertex = polyIt.vertexIndex( count );

            if( numNormals == numPoints )
              normalAttArray.set(normals[normal], vertex);
            else
              normalAttArray.set(normals[normal], faceVertex);

            ++faceVertex;
          }
          ++face;
        }

        MFnVectorArrayData pArrayData;
        MObject prefDefault = pArrayData.create( normalAttArray );
        MPlug nodePlug( depNodeObj, prefAttr );
        nodePlug.setValue( prefDefault );

      } 
      else 
      {
        // TODO: do we need to account for the altMeshExport algo that's
        // used in liquidRibMeshData?
        // Moritz: no, it's basically the same as the algo below
        for ( MItMeshPolygon polyIt( dagNode, MObject::kNullObj ); !polyIt.isDone(); polyIt.next()) 
        {
          count = polyIt.polygonVertexCount();

          while ( count > 0 ) 
          {
            --count;
            unsigned	vertexIndex = polyIt.vertexIndex( count );
            MPoint nodePoint = (worldSpace)? polyIt.point( count, MSpace::kWorld ) : polyIt.point( count, MSpace::kObject );
            // Moritz: this returns MS::kFailure but seems to work?!
            nodePArray.set( nodePoint, vertexIndex );
          }
        }

        MFnPointArrayData pArrayData;
        MObject prefDefault = pArrayData.create( nodePArray );
        MPlug nodePlug( depNodeObj, prefAttr );
        nodePlug.setValue( prefDefault );

      }
    } else cerr << "Neither a Nurbs nor a Mesh !!" << endl;
  }
  return MS::kSuccess;
}
Esempio n. 2
0
// --------------------------------------------------------------------------------------------
MStatus polyModifierCmd::processUpstreamNode( modifyPolyData& data )
// --------------------------------------------------------------------------------------------
{
	MStatus status = MS::kSuccess;

	// Declare our function sets - Although dagNodeFn derives from depNodeFn, we need
	//							   both since dagNodeFn can only refer to DAG objects.
	//							   We will use depNodeFn for all times other when dealing
	//							   with the DAG.
	//
	MFnDependencyNode	depNodeFn;
	MFnDagNode			dagNodeFn;

	// Use the selected node's plug connections to find the upstream plug.
	// Since we are looking at the selected node's inMesh attribute, it will
	// always have only one connection coming in if it has history, and none
	// otherwise.
	//
	// If there is no history, copy the selected node and place it ahead of the
	// modifierNode as the new upstream node so that the modifierNode has an
	// input mesh to operate on.
	//

	//save the meshDagPath for later use
	MDagPath::getAPathTo(data.meshNodeShape,myMeshPath);

	MPlugArray tempPlugArray;

 	if( fHasHistory )
	{
		// Since we have history, look for what connections exist on the
		// meshNode "inMesh" plug. "inMesh" plugs should only ever have one
		// connection.
		//
		data.meshNodeDestPlug.connectedTo( tempPlugArray, true, false);
		

		// ASSERT: Only one connection should exist on meshNodeShape.inMesh!
		//
		MStatusAssert( (tempPlugArray.length() == 1),
					   "tempPlugArray.length() == 1 -- 0 or >1 connections on meshNodeShape.inMesh" );
		data.upstreamNodeSrcPlug = tempPlugArray[0];

		
		// Construction history only deals with shapes, so we can grab the
		// upstreamNodeShape off of the source plug.
		//
		// Dieser Bereich muss bleiben, weil diese Attribute noch bentigt werden
		data.upstreamNodeShape = data.upstreamNodeSrcPlug.node();
		depNodeFn.setObject( data.upstreamNodeShape );
		data.upstreamNodeSrcAttr = data.upstreamNodeSrcPlug.attribute();
		

		// Disconnect the upstream node and the selected node, so we can
		// replace them with our own connections below.
		//
		MPlug	nodePlug(data.meshNodeShape,data.meshNodeDestAttr ) ;
		INVIS(cout<<data.upstreamNodeSrcPlug.name().asChar()<<" --|-- "<<nodePlug.name().asChar()<<endl);
		status =	fDGModifier.disconnect( data.upstreamNodeSrcPlug,
											nodePlug );
											
		
		MCheckStatus( status, "Disconnect Upstream mit meshNode" );


	}
	else	// No History (!fHasHistory)
	{
		// Use the DAG node function set to duplicate the shape of the meshNode.
		// The duplicate method will return an MObject handle to the transform
		// of the duplicated shape, so traverse the dag to locate the shape. Store
		// this duplicate shape as our "upstream" node to drive the input for the 
		// modifierNode.
		//
		depNodeFn.setObject( data.meshNodeShape );
		data.upstreamNodeTransform = createDuplicate.createNode("mesh");
		createDuplicate.doIt();

		dagNodeFn.setObject( data.upstreamNodeTransform );
		

		// Ensure that our upstreamNode is pointing to a shape.
		//
		MStatusAssert( (0 < dagNodeFn.childCount()),
					   "0 < dagNodeFn.childCount() -- Duplicate meshNode transform has no shape." );
		data.upstreamNodeShape = dagNodeFn.child(0);

		MPlug outMeshPlug = depNodeFn.findPlug("outMesh");
		depNodeFn.setObject(data.upstreamNodeShape);

		//jetzt inMesh upstreamNodeShape mit outMesh meshShape füllen
		MDGModifier tempMod;
		tempMod.connect(outMeshPlug,depNodeFn.findPlug("inMesh"));
		tempMod.doIt();

		//force DGEVAL
		MString cmd = "dgeval -src ";
		cmd += depNodeFn.name();
		cmd += ".outMesh";
		MGlobal::executeCommand(cmd,false,false);

		tempMod.undoIt();

		
		// Re-parent the upstreamNodeShape under our original transform
		//
		reparentDuplicate.reparentNode( data.upstreamNodeShape, data.meshNodeTransform );
		reparentDuplicate.doIt();


		deleteDuplicate.deleteNode( data.upstreamNodeTransform );
		deleteDuplicate.doIt();
		/*
		status = fDagModifier.reparentNode( data.upstreamNodeShape, data.meshNodeTransform );
		MCheckStatus( status, "reparentNode" );

		// Perform the DAG re-parenting
		// 
		// Note: This reparent must be performed before the deleteNode() is called.
		//		 See polyModifierCmd.h (see definition of fDagModifier) for more details.
		//
		status = fDagModifier.doIt();
		MCheckStatus( status, "fDagModifier.doIt()" );
		*/
		// Mark the upstreamNodeShape (the original shape) as an intermediate object
		// (making it invisible to the user)
		//
		dagNodeFn.setObject( data.upstreamNodeShape );
		dagNodeFn.setIntermediateObject( true );

		// Get the upstream node source attribute
		//
		data.upstreamNodeSrcAttr = dagNodeFn.attribute( "outMesh" );
		data.upstreamNodeSrcPlug = MPlug(data.upstreamNodeShape, data.upstreamNodeSrcAttr);

		/*
		// Remove the duplicated transform node (clean up)
		//
		status = fDagModifier.deleteNode( data.upstreamNodeTransform );
		MCheckStatus( status, "deleteNode" );

		// Perform the DAG delete node
		//
		// Note: This deleteNode must be performed after the reparentNode() method is
		//		 completed. See polyModifierCmd.h (see definition of fDagModifier) for
		//		 details.
		//
		status = fDagModifier.doIt();
		MCheckStatus( status, "fDagModifier.doIt()" );
		*/

		// Cache the DAG path to the duplicate shape
		//
		dagNodeFn.getPath( fDuplicateDagPath );

		//finally delete the tweaks to avoid double transformation
		deleteTweaks();
	}

	return status;
}