mayaAPI(3)-mll

maya Developer Resources一共是三章,第一章是API,现在开始API第三节。

躺在床上思考了一下DG和DAG。两者都是数学上的名词,在计算机里面用面向对象的方法来表达。

所以这两个类在计算机里都会变得非常不一样。毕竟计算机它不知道数学那些表达符号是什么意思,都得我们自己来做。

DAG这个类,在maya里面就是MDagPath,maya用这个类来管理一个或者多个DAG Node。每个MDagPath的实例,都有很多的方法,它可以得到与路径有关的(父,子,路径名等等)以及类型,名字这一些通用属性。

所以说,在maya里面,一个DAG Node是和path融合在一起写为一个类的,是不能分开的。(这样我们也方便了,不用新建两个类,我们写一个类就OK了。)

DG的话题以后再说,现在继续研究plugin,抛开MSimple这个macor头文件。

——————>
突然发现vs6之后,就没有make file了。这让我有写一个bat和make file的冲动。。

想到这个念头,就又去看了看masm里面的bat写法,果然很强大,以前没有注意到命令行的if语句,现在知道了。

真的很想多学学nmake的语法,还有cl和link的各种选项以及PE文件。。希望更加熟悉一点。。不过,还是暂时放着吧。。

咱还是有VS2005 的IDE的,虽然不够完全灵活,但是至少很实用。。

不过这个IDE产生了很多的废文件。。比如ncb,比如sln。。

——————>回到maya plugin

helix2这个plugin 充分演示了redo-undo plugin该是如何来写,以及非常实用的maya API的使用方法。

我们来看helix2这个cpp的写法。

它在逻辑上是有这样一个过程:

1)

我们把这个cpp编译成dll,虽然它的后缀是mll

这个dll有2个导出函数(链接器选项里面有,这是maya template wizard做的,虽然这个导出也是可以在代码里面写特定的calling convention,但是maya的标准template并没有显式声明calling convention ):

initializePlugin和uninitializePlugin

插一段:在C++中要写个dll有三种方法:

前提是要写好一个dllentry方法,然后再link里面加上/dll

1.使用def文件,这个比较平常的,它的写法是:

LIBRARY   BTREE    // 库名为BTREE,省略库名即为动态链接库文件名
EXPORTS        // 输出
Insert   @1    // 带序号的输出函数名
Delete   @2
Member   @3
Min   @4

(library这行在VS里面似乎有些不同,似乎和工程名要对应。)

2.直接在link后面加上后缀/export:xxx 。有几个就加几个。

3.使用C++的_declspec(dllexport)引用约束前缀来(附加上extren “C”更好)来进行prototype声明(这种calling convention用起来比较麻烦)

使用dll:

如果是前2种写的dll,那么使用起来很简单,就和其他的系统API使用是一样的,毕竟在C和C++中都是_cdel这个引用约束。而第三种由于改变了引用约束,所以,我们需要用_declspec(dllimport)来声明prototype。

2)

may会调用initializePlugin并且会传入一个MObject的对象,里面有一些信息

我们使用:

MFnPlugin plugin( obj, “lizhong”, “2009″, “Any”);

obj里面有什么信息呢:

This MObject contains Maya private information such as the name of the plug-in file and the directory it was loaded from.

比较神奇的是,我在MObject的API里面找不到这样的公开方法,似乎是没有公开的API部分。。

然后:

status = plugin.registerCommand( “LzHello”, LzHello::creator );

我们传递了一个字符串,以及一个函数的地址过去。

API是这样解释的:

MStatus MFnPlugin::registerCommand  ( const MString &  commandName,
  MCreatorFunction  creatorFunction,
  MCreateSyntaxFunction  createSyntaxFunction = NULL
 )    

Register a new command with Maya. Once registered,
the command can be invoked from MEL in a manner identical to built-in Maya commands.

Parameters:
[in]  commandName  the name of the command to register
[in]  creatorFunction  a pointer to a function that will return a pointer
to a new instance of the class (derived from MPxCommand)
 that implements the new command.
[in]  createSyntaxFunction  a pointer to a function
that will return a new instance of a syntax object (MSyntax)
that implements the syntax of the command.

它解释的很清楚了,不过第三个参数涉及到MSyntax,以后再说。

有了这个函数地址,我们就可以调用这个函数,一个这样的函数最大的用途就是返回一个我们写的类的new实例,也就是申请一块内存来初始化我们的类。

因为maya从始至终都不知道我们的代码会是什么样子的,它只会一步一步执行下去,我们要做完所有的事情。

我们的这个类不能随便编写一个了事,我们必须按照maya给我们的规范(因为maya只会调用固定的接口,它只访问固定的几个函数地址)

我们的代码就是这样声明的:

class LzHello : public MPxCommand
{

public:
	LzHello();
	virtual		~LzHello();

	MStatus		doIt( const MArgList& );
	MStatus		redoIt();
	MStatus		undoIt();
	bool		isUndoable() const;

	static		void* creator();

};

这里还有个MArgList,所以前面可以写个类前置声明,或者导入这个头文件。

对于C++来说,构造函数和析构函数是不可少的,对于maya来说,这5个方法是不可少的。

所以就一共7个方法,至于拷贝构造函数这个东西,不知道在我们写的类中会不会出现new操作符呢。

