发帖说明:
  1. 发布信息前请阅读华语CG 论坛相关条款声明,一旦发布便表示你已经同意并遵守华语CG条款声明。
  2. 请不用因为不知道主题应该发布在哪板块而担心,华语CG 论坛管理人员会为你解决。
华语CG! » 华语CG 3D技术交流论坛 3D Techiques and Theories 订阅本帖最新内容
翻译一节国外教材,有兴趣学学MAXScript的请进!


编号:1224
等级:护卫
发帖:576
精华: 2
在线:67小时
好评:73 点
贡献:13 点
加入时间:
2005-12-05
30 楼 [只看] ·2006-03-29 11:24 |

 

创造一个功能完整的工具

1.再次启动Visual MAXScript Editor可视化界面编辑器(如果你不是从前边练习继续到这里的话,就先打开 quickDraft_interface02.ms)。

2.在主菜单中,选择MAXScript -> Open Script... 打开DVD上的quickDraft_proof_of_concept.ms。

3.在界面编辑器里选择Render Hidden复选框,然后在右边属性页顶端选择Event Handlers事件处理器页面。

  Event Handlers是根据事件来触发指定动作的脚本模块。例如本例中的事件就是复选框被选择或清除时的操作。当我们点击一个复选框时,其中的处理器changed被触发,或者说被调用,而此时复选框的开关状态会被赋予一个叫做state的变量,并传达到事件处理代码部分进行运算。

4.点击event handler列表中的changed (只有这一个:),可以看到一个Edit Event Handler窗口弹出,这就是我们将要输入脚本来使Render Hidden复选框起作用的地方了。

5.在proof-of-concept.ms中找到--Render Hidden段,把它复制/粘贴到Edit Event Handler窗口中(如图6.8),OK关闭窗口。用同样的方法为其他每个复选框添加对应脚本。(前面有 -- 符号的代码表示注释,也就是给人阅读而不是给电脑处理的内容,在脚本编辑器中被染成绿色,因此实际上只需要复制该行下面的部分而不包括它本身即可。)
  • 编辑此贴
  • 回复此贴


编号:1224
等级:护卫
发帖:576
精华: 2
在线:67小时
好评:73 点
贡献:13 点
加入时间:
2005-12-05
31 楼 [只看] ·2006-03-29 11:24 |

 

图片:
图6.8 将"概念实证"代码拷贝到事件处理编辑器中

  提示:在proof-of-concept.ms中有两个Render Elements段落,第一个是用于event handler的,而后面的是另一个示例,并不是在这里使用的。

6.选择可视化编辑器菜单File -> Save 来将脚本写入脚本编辑器,关闭可视化编辑器,并将脚本保存为 quickDraft_interface03.ms。

7.在整个脚本的最末端,最后一个括号关闭之后,添加这样一行:

createDialog quickDraft_rollout width:111 height:216 escapeEnable:false

  (↑作用就是命令MAXScript执行“创建窗口”动作)

8.好啦!在你的脚本编辑器窗口中按Ctrl+E也就是File菜单中的Evaluate All 全部运算。我们的脚本代码就变成了功能完整的悬浮工具框出现在界面中了。打开庞大的Render Scene 渲染设置窗口,在你的快捷草图小工具中测试点击每一个复选框并观察对应的设置项目在Render Scene大窗口中的变化。(渲染高手们别忘了把渲染器改回Scanline先:)

  如果你的脚本中没有什么手工输入内容的误差的话(可以全部来自界面工具的生成以及复制/粘贴操作),那么所有的控制功能应该都会正确生效,不过有些选项可能需要先点几下来使它们的开关与当前场景设置同步。(因为到目前为止该工具只是具有设置作用,并不会在打开时反映当前场景已有的设置,例如:即使渲染器默认状态的阴影是开启的,但启动我们的工具时它的阴影复选框仍然显示为关,即未选状态;并且你可以发现如果在大的渲染设置窗口中更改某项设置时并不会引起小工具框中的任何变化。)

  要解决这一问题,我们将在脚本中继续添加event handler事件,来使快捷草图工具在初次开启时能够反映当前的渲染器设置。这个事件不属于任何一个界面元素,而是属于工具本身的。

