MStatus polyModifierCmd::doModifyPoly() { MStatus status = MS::kFailure; if( isCommandDataValid() ) { // Get the state of the polyMesh // collectNodeState(); if( !fHasHistory && !fHasRecordHistory ) { MObject meshNode = fDagPath.node(); // Pre-process the mesh - Cache old mesh (including tweaks, if applicable) // cacheMeshData(); cacheMeshTweaks(); // Call the directModifier // status = directModifier( meshNode ); } else { MObject modifierNode; createModifierNode( modifierNode ); initModifierNode( modifierNode ); status = connectNodes( modifierNode ); } } return status; }
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; }
// -------------------------------------------------------------------------------------------- MStatus polyModifierCmd::doModifyPoly() // -------------------------------------------------------------------------------------------- { MStatus status = MS::kFailure; if( isCommandDataValid() ) { // Get the state of the polyMesh // collectNodeState(); if( !fHasHistory && !fHasRecordHistory ) { MObject meshNode = fDagPath.node(); // Pre-process the mesh - Cache old mesh (including tweaks, if applicable) // cacheMeshData(); cacheMeshTweaks(); // Call the directModifier // status = directModifier( meshNode ); } else { MObject modifierNode; createModifierNode( modifierNode ); initModifierNode( modifierNode ); status = connectNodes( modifierNode ); MFnDependencyNode depNodeFn(modifierNode); MString newName; getModifierUINodeName(newName); depNodeFn.setName(newName); //jetzt noch die customAttributes nonKeyable machen //koennte zu fehlern führen bei undo und redo ->tuts aber nicht :) if(createAnimCurves) {//diese Attribute koennen nur gesetzt werden, wenn eine BPTNode erstellt wird depNodeFn.findPlug("customSlFalloff").setKeyable(false); } // Selection vorher frei machen, weil unter umstnden noch eine parameter gewhlt war, welcher // dann verhindert, dass die Channelbox den neuen anzeigt // MGlobal::clearSelectionList(); //jetzt die Node auf die SelectionList setzen/hinzufügen MGlobal::select(modifierNode); } } return status; }