本文描述了在3dsMax插件开发中必需的函数,同时也介绍了在每一个插件中必需的对象Descriptor。3ds Max的插件采用的是动态链接库(DynamicLinkLibraries)的方式实现的,动态链接库可以让多个程序共享它的代码、数据和资源。
DllMain()这个函数是Windows系统用来出事化DLL的钩子(hook),当DLL加载的时候,Windows会首先调用这个函数。DLLMain函数并没有做什么特别的事情,它只是用来保持这样一个DLL实例对象。如果在DLL_THREAD_ATTACH和DLL_THREAD_DETACH的时候没有特别的操作,可以调用DisableThreadLibraryCalls()。
如果需要在DLL初始化的时候进行特殊的操作,可以实现LibInitialize()函数,同样如果需要在清除DLL的时候进行某些操作,可以在LibShutdown()函数中实现。
DllMain函数的原型如下:
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved)这个函数在DLL加载的时候或者某些特殊的时候(如渲染场景)被系统调用,下面是一个简单的DllMain函数的实现:
HINSTANCE hInstance; /** public functions **/ BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved) { switch(fdwReason) { case DLL_PROCESS_ATTACH: hInstance = hinstDLL; DisableThreadLibraryCalls(hInstance); break; }<pre name="code" class="cpp">const TCHAR* LibDescription()
LibInitialize函数的原型如下:
int LibInitialize(void);
这个函数允许你在进程中开始使用DLL之前做一些特殊的初始化操作
LibShutdown函数的原型如下:
int LibShutdown(void);这个函数在3ds Max结束使用DLL之后被调用
以下一些函数用来描述插件中的属性信息
下面详细阐述上述的几个函数
const TCHAR* LibDescription()设想这样一种情况:3dMax文件在A的计算机上生成,A的计算机里面有一个他自己写的3ds插件,在生成3dsMax文件的时候他用到了他写的插件,于是他的max文件中就包含着一个他自己写的实体,但是这个实体B的电脑上却没有,因为B的电脑中的Max软件中并没有A写的插件,于是就出现这样一个问题:当A把自己的Max文件共享给B的时候,B用他自己的3dMax软件打开,但是这种情况下他应该加载不了这个Max文件的全部实体(因为A并没有把他的插件给B),于是这种情况下系统会报错,提示B缺少xx插件。以上场景就是我们这个函数的应用场合,我们使用LibDescription写下字符串,让B在加载的时候看到这样一个提示信息,这样他就会去找A要回A使用的插件。
缺少插件支持的实体被称为orphaned entities(孤实体)
int LibNumberClasses()当3dMax启动的收,它会寻找DLL进行加载,当寻找到一个的时候,它需要知道这个DLL中有多少个插件类,程序员需要提供这样一个信息给3dMax。
ClassDesc* LibClassDesc(int i)该函数用来获取DLL中第i个插件类的信息(在一个DLL中不止有一个Plugin-class),示例代码如下:
__declspec(dllexport) ClassDesc *LibClassDesc(int i) { switch(i) { case 0: return &MeltCD; case 1: return &CrumpleCD; default: return 0; } }注意参数i的取值是从0开始的,0代表第一个,以此类推
ULONG LibVersion()返回3dsMax插件的版本信息,以帮助3dMax实现插件是否加载