在Maya上开发插件的三种方法

发布时间:
浏览次数: 705

好酷屋教程网小编为您收集和整理了在Maya上开发插件的三种方法的相关教程:我们知道,maya是一个基于结点的插件式软件架构,这种开放式的软件架构是非常优秀的,它可以让用户非常方便地在其基础上开发一些自已想要的插件,从而实现一些特殊的功能或效果。在MAYA上开发自已的插件,

我们知道,maya是一个基于结点的插件式软件架构,这种开放式的软件架构是非常优秀的,它可以让用户非常方便地在其基础上开发一些自已想要的插件,从而实现一些特殊的功能或效果。

在MAYA上开发自已的插件,你有3种选择。

第一种是使用MEL语言开发脚本插件,使用MEL语言来编插件的最大优点是方便易学,MEL代码在MAYA上直接可以运行,不用任何辅助工具,在MAYA2008之前,MAYA的整个界面都是用MEL语言来写的,可见MEL语言也足够的强大,但是毕竟它是一个解析型的脚本言语,而且是一种面向过程的语言,因此,当我人要实现一些高性能的,或者是一些代码量非常大,对像关系非常复杂的功能时,MEL语言就是显得有点力不从心。

这时候,你就有了第二种选择,基于C++语言的MAYAApI插件,ApI插件的最大优点是高效,一般来说,用C++来写的ApI插件要比MEL语言插件运行速度要快10倍以上,试想一下,你如果要对一个有100万面的模型的每条边逐一搜索,用MEL来做,肯定要处理很长时间,但是用C++则可以非常轻松实现,可以说,MAYA的核心就是C++和OpenGL构建起来的。但是ApI插件,也有它的缺点,最大的缺点就是用必须要用C++编程,而C++又偏偏是公认的最难学的语言之一,很多计算机专科毕业的人对它都是一知半解,所以对于多数的美术制作人来说,也只能望而却步了。