9.再次打开可视化脚本编辑器,选择工具框本身,然后查看Event Handler编辑页面。

  工具界面本身有一个open处理器,它会在工具框初次启动时被执行。我们要做的是在open处理器中输入脚本,让它把工具框中的各项设置开关显示为与渲染器设置相同。和MAXScript中的其他元素一样,UI界面元素也有各自的属性,因此要设置复选框的状态,只要读取场景渲染设置中的各项参数值,并将其赋予各个复选框的.state属性就可以了。

  通过把概念实证脚本中的写入渲染器参数改为读取当前设置,即可完成我们的open处理器,这不是什么麻烦事。

10.点击open hendler,在处理器编辑框中输入下面的脚本(如果你想复制粘贴的话还可以在DVD上的quickDraft_open_handler.ms中找到)

  hidden.state = rendHidden
  rfw.state = rendShowVFB
  save.stage = rendSaveFile   re = maxops.getCurRenderElementMgr()   elements.state = re.getElementsActive()   aa.state = renderers.current.antiAliasing   samp.state = not renderers.current.enablePixelSampler   shad.state = renderers.current.shadows   area.state = rendSimplifyAreaLights   rt = rayTraceGlobalSettings()   raytrace.state = rt.enable_raytracing   atmo.state = rendAtmosphere   displace.state = renderDisplacements
11.成功了!保存界面代码,关闭可视化编辑器,再保存脚本为quickDraft_interface04.ms。之后使用Ctrl+E全部运算,就启动了我们快捷草图工具的最新版本!
  • 编辑此贴
  • 回复此贴


编号:1224
等级:护卫
发帖:576
精华: 2
在线:67小时
好评:73 点
贡献:13 点
加入时间:
2005-12-05
32 楼 [只看] ·2006-03-29 11:25 |

 

现在我们的小工具界面上应该已经可以反映当前渲染器的设置了(仅限于初次打开的情况下,在这之后修改大的渲染设置窗口仍然无法反映在小的工具中,这一问题在本例教程中没有涉及,深表遗憾……)。此外如果上一个版本的工具框你没有关闭的话也还在那里保持原样。

12.在更理想的情况下,我们希望它再聪明一点,在开启工具界面时懂得关闭已有的同名工具框。这一功能可以通过在整个脚本的开端使用destoryDialog命令来实现,现在在所有代码的最前面回车添加一个空行,输入:

try(destoryDialog quickDraft_rollout)catch()

  其中的try()和catch()在所有类型的脚本任务中都非常有用!当一段脚本被放进try()语句中执行的时候,出现的任何错误都不会导致MAXScript的抱怨和停工,而是转为执行catch()语句所包含的动作。而在上面的例子中,catch()没有任何内容,是个空括号,这就等于我们在告诉MAXScript忽略任何错误信息(例如没有发现叫做quickDraft_rollout的工具框,无法关闭目标)。

  假如在上面脚本中去掉try()和catch()组合(即直接用destroyDialog),整个脚本就可能在开始时由于没有发现名叫quickDraft_rollout的工具框而运行失败。加上它们就可以运行,而且是正点运行,无论我们是要替换先前的工具框还是开启一个新的。

13.在快捷渲染工具框开启和关闭的情况下尝试运行新的脚本,测试新功能是否工作正常。有必要把原有工具框移动一下位置来观察它们是否被关闭,否则可能是和新工具框重合的。

  如果你又成功了,那现在离我们的目标达成还剩下一步:我们要在脚本中添加几行代码来把它变成一个 macroScript宏脚本。宏脚本包含了额外的信息来为我们实现诸如赋予快捷键、成为工具按钮以及右键菜单等功能,此外它的扩展名为.mcr而不是普通脚本的.ms

  当我们运行一个宏脚本的时候,脚本代码不会被立即执行……而是在max目录里的UI/MacroScripts目录中建立了一个和它本身略有不同的版本,这时该脚本工具就可以在Customize User Interface自定义用户界面对话框中找到,我们也就可以把它做成标准界面工具的一部分了。实际上,大量的3ds max内置工具都是宏脚本。

  提示: 如果你要更改UI/MacroScripts目录中已有的宏脚本,把那个mcr文件复制到另一个目录下再编辑,然后通过MAXScript菜单运行它,就更新了目前正在使用的版本在界面中的定义。这样可以保证该界面元素被更新之后保持它们的代码与界面之间的连接。

