Maya插件开发笔记(2) 编译测试插件
这里要注意,插件有个选项叫适用于API版本,Maya这种工业软件API会经常改变,所以每次有新版本,你都需要更新你的插件来支持Maya的新版本,不管怎么说还是比Blender这种频繁更新版本换API的要稳定一点,一般公司里用的话,一两个特定版本就能用到项目组解散或者公司倒闭,所以一般情况不需要担心这一点,除非你做的是对外开放的商业插件,那几乎每个新版本都要去测试、重构支持。你不知道这是干嘛的,这里
我们在上一节 Maya插件开发笔记(1) 开发环境搭建中搭建好了开发环境,现在我们需要使用CMake来创建一个VisualStudio项目来进行插件代码开发。
首先需要安装CMake,安装好之后进行后续的步骤,这里省略CMake安装步骤。
这里我们跟着官方文档的示例操作一遍:
首先切换到你的 C:\Users\Administrator\devkitBase\plug-ins\plug-ins\
文件夹下面,然后
然后在这里创建CMakeList.txt
,输入以下内容:
cmake_minimum_required(VERSION 3.22.1)
set(PROJECT_NAME helloWorld)
project(${PROJECT_NAME})
include($ENV{DEVKIT_LOCATION}/cmake/pluginEntry.cmake)
set(SOURCE_FILES
helloWorld.cpp
)
set(LIBRARIES
OpenMaya Foundation
)
build_plugin()
然后创建一个helloWorld.cpp
,输入以下内容
#include <stdio.h>
#include <maya/MString.h>
#include <maya/MArgList.h>
#include <maya/MFnPlugin.h>
#include <maya/MPxCommand.h>
#include <maya/MIOStream.h>
class helloWorld : public MPxCommand
{
public:
MStatus doIt( const MArgList& args );
static void* creator();
};
MStatus helloWorld::doIt( const MArgList& args ) {
cout << "Hello World " << args.asString( 0 ).asChar() << endl;
return MS::kSuccess;
}
void* helloWorld::creator() {
return new helloWorld;
}
MStatus initializePlugin( MObject obj ) {
MFnPlugin plugin( obj, "Autodesk", "1.0", "Any" );
plugin.registerCommand( "HelloWorld", helloWorld::creator );
return MS::kSuccess;
}
MStatus uninitializePlugin( MObject obj ) {
MFnPlugin plugin( obj );
plugin.deregisterCommand( "HelloWorld" );
return MS::kSuccess;
}
然后打开CMD命令控制台,切换到这个目录,运行这个命令:
cmake . -Bbuild -G "Visual Studio 17 2022"
这里参数的含义简单说明一下,官网提供的示例命令是cmake -H. -Bbuild -G "Visual Studio 17 2022"
在我下载的CMake3.28.1
上面不管用,测试了几次才发现-H
已经不是设置目录了,而是和--help
一样的效果,这说明Maya官方的文档已经很久没更新了,所以我又摸索出来了上面正确的命令。
其中cmake后面的 .
代表当前目录, -B
代表构建目录的名称,后面可以紧跟着也可以空格隔开你指定的构建目录的名称,这里我们指定的是build
,-G
选项用于指定生成器(Generator)或构建系统的名称,这里指的是使用VisualStudio构建,C++标准为C++17,版本号为Visual Studio 2022版本。
运行后会在当前目录下生成一个build
目录,目录下面就是一个VisualStudio项目。
现在我们就可以打开这个helloWorld.sln
进行编译了。
切换到Release X64,进行编译
编译完成后目录下出现Release
目录,下面有个.mll
文件,这就是编译好的插件
(当然你选Debug也行,只不过出来的文件是在Debug目录下面,不要死按步骤来,灵活学习这个过程的本质)
然后接下来进入Maya,使用Plug-in Manager
(插件管理器
)导入插件,或者把插件复制到plug-ins
目录下面。
原理就是maya运行时会自动加载你之前设置好的plug-ins
目录下面的插件,如果不直接放在plug-ins
目录下,那就加载不到,这里因为我们是在嵌套的build
的Release
下面,所以无法直接读取到,所以得手动加载。
这里我们选择 窗口
=>设置/首选项
=>插件管理器
可以看到它并没有在我们上一节设置的环境变量那个plug-ins
目录里读取到任何插件
然后我们点击浏览,选中这个插件的路径,然后点击打开
加载后是酱紫的,通过浏览手动加载的插件不会在Maya启动时自动加载,而是需要你每次启动Maya都手动加载,所以这里我们可以勾选上自动加载,这样这个插件就会在Maya每次启动时进行加载了。
这个界面自动加载后面有个 圆圈 i ,点它就会出现一个窗口显示这个插件的信息:
这里要注意,插件有个选项叫适用于API版本,Maya这种工业软件API会经常改变,所以每次有新版本,你都需要更新你的插件来支持Maya的新版本,不管怎么说还是比Blender这种频繁更新版本换API的要稳定一点,一般公司里用的话,一两个特定版本就能用到项目组解散或者公司倒闭,所以一般情况不需要担心这一点,除非你做的是对外开放的商业插件,那几乎每个新版本都要去测试、重构支持。
到这里,这个Maya插件就加载到项目里面了,然后我们来使用它一下试试。
打开Maya命令行,也就是脚本编辑器,一般在右下角
可以看到,运行完成后这里显示了HelloWorld,这说明我们运行成功了。
(这里之所以用HelloWorld 命令进行测试,是因为我们这里代码注册的命令就叫HelloWorld)
好了,到这里我们就走通了基本的配置环境,构建项目,编译项目,加载插件,测试插件的整个流程了,如果有条件的话可以跟着步骤测试一遍,基本上就能掌握这些基础了。
接下来我们来看一下这个最简单的helloWorld.cpp
里的代码,它虽然简单,但是里面包含了几个我们第一次学习Maya插件开发必须了解的概念。
首先就是doIt()
函数,它的作用是解析传递过来的参数列表,然后把它输出到Maya的output窗口。
MStatus helloWorld::doIt( const MArgList& args ) {
cout << "Hello World " << args.asString( 0 ).asChar() << endl;
return MS::kSuccess;
}
MArgList
会收集传递过来的参数并把它们放到一个列表里,它就和C++的main
方法里接收的argc
和argv
的概念比较类似,就是纯用来接收参数的这么一个数据类型。asString()
会把参数列表转换为一个MString
对象,然后asChar()
把MString
又转换为C++的char *
类型,这样才能交给cout
进行输出。
Maya的官方文档提到,在更加复杂的插件里,doIt()
的作用一般是解析参数,设置内部变量的值,或者做其他准备性的工作,doIt()
会在调用redoIt()
之前完成这些工作,然后redoIt()
才是真正调用command命令的地方。
可能突然又出现个redoIt()
你不知道这是干嘛的,这里就不得不提到Maya的设计了,如果你设计的这个插件的这个命令是可以被撤销的,那doIt()
里只能放准备工作的代码,真正执行命令的代码要放到redoIt()
,然后你还得额外提供一个undoIt()
来撤销redoIt()
里干的事情,这个就是Maya的一种设计规范,还是有点麻烦的不如Blender封装的好,不过更低的粒度意味着我们有更多的空间来开发出更强大的插件,所以其实是好事儿。。
当然,如果你的插件提供的命令是不可撤销的,那就不用实现redoIt()
和undoIt()
了,比如只是简单的打印几个字符串输出之类的,但是大部分对数据对象的操作我们都需要提供可以撤销的命令,不然不小心用错了没法撤销是很严重的事情。
接下来看插件的命令,插件的命令是使用creator()
来实例化的。
void* helloWorld::creator() {
return new helloWorld;
}
然后是初始化插件和取消插件的初始化
MStatus initializePlugin( MObject obj ) {
MFnPlugin plugin( obj, "Autodesk", "1.0", "Any" );
plugin.registerCommand( "HelloWorld", helloWorld::creator );
return MS::kSuccess;
}
MStatus uninitializePlugin( MObject obj ) {
MFnPlugin plugin( obj );
plugin.deregisterCommand( "HelloWorld" );
return MS::kSuccess;
}
所有的Maya插件都需要实现initializePlugin()
和uninitializePlugin()
函数,如果initializePlugin()
函数运行失败了,则整个插件都无法成功加载,initializePlugin()
函数里会调用registerCommand()
来注册一个新的命令,uninitializePlugin()
函数会调用deregisterCommand()
来取消一个命令的注册。
可以说initializePlugin()
和uninitializePlugin()
函数就是Maya插件的入口点,initializePlugin()
函数一般会注册比如命令,节点,工具,以及其它额外的东西,uninitializePlugin()
函数则是在插件卸载的时候要执行的操作,他会把插件在加载时注册的东西全部取消注册一遍。
对于一个命令类插件,initializePlugin()
必须得调用registerCommand()
,uninitializePlugin()
函数必须得调用deregisterCommand()
。
对于一个依赖节点类型插件(dependency node),initializePlugin()
必须调用registerNode()
来注册命令,同样,uninitializePlugin()
函数必须得调用deregisterNode()
因为initializePlugin()
和uninitializePlugin()
函数就是Maya插件的入口点,所以如果你的Maya插件代码里不提供这俩函数的话,基本上插件是无法被Maya加载的。
好了,到这里基本上你就能编译出一个最简单的Maya插件来进行测试了,当你整个流程测试通过,并且理解了Maya插件的入口点initializePlugin()
和uninitializePlugin()
函数的设计之后,我们就可以开始后面的学习了,后面的内容可能会记录Maya一些基础API的用法,或者是一些效果的实现案例。
本节内容就到此结束,希望能对你有所帮助。
更多推荐
所有评论(0)