查看: 1479|回复: 0
打印 上一主题 下一主题

3dmax插件学习笔记-现学现用

[复制链接]
.    

3797

主题

11

听众

5万

积分

首席设计师

Rank: 8Rank: 8

纳金币
32328
精华
41

活跃会员 优秀版主 荣誉管理 论坛元老

跳转到指定楼层
楼主
发表于 2012-12-21 14:47:34 |只看该作者 |倒序浏览
这些允许3ds max访问、维护在DLL内在插件并与之协同工作。这些函数的详情见“DLL, LIbrary Functions, and Class Descriptors”。  2.1.2
重入与线程安全的插件 3DS MAX插件必须是可重入与线程安全的。详在高级主题的“Thread Safe Plug-Ins”章节里。
2.2、插件必须的函数
3DS MAX进行DLL装入、分类、管理插件。包括DLL例程和类描述类。
“Class Descriptors”提供插件类的信息,用以实现LibClassDesc()函数。
2.2.1 DLL functions DllMain(HINSTANCE hinstDLL, ULONG fdwReason, LPVOID lpvReserved) 当DLL被装入时由windows调用。该函数也会在时间关键性操作期间被多次调用,如渲染。所以开发者在该函数内要小心谨慎。注意以下的示意代码中,在DLL第一次调用以后只有很少的语句被执行。该函数应该返回TRUE。
int controlsInit = FALSE;
BOOL
WINAPI
DllMain(HINSTANCE
hinstDLL,ULONG
fdwReason,LPVOID
lpvReserved)
{
//
Hang
on
to
this
DLL's
instance
handle.
hInstance
=
hinstDLL;
if
(!
controlsInit)
{
controlsInit
=
TRUE;
//
Initialize
MAX's
custom
controls
InitCustomControls(hInstance);
//
Initialize
Win95
controls
InitCommonControls();
}
return(TRUE);
}
2.2.2
LibNumberClasses()

