Here is a plugin I wrote as a start for a corrective sculpting tool. It doesn't have undo yet.
I also included some intro api coding tips I wrote. Hope they are helpful.
/**@file printVertexSubtractCmd.cpp @note select two polygon and type in mel -- printVertexSubtractCmd; it will print for all vertices in order the vertex first poly minus vertex second poly. (local position difference) @author Nathaniel O. Anozie (ogbonnawork at gmail dot com) @note Modify at your own risk @note date created: 07/18/2013 */ #include#include #include #include #include #include #include DeclareSimpleCommand( printVertexSubtractCmd, "Nathaniel Anozie", "1.0"); MStatus printVertexSubtractCmd::doIt( const MArgList& ) { MStatus stat; //------get the two polygons selected MSelectionList selList; stat = MGlobal::getActiveSelectionList(selList); if(MS::kSuccess != stat){ MGlobal::displayError("Needs two Polygons selected !!!\n"); return stat; } //need two things if( selList.length() != 2 ){ MGlobal::displayError("Needs two Polygons selected !!!\n"); return stat; } //make sure selected are polygons, needed to tell the number of vertices of polygon MDagPath firstPath; //hold path stat = selList.getDagPath(0, firstPath); if(MS::kSuccess != stat){ MGlobal::displayError("Needs two Polygons selected !!!\n"); return stat; } if( firstPath.hasFn(MFn::kMesh) ){} else{ MGlobal::displayError("Needs two Polygons selected !!!\n"); return MS::kFailure; } MDagPath secondPath; //hold path stat = selList.getDagPath(1, secondPath); if(MS::kSuccess != stat){ MGlobal::displayError("Needs two Polygons selected !!!\n"); return MS::kFailure; } if( secondPath.hasFn(MFn::kMesh) ){} else{ MGlobal::displayError("Needs two Polygons selected !!!\n"); return MS::kFailure; } //-------- //---make sure selected have identical number of vertices, kind of like making sure they have same topology but not really //first poly data int firstNumVtx; //hold number of vertices MFnMesh firstMeshFn( firstPath ); //make and set function set used to get vertex info firstNumVtx = firstMeshFn.numVertices(); MGlobal::displayInfo(MString("Poly Number of Vertices Are:")+firstNumVtx+"\n"); //second poly data int secondNumVtx; //hold number of vertices MFnMesh secondMeshFn( secondPath ); //make and set function set used to get vertex info secondNumVtx = secondMeshFn.numVertices(); if(firstNumVtx != secondNumVtx){ MGlobal::displayError("Requires Identical Number Vtx of Selected!!!\n"); return MS::kFailure; } //--- //---all is good so store local positions for both selected things //result data MPoint* result;//will hold the result delete [] result; result = new MPoint[firstNumVtx]; //first vertex data MPoint* firstLocalVtxPositions; delete [] firstLocalVtxPositions; firstLocalVtxPositions = new MPoint[firstNumVtx]; MObject firstVtx; //hold each vertex int i = 0; //hold index we will use soon MItMeshVertex firstVtxIter( firstPath, firstVtx, &stat); if( MS::kSuccess == stat ){ i=0; for( ; !firstVtxIter.isDone(); firstVtxIter.next() ){ firstLocalVtxPositions[i] = firstVtxIter.position( MSpace::kObject); //local space i++; } } else{ MGlobal::displayError("Vertex Iterator Error!!!\n"); return stat; } //second vertex data MPoint* secondLocalVtxPositions; delete [] secondLocalVtxPositions; secondLocalVtxPositions = new MPoint[secondNumVtx]; MObject secondVtx; MItMeshVertex secondVtxIter( secondPath, secondVtx, &stat); if( MS::kSuccess == stat ){ i=0; for( ; !secondVtxIter.isDone(); secondVtxIter.next() ){ secondLocalVtxPositions[i] = secondVtxIter.position( MSpace::kObject); //local space i++; } } else{ MGlobal::displayError("Vertex Iterator Error!!!\n"); return stat; } //----- //compute result i = 0; MPoint a; MPoint b; MPoint diff; for( i = 0; i < firstNumVtx; i++) { a = firstLocalVtxPositions[i]; b = secondLocalVtxPositions[i]; //first poly minus second poly //if used MPoint minus MPoint would get an MVector a little more to do diff.x = a.x - b.x; diff.y = a.y - b.y; diff.z = a.z - b.z; result[i] = diff; MGlobal::displayInfo(MString("Vtx Differences Are:") + diff.x + "," + diff.y + "," + diff.z + "\n"); } return stat; }
Some intro API coding tips,
1. Taking screengrabs of parts of plugins
take screenshots of particular parts of plugins so they can be accessed for quickly studying later. (example main parts of a command doIt,initializePlugin ..., or node.. create, initialize …)
I made folder for Node, and Commands and in them have all the needed parts labeled sometimes by their function name. Its helpful to have the class declaration and the main use of the function in one place.
2. Finding how to use API function tip
duplicate Autodesk tutorial devkit sample code into a new folder. Then to search for how to use certain function could type in terminal
grep -n 'greatDayThisIscodeLookingFor' *
it gives us all line numbers and files that use the greatDayThisIscodeLookingFor
3. Header tip
after writing command etc, can go through all the objects used and do includes using that objects name with a .h at end. most of the time the header is named the same as when created the object.
4. Using API docs
google search class name to find api docs on all the functions that class has. Sometimes there are even more if the class inherits other functions. Then with the function we need can do the (tip on finding use of function) to see how its used in real examples.
5. Start with DeclareSimpleCommand
When writing first commands use MSimple.h. It helps eliminate alot of extra stuff so can start writing code.
6. template Make File
Have a template make file, there are lots of examples on google. This way just need to change .cpp name … bundle name to compile and build plugin.
7. Finding API Type Constants
To find constants ex: what is local space. First google the class with the function. Then in API docs find the function and read the class that has that argument. Then google that class and open the API docs. It should be easy to find that the local space is kObject.
cheers,
Nate