14.为整个脚本的开端部分添写下列代码:

macroScript quickDraft Category:"Render" Tooltip:"quickDraft"
(

 ↑ 前两个词是把整个脚本做成一个名为quickDraft的工具,Category将它定位在自定义用户界面的Render分类中,Tooltip是在该工具作为按钮时,鼠标指向它时所出现的工具提示信息。

  注意上面脚本末尾是一个打开的括号,为了使MAXScript运转得高兴些,我们得在整个脚本的最后输入:

)

15.大功告成!把你现在的宏脚本保存吧,命名为quickdraft_final.mcr

16.从max主菜单中选择MAXScript -> Run Script,浏览到刚刚保存新鲜的quickdraft_final.mcr,打开它……看起来什么都没有发生,不过这一操作已经使quickDraft成为自定义用户界面中的一个命令了。

17.选择主菜单Customize -> Customize User Interface, 在自定义用户界面窗口上方选择Quads页面,即定义右键菜单功能。在左边Category类别下拉列表中选择Render,在下边标题为Action的长长的列表中随意选一个项目并按Q键,即可迅速翻到以字母Q开头的项目上,之后找到quickDraft,再用鼠标把它拖动到右边默认的菜单列表中一个合适的位置上。

18.关闭Customize User Interface 对话框,右键点击视图,从菜单中选择quickDraft即可启动我们的快捷草图工具框了。
  • 编辑此贴
  • 回复此贴


编号:1224
等级:护卫
发帖:576
精华: 2
在线:67小时
好评:73 点
贡献:13 点
加入时间:
2005-12-05
33 楼 [只看] ·2006-03-29 11:25 |

 

图片:
(↑如果不喜欢改变右键菜单,还可以去Toolbars页找到它,拎出来塞到任何一个工具按钮缝隙里,如上图。另外还可以把caption做成中文版什么的,适合给公司里鸟语不通的同志们分享:)

  恭喜恭喜!你已经完成了设计、验证、编写、测试、除错和安装你的个人脚本工具的伟大工程!在我们目前所涉及的常用基础范围内,创建该工具所使用的原理与技术几乎在所有方面都通用!
  • 编辑此贴
  • 回复此贴


编号:1224
等级:护卫
发帖:576
精华: 2
在线:67小时
好评:73 点
贡献:13 点
加入时间:
2005-12-05
34 楼 [只看] ·2006-03-29 11:25 |

 

下面是我翻译的 proof-of-concept 也就是前面需要参考和复制代码的那个脚本文件内容,直接发文字版的便于查看,也可以把它们复制到MAXScript编辑器中,得到着色显示效果

------------

--quickDraft 概念实证代码

--下面这行代码使我们能简单地运行脚本来测试我们的代码
--在完成后的工具中,名为state的变量将被对应复选框上的代码所支持
--在所有属性中把下面这行的true/false更改并运行,观察它们的变化
state = false

-------------------------------------
--renderers.current的子属性
------------------------------------
--Antialiasing 抗锯齿
renderers.current.antiAliasing = state

--Disable all Samplers 关闭采样
--***其中的true/false状态取值与复选框状态相反***
--在on Open handler中有这一用法的相关解释←该句翻译可能不准确,请参见原文
renderers.current.enablePixelSampler = not state

--shadows 阴影开关
renderers.current.shadows = state

