//- // ========================================================================== // Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved. // // Use of this software is subject to the terms of the Autodesk // license agreement provided at the time of installation or download, // or which otherwise accompanies this software in either electronic // or hard copy form. // ========================================================================== //+ // // File: splitUVCmd.cpp // // MEL Command: splitUV // // Author: Lonnie Li // #include "splitUVCmd.h" #include "splitUVNode.h" // Function Sets // #include <maya/MFnDependencyNode.h> #include <maya/MFnMesh.h> #include <maya/MFnSingleIndexedComponent.h> // Iterators // #include <maya/MItSelectionList.h> #include <maya/MItMeshPolygon.h> // General Includes // #include <maya/MGlobal.h> #include <maya/MSelectionList.h> #include <maya/MPlug.h> #include <maya/MIOStream.h> // Status Checking Macro - MCheckStatus (Debugging tool) // #define MCheckStatus(status,message) \ if( MS::kSuccess != status ) { \ cerr << message << "\n"; \ return status; \ } splitUV::splitUV() // // Description: // splitUV constructor // {} splitUV::~splitUV() // // Description: // splitUV destructor // {} void* splitUV::creator() // // Description: // this method exists to give Maya a way to create new objects // of this type. // // Return Value: // a new object of this type // { return new splitUV(); } bool splitUV::isUndoable() const // // Description: // this method tells Maya this command is undoable. It is added to the // undo queue if it is. // // Return Value: // true if this command is undoable. // { return true; } MStatus splitUV::doIt( const MArgList& ) // // Description: // implements the MEL splitUV command. // // Arguments: // args - the argument list that was passes to the command from MEL // // Return Value: // MS::kSuccess - command succeeded // MS::kFailure - command failed (returning this value will cause the // MEL script that is being run to terminate unless the // error is caught using a "catch" statement. // { MStatus status; // Parse the selection list for objects with selected UV components. // To simplify things, we only take the first object that we find with // selected UVs and operate on that object alone. // // All other objects are ignored and return warning messages indicating // this limitation. // MSelectionList selList; MGlobal::getActiveSelectionList( selList ); MItSelectionList selListIter( selList ); selListIter.setFilter( MFn::kMesh ); // The splitUV node only accepts a component list input, so we build // a component list using MFnComponentListData. // // MIntArrays could also be passed into the node to represent the uvIds, // but are less storage efficient than component lists, since consecutive // components are bundled into a single entry in component lists. // MFnComponentListData compListFn; compListFn.create(); bool found = false; bool foundMultiple = false; for( ; !selListIter.isDone(); selListIter.next() ) { MDagPath dagPath; MObject component; selListIter.getDagPath( dagPath, component ); // Check for selected UV components // if( component.apiType() == MFn::kMeshMapComponent ) { if( !found ) { // The variable 'component' holds all selected components on the selected // object, thus only a single call to MFnComponentListData::add() is needed // to store the selected components for a given object. // compListFn.add( component ); // Copy the component list created by MFnComponentListData into our local // component list MObject member. // fComponentList = compListFn.object(); // Locally store the actual uvIds of the selected UVs so that this command // can directly modify the mesh in the case when there is no history and // history is turned off. // MFnSingleIndexedComponent compFn( component ); compFn.getElements( fSelUVs ); // Ensure that this DAG path will point to the shape of our object. // Set the DAG path for the polyModifierCmd. // dagPath.extendToShape(); setMeshNode( dagPath ); found = true; } else { // Break once we have found a multiple object holding selected UVs, since // we are not interested in how many multiple objects there are, only // the fact that there are multiple objects. // foundMultiple = true; break; } } } if( foundMultiple ) { displayWarning("Found more than one object with selected UVs - Only operating on first found object."); } // Initialize the polyModifierCmd node type - mesh node already set // setModifierNodeType( splitUVNode::id ); if( found ) { if( validateUVs() ) { // Now, pass control over to the polyModifierCmd::doModifyPoly() method // to handle the operation. // status = doModifyPoly(); if( status == MS::kSuccess ) { setResult( "splitUV command succeeded!" ); } else { displayError( "splitUV command failed!" ); } } else { displayError( "splitUV command failed: Selected UVs are not splittable" ); status = MS::kFailure; } } else { displayError( "splitUV command failed: Unable to find selected UVs" ); status = MS::kFailure; } return status; } MStatus splitUV::redoIt() // // Description: // Implements redo for the MEL splitUV command. // // This method is called when the user has undone a command of this type // and then redoes it. No arguments are passed in as all of the necessary // information is cached by the doIt method. // // Return Value: // MS::kSuccess - command succeeded // MS::kFailure - redoIt failed. this is a serious problem that will // likely cause the undo queue to be purged // { MStatus status; // Process the polyModifierCmd // status = redoModifyPoly(); if( status == MS::kSuccess ) { setResult( "splitUV command succeeded!" ); } else { displayError( "splitUV command failed!" ); } return status; } MStatus splitUV::undoIt() // // Description: // implements undo for the MEL splitUV command. // // This method is called to undo a previous command of this type. The // system should be returned to the exact state that it was it previous // to this command being executed. That includes the selection state. // // Return Value: // MS::kSuccess - command succeeded // MS::kFailure - redoIt failed. this is a serious problem that will // likely cause the undo queue to be purged // { MStatus status; status = undoModifyPoly(); if( status == MS::kSuccess ) { setResult( "splitUV undo succeeded!" ); } else { setResult( "splitUV undo failed!" ); } return status; } MStatus splitUV::initModifierNode( MObject modifierNode ) { MStatus status; // We need to tell the splitUV node which UVs to operate on. By overriding // the polyModifierCmd::initModifierNode() method, we can insert our own // modifierNode initialization code. // MFnDependencyNode depNodeFn( modifierNode ); MObject uvListAttr; uvListAttr = depNodeFn.attribute( "inputComponents" ); // Pass the component list down to the splitUV node // MPlug uvListPlug( modifierNode, uvListAttr ); status = uvListPlug.setValue( fComponentList ); return status; } MStatus splitUV::directModifier( MObject mesh ) { MStatus status; fSplitUVFactory.setMesh( mesh ); fSplitUVFactory.setUVIds( fSelUVs ); // Now, perform the splitUV // status = fSplitUVFactory.doIt(); return status; } // Private Methods // bool splitUV::validateUVs() // // Description: // // Validate the UVs for the splitUV operation. UVs are valid only if they are shared // by more than one face. While the splitUVNode is smart enough to not process the // split if a UV is not splittable, a splitUV node is still created by the polyModifierCmd. // So call this method to validate the UVs before calling doModifyPoly(). // // validateUVs() will return true so long as there is at least one valid UV. It will // also prune out any invalid UVs from both the component list and UVId array. // { // Get the mesh that we are operating on // MDagPath dagPath = getMeshNode(); MObject mesh = dagPath.node(); // Get the number of faces sharing the selected UVs // MFnMesh meshFn( mesh ); MItMeshPolygon polyIter( mesh ); MIntArray selUVFaceCountArray; int i; int j; int count = 0; int selUVsCount = fSelUVs.length(); for( i = 0; i < selUVsCount; i++ ) { for( ; !polyIter.isDone(); polyIter.next() ) { if( polyIter.hasUVs() ) { int polyVertCount = polyIter.polygonVertexCount(); for( j = 0; j < polyVertCount; j++ ) { int UVIndex = 0; polyIter.getUVIndex(j, UVIndex); if( UVIndex == fSelUVs[i] ) { count++; break; } } } } selUVFaceCountArray.append(count); } // Now, check to make sure that at least one UV is being shared by more than one // face. So long as we have one UV that we can operate on, we should proceed and let // the splitUVNode ignore the UVs which are only shared by one face. // bool isValid = false; MIntArray validUVIndices; for( i = 0; i < selUVsCount; i++ ) { if( selUVFaceCountArray[i] > 1 ) { isValid = true; validUVIndices.append(i); } } if( isValid ) { pruneUVs( validUVIndices ); } return isValid; } MStatus splitUV::pruneUVs( MIntArray& validUVIndices ) // // Description: // // This method will remove any invalid UVIds from the component list and UVId array. // The benefit of this is to reduce the amount of extra processing that the node would // have to perform. It will result in less iterations through the mesh as there are // less UVs to search for. // { MStatus status; unsigned i; MIntArray validUVIds; for( i = 0; i < validUVIndices.length(); i++ ) { int uvIndex = validUVIndices[i]; validUVIds.append( fSelUVs[uvIndex] ); } // Replace the local int array of UVIds // fSelUVs.clear(); fSelUVs = validUVIds; // Build the list of valid components // MFnSingleIndexedComponent compFn; compFn.create( MFn::kMeshMapComponent, &status ); MCheckStatus( status, "compFn.create( MFn::kMeshMapComponent )" ); status = compFn.addElements( validUVIds ); MCheckStatus( status, "compFn.addElements( validUVIds )" ); MObject component = compFn.object(); // Replace the component list // MFnComponentListData compListFn; compListFn.create(); status = compListFn.add( component ); MCheckStatus( status, "compListFn.add( component )" ); fComponentList = compListFn.object(); return status; }
Autodesk® Maya® 2009 © 1997-2008 Autodesk, Inc. All rights reserved. | Generated with 1.5.6 |