Upload
duongkhanh
View
250
Download
3
Embed Size (px)
Citation preview
Introduction to the MayaC++ API
Tuesday, 17 April 12
API Basics
• Maya has both a python and a C++ API
• In most cases either can be used to accomplish tasks
• For this lecture we will look at the C++ API
• There are a series of headers and libraries shipped with maya which allow us to write plugins
• These come in many forms and will be discussed today
Tuesday, 17 April 12
C++ API• The maya api uses inheritance to extend the basic
functionality of maya.
• There are a number of different class types we can work with and these will change depending upon the context
Tuesday, 17 April 12
MFn function Sets• “Set of functions” for creating, querying, and operating on a type of object
• MFnCamera
• MFnLight
• MFnFluid
• MFnPlugin
• MFnNurbsSurface
• MFnDagNode (DagNode has visible component in UI)
• MFnDependencyNode (dependency node has no visible component in UI)
• An object can be compatible with more than one type of function set . . .
• Example: a NURBS object is compatible with/can be operated on by MFnNurbsSurface, MFnDagNode, MFnDependencyNode etc.
Tuesday, 17 April 12
Proxy MPx• Base classes inherited to define new types of Maya objects
• Examples:
• MPxCommand – define new commands
• MPxNode – define new (generic) nodes
• MPxDeformerNode – define deformer type
• MPxIkSolver – define new IK solver
• MPxFileTranslator – define file exporter
• Proxies understand Maya’s internals; developer implement the new/unique features
Tuesday, 17 April 12
Iterators MIt
• Used to traverse a category of objects
• Examples:
• MItKeyframe – iterate over keyframes of anim curve
• MItSurfaceCV
• MItCurveCV
• MItDependencyGraph – iterate over all nodes (in)directly connected to a given node
• MItDependencyNodes – traverse all the nodes in Maya’s Dependency Graph
Tuesday, 17 April 12
Utility Classes• MGlobal – a static class. Members perform mostly
UI-related tasks
• MStatus – passes return status codes (always check)
• MString
• MVector
• MDagPath
Tuesday, 17 April 12
MObject• Is a handle/reference to a Maya internal object
• Valid use: determine object type and compatible function sets
• Maya controls the deletion of MObjects
• NEVER store an MObject – use immediately
• MDagPaths can be stored
Tuesday, 17 April 12
Getting Started• Maya plugins are built as platform specific shared
libraries, (.so, .dll , .bundle)
• Under mac/linux we must use the same version of the compiler as used to build maya to avoid linker problems with the standard libraries
• Linux: stdout is directed to shell (where goMaya was called in the case of the studio)
• Windows: stdout is directed to an output window
• General: stdout may not appear unless flushed
Tuesday, 17 April 12
mayald• mayald is a shell script shipped with maya to simplify
the building of maya plugins / projects
• It contains commands / paths to use when building maya plugins
• It also links against all of the libraries required for every type of maya application we may wish to build
• It is found in /usr/autodesk/maya/bin in the current lab build
Tuesday, 17 April 12
Qt Project• To help aid with development I have created a basic
qt .pro file which will allow for maya plugin development
• At present it works for both mac and linux and will select the correct versions of the compiler etc bases on the platform
• This gives the advantage of using the Qt IDE for our development.
Tuesday, 17 April 12
# These are the maya libs we need to link to, this will change depending# upon which maya framework we use, just add them to the end of# this list as required and they will be added to the buildMAYALIBS=-lOpenMaya \
-lFoundation
LIBS=-L${MAYA_LOCATION}/lib \-lOpenMayalib \-lOpenMaya \-lAnimSlice \-lDeformSlice \-lModifiers \-lDynSlice \-lKinSlice \-lModelSlice \-lNurbsSlice \-lPolySlice \-lProjectSlice \-lImage \-lShared \-lTranslators \-lDataModel \-lRenderModel \-lNurbsEngine \-lDependEngine \-lCommandEngine \-lFoundation \-lIMFbase \-lm -ldl
;;
mayald by default adds all theselibs
the Qt project will need them adding when required
Tuesday, 17 April 12
A Simple Maya Command• The following example will create and register a
simple maya command
• We are going to use a macro supplied with the maya API which will create the correct class / code we require
• This is the simplest possible way and is good for quick command development
Tuesday, 17 April 12
#define DeclareSimpleCommand( _className, _vendor, _version ) \
#include <maya/MSimple.h>#include <maya/MIOStream.h>#include <maya/MGlobal.h>
// This is a macro to create a simple command
// the compiler expands it to a bunch of code
DeclareSimpleCommand( HelloMaya , "NCCA", "Maya 2011");
MStatus HelloMaya::doIt( const MArgList& ){std::cout<<"This should come from the shell\n";MGlobal::displayInfo("Hello Maya in the maya command shell");return MS::kSuccess;
}
name of command who wrote it maya version
Tuesday, 17 April 12
Loading Plugin• To load the plugin select
• Windows->Settings/Preferences->Plugin-Manager
• Click browse and find the plugin in your file system
• Click on the and you will see the info
Tuesday, 17 April 12
running the command
import maya.cmds as cmdscmds.HelloMaya()
HelloMaya
python
mel
Tuesday, 17 April 12
MPxCommand• The MPxCommand class is used to create our own
command
• Each command is derived from this one, and must have a doIt method
• optionally we can also implement an undoIt and redoIt method to allow us to hook into the maya undo / redo system
Tuesday, 17 April 12
customCreateSphere• This command will generate a number of random
spheres based on a user argument
Tuesday, 17 April 12
CustomSphere
• We will implement the following virtual methods from the MPxCommand class
• the main code for executing the command will be placed in the redoIt and called from the doIt method when constructed
• As we have no dynamic memory we don’t actually use the dtor.
+ ~CustomSphere+ doIt( _args : MArgList& ) : MStatus+ redoIt() : MStatus+ undoIt() : MStatus+ isUndoable() : bool+ creator() : static void*
- m_count : uintCustomSphere
MPxCommand
Tuesday, 17 April 12
Utility macros
• This macro makes it easy to check for errors and will be replaced by the compiler every time we use it.
/// @brief simple macro to check status and return if error
/// originally written by Sola Aino
#define CHECK_STATUS_AND_RETURN_IF_FAIL( stat , message ) \if( !status ) \{ \MString errorString = status.errorString() + MString( message); \MGlobal::displayError( errorString ); \return MStatus::kFailure; \
} \
Tuesday, 17 April 12
Basic MethodsCustomSphere::˜CustomSphere()
{
// as we have no dynamic allocation
// we don't need to do anything here
}
bool CustomSphere::isUndoable() const
{
return true;
}
void
*
CustomSphere::creator()
{
return new CustomSphere();
}
Note the creatormethod is called by maya and we use it to call our
ctor
Tuesday, 17 April 12
doIt method• the doIt method will be passed any arguments
passed when the command is invoked.
• It is the responsibility of the doIt command to parse these and store in the class any values which may be required for do / undo.
• Arguments are processed by the MArgList class as shown in the following example
Tuesday, 17 April 12
MStatus CustomSphere::doIt( const MArgList& _args )
{
MStatus status;
// Verify argument count
if ( _args.length() != 1 )
{
MGlobal::displayError( "Command requires one argument" );
return MStatus::kFailure;
}
// Check aurgument type
m_count = _args.asInt( 0, &status );
if( !status )
{
MGlobal::displayError( "argument is not an integer" );
return MStatus::kFailure;
}
// Check argument range
if( m_count <= 0 )
{
MGlobal::displayError( "argument must be greater than zero" );
return MStatus::kFailure;
}
// now call the redoIt method which actually does the work
return redoIt();
}
Tuesday, 17 April 12
redoIt method• In this case the redoIt method will do the creation
of the spheres
• This will loop for the number of times specified on the command line, and execute a maya command to create a sphere with a random radius
• Next a move command will be executed to move the sphere to a random position
• For ease boost::format is used to form the format strings.
Tuesday, 17 April 12
MStatus CustomSphere::redoIt(){// loop for the number of arguments passed in and create some random spheres
for( unsigned int i = 0; i < m_count; ++i ){// fist I'm going to create a maya command as follows
// sphere -name "sphere[n]" where n is the value of i
std::string cmd;float rad=randFloat(0.2,2.5);cmd=boost::str(boost::format("sphere -name \"sphere%d\" -r %f") %i %rad) ;// now execute the command
MStatus status = MGlobal::executeCommand( cmd.c_str() );// and check that is was succesfull
CHECK_STATUS_AND_RETURN_IF_FAIL(status,"Unable to execute sphere command");
// now move to a random position first grab some positions
float x=randFloat(-20,20);float y=randFloat(-20,20);float z=randFloat(-20,20);// build the command string
// move x y z "sphere[n]"cmd=boost::str(boost::format("move %f %f %f \"sphere%d\"") %x %y %z %i) ;// execute
status=MGlobal::executeCommand(cmd.c_str());CHECK_STATUS_AND_RETURN_IF_FAIL(status,"unable to move object");
}std::string mesg=boost::str(boost::format("%d Spheres created") %m_count) ;MGlobal::displayInfo( mesg.c_str() );return MStatus::kSuccess;
}
Tuesday, 17 April 12
MStatus CustomSphere::undoIt(){// here we undo what was done in the re-do method,
// this will be called when maya calles the undo method
for( unsigned int i = 0; i < m_count; ++i ){std::string cmd;// delete the objects as created previously
cmd=boost::str(boost::format("delete \"sphere%d\"") %i) ;MStatus status=MGlobal::executeCommand(cmd.c_str());// check that is was ok
CHECK_STATUS_AND_RETURN_IF_FAIL(status,"unable to delete objects in undo");
}return MStatus::kSuccess;
}
float randFloat(float _min, float _max){return ((_max-_min)*((float)rand()/RAND_MAX))+_min;}
Tuesday, 17 April 12
plugin code• to register our command we need to add some
plugin code to allow the register / deregister of the plugin
• This is as followsMStatus initializePlugin( MObject obj ){MStatus status;MFnPlugin plugin( obj, "", "NCCA" , "Any" );
status = plugin.registerCommand( "customCreateSphere", CustomSphere::creator );if ( !status ){status.perror( "Unable to register command \"customCreateSphere\"" );return status;
}
return status;}
Tuesday, 17 April 12
MStatus uninitializePlugin( MObject obj ){MStatus status;MFnPlugin plugin( obj );
status = plugin.deregisterCommand( "customCreateSphere" );if ( !status ){status.perror( "Unable to register command \"customCreateSphere\"" );return status;
}
return status;}
import maya.cmds as cmds
cmds.customCreateSphere(300)
Tuesday, 17 April 12
Exercise• Using the maya api documentation for MArgList
modify the customCreateSphere plugin to take the following arguments
• -mr [double] the minimum radius must be >0
• -mm [double] the max radius
• -x [double] the ±x extents
• -y [double] the ±y extents
• -z [double] the ±z extents
• -n [int] the number of spheres to create
import maya.cmds as cmds
cmds.customCreateSphere(n=300,mr=0.1,mm=2,x=2,y=5,z=20)
Tuesday, 17 April 12
Hint• You will need to add class attributes for each of
the new parameters, there is quite a lot of sample code in the MArgList class you can use.
• If you want a more advanced solution follow this tutorial http://nccastaff.bournemouth.ac.uk/jmacey/RobTheBloke/www/maya/MSyntax.html
• Solution next week (mine is based on the above)
Tuesday, 17 April 12
references• Introduction to the Maya API Sola Aina
NCCA 2011
• Autodesk Maya 2011 help
Tuesday, 17 April 12