/*
------------------------------
System Globals 系统全局变量
------------------------------
根据MAXScript参考手册中的解释,这些属性并非与Render Scene窗口中
所显示的状态直接关联。不过"renderSceneDialog"章节提供了一个工作区:调用

renderSceneDialog.update()

即可用MAXScript中的参数值更新当前渲染设置框中的状态,使它们保持同步

测试表明这种方法即使在渲染设置框没有打开的情况下也不会报错,因此我们可以
把它直接投入event handler使用而不必添加错误检查代码。

它们属于全局变量,我们可以在脚本开头的Open中直接调用,不必跳转于各个环节。

*/
--Render Hidden 渲染隐藏物体
rendHidden = state
renderSceneDialog.update()

--Rendered Frame Window 渲染结果显示窗口,以前叫Virtual Frame Buffer,即VFB
rendShowVFB = state
renderSceneDialog.update()

--Save File 保存文件
rendSaveFile = state
renderSceneDialog.update()

--Treat Area Lights as Point Lights 将区域灯光作为点光源
--
--提示:这一参数在脚本参考手册的对应章节无法找到,然而可以通过
--搜索关键字"area NEAR point"的结果中发现它存在于
--"What was new in MAXScript in 3ds max 6"章节中。←我晕~

rendSimplifyAreaLights = state
renderSceneDialog.update()

--Atmospherics 大气效果
rendAtmosphere = state
renderSceneDialog.update()

--Displacement 位移贴图
renderDisplacements = state
renderSceneDialog.update()

/*
----------------------------
结构成员

某些参数是隐藏在一些结构(structs)内部的。要想使其能够访问,
必须先为一个变量赋予该结构的副本,之后通过该变量的子属性形式
来访问所需参数。

在光线追踪器raytracer的全局变量结构中,这些变量可以直接操作,
但对于渲染元素render elements结构,则需要调用内置函数来访问和修改参数。
这意味着在Open hendler中需要添加额外的代码来获取当前状态

-------------------------------
*/
--Raytracing 光线追踪
rt = rayTraceGlobalSettings() --把光线追踪的全局变量副本,赋予一个名为rt的变量
rt.enable_raytracing = state

--Render Elements 渲染元素
-------------------
--******************下面两行代码是写入事件处理器用********************
re = maxops.getCurRenderElementMgr() --设置新值
re.setElementsActive state --注意此处没有等号,当前状态值将被传递到一个
--叫做setElementsActive的黑盒子函数中,这样完成了赋值过程.

--下面是在Open handler中用于获取当前渲染设置的代码
--********************下列代码不是用于事件处理器中的*****************
re = maxops.getCurRenderElementMgr()
re.getElementsActive() --获取true或false的函数
  • 编辑此贴
  • 回复此贴


编号:1224
等级:护卫
发帖:576
精华: 2
在线:67小时
好评:73 点
贡献:13 点
加入时间:
2005-12-05
35 楼 [只看] ·2006-03-29 11:28 |

 

OK...又一段落,不过这一节并没有完,还有个迷你颜色剪贴版的制作过程稍后奉上,快了……
  顺便说一下,我在译文中为了表达清楚,有时将同一个词的中英文并列写出,比如“UI界面”、“MacroScript宏脚本”这种,但我们实际交流和表达时没必要这样,说UI就说UI,说界面就说界面或用户界面就可以了,如果把两个一起说出来就好象英语里说 Changjiang River 一样荒唐……虽然按照国际惯例也凑合用了,还是简洁和舒服一点更好
  • 编辑此贴
  • 回复此贴


编号:1224
等级:护卫
发帖:576
精华: 2
在线:67小时
好评:73 点
贡献:13 点
加入时间:
2005-12-05
36 楼 [只看] ·2006-03-29 11:28 |

 

创建一个嵌入式工具条:颜色剪贴板

  有很多时候即使一个最小的浮动窗口工具都会令我们觉得干扰界面操作。而自从max5开始,脚本编写者们就可以把工具框做成可嵌入式工具条。它可以包含任何MAXScript可以创建的UI界面元素,干净整齐地排列成标准工具按钮的样子。

  在下面一节中,我们就将建立一个简单而整齐的嵌入式工具条来代替原本隐藏在Utility面板中的颜色剪贴板的浮动工具框。和我们制作quickDraft的目的一样,制作这个工具也是为了避免我们把过多的时间耗费在频繁转战于各个面板之间,从而可以提高工作效率。