3DS
MAX
启动之后,它找到并装入这些DLLs。然后,它需要有个方法判断DLL中的插件类数目。开发者应当在本函数中提供,例如:
__declspec(dllexport)
int
LibNumberClasses()
{
return
1;
}
返回值即插件类的个数。
2.2.3
LibClassDesc(i)
插件必须向系统提供一个方法以获取插件定义的类的描述器(
Class
Descriptors

。类描述器向系统提

DLL
中的插件类的信息。本函数使系统可以访问类描述器,返回值应该是指向第
i
个类描述器的指针。
(一个
DLL
中可以有许多个类描述器)
。例如:
__declspec(dllexport)
ClassDesc
*LibClassDesc(int
i)
{
switch(i)
{
case
0:
return
&MeltCD;
case
1:
return
&***mpleCD;
default:
return
0;
}
}
这里是有关必须被
LibClassDesc(i)
返回的类描述器的资料。类描述器(
Class
Descriptors
)向系统提供
DLL
中插件类的信息。类描述的一个方法负责分配插件类的新实例(
Create

。开发者通过从
ClassDesc

生一个子类并实现若干方法成员来建立类描述器。下面是个简单的类描述器及其静态实例的例子。
class
MeltClassDesc
:
public
ClassDesc
{
public:
int
IsPublic()
{
return
TRUE;
}
void
*
Create(BOOL
loading=FALSE)
{
return
new
MeltMod();
}
const
TCHAR
*
ClassName()
{
return
_T("Melt");
}
SClass_ID
SuperClassID()
{
return
OSM_CLASS_ID;
}
Class_ID
ClassID()
{
return
Class_ID(0xA1C8E1D1,
0xE7AA2BE5);
}
const
TCHAR*
Category()
{
return
_T("");
}
};
static
MeltClassDesc
MeltCD;
2.2.4
LibDescription()
当包含入口(过程物体、修改器或控制器等)的
MAX
文件被装入且系统还没有访问它时(如
DLL

效)
,一个消息被发给用户。当
DLL
不可用时,系统要求每个
DLL
返回一个字符串向用户说明情况。例如,
假定用户有一个融化修改器,他将此融化修改器应用到场景中的某个节点上,并保存此文件。当他将这个
文件给一个没有这个融化
DLL
的朋友,这个朋友打开这个文件时,系统将发出一条消息说明文件中的一个
入口所依赖的
DLL
找不到,这个消息可能是

融化修改器。想要请打电话
025-1234PLUG-
INS


DLL
必须实现
LibDescription()
才能向系统提供这个字符串。
该函数返回值即为当找不到该
DLL
时要显
示的文字。该字符串也将显示在
Summary
Info/Plug-In
Info...
对话框中。一旦
DLL
中的一个插件已经在场景
中使用过,系统就会把这个字符串保存到
max
文件里(以便在
DLL
丢失时显示)

注意
:即使
DLL
缺席时场景仍然会被打开。
3DS
MAX
保留任何
DLL
丢失的节点(
entities

,这样如
果文件被修改并保存然后再在有
DLL
的系统打开修改后的文件,这些节点仍然存在并链接进场景。不能访
问其
DLL
的入口称为封闭入口(
orphaned
entities


封闭入口将作为其超类(
SupperClass
)的通用代表导入。该代表将在场景中显示最少的信息。举个实
例:如果入口是个修改器,它将在修改器清单中显示自己的名字,但不会显示任何参数。如果没有对象类
型信息,那么将在场景中显示为虚物体(
dummy

。它们可以被移动、旋转、缩放、链接、组合、删除
……
任何与节点相关的操作。丢失的控制器只提供不变的默认值,这些值是不可调的。
参考

Read
Only
Plug-Ins

部分。通过允许插件工作在只读模式,用户可以自由分发
DLL
,其他人除非
通过了基于硬件锁
ID
的认证可以运行它,否则使用将受到限制直到购买自己的拷贝。
以下是该函数实现的
一个例子:
__declspec(
dllexport
)
const
TCHAR
*LibDescription()
{
return
_T("Melt
Modifier.
Call
1-800-PLUG-INS
to
obtain
a
copy");
}
2.2.5
LibVersion()
开发者必须实现一个函数以便系统处理不同版本的
3DS
MAX
插件
DLL
。因为
MAX
体系与插件的关
系如此之紧密,系统有时候需要阻止插件的老版本被调用。要使
MAX
能够完成它,
DLL
必须实现一个名

LibVersion()
的函数。
这个函数只简单的返回一个预定义的常量,
这个常量表明在插件编译时系统的版本。
未来版本的
MAX
可能更新该常量,而老的
DLL
总是返回以前的值。该函数使得系统可以检查任意一个
DLL
是否已经被装入,如果是这样则显示一条消息。
__declspec(
dllexport
)
ULONG
LibVersion()
{
return
VERSION_3dsmax;
}
注意
:开发者可以用下面的全局函数获取该值。
DWORD
Get3DSMAXVersion();







MAX







MAXSDKINCLUDEPLUGAPI.H







VERSION_3DSMAX
宏定义的状态。
总结
插件必须实现这五个函数:
DLLMain()

LibNumberClasses()

LibClassDesc(i)

LibDescription()

LibVersion()
。这些函数允许系统取得
DLL
中插件的信息。
2.3
、六个类描述器方法成员
下面我们来讲讲六个类描述器方法成员:
IsPublic()

Create()

ClassName()

SuperClassID()

ClassID()

Category()

2.3.1
IsPublic()
该方法返回一个布尔值。如果插件可以被用户选取和指派,正是常见的情况,返回
TRUE
。某些插件
可能是同一
DLL
的实现的其它插件私有专用的,并不出现在清单供用户选择。这些插件将返回
FALSE

2.3.2
Create(BOOL
loading
=
FALSE)
MAX
在需要得到一个指向插件类的新实例的时候调用该方法。例如,如果
MAX
从磁盘打开一个包含
前边用过的插件的文件,它将调用插件的
Create()
方法。插件负责分配一个插件类的新实例。在上边的例子
的是用一个
“new”
操作简单实现的。
Create()
的可选参数是一个标识表明要创建的类是否将从一个磁盘文件中装入。如果该标识为
TRUE

插件可以不必做任何初始化工作,因为装入进程将会处理它。见

Loading
and
Saving

章节。
当系统需要删除一个插件类的实例时,它会调用
Animatable

DeleteThis()
方法。插件开发者必须实现
该方法。因为开发使用
new
操作分配内存,它也应该用
delete
操作释放之。如开发者可以如下实现
DeleteThis()

void
DeleteThis()
{
delete
this;
}
进一步的细节参考

Memory
Allocation

章节。
2.3.3
ClassName()
该方法返回类的名字。这个名字将出现在
MAX
用户界面的插件按钮上。该方法也在调试时显示类的
名字。
2.3.4
SuperClassID()
该方法返回系统预定义的常量,该常量表示插件类是从哪个类衍生来的。例如,弯曲修改器返回
OSM_CLASS_ID

这个超类
ID
被所有对象空间修改器使用。
其它的超类
ID
例子有:
CAMERA_CLASS_ID

LIGHT_CLASS_ID

SHAPE_CLASS_ID

HELPER_CLASS_ID

SYSTEM_CLASS_ID
。完整的清单见

List
of
Super
Class
IDs


2.3.5
ClassID()
该方法必须为对象返回一个唯一性
ID

3DS
MAX
SDK
中包含一个生成这种
ClassID
的程序。使用该
程序为你的插件创建
ClassID
是非常重要的。如果如果你使用任何一个例子程序的源代码来建立自己的插
件,必须改变已经存在
Class_ID
。如果不这样,将会出现冲突。如果两个
ClassID
冲突,系统将加载它找
到的第一个(并将在试图加载第二个时显示存在
Class_ID
冲突)

一个
Class_ID
包含两个无符号的
32
位整数。建构函数为每一个赋值,如
Class_ID(0xA1C864D1,
0xE7AA2BE5)
。参见

Class
Class
ID


注意在
MAX
使用的插件样本代码将类
ID
第二个
32
位整数设为
0

只有与
MAX
一起发售的内建插件
才可以这样做。所有的插件开发者都应该同时使用两个
32
位整数。还有,确保你使用
SDK
提供程序建立

ID
,这可确保两个插件类之间不会冲突。要生成一个随机的
Class_ID
并可选的将其拷贝至剪帖板中,单

DLL
Function
and
Class
部分的

Generate
a
Class_ID


2.3.6
Category()
在建立面板底部下拉选单选择类别。如果设成已经存在的类别(
i.e.
"Standard
Primitives",
"article
Systems",
etc

,插件将会出现在那个类别里。开发者不应该加到
MAX
提供的类别里(见下边的注释)
。如
果类别还不存在,则将被创建。如果插件不需要出现在清单中,它可以简单的返回一个
null
字符串
_T("")

Category()
也被按钮设置对话框中用于插件分类。
重要说明

MAX
体系在
Create
分支面板里有每类
12
个插件的限制。为预防每个类别有太多插件的问
题,开发者应该总是为自己的插件建立一个新的类别而不是使用一个
MAX
标准插件已经使用的类别。注
意早于
1.2
版本的
MAX
在每个类别有多于
12
个按钮时会崩溃。
管理过程物体创建过程并编辑其参数
这部分讨论以下方法:
GetCreateMouseCallBack()
proc()
BeginEditParams()
EndEditParams()
GetValue()
SetValue
NumSubs()
SubAnim()
SubAnimName()

MAX
用户将要建立一个新的过程物体时,系统会调用插件的一个方法接管创建阶段的用户输入活
动。插件可以任意实现其用户界面,但必须向
MAX
提供一个途径与用户交互过程联系。插件要实现
GetCreateMouseCallBack()
函数以向
MAX
提供该途径。
这个函数返回一个指向
CreateMouseCallBack
衍生类
实例的指针。这个类有一个
proc()
方法,程序员在这个函数里定义物体创建阶段的用户交互活动。系统实
际上需要一个函数指针,这个函数是由插件实现可以被系统调用。参考
sphere_c.cpp
源代码。
插件必须实现一些方法以处理用在命令面板中的输入。插件要负责实现从
Animatable
类继承来的两个
方法,这两个方法用来处理用户在命令面板中的输入:
BeginEditParams()

EndEditParams()

Begin
在用户
可以编辑实体参数时由系统调用(物体创建或修改已经存在的实体时都可能调用)
,它负责向面板里添加卷
展栏并将其注册到系统中。加入卷展栏函数带有一个
Dialog
Proc
参数。这个对话处理过程控制用户与对话
框控件的交互活动。
过程球体的例子使用了参数映射机制来简化开发者与管理用户界面控制相关工作任务。
参数映射被用于管理
UI
交互活动。见参数映射。
End
方法则在用户结束编辑一个物体的参数时被调用。系统将传递一个标识给
EndEditParams()
以指示
卷展栏是否应该删除。如果为
TURE
,插件必须注销卷展栏,并将其从面板中删掉。在某些情况,物体的
卷展栏应该保留在命令面板里。例如如果用户已经完成一个过程球体的建立,它的
EndEditParams()
方法被
调用。然而用户可能希望建立另一个球,这样开发者不可以立刻移走卷展栏。这样用户界面不会因为删除
后立刻加回来而闪烁。
参数映射
这部分对于理解例子及简化开发相当有用,所以列入基本内容。参数映射用于最小化插件管理用户界
面参数所需的编程工作。一个简单插件,如过程球体,拥有由类似微调控件(
to be
continued...)

【来源:互联网】
更多精彩教程,尽在web3D纳金网http://www.narkii.com/college/
分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-9-20 22:30 , Processed in 0.219088 second(s), 33 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部