Example #1
0
MStatus polyModifierCmd::getFloat3PlugValue( MPlug plug, MFloatVector & value )
{
	// Retrieve the value as an MObject
	//
	MObject object;
	plug.getValue( object );

	// Convert the MObject to a float3
	//
	MFnNumericData numDataFn( object );
	numDataFn.getData( value[0], value[1], value[2] );
	return MS::kSuccess;
}
Example #2
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;
}
Example #3
0
//-----------------------------------------------------------------------
void visualizeMeshNode::draw( M3dView & view, const MDagPath & path, 
							 M3dView::DisplayStyle style,
							 M3dView::DisplayStatus status )
//-----------------------------------------------------------------------
{ 
	// cout << "cvColor::draw\n";

	MStatus		stat;
	MObject		thisNode = thisMObject();

	MPlug		plug(thisNode, drawingEnabled) ;
	
	//soll überhaupt etwas gezeichnet werden?
	bool doDraw;
	plug.getValue(doDraw);


	if (!doDraw)
		return;

	//Okay, also die restlichen Daten extrahieren	

	//Lokale Variablen
	float	fPointSize;


	//PointSize holen
	
	plug.setAttribute(pointSize);	
	plug.getValue(fPointSize);
	

	bool	allowBeautyMode = true;

	// Jetzt das Plug auslesen um herauszufinden, ob man schön zeichnen darf oder nicht
	// TODO

	
/*
	// Test
	HDC dc;
	dc = view.deviceContext();
	
	PIXELFORMATDESCRIPTOR pfd;
	int  iPixelFormat;
	
	// get the current pixel format index 
	iPixelFormat = GetPixelFormat(dc); 
	
	// obtain a detailed description of that pixel format 
	int returnVal = DescribePixelFormat(dc, iPixelFormat, 
        sizeof(PIXELFORMATDESCRIPTOR), &pfd); 

	//cout<<pfd.nSize<<endl;
	//cout<<sizeof(PIXELFORMATDESCRIPTOR)<<endl;
	
	cout<<pfd.iPixelType<<" = ReturnVal"<<endl;
	cout<<returnVal<<" = ReturnVal"<<endl;
	cout<<iPixelFormat<<" = PixelFormat"<<endl;
*/



	//Farbe holen	-> Diese Schreibweise hat den (hier unbedeutenden) Vorteil, dass Objekte automatisch zerstört werden - sie existieren nur innerhalb der Klammern
	{
		MColor tmpColor;
		

		plug.setAttribute(vtxColorObj);
		MObject colorObj;
		plug.getValue(colorObj);
		
		
		MFnNumericData	numDataFn(colorObj);
		numDataFn.getData(tmpColor.r, tmpColor.g, tmpColor.b);

		//wenn sich die Farben verändert haben, dann die liste updaten - und alles neuzeichnen
		if(tmpColor != vtxColor)
		{
			vtxColor = tmpColor;

			listNeedsUpdate = true;
		}

		plug.setAttribute(vtxColorObj2);
		plug.getValue(colorObj);
		numDataFn.setObject(colorObj);

		numDataFn.getData(tmpColor.r, tmpColor.g, tmpColor.b);

		if(tmpColor != vtxColor2)
		{
			vtxColor2 = tmpColor;
			
			listNeedsUpdate = true;
		}

	}


	//jetzt noch die Node ermuntern, die comuteMethode aufzurufen
	plug.setAttribute(vtxLocations);
	bool dummy;
	plug.getValue(dummy);


	//vtxWeights müssen gesetzt sein
	if(vtxWeightArray.length() == 0)
		return;



	//MeshData holen
	plug.setAttribute(inputMesh);
	
	MObject meshData;
	plug.getValue(meshData);


	visualizeMeshNode::meshStatus mStat = getMeshStatus();

	// Wenn sich der Anezigstatus des Meshes ändert, dann muss die DisplayList neu erstellt werden
	// Nur um den PolygonOffset zu aktualisieren
	if(mStat != lastStat)
	{
		lastStat = mStat;

		listNeedsUpdate;
	}

	//if( mStat == kNone)	// Nichts zeichnen, wenn nix selected
	//	return;




	view.beginGL(); 
//	view.beginOverlayDrawing(); 
	
	
	//Im PointMode werden PointsGezeigt, und wenn das Objekt selected ist (dann funzt shaded nicht mehr)
	if( style == M3dView::kPoints || (mStat == kSelected ) || wasInCompute || !allowBeautyMode)
	{

		//VertiIter initialisieren
		MItMeshVertex vertIter(meshData);
		
		drawPoints(vertIter, fPointSize);
		
		// Das updaten der DisplayLists ist zu langsam, weshalb automatisch vtxMode genommen wird
		wasInCompute = false;

	}
	else
	{//in diesem Modus werden Faces gezeichnet, mit entsprechenden alphawerten als zeichen ihrer Farbe
		
		MItMeshPolygon polyIter(meshData);
		MItMeshVertex	vertIter(meshData);
		


		//Die displayList prüfen
		if( (listNeedsUpdate & !wasInCompute) || lastDMode != style )
		{//neue Liste erzeugen - wird eigentlich nur einmal pro drawAktion gemacht
			
			lastDMode = style;

			if( list != 450000 ) 
				//alte liste löschen
				glDeleteLists(list, 1);
			
			list = glGenLists(1);

			if(glIsList(list))
			{
				listNeedsUpdate = wasInCompute = false;


				//#######################
				//NEUE LISTE AUFZEICHNEN
				//#######################
				glNewList(list, GL_COMPILE_AND_EXECUTE);

		
				//drawShaded(polyIter, vertIter, style, mStat);
				drawShadedTriangles(polyIter, vertIter, style, mStat);


				//#######################
				//ENDE LISTE AUFZEICHNEN
				//#######################

				glEndList();

			}
			else
			{
				//fehler, also alles ohne displayList zeichnen
				//drawShaded(polyIter, vertIter, style, mStat);
				drawShadedTriangles(polyIter, vertIter, style, mStat);
			}

		}
		else 
		{
			glCallList(list);
			wasInCompute = false;
		}

	}



	view.endGL();
//	view.endOverlayDrawing();
}
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;
}