设计要素

  为了使我们的UI工具按钮放得进标准工具栏,我们在其尺寸上要多多留心,以使它的高度与标准工具栏可以匹配,同时我们不需要它有过多的控制项目,因为工具栏上的空间也并不宽裕,尤其在分辨率不是很高的情况下。

  在空间与实用性兼顾的指导思想下,我们来把这个工具做成6格的颜色样本框吧。  

  制作这一工具有一个相当便利的条件是:colorPicker颜色拾取器的UI界面元素内置了对鼠标拖放操作功能的支持,所以它里面没有什么event handler事件处理代码,也就不需要我们做所谓“概念实证化”的工作步骤了。

编写脚本

  没有什么需要检验和证明的,让我们直接进入正式步骤。为界面规划找出一个合适的尺寸数值可能是一个比较耗时的过程,因此我们在这里已经先给出了这些值。

  提示:工具栏按钮的大小会因你的界面设置而改变(主菜单 Customize -> Preferences中的 Use Large Toolbar Buttons工具栏使用大按钮设置),本节中我们按照小型按钮进行尺寸匹配。

  如果你喜欢大按钮,可以用四个而不是六个颜色拾取器,把下面将要给出的规格换为height 39,width 152,颜色框之间的X spacing间距 32 ,还有颜色框本身的高和宽也都为32。

  DVD上包含了这个工具的一个完整的大按钮版本 colorClip_large.mcr

1.打开一个MAXScript Editor,选择Edit -> New Rollout或者按F2来启动Visual MAXScript。

2.为界面属性页输入如下参数:

name:colorClip

Caption: Color Clipboard

width:160

height:30

3.然后在界面上画出一个colorPicker(颜色拾取器工具的按钮就是下面唯一是彩色的那个),先不必管它大小因为我们即将手动设置。

4.为颜色拾取器设置下列参数:

caption: 删除原标题,将该栏目留空

x-pos: 2

y-pos: 3

width: 20

height: 20

color: (color 128 128 128)

5.把设置好的颜色拾取器进行五次的复制/粘贴,再手动把它们的x-pos即x轴位置属性分别改为 26,50,74,98,122。并且确保全部y-pos属性为3。这样你的界面应该和图6.9一样了(如果你和我一样忘了删除原标题,那么该按钮就显示为标题名而不是彩色图标了)。此外横向上之所以留出额外的空白,是留给该工具在界面中放置时将要出现的移动手柄的。
  • 编辑此贴
  • 回复此贴


编号:1224
等级:护卫
发帖:576
精华: 2
在线:67小时
好评:73 点
贡献:13 点
加入时间:
2005-12-05
37 楼 [只看] ·2006-03-29 11:28 |

 

图片:
图6.9 在Visual MAXScript中规划Color Clipboard颜色剪贴板工具界面
  • 编辑此贴
  • 回复此贴


编号:1224
等级:护卫
发帖:576
精华: 2
在线:67小时
好评:73 点
贡献:13 点
加入时间:
2005-12-05
38 楼 [只看] ·2006-03-29 11:29 |

 

.保存并关闭你的Visual MAXScript

7.再保存脚本为 colorClip_layout.ms

8.现在我们来为它加上成为宏脚本所需的 header头,closer尾,和dialog declaration“建框声明”,就和quickDraft中所用的差不多。在全部脚本的最前面,加入:

macroScript ColorClip Category:"Color Clipboard" Tooltip:"Toolbar Color Clipboard"
(
try(destroydialog colorClip)catch()

在最后面加入:

createDialog colorClip width:160 height:30 style:#(#style_toolwindow) escapeEnable:false
)

9.为了使这个工具框可以嵌入工具按钮栏,我们需要再添加两行代码。在脚本末尾部分,createDialog行与最后的关闭括号之间写入一行:

cui.registerdialogbar ColorClip style: #(#cui_dock_horz,#cui_floatable,#cui_handles) minsize:[160,30] maxsize:[160,30]

  (↑注意是单行)这一行代码就可以告诉max把我们的工具框当作可嵌入界面的工具按钮来使用