当然,在MAYA2008之后,我们又有了第三个选择,那就是python,这是一个在MEL与C++之间的折中选择,python本身它是一种脚本语言,因此它也可以和MEL一样直接在MAYA窗口运行,而且也比较好学,同时时呢,它又拥有C++的面向对像的特性,因此呢,你可以用python来开发足够复杂的程序。可见三种方案,各有所长,没有最好,只有最适合,选用哪种方案,得视实际的需求来定夺。在这里,我详细说一下用如何C++来编写MAYAApI插件,只为有这方面需求的朋友提供一个入门级的帮助,当然,前提是你要会C++编程。我们选用的编译环境是Maya2010和MicrosoftVisualStudio2005,要编写MAYAApI插件就得用到MAYA的开发包,没默认情况下,MAYASDK会随MAYA程序一起被安装到相应目录下,如:D:/programFiles/Autodesk/Maya2010/include和D:/programFiles/Autodesk/Maya2010/lib,对于入门的朋友,可以使用MAYAApI插件编程向导MayapluginWizard2.0,这个向导能快速地都你在VS2005上搭建插件编程框架。打开文件夹D:/programFiles/Autodesk/Maya2010/devkit/pluginwizard,里面有安装说明,安步骤把MayapluginWizard2.0.zip安装到VS2005中去。值得注意的是Maya2010的插件工程向导是基于VS2005的,你如果用的是VS2008或其它VS编译器,这个向导安装上去可能没法正确运行,这是因为版本识别问题,你可以用记事本把文件文件MayapluginWizard.vsz及MayapluginWizard/Templates/1033/plugin.vcproj打开,把里面的8.0改为9.0,就可以在VS2008中运行了。如果向导工具安装成功,打开VS2005的新建工程向导,我们可以看到以下的界面我们选择MayapluginWizard来新建一个项目:默认情况下,developerKitlocation是指向C盘的,如果你的MAYA安装在基它地方,则需要指定相应的MAYA安装路径:我们首先来创建一个最简单的MAYA插件,就是一个不带Undo/Redo功能的maya命令。点Finish之后,工程就创建好了,代码很简单,整个工程只有一个Cpp文件,代码如下:#includeDeclareSimpleCommand(sayHello,””,”2010″);MStatussayHello::doIt(constMArgList&args)//ReturnValue://MS::kSuccess-commandsucceeded//MS::kFailure-commandfailed(returningthisvaluewillcausethe//MELscriptthatisbeingruntoterminateunlessthe//erroriscaughtusinga”catch”statement.//{MStatusstat=MS::kSuccess;displayInfo(“HelloWorld!”);//SincethisclassisderivedoffofMpxCommand,youcanusethe//inheritedmethodstoreturnvaluesandseterrormessages//setResult(“sayHellocommandexecuted!/n”);returnstat;}我们在doIt()函数中加入一行:displayInfo(“HelloWorld!”);这个对于程序员来说近乎圣经般入门代码。然后进行编译,如果一切顺利,在我们工程的Debug文件夹中就生成了一个叫sayHello.mll文件,这就是一个MAYA插件了,安装MAYA插件也挺简单,把sayHello.mll文件拷贝到D:/programFiles/Autodesk/Maya2010/bin/plug-ins目录下,然后重新打开maya2010,从菜单window->settings/preferences->plug-InManager打开插件加载窗口:把我们的sayHello.mll插件加载进来,然后在我们的maya命令行窗口中输入sayHello;命令对插件进行测试。久违的HelloWorld!问候最终是成功地显示。MAYA的插件大体上分为两大类型,命令(Command)和结点(Node),多数情况下,命令都是为结点服务的,下面我们来说一下如何编写一个简单的Maya结点。那么什么maya的结点呢?我们可以把结点想像为一个数据流处理器,每个结点,它都有输入接口,输出接口,及对数据进行处理的内核,如图:我们说MYAY是基于结点的插件式软件架构,所以在MAYA底层,对所有的数据都是通过把大量这的结点连接起来,一层层地进行运算和处理才得到最终的结果。这种基于结点的软件架构,其最大的好处就是制作人员可以根据需求把各种随意地连接起来,从而实现让制作人员可以最大限度在发挥自已的想像空间和创意能力。下面我们来实现一个功能简单的结点,该结点只有一个输入接口和一个输出接口(注:一个结点可以有多个输入接口和输出接口),要实现的功能是把输入的数据乘以0.5变成原来的一半,然后输出。打开MayapluginWizard,新建一个DependencyGraphNode插件////Copyright(C)////File:pluginMain.cpp////Author:Mayaplug-inWizard2.0//#include”halfScaleNodeNode.h”#includeMStatusinitializeplugin(MObjectobj)////Description://thismethodiscalledwhentheplug-inisloadedintoMaya.It//registersalloftheservicesthatthisplug-inprovideswith//Maya.////Arguments://obj-ahandletotheplug-inobject(useMFnplugintoaccessit)//{MStatusstatus;MFnpluginplugin(obj,””,”2010″,”Any”);status=plugin.registerNode(“halfScaleNode”,halfScaleNode::id,halfScaleNode::creator,halfScaleNode::initialize);if(!status){status.perror(“registerNode”);returnstatus;}returnstatus;}MStatusuninitializeplugin(MObjectobj)////Description://thismethodiscalledwhentheplug-inisunloadedfromMaya.It//deregistersalloftheservicesthatitwasproviding.////Arguments://obj-ahandletotheplug-inobject(useMFnplugintoaccessit)//{MStatusstatus;MFnpluginplugin(obj);status=plugin.deregisterNode(halfScaleNode::id);if(!status){status.perror(“deregisterNode”);returnstatus;}returnstatus;}halfScaleNodeNode.h#ifndef_halfScaleNodeNode#define_halfScaleNodeNode////Copyright(C)////File:halfScaleNodeNode.h////DependencyGraphNode:halfScaleNode////Author:Mayaplug-inWizard2.0//#include#include#includeclasshalfScaleNode:publicMpxNode{public:halfScaleNode();virtual~halfScaleNode();virtualMStatuscompute(constMplug&plug,MDataBlock&data);staticvoid*creator();staticMStatusinitialize();public://ThereneedstobeaMObjecthandledeclaredforeachattributethat//thenodewillhave.Thesehandlesareneededforgettingandsetting//thevalueslater.//staticMObjectinput;//ExampleinputattributestaticMObjectoutput;//Exampleoutputattribute//Thetypeidisaunique32bitindentifierthatdescribesthisnode.//Itisusedtosaveandretrievenodesofthistypefromthebinary//fileformat.Ifitisnotunique,itwillcausefileIOproblems.//staticMTypeIdid;};#endifhalfScaleNodeNode.cpp////Copyright(C)////File:halfScaleNodeNode.cpp////DependencyGraphNode:halfScaleNode////Author:Mayaplug-inWizard2.0//#include”halfScaleNodeNode.h”#include#include#include#include//YouMUSTchangethistoauniquevalue!!!Theidisa32bitvalueused//toidentifythistypeofnodeinthebinaryfileformat.////#errorchangethefollowingtoauniquevalueandthenerasethislineMTypeIdhalfScaleNode::id(0x02010);//Exampleattributes//MObjecthalfScaleNode::input;MObjecthalfScaleNode::output;halfScaleNode::halfScaleNode(){}halfScaleNode::~halfScaleNode(){}MStatushalfScaleNode::compute(constMplug&plug,MDataBlock&data)////Description://Thismethodcomputesthevalueofthegivenoutputplugbased//onthevaluesoftheinputattributes.////Arguments://plug-theplugtocompute//data-objectthatprovidesaccesstotheattributesforthisnode//{MStatusreturnStatus;//Checkwhichoutputattributewehavebeenaskedtocompute.Ifthis//nodedoesntknowhowtocomputeit,wemustreturn//MS::kUnknownparameter.//if(plug==output){//Getahandletotheinputattributethatwewillneedforthe//computation.Ifthevalueisbeingsuppliedviaaconnection//inthedependencygraph,thenthiscallwillcauseallupstream//connectionstobeevaluatedsothatthecorrectvalueissupplied.//MDataHandleinputData=data.inputValue(input,&returnStatus);if(returnStatus!=MS::kSuccess)MGlobal::displayError(“NodehalfScaleNodecannotgetvalue\n”);else{//Readtheinputvaluefromthehandle.//floatresult=inputData.asFloat();result*=0.5;//Getahandletotheoutputattribute.Thisissimilartothe//”inputValue”callaboveexceptthatnodependencygraph//computationwillbedoneasaresultofthiscall.//MDataHandleoutputHandle=data.outputValue(halfScaleNode::output);//Thisjustcopiestheinputvaluethroughtotheoutput.//outputHandle.set(result);//Markthedestinationplugasbeingclean.Thiswillpreventthe//dependencygraphfromrepeatingthiscalculationuntilaninput//ofthisnodechanges.//data.setClean(plug);}}else{returnMS::kUnknownparameter;}returnMS::kSuccess;}void*halfScaleNode::creator()////Description://thismethodexiststogiveMayaawaytocreatenewobjects//ofthistype.////ReturnValue://anewobjectofthistype//{returnnewhalfScaleNode();}MStatushalfScaleNode::initialize()////Description://Thismethodiscalledtocreateandinitializealloftheattributes//andattributedependenciesforthisnodetype.Thisisonlycalled//oncewhenthenodetypeisregisteredwithMaya.////ReturnValues://MS::kSuccess//MS::kFailure//{//Thissamplecreatesasingleinputfloatattributeandasingle//outputfloatattribute.//MFnNumericAttributenAttr;MStatusstat;input=nAttr.create(“input”,”in”,MFnNumericData::kFloat,0.0);//AttributewillbewrittentofileswhenthistypeofnodeisstorednAttr.setStorable(true);//AttributeiskeyableandwillshowupinthechannelboxnAttr.setKeyable(true);output=nAttr.create(“output”,”out”,MFnNumericData::kFloat,0.0);//Attributeisread-onlybecauseitisanoutputattributenAttr.setWritable(false);//AttributewillnotbewrittentofileswhenthistypeofnodeisstorednAttr.setStorable(false);//Addtheattributeswehavecreatedtothenode//stat=addAttribute(input);if(!stat){stat.perror(“addAttribute”);returnstat;}stat=addAttribute(output);if(!stat){stat.perror(“addAttribute”);returnstat;}//Setupadependencybetweentheinputandtheoutput.Thiswillcause//theoutputtobemarkeddirtywhentheinputchanges.Theoutputwill//thenberecomputedthenexttimethevalueoftheoutputisrequested.//stat=attributeAffects(input,output);if(!stat){stat.perror(“attributeAffects”);returnstat;}returnMS::kSuccess;}我们可以看到,现在的工程代码比刚才的命令插件要复杂多了,除了有对应的halfScaleNode.cpp和halfScaleNode.h文件之外,还有一个pluginMain.cpp文件,这是每个MAYA插件的入口,MAYA在加载该结点的时候,会自动运行initializeplugin(MObjectobj)函数,因此我们就可以在这里做一些初始化的操作,其中最重要的就是要注册这个maya结点。status=plugin.registerNode(“halfScaleNode”,halfScaleNode::id,halfScaleNode::creator,halfScaleNode::initialize);if(!status){status.perror(“registerNode”);returnstatus;}所有自定义的maya结点及命令,都必须在初始化的时候注册,才能被MAYA识别和使用。注册的时候我们要注意的是,新的结点名和结点ID不能与已有的结点冲突,也就是说结点名和结点ID在整个MAYA系统中都必须是唯一的。所以在halfScaleNodeNode.cpp文件的开始有这样一个定义结点ID的代码//YouMUSTchangethistoauniquevalue!!!Theidisa32bitvalueused//toidentifythistypeofnodeinthebinaryfileformat.#errorchangethefollowingtoauniquevalueandthenerasethislineMTypeIdhalfScaleNode::id(0x00001);这里就提示我们必须要给该结点分配一个唯一的ID,要不就没法通过编译。我们可以把以上代码改为//#errorchangethefollowingtoauniquevalueandthenerasethislineMTypeIdhalfScaleNode::id(0x02010);这样我们就可以正常地编译代码了。接下来我们来详细说一下每个结点的核心运算函数:compute(constMplug&plug,MDataBlock&data);前面我们说过,一个结点是由输入接口、输出接口及运算核心组成,这里的运算核心就是compute()函数,而输入输出接口则被封装在MDataBlock&data这个对像里面,我们通过相应的函数,就可以取得输入口和输出口所对应的地址,然后对这些数据进行操作:MDataHandleinputData=data.inputValue(input,&returnStatus);MDataHandleoutputHandle=data.outputValue(halfScaleNode::output);floatresult=inputData.asFloat();这里,result所得到的就是输入数据的原始值,如果我们不作任何运算,直接把它赋值给输出接口outputHandle.set(result);那么得到的输出结果,也不会有任何改变。现在我们把输入数据乘以0.5然后再赋给输出接口:floatresult=inputData.asFloat();result=result*0.5;outputHandle.set(result);很容易地,我们就达到了我们所想要实现的功能。把工程编译一下,得到一个叫halfScaleNode.mll的MAYA插件,和前面所说的安装方式一样,我们把halfScaleNode.mll拷贝到plug-in文件夹中,然后在MAYA插件管理器中加载该插件。我们来验检一下该结点插件是否能正确运行。我们要在maya场景中建两个小球,在命令窗口中输入并运行以下mel代码:polySphere;createNodehalfScaleNode;connectAttrhalfScaleNode1.outputpSphere2.translateX;从超图上我们可以后清晰地看到,pSphere1的translateX属性被连接到halfScaleNode1的input输入口,经过运算后,输出给pSphere2的translateX属性。现在我们选择pSphere1然后沿X轴平称,我们可以看到,pSphere2会跟随pSphere1一起移动,但总是慢半拍,这正是我们想要的效果。这样,一个简单的MAYA插件也就完成了。从上面的操作,我们也可以看到,一般一就,单独一个MAYA结点,如果用手工,是很难被正确连接起来的,所以多数情况下,结点插件都会结合mel脚本或ApI命令来一起使用。以上,只是简单地介绍了编写MAYAApI插件的入门知识,在实际应用中,一个MAYAApI插件要比这个复杂得多,一个MAYA结点,它可以包括多个接口,而每个接口可以是各种类型的参数,如,浮点、整型、向量、矩阵等等,甚至可以是一个mesh对像或是一个二维数组。这些,我们都可以在每个结点的initialize()函数中生成和指定。为了管理上的方便,我们可以在一个MAYAApI插件中包含多个结点和命令,也就是说一个mll文件中可能有多个node和command,我们只要把它们都在pluginMain.cpp中的MStatusinitializeplugin(MObjectobj)函数进行注册就可以了。

以上就是好酷屋教程网小编为您收集和整理的在Maya上开发插件的三种方法相关内容,如果对您有帮助,请帮忙分享这篇文章^_^

本文来源: https://www.haoku5.com/IT/6530a2419bfc6ab9120fcf71.html

相关推荐

分享到: