西青房地产网站建设,可以看电视剧的网站,网站的开发建设费,如何在电脑上做物流网站Maya开发#xff08;一#xff09;-- 绪论 #xff08;翻译自Maya官方文档#xff09;2008-05-09 15:33        绪论     Autodesk Maya 是一个开放的产品,就是说任何Autodesk以外的人都可以改变Maya现有的特征,或者 增加新的特性.你可以用两个方法来修改MAYA:          ME…Maya开发一-- 绪论 翻译自Maya官方文档2008-05-09 15:33        绪论     Autodesk® Maya® 是一个开放的产品,就是说任何Autodesk以外的人都可以改变Maya现有的特征,或者 增加新的特性.你可以用两个方法来修改MAYA:          MEL™ -- (Maya Embedded Language Maya内嵌语言)这是一个强大又简单易学的脚本语言.可以完成大部分的操作。     Python™-- 这是一个强大又简单易学的脚本语言提供了Maya命令接口。     API -- (Application Programmer Interface 应用程序接口)可以提供比MEL更好的性能实现.你可以用API向MAYA         中增加新的对象,而代码执行的速度差不多比MEL执行同样的工作快10倍.当然你可以从API里执行MEL代码.     Maya Python API -- 基于API允许通过Python脚本语言来使用API。                   总览     MAYA API是一种提供了访问MAYA内部特性的C API.在以下平台下都有实现:Microsoft® Windows®, Linux®,  and Apple® Mac OS® X. 你可以利用API来实现两种代码资源:扩展MAYA功能的plug-ins,或者一个可以用来访问和 操作MAYA模型的独立应用程序.          Plug-ins被建成利用标准系统的功能载入MAYA的动态可重定位的库.Plug-ins通过访问宿主程序MAYA的代码空间 来工作,但不能访问其他被载入的Plug-ins的代码空间. 根据操作系统的不同,对于建立和命名Plug-ins也有些限制.因此Plug-ins程序的后缀在各个平台上也是不同的. MAYA使用的Plug-ins为:         * Linux: .so         * Windows: .mll         * Mac OS X: .lib 开发工具     MAYA API被放在MAYA安装目录中的开发者工具目录中.有一些平台默认是不安装开发者工具的.这种情况下你需要在 安装MAYA的时候进行特别指定需要安装开发者工具.开发者工具主要由3个部分组成:包含头文件,库文件和用例. Include Files     我们提供了一些头文件作为MAYA的接口.头文件存放在开发者工具目录中的include/maya中.MAYA的头文件一般以 M开头.跟在M后面的名字表示的类型有:Fn表示函数集,It表示迭代器,Px 表示代理类.          Libraries     API被封装成MAYA各种相应功能领域的库中.这些库有:                  OpenMaya - 包含了基本类,定义了节点和命令,并装配他们进Plug-ins.         OpenMayaUI - 包含了生成新的用户界面的类,比如控制器,上下文菜单和定位器等;         OpenMayaAnim - 包含了动画类,包括造型和反向动力学.         OpenMayaFX - Autodesk® Dynamics™类         OpenMayaRender - 渲染类     这些都是共享库,所以可以被若干个Plug-ins同时使用.库文件存放在lib目录中.          Examples     MAYA API的用例程序包含在devkit目录中.有application和plug-ins两个文件夹.application里包含了 独立应用程序的例子,而plug-ins则包含了插件的例子.制作应用程序和插件的方法在不同的平台有些不同.一般情况下 可以使用MakeFiles文件.在Windows和Max OS X下我们为大部分用例提供了IDE的工程. Documentation     我们提供了丰富的MAYA API的文档资料.主要由两部分组成:         * This technical introduction to the Maya API    技术解说         * The API class descriptions                    类参考     根据文档可以了解以下内容:         * The MEL and Expressions guide             MEL和表达式指南         * The Maya MEL command reference             MEL命令参考         * The Maya Nodes and Attributes reference. Working with Maya nodes is a normal part of programming the Maya API             MAYA节点和属性参考.使用节点是MAYA API编程的普遍方法.         * The What’s New information provided with each release             每个发行版本的更新点         * The Release Notes that provide items of interest for developers             发行说明 可以通过MAYA HELP来访问这些资源(Help  Maya Help).          Other Requirements     既然MAYA API是C程序.那么你最好能理解以下内容:         * virtual functions             虚函数         * class inheritance (including multiple)             类继承(包括多态)         * stream classes             流类型         * operator methods(there are many operator methods in the Maya API)             操作符方法(MAYA里有很多操作符方法)      
// //     载入一个插件     有两个方法来载入或卸载插件.最简单的方法是使用插件管理器(Plug-in Manager). 从插件管理器载入插件:         1. 选择 Window  Settings/Preferences  Plug-in Manager 菜单来打开管理器窗口来显示已知插件列表.         2. 找到你需要的插件勾选上loaded或者auto load来载入插件.          插件管理器使用MAYA_PLUG_IN_PATH环境变量来定位有效的插件来载入.          MAYA_PLUG_IN_PATH只在管理器窗口第一次被打开的时候进行扫描定位,这是为了以后再次打开的时候能够加快速度.因此,如果 在MAYA运行的时候新建了一个插件,那有可能并不会在插件管理器内显示.访问新建的插件请参照以下方法之一:     * 点选管理器窗口中的Refresh(刷新)按钮来更新列表.可以使目录再次被扫描并更新列表中的内容.     * 使用loadPluginMEL命令.     * 重启Maya. 从命令行载入插件:     假设你有一个插件名字叫hello在MAYA_PLUG_IN_PATH目录内.你可以用MEL命令loadPlugin.         loadPlugin hello;     如果在LINUX平台下这会在MAYA_PLUG_IN_PATH位置寻找名叫hello.so的文件,Windows平台则是hellp.mll,而在Mac OS X下则是     hello.lib.一旦找到,则会作为一个插件被载入MAYA.      // //     卸载插件     通过MEL卸载一个插件很简单 -- 你可以使用unloadPlugin命令加插件名. 注意:     # 一个插件在被重编译前必须卸载,否则可能导致MAYA崩溃.     # 在你可以卸载一个插件前,你必须删除所有场景中使用到它的地方.在将插件中定义的节点从场景中删除前,还需要更新删除掉的         节点和执行过的UNDO队列命令中使用的引用.虽然这些内容不在场景中,但是为了UNDO,其实它还在那儿.     # 如果你在一个插件正在使用的时候强行卸载.那将无法再次载入插件节点.这是因为在场景中的节点会转换成Unknown节点,         然后在插件重载入的时候,将不被允许改变那些存在的节点的类型. // //     编写一个简单的插件     以下解说了如何编写一个简单的Hello world插件          编写你第一个插件     当学习一个新的计算机语言的时候,你常可以看到的第一个程序是Hello world.遵循这个传统,我们第一个插件就是Hello world. 只是在MAYA启动的时候简单得输出Hello world在窗口中. #include maya/MSimple.h          #include maya/MIOStream.h          DeclareSimpleCommand( helloWorld, Autodesk, 8.0);          MStatus helloWorld::doIt( const MArgList )          {              cout  “Hello World\n”;              return MS::kSuccess;          }               LINUX:     如果这些保存到一个helloWorld.cpp 文件中,那么可以被这样编译:         g402 -c -I. -I.. -I/usr/aw/maya8.0/include -I/usr/X11R6/include          -m32 -O3 -pthread -pipe -D_BOOL -DLINUX -DREQUIRE_IOSTREAM -         mtunepentium4 -Wno-deprecated -fno-gnu-keywords helloCmd.cpp          g402 -shared -m32 -O3 -pthread -pipe -D_BOOL -DLINUX -         DREQUIRE_IOSTREAM -mtunepentium4 -Wno-deprecated -fno-gnu-         keywords -Wl,-Bsymbolic -o helloCmd.so helloCmd.o -L/usr/aw/         maya8.0/lib -lOpenMaya -lFoundation               Windows和Mac OS X:     参考章节12,设定编译环境               一旦编译完成,你可以载入MAYA,在命令窗口内打入helloworld(按回车执行命令),然后Hello world会在输出窗口中显示.           // //     重要的插件特性     Hello world插件有几个重要的特性.          MSimlpe.h     为简单命令行插件使用的一个特殊的头文件.它利用DeclareSimpleCommand宏,接管了所有需要的工作来注册一个MAYA新命令,但是只能     创建一个插件来对应一个命令.          注意:         # 很可能并且也很普遍的是,编写一个插件来实现几个特性,就像依赖图节点和命令组.这样的插件就不能使用MSimple.h.             你必须编写自定义的注册代码来告诉MAYA插件的功能.         # 这个宏主要的限制就是你只能创建一个非UNDO的命令.              MStatus      指示一个方法是否成功或者失败.大部分方法都通过MStatus来返回一个状态代码,每一个方法的文档都详细介绍了可能的状态返回值.     为了避免和其他状态代码的命令空间冲突,所有的MStatus状态值都被MS所封装.比如MS::kSuccess是一个表示成功的代码.详细的列     表在MStatus.h内.          注意:         API使用很少的状态码,如果通过MGlobal::startErrorLogging()开启错误日志系统,则当一个方法返回非MS::kSuccess时,额外的错误         信息将被输出到日志文件中.              DeclareSimpleCommand      DeclareSimpleCommand 需要3个参数:类名,作为一个命令的实现.提供者名.命令的版本号.          MSimple.h内,DeclareSimpleCommand()宏省下了你自行编写注册代码的时候,为了保持简单性,你不能为这个命令使用UNDO方法. 所以你不能用这个宏生成一个真正的可以UNDO的命令          注意:     不管怎样,不支持UNDO的命令不能改变场景中的状态属性.它们可以去查询场景的不同视点位置而不能去改变它.如果一个非UNDO的命令确实     改变了什么,那么MAYA的UNDO功能就会被破坏.               编写一个可以和MAYA交互的插件     这和Hello world只有很少的差别.(既然hello world总是输出同样的内容,你或许像写一个可以和MAYA交互的插件.(其中一个方法是在MEL命令 行中增加参数))          下面是另一个简单的程序,在它的输入内容后打印Hello.              #include maya/MSimple.h          #include maya/MIOStream.h          DeclareSimpleCommand( hello, Autodesk, 8.0);          MStatus hello::doIt( const MArgList args )          {              cout  Hello   args.asString( 0 ).asChar()  endl;              return MS::kSuccess;          }                        当载入以后,输入命令hello neighbor则会输出Hello neighbor               MArgList     MArgList类提供了一种类似C和C程序入口中argc/argv参数的机能.提供一个参数列表给你的函数.类提供方法把参数作为各种类型来取得,     比如包括了integer,double,string,或者vector.          下面一个例子中,helix命令被定义成通过MArgList对象得到若干个参数.两个参数为pitch和radius.         #include math.h          #include maya/MSimple.h          #include maya/MIOStream.h          #include maya/MFnNurbsCurve.h          #include maya/MPointArray.h          #include maya/MDoubleArray.h          #include maya/MPoint.h          DeclareSimpleCommand( helix, Autodesk - Example, 3.0);          MStatus helix::doIt( const MArgList args )          {              MStatus stat;              const unsigned    deg      3;            // Curve Degree              const unsigned    ncvs      20;            // Number of CVs              const unsigned    spans      ncvs - deg;    // Number of spans              const unsigned    nknots     spans2*deg-1;// Number of knots              double    radius             4.0;            // Helix radius              double    pitch              0.5;            // Helix pitch              unsigned    i;              // Parse the arguments.              for ( i  0; i  args.length(); i )                  if ( MString( -p )  args.asString( i, stat )                           MS::kSuccess  stat)                  {                      double tmp  args.asDouble( i, stat );                      if ( MS::kSuccess  stat )                          pitch  tmp;                  }                  else if ( MString( -r )  args.asString( i, stat )                           MS::kSuccess  stat)                  {                      double tmp  args.asDouble( i, stat );                      if ( MS::kSuccess  stat )                          radius  tmp;                  }              MPointArray    controlVertices;              MDoubleArray knotSequences;              // Set up cvs and knots for the helix              //              for (i  0; i  ncvs; i)                  controlVertices.append( MPoint( radius * cos( (double)i ),                      pitch * (double)i, radius * sin( (double)i ) ) );              for (i  0; i  nknots; i)                  knotSequences.append( (double)i );              // Now create the curve              //              MFnNurbsCurve curveFn;              MObject curve  curveFn.create( controlVertices,                                              knotSequences, deg,                                                       MFnNurbsCurve::kOpen,                                              false, false,                                              MObject::kNullObj,                                              stat );              if ( MS::kSuccess ! stat )                  cout  Error creating curve.\n;              return stat;          }                        提醒:     和argc/argv一个重要的不同是,MArgList的第0个元素是命令之后的第一个参数,而不是像C和C那样是命令的名字.                    利用插件创建一个曲线     下面一个例子是用插件建立一个螺旋的曲线.         #include math.h          #include maya/MIOStream.h          #include maya/MSimple.h          #include maya/MPoint.h          #include maya/MPointArray.h          #include maya/MDoubleArray.h          #include maya/MFnNurbsCurve.h          DeclareSimpleCommand( doHelix, Autodesk - Example, 8.0);          MStatus doHelix::doIt( const MArgList )          {              MStatus stat;              const unsigned     deg        3;                 // Curve Degree              const unsigned     ncvs       20;                // Number of CVs              const unsigned     spans      ncvs - deg;        // Number of spans              const unsigned     nknots     spans2*deg-1;     // Number of knots              double     radius             4.0;               // Helix radius              double     pitch              0.5;               // Helix pitch              unsigned     i;              MPointArray     controlVertices;              MDoubleArray    knotSequences;              // Set up cvs and knots for the helix              //              for (i  0; i  ncvs; i)                  controlVertices.append( MPoint( radius * cos( (double)i ),                      pitch * (double)i, radius * sin( (double)i ) ) );              for (i  0; i  nknots; i)                  knotSequences.append( (double)i );              // Now create the curve              //              MFnNurbsCurve curveFn;              MObject curve  curveFn.create( controlVertices, knotSequences, deg,                                                 MFnNurbsCurve::kOpen, false, false,                                                  MObject::kNullObj, stat );              if ( MS::kSuccess ! stat )                  cout  “Error creating curve.\n”;              return stat;          }    和MAYA进行交互     MAYA的API包含了四种和MAYA进行交互的C对象.它们是:wrappers, objects, function sets, 和proxies.          API中的对象所有权     将一个对象和函数集进行联合有点类似wrappers.但区别是需要一样的对象所有权.在API中对象的所有权很重要.如果没有适当的定义,你可能 删除一个系统需要的东西.或者使用了一个系统已经删除了的内容.APIwrappers, objects,和function sets消除了关于所有权的问题. 因此潜在的在一个不适当的时候使用一个对象,比如在系统已经删除了它的时候.这种情况被避免了. // //     MObject      访问所有的MAYA对象(curves, surfaces, DAG nodes, dependency graph nodes, lights, shaders, textures, 等.)可以通过一个叫 MObject.的句柄对象.这个句柄通过一些简单的方法来帮助检测对象的类型.MObject析构函数并不删除它所指向的MAYA对象.调用MObject 的析构函数只是删除MObject对象本身,因此保护了对象所有权.          重要提醒:     你应该永远不在插件运行的时候保持一个指向MObject的指针.相代替的是,可以使用MObjectHandle,当这个对象包含了MObject有效信息的时候.      // //     Wrappers     Wrappers作为简单的对象存在,比如数学类(比如矢量或者矩阵),它们一般是带构造和析构的C类的完全实现.API方法可以返回一个wrapper, 你有责任在离开使用区间时删除这个wrapper.你也可以在需要的时候自由地申请释放它们.在前面的例子中MPointArray和MDoubleArray是 wrappers,你总是拥有你使用的wrappers. 重要提醒:     把wrappers的声明尽可能放在深度循环的外面.很多情况下wrappers的构造函数会申请分配MAYA内建类.因此如果在深度循环中声明wrapper ,     则wrapper 可能反复得被申请和释放内存.     此提醒不适用静态wrapper ,比如MGlobal.                // //     Objects and Function Sets (对象和函数集)     对象和函数集常常在一起被使用.他们被分成很容易建立所有权 -- 对象总是属于MAYA,函数集数总是属于你.          Function sets(函数集)     函数集是一种操作对象的C类.在前面用插件生成曲线的例子中,MFnNurbsCurve是一个函数集,(MFn前缀指明它)          通过两行代码生成曲线:         MFnNurbsCurve curveFn;          MObject curve  curveFn.create( ... );                   * MFnNurbsCurve curveFn; 创建一个包含了各种操作曲线对象方法的新函数集, 在这儿是为了生成新的曲线.         * MObject curve  curveFn.create( ... );创建一个新的MAYA曲线对象来使用.     如果你增加第三行: curve  curveFn.create( ... );           那第二条曲线就被创建并被curve对象所引用,第一条曲线依然存在,但是不在被MObject对象所指向.          Proxies(代理)     MAYA API通过Proxies对象来创建新的MAYA对象类型.Proxies是一个你创建但MAYA拥有的对象.          一个普遍的误解是你可以通过一个现有的函数集起源来创建一个新的对象类型.比如:MFnNurbsSurface起源于MFnDagNode,你可能会觉得     如果你让MySurface源自MFnDagNode,并且提供所有的对新类型面的操作方法,你可以给MAYA增加一个新的表面类.很不幸,这并不能工作.     你所得到的只是一个使用新方法操作现有对象新的函数集.记住,函数集完全属于你,而MAYA永远看不到也用不到他们.MAYA只能使用依赖于     MObject的对象.          Typelessness(轻类型)     对象和函数集分离的一个有趣的结果是API可以进行一个轻类型的操作.比如:         MFnNurbsCurve curveFn;          MObject curve  curveFn.create( ... );          MFnNurbsSurface surface( curve );               这段代码创建了一个曲线并把它传给一个曲面操作函数集.既然MFnNurbsSurface只能操作表面对象,上面的代码将什么都不做.但你可能根本不知道.     API的错误检测代码按预置处理这些错误.          函数集接受任何类型的MObjects对象,如果它们不能识别的话,无论你怎么试着操作他们都会忽略他们并且返回错误值.      
// //     命名规则(Naming Conventions)     MAYA用前缀来表示它的类类型.          MFn            任何使用这个前缀的类是可以操作一个具体MObjects类型的函数集.          MIt            这是一种迭代器,比函数集更多地和MObjects一起.比如MItCurveCV被用来操作单独的NURBS curve CV(而不是用MFnNurbsCurveCV),                 或者迭代所有在曲线上的的CV.          MPx            代理类,被设计成用来生成用户对象类型.          M            大部分这种类是一个Wrappers,比如函数集是操作MAYA的内部对象的,而MGlobal是一个静态方法类,用来操作全局内容,而不需要传入MObject.           // //     增加参数     螺旋插件生成一个简单的曲线,但是它总是输出同样的曲线.          给曲线例子增加参数.     你可以稍微修改一下代码,使你可以给曲线指定半径和倾斜度.修改函数定义,增加参数:         MStatus doHelix::doIt( const MArgList args )      在变量声明后面增加下面几行         // Parse the arguments.          for ( i  0; i  args.length(); i )              if ( MString( “-p” )  args.asString( i ) )                  pitch  args.asDouble( i );              else if ( MString( “-r” )  args.asString( i ) )                  radius  args.asDouble( i );                       这段程序读入参数,这样你可以用来改变生成的螺旋的半径和倾斜.这些修改是很简单的:     for循环查询所有的MArgList封装了的参数,两个if段转换当前的参数(变量i来指定访问)为MString(Maya的字符串封装),然后把他们和两个     参数标识相比较.     如果匹配,下一个参数转换成double并保存到相应的变量内.比如:         doHelix -p 0.5 -r 5      生成一个半径5个单位,倾斜为0.5个单位的螺旋.           // //     错误检测     例子已经做了很多的工作了,这时你还没有做一些错误检测.对于例子这没什么,不过当制作一个产品级的插件时,你真的需要做检测错误.          很多方法最后都带一个可选的参数.一个指向MStatus变量的指针,存放状态返回值.          如果你用以下代码替代螺旋例子中的参数分析代码,那么例子将检查并处理大部分可能的错误.              // Parse the arguments.          for ( i  0; i  args.length(); i )          if ( MString( “-p” )  args.asString( i, stat )                MS::kSuccess  stat )          {               double tmp  args.asDouble( i, stat );               // argument can be retrieved as a double               if ( MS::kSuccess  stat )                    pitch  tmp;          }          else if ( MString( “-r” )  args.asString( i, stat )                MS::kSuccess  stat )          {               double tmp  args.asDouble( i, stat );               // argument can be retrieved as a double               if ( MS::kSuccess  stat )                    radius  tmp;          }           增加在asString() 和asDouble() 方法里的stat参数可以检查类型转换操作是否成功.          比如,当索引大于参数个数的时候args.asString(i, stat)可能返回MS::kFailure.或者,参数不能转换成double的时候,     args.asDouble(i, stat)操作可能会失败.           // //     MStatus 类     MStatus类可以检测方法是否失败.          很多API的方法返回一个MStatus类的实例,或者把这实例传回给一个可选的参数.MStatus类包含了一个error方法,和一个被     重载了的操作bool,如果这实例是包含错误状态的话,以上两者都会被传会false.这意味着你可以很快得检查一个调用是否正确.     比如:         MStatus status  MGlobal::clearSelectionList();          if (!status) {              // Do error handling              ...          }               如果status包含错误信息的话,你可以做以下几件事:              * 用statusCode方法来得到MStatusCode的枚举来指出错误的原因.         * 用errorString方法来得到一个包含错误详细解释的MString.         * 用perror方法向标准错误输出错误的详细解释.或者是你预先提供的信息字符串.         * 用重载了的相等或不相等操作和一个特定的错误码相比较.         * 用clear方法重设置实例状态为成功. // //     错误日志     就想使用MStatus类一样,你可以用错误日志来检查API方法的错误.          有效或无效错误日志:     1.在MEL里,用带-errlog标志的openMayaPref命令.     2.在插件里,用MGlobal::startErrorLogging()和MGlobal::stopErrorLogging()方法.          一旦你有效了错误日志,MAYA生成一个日志文件,每次一个API方法失败的时候,MAYA将带有可以显示哪儿做了调用的小型堆跟踪的错误解释写入日志文件.     默认的文件是在当前目录中的OpenMayaErrorLog文件.这也是可以被修改的,如下:         MGlobal::setErrorLogPathName().              提示:     插件也可以使用MGlobal::doErrorLogEntry()方法来把它们自己的错误信息加入到错误日志中. 总览     一个命令总是用来得到选择表中的输入内容.MGlobal::getActiveSelectionList()方法的结果包含了所有的选择了的对象,可以     很简便地使用MSelectionList 和MItSelectionList来检查.这两个API也可以被用来编辑选择列表. 
// // 一个全局的当前选择表可以通过MGlobal::getActiveSelectionList()得到一个MSelectionList的拷贝.     除非你使用MGlobal::setActiveSelectionList(),任何你作用于MSelectionList的修改都不会影响全局的选择表.          你也可以用MSelectionList创建你自己的选择表,并和其他表进行合并.包括全局表.你也可以用这个表来创建对象集.      // //     MSelectionList     MSelectionList提供了让你可以从列表内增加或者删除对象的方法.就像在表里遍历对象一样.          比如,以下插件代码打印所有已选择的DAG节点的名字.如果你生成一个几何体,然后选择它,这个插件会打印每一个选择了的对象的名字.              #include maya/MSimple.h          #include maya/MGlobal.h          #include maya/MString.h          #include maya/MDagPath.h          #include maya/MFnDagNode.h          #include maya/MSelectionList.h          #include maya/MIOStream.h          MStatus pickExample::doIt( const MArgList )          {              MDagPath            node;              MObject             component;              MSelectionList      list;              MFnDagNode          nodeFn;              MGlobal::getActiveSelectionList( list );              for ( unsigned int index  0; index  list.length(); index )              {                  list.getDagPath( index, node, component );                  nodeFn.setObject( node );                  cout nodeFn.name().asChar()  “ is selected”  endl;              }              return MS::kSuccess;          }          DeclareSimpleCommand( pickExample, Autodesk, 1.0 );  MFnDagNode内的setObject()方法是继承自MFnBase的所有功能,用来设置当前函数集要操作的对象.一般可以通过函数集的构造     方法来做,但是如果函数集已经被创造了,或者你想改变想要操作的对象的时候,你可以用setObject().这比你每次需要的时候构造     析构函数集要有效.          MAYA的选择构架单一化对象组件的选择就像CVs之类.父对象被放进表内,组件被组织在一起成为一个组,而不是把每个组件都放到表里.     比如,如果nurbSphereShape1上的几个CVs被选择了,上面代码中list.getDagPath()的调用将返回一个指向nurbSphereShape1的MDagPath     和一个包含了所有的已选CVs的MObject.          如果你一直选择同一个物体中的一部分,那么这个物体只在选择表中出现一次.而如果你在一个物体上选择了一些组件,然后在另外的物体上     选择一些,然后在第一个物体上再选择一部分,那第一个物体会在表中出现两次.这样你可以通过表来检测物体选择的顺序. // //     MItSelectionList     MItSelectionList是一个包含了已选物体的封装类.既可以是全局选择表的一个拷贝,也可以是你自己创建的一个表.          MItSelectionList可以让你过滤已选物体通过指定特定的类型.(MSelectionLis不能过滤选择物体) MGlobal::getActiveSelectionList( list );          for ( MItSelectionList listIter( list ); !listIter.isDone();          listIter.next() )          {              listIter.getDagPath( node, component );              nodeFn.setObject( node );              cout  nodeFn.name().asChar()  “%s is selected”  endl;          }  MSelectionList的例子可以修改成用MItSelectionList来遍历表.其效果和之前一样.          你可以简单地修改代码,使之能选择特定的类型,比如,修改迭代器的构造函数为:         MItSelectionList listIter( list, MFn::kNurbsSurface )          那么循环只能选择NURB面 -- 它也会忽略surface CVs.当然,如果你想得到选择了的surface CVs,你可以这样修改:         MItSelectionList listIter( list, MFn::kSurfaceCVComponent )           这只会得到已选的CVs.           // //     MFn::Type enumeration     MFn::Type enumeration在整个API里都被使用,用来标识对象类型.         * 函数集都有一个apiType()方法,可以用来检测MObject所指向的对象类型.每个函数集都有一个type()方法可以用来检测函数集的类型.         * MGlobal::getFunctionSetList()可以返回一个字符串数组来显示可以接受指定对象的函数集类型. // // MGlobal::selectByName()     MSelectionList里的add()方法和MGlobal::setActiveSelectionList()联合使用.提供了一个插件用来修改当前选择列表的方法.          另外一个方法是使用MGlobal::selectByName().这会找到所有符合匹配的对象,并添加他们到当前选择表中.比如:         MGlobal::selectByName( “*Sphere*” );      选择所有名字中有Sphere的物体.          提示:     你也可以用MGlobal::select()来添加对象到当前选择列表,而不需要创建MSelectionList .