10.在开始的部分,第一个开括号与 destroyDialog行之间,加入:

try(cui.unregisterdialogbar ColorClip)catch()

  ↑需要这行代码的原因是:我们要使destroyDialog行的操作生效,就必须先把可嵌入工具框改回标准工具框,所谓cui.unRegisterDialogBar的就是在界面中用来取消某个嵌入工具的

11.我们又完成了!把现在的脚本保存为 colorClip_complete.mcr。

12.通过主菜单 MAXScript -> Run Script来运行该脚本,从而将其注册为宏脚本

13.打开自定义用户界面即Customize User Interface对话框,在右键菜单或者工具按钮项中放入我们新出炉的Toolbar Color Clipboard。如图6.10
  • 编辑此贴
  • 回复此贴


编号:1224
等级:护卫
发帖:576
精华: 2
在线:67小时
好评:73 点
贡献:13 点
加入时间:
2005-12-05
39 楼 [只看] ·2006-03-29 11:29 |

 

图片:
图6.10 将颜色剪贴板宏脚本加入右键菜单
  • 编辑此贴
  • 回复此贴


编号:1224
等级:护卫
发帖:576
精华: 2
在线:67小时
好评:73 点
贡献:13 点
加入时间:
2005-12-05
40 楼 [只看] ·2006-03-29 11:29 |

 

图片:
14.用右键菜单启动该工具,测试它的效果满意否,如图6.11
  • 编辑此贴
  • 回复此贴


编号:1224
等级:护卫
发帖:576
精华: 2
在线:67小时
好评:73 点
贡献:13 点
加入时间:
2005-12-05
41 楼 [只看] ·2006-03-29 11:30 |

 

好了,我们关于MAXScript所学的十个单词和两个工具到此告一段落。希望这一章节的内容已经帮大家打开了MAXScript的视野,也使它看起来有着更多的可能性和易用性。下面总结一下前边的要点:

几个单词的强大功能 我们已经学习了在Listener中,通过一个小小的词汇库,使用show命令得到的一点点帮助信息以及for循环,就能够批量处理场景中的参数,还有关于random命令的实例帮助我们以更少的操作达到可信的效果。
人人需要帮助手册 标准的MAXScript参考手册是必不可少的,即使对于专业技术人员也是一样。请多多参考它,并灵活运用搜索功能。此外网络上也有很多高明而友好的脚本编写者,可以通过你的方式请教他们。
使用可视化界面编辑 我们已经知道Visual MAXScript 工具可以用来以不必编写脚本的方式创建个性化工具界面,因此建立一个完整的工具就只是往界面元素的事件处理器中添加代码的事,除错也是根据返回的错误信息来完成的。
嵌入式工具框使我们可以在自定义按钮工具栏上使用MAXScfript元素 我们先学会了把脚本转换为工具框,又知道了如何把工具框嵌入界面成为工具按钮栏的一部分。
  总而言之,这些技术提供给我们一套强大的省时省力工具库。提高这种技能的有效途径是在你的工作中寻找可以使用脚本的时机,努力坚持使用它,即使初期练起来显得更慢。

  两个适合使用脚本解决问题的信号是:

厌倦 重复的任务,如调整大量物体的同一属性,在许多文件里做大量相同操作之类,通常可通过for循环脚本解决
累手腕的事 3dsmax是一个庞大的程序,而它的界面又是考虑了所有用户的所有需要而设计的。如果你发现自己在工作中经常深入一些隐蔽面板去挖出你需要的工具框,不妨考虑一下自己做点什么来把它搞得更表面一些。
  一旦你决定要使用脚本完成任务,拿起本章讲述的设计-证明-实验-工具法则。现在开始吧,把每天辛苦工作的时间缩短再缩短!
  • 编辑此贴
  • 回复此贴


编号:11710
等级:论坛游民
发帖:67
精华: 0
在线:28小时
好评:0 点
贡献:1 点
加入时间:
2006-12-01
42 楼 [只看] ·2006-12-03 12:22 |

 

很不错,还有吗.赞~~~~~~~~
  • 编辑此贴
  • 回复此贴
主题操作 ×