这里之所以使用virtual析构函数,也就是考虑到我们写的类也可能要被继承的,所以当出现动态绑定的时候用virtual可以解决子类动态申请的内存不被释放的问题。

3)

在函数执行完构造函数之后,它会调用doIt方法

doIt方法里面就可以处理2方面的问题,1是参数列表,2是MGlobal selectionlist

这时,产生的数据都可以存为私有成员属性,doIt方法只会调用一次,所以作为数据存储方法是再好不过了。

而redo方法是作为真正的执行方法(这样也就是做到了各司其职,代码复用)

4)redo方法里就可以随意私有成员对象进行处理了。不过,如果要对目标进行改造的时候,要记得存储改动的数据,这个也要存在私有成员属性里面,不然我们undo的时候就没办法还原了。

5)undo其实很简单,在redo里面已经保存好了改动前的目标属性,我们只要利用这个原始属性变回来就可以了。

6)我们的函数也可以有返回值,这个返回值可以输出到output窗口里面,也可以输出到mel 命令行窗口里面。

这个就是SetResult。API里面有3个例子来说明,总而言之我们主要有3个API可以用:

clearResult();

appendToResult();

setResult();

具体还是参看MPxCommand这个的API。

不过SetResult被重载了相当多次。。

static void  setResult (int val)
static void  setResult (double val)
static void  setResult (bool val)
static void  setResult (const char *val)
static void  setResult (const MString &val)
static void  setResult (const MIntArray &val)
static void  setResult (const MDoubleArray &val)
static void  setResult (const MStringArray &val)

——————>

maya的API明显非常强大,不过好像依靠它开发的人不太多,毕竟CG也没多少岁数,maya的岁数也很小,而且也不像操作系统那样受众广泛,其实maya从中国开始流行估计也就是05年的样子吧。98年生出来的软件,现在13岁了。不像商用操作系统那样,都已经20岁了。在中国,时间得退个至少年,操作系统的利用还处于初中生阶段,maya这样的三维软件的应用。。刚入小学。。说明我还是挺明智的。。

其实你要掌握一样计算机工具来实现电脑效果,最直接的方法就是编程。虽然三维中有许多方面还是与二维绘画有关,不过openGL毕竟是计算机绘图接口,编程占有的比重更大。

——————>Syntax Object

maya的API帮助文档上的文字硬邦邦的,思维都没个衔接。。明晃晃的不带衔接的总分-总分-总分结构

首先是三个类:

MSyntax

MArgDatabase

MArgParser(这个与Context Commands,说到context那就是与IO设备有关了。)

这个Sytax是干嘛的呢,这个是专门为参数准备的数据结构,我们要用C++来处理类似windows命令行类型的参数传递方式,就必须要有处理方法。

MArgDatabase就带有处理参数的方法集

先看看API说明:

MSyntax:

This class is used to specify flags and arguments passed to commands. Once the syntax of the command has been defined by calls to the methods in this class, Maya will be able to automatically parse invocations of the command and reject syntactically invalid ones.

常用的API有这么几个:

addFlag(),makeFlagMultiUse(),useSelectionAsDefult()以及setObjectType()

前2个是用来设置command argument的,后两个是设置object。
addFlag支持设置6个command argument,也就是我们可以在一个flag后面最多跟着6个argument。

object和command argument是不兼容的,我们可以看到mel表达式里面,flag argument都是有”-”前缀的flag,而object是没有的。

——————>晚上10点多睡,然后凌晨4点钟起来的话,对白天的影响其实不大,可以试试到4点半之后吧,那样身体应该会更舒服一点。但肯定不要两点起床。。我试过。。很不舒服。

MSyntax nodeInfo::newSyntax()
{
	MSyntax syntax;
	syntax.addFlag(NFLAG, NFLAGLONG, MSyntax::kString) ;
	syntax.makeFlagMultiUse(NFLAG) ;
	return syntax;
}

我们要写一个类似这样的静态方法,其实声明static的意思,就是说明这个方法是类的通用方法,那么我们就可以在类的内部调用这个方法了,而不需要实例化。
这个方法要在类注册的时候使用,作为第三个参数。

——————>MArgDatabase

这个类是用来处理参数的,它继承于MArgParser

所以,我们很多方法都是用继承自MArgParser的公开方法。

我们新建MSytax实例,并设置好我们需要的flag和object之后,在doIt方法中,同MArgList实例一起,来初始化MArgDatabase。

常用方法是:
isFlagSet(),getFlagArgument(),getObjects()

如果有在MSytax中有makeFlagMultiUse(),那么我们需要用getFlagArgumentList()
getFlagArgumentList和getFlagArgument参数相同,但是意义好像有些许不同。
第一个参数都是Flag(我可以传字符串,也可以定义宏),
在getFlagArgument中:
the index of the argument to the flag
在getFlagArgumentList中:
the desired instance of the flag on the command line
对于getFlagArgument来说,指定的i是后面argument的index,我们要获取argument需要给第三个参数指定合适的结构来存,

这些结构除了MSelectionList(存放MObject)可以放对象之外,其他都是存放单个对象,就是说,这里并没有对Array的支持!

所以,maya在这里就是说,argument要一个一个的取。取完之后要放在Array或者Point之类的结构,需要自己一个一个放。

发表评论

您的电子邮箱不会被公开。 标记为 * 的区域必须填写

*


您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>