2012-06-04 18:10:15| 分类: RealFlow探索 | 标签: |举报 |字号大中小 订阅
6.1什么是图形用户界面?
图形用户界面(GUI)一种给用户带来友好交互环境的工具。每次你启动电脑就能看到GUI。调色板,按钮,工具栏,和值字段都是界面元素。包括RealFlow也提供了图形用户界面,它包括,窗口,参数标签,和选择列表里的发射器(emitters),辅助器(daemons)或约束器(constraints)。
你已经从前面小节学习作用了变量(Variables),像标量(Scalar)、列表(List)或矢量(Vector)。直到现在,你必须在脚本一开始定义所有变量,包括函数或循环什么。如果想让用户自己输入初使值,而不用你在源代码改变参数。能不能实现呢?
RealFlow中的Python提供了创建GUI的功能函数。
它们不像你掌握的别的软件的图形界面那么复杂。你可以用自定义的值创建一个窗口。这些值将由RealFlow接管,然后使用你的当前脚本。
(拓展:图形用户界面(Graphical User Interface,简称 GUI,又称图形用户接口)是指采用图形方式显示的计算机操作用户接口)
摘自维基百科:http://zh.wikipedia.org/zh-cn/GUI
GUI可以用在批处理脚本(Batch),和事件脚本(Events scripts),但大部分用在批处理脚本。事件脚本要使用GUI,只能在onSimulationBegin 和onSimulationEnd 模块下。
GUI使用一个特定的结构。这个结构都是一样的,只有内容(content)是不同的。另一个非常重要的问题是,所使用的数据类型。如同所有的变量,正确规范的使用数据类型是,脚本执行的前提。定义一个数据类型要避免写成这样:
number_of_objects = 23
在这个例子里,这值显然是一个Integer(整型)带有GUI情况是不同的,因为你得希望从用户那里得到一个确切的数据类型去定义。因此在你开始建立一个GUI前,要决定你到底要使用哪个类型,是必不可少的。做了一些练习后你会很快就会对变量有感觉的。
用RealFlow GUI不仅能创建自定义窗口,还能添加自定义反馈信息和使用文件,或结点选择器(node picker)。最常见的应用形式肯定是自定义默认值。GUI的工作进程分为两个步骤:
1.创建所有你要提供给用户的字段(field)和变量(Variable)
2.传递到脚本所用到的自定义项。
第一步是定义一个新的变量,包含GUI对话窗口:
form = GUIFormDialog.new()
这个语句作用是初始化窗口。对话窗口也被称为(modal window)模式窗口.这种类型的窗口总是前置的,只要这个模式窗口是打开的,主程序就无法访问执行。
你的下一个任务是定义用户变量。RealFlow几乎支持所有数据类型。
form.addIntField()
form.addFloatField()
form.addVectorField()
form.addListField()
form.addBoolField()
form.addStringField()
唯一一种数据类型不支持的是Dictionary。(配对列表或译作“字典”)
让我们仔细看看在这些附加语句。每条语句有一系列参数,定义用户基本信息:
The field's name (字段名称)
The default value(默认值)
addListField()也需要List项,例如粒子类型像Dumb,Liquid,Gas,Elastic或自定义。List必须在使用GUI指令前定义。另一个需要注意的是使用唯一的名称,你不能用同样的名字给两个或两个以上的字段。
为了给你一个创建GUI的第一印象。这里给出一个例子,设置基本场景发射器,在Batch Script:
form = GUIFormDialog.new()
e_types = ["Circle","Square","Sphere","Triangle"]
p_types = ["Liquid","Dumb","Elastic","Gas","Custom"]
form.addListField("Emitter", e_types, 0)
form.addListField("Type", p_types, 0)
form.addFloatField("Resolution", 1.0)
form.addFloatField("Density", 1000.0)
form.addFloatField("Viscosity", 3.0)
form.addStringField("Name","BasicEmitter")
如你在例子中看到的List变量被使用在addListField()语句,当然所有非变量要写在引号之间,同样List和参数要写在括号里。
至今为止这些脚本片段还不能在RealFlow里运行,因为一些函数不存在。下面有最终效果的预览,稍后会讲怎么得到这个窗口。 你可能会注意到在GUI中字段名称不需要排列成某些顺序。RealFlow是按字母顺序排列字段的,但这不影响GUI的功能。
第二步要使GUI完成,要用给脚本设置变量。应该告诉脚本,用户当前输入的值要做什么。这样的转换通常要引用户if语句。if (form.show() == GUI_DIALOG_ACCEPTED):
GUI_DIALOG_ACCEPTED) 是一个固定的用法,判断用户是否点击了OK(确定)。不确定(cancel)就是 GUI_DIALOG_REJECTED)。现在,你传递值到变量里。关键指令写成这样:
variable_name = form.getFieldValue()
这getFieldValue()语句需要一个参数,这正好是字段的名称。
emitter_type = form.getFieldValue("Emitter")
particle_type = form.getFieldValue("Type")
resolution = form.getFieldValue("Resolution")
density = form.getFieldValue("Density")
viscosity = form.getFieldValue("Viscosity")
name = form.getFieldValue("Name")
这也是为什么不能允许用户不能用重名,因为结果不能模棱两可。在此过程中创建的变量,与之前任何变量一样使用。总之这些指令能设置出一个新的用户对话窗口了。
Batch Script: CreateBasicEmitter.rfs
# Create new modal window and define fields
form = GUIFormDialog.new()
e_types = ["Circle","Square","Sphere","Triangle"]
p_types = ["Liquid","Dumb","Elastic","Gas","Custom"]
form.addListField("Emitter", e_types, 0)
form.addListField("Type", p_types, 0)
form.addFloatField("Resolution", 1.0)
form.addFloatField("Density", 1000.0)
form.addFloatField("Viscosity", 3.0)
form.addStringField("Name","BasicEmitter")
# Transform user values into variables
if (form.show() == GUI_DIALOG_ACCEPTED):
emitter_nr = form.getFieldValue("Emitter")
particle_nr = form.getFieldValue("Type")
resolution = form.getFieldValue("Resolution")
density = form.getFieldValue("Density")
viscosity = form.getFieldValue("Viscosity")
name = form.getFieldValue("Name")
# Get the emitter/particle type from the lists
emitter_type = e_types[emitter_nr]
particle_type = p_types[particle_nr]
# Create emitter using the new variables
emitter = scene.addEmitter(emitter_type)
emitter.setParameter("Type", particle_type)
emitter.setParameter("Resolution", resolution)
emitter.setParameter("Density", density)
emitter.setParameter("Viscosity", viscosity)
emitter.setName(name)
这个是完整脚本,前两个部分在上面已经做过解释。发射器的创建过程仅仅使用了get和set指令(Get&Set知识请看第五节)。而真正的名称和数字,像1000.0或3.0,仅仅使用了变量。为了更好理解,我想通过输入值来解释脚本:
1.添加字段,名称是Resolution 用默认的值1.0
2.用户输入一个值 5.0
3.脚本从GUI窗口获得到值5.0
4.resolution变量值设置成5.0
5.5.0给setParameter语句使用
6.脚本插入5.0给结点中的分辨率(Resolution)
列表对像是有一点棘手,但这里不会教引入新东西,也就是这里所有知识点都是已经讲过的。
addList
Field()语句不会处理字符串,但可以处理序列(索引)。不是这样
form.addListField("Emitter", e_types, "Circle")
参数需要一个序列(索引,index)识别正确的类型在e_type列表。因为列表默认从0开始,所以
form.addListField("Emitter", e_types, 0)
从GUI窗口获得正确的类型。问题是GUI也设置0在这个表达式中:
emitter_nr = form.getFieldValue("Emitter")
我们需要从这个表达式中获得字符串,不是数字。因为没有发射器类型称为 0:
emitter = scene.addEmitter(emitter_type)
用这个表达式我们从e_types列表获得字符串:
e_types = ["Circle","Square","Sphere","Triangle"]
emitter_type = e_types[emitter_nr]
emitter_type = e_types[0]
跟遍历粒子一样,创建的GUI也遵循这个规则。请你一定手动实践一下,光看是理解不了的。
6.3文件和节点选择器
本章的最后一部分是打开文件和选择节点(节点也就是是对一些功能的称呼,如发射器结点,辅助器功能等)。RealFlow有解决这个问题的两个指令,两者很相似:
files = GUIFilePickerDialog.new()
path = files.show( FILE_PICKER_LOAD, "/Users/tsn/RF",
"*.jpg;*.tga;*.tif", "Load Images" )
在这里关键字是FILE_PICKER_LORD,用于保存的是FILE_PICKER_SAVE. 下一个表达式指定你,正在寻找的文件相应目录的路径,包括文件扩展名。最后这句话表明窗口名称。
可以扩展到其他各种文件格式。假如你要使用RealFlow里的序列图片。图片被保存成JPG,TGA或TIF格式,别的格式不能支持:
"*.jpg;*.tga;*.tif"
如果你不想限制文件类型,只要用通配符“*.*”
节点选择器打开一个窗口,在节点窗口显示所以存在的项。在此窗口中可以进行多重选择,所选的对像可用于你的脚本。此操作的结果是一个列表,其中存储所有的名称。
dialog = GUINodesPickerDialognew()
nodes = dialog.show( TYPE_EMITTER | TYPE_DAEMON )
for node in nodes:
scene.message(node.getName())
这个例子是直接取自的RealFlow的联机帮助,并显示了创建该方法。这个类型表达式,只能允许几个对像类型,被用在RealFlow里。更详细的这些类型是:
TYPE_DAEMON
TYPE_OBJECT
TYPE_EMITTER
TYPE_MESH
TYPE_CONSTRAINT
TYPE_REALWAVE
ALL_TYPES
类型关键字之间的分隔符是所谓的管道字符(Pipe character),可以按下ALT +\(windows系统),或者 ALT+7(OS X 苹果系统). ( 在" 】"号后面那个键)
我总是建议要通过实践找出这些GUI数据类型.可以运行了吧。特别是新手总会迷惑,到底要用哪个数据类型,和怎么处理列表(List)输入项呢。你只要从简单的脚本开始,在前面的方案的基础上,然后进行更加困难的GUI。
(下一节是压箱底的非常完整案例。浪花泡沫,是需要前面所有知识点的,如果你想学习下面一节,一定要把前面所有节再复习一次听我的没错。老实说,前面我看了至少50多遍啊,才能看懂后面的案例。)
评论