原文链接
Blender Interface
Blender 主要有两种 UI:
- 继承自
bpy.types.Panel, 有 properties 和 draw function bpy.types.Operator, 有 properties, execute function, 可选的 invoke function
一个注册文件中所有类的方法是 bpy.utils.register_module(__name__)
Panels and buttons
可以通过以下代码添加一个按钮
self.layout.operator("hello.hello", text='Hej').country = "Sweden"
UILayout.operator 具有额外参数:
text: 按钮上的字text_ctxt: 用于翻译translate: 是否翻译icon: 图标, 比如 QUESTION, ERROR, CANCELemboss: bool, 是否显示按钮的凸起
同时这个函数具有返回值, 可以对对应的 operator 设置调用时的 properties, 可以设置多个 properties, 如下:
op = row.operator("transform.translate")
op.value = (1,-1,-1)
op.proportional_size = 1
和 operator 一样, panel 同样有 bl_* 的前缀, 常用的有
bl_idname: idbl_label: label, 提示性文字, 标题bl_space_type: 属于哪个 space, 如 VIEW_3D, PROPERTIESbl_region_type: 属于哪个 region, 如 TOOLS, TOOL_PROPSbl_context: 取决于具体环境, 这三项从上到下决定了具体 panel 的具体位置
可重载函数:
classmethod poll(context): 返回 bool, 是否绘制 uidraw_header(context): 用来绘制标题draw(context): 用来绘制 panel
Panel properties
除了 operator, 还可以使用 panel 控制 properties, 如下:
layout.prop(ob, 'myRnaInt') # RNA properties
layout.prop(ob, '["myRnaInt"]') # ID properties
以及一些常用的 ui 元素:
layout.template_ID: ID 链接prop_menu_enum: 枚举类菜单
Panel layout
layout.row(): 在同一行, 有一个参数, align, 表示元素是否为紧凑排列layout.column(): 同 row, 按列排列layout.alignment: 设置对齐方式layout.box(): 包围盒layout.separator(): 分隔符layout.split(): 有一个参数 percentage, 按行宽度百分比拆分
menu
找到对应的菜单, 使用 prepend/append 函数添加绘制函数
bpy.types.INFO_MT_mesh_add.prepend(menu_func)
bpy.types.INFO_MT_mesh_add.append(menu_func)
bpy.types.INFO_MT_mesh_add.remove(menu_func)
A modal operator
modal operator 和普通的 operator 的 区别 是, Operator.modal 被重载用来处理事件, 主要用于交互式的 operator
modal 函数的返回值有 4 种 :
FINISHED: 结束CANCELLED: 取消RUNNING_MODAL: 等待下一个事件触发继续运行PASS_THROUGH: 不知道… 把 blender 整个代码搜了一遍也只有很少很集中的地方用到了, 应该不用也没问题, 感觉像是多个 modal operator 调用时处理的事情?
可以通过重载 __init__ 和 __del__ 获得 modal operator 开始和结束的信息
在调用时使用语句 context.window_manager.modal_handler_add(self)
Blender Addon
bl_info,包含字段仅用于在 user preference 显示用
register 与 unregister 将会被调用,当在 user preference 里对 addon 激活和关闭时
bpy.types.Operator 继承
bl_idname: 必须,且唯一,用于 api 调用bl_label: 必须,表示操作名称__doc__: 用于显示为 tooltipbl_options: 枚举类集合
REGISTER默认选项UNDO支持撤销BLOCKINGMACROGRAB_POINTERPRESET在操作设置显示一个 preset 按钮INTERNAL无法从外部搜索到
execute(context): 运行 op,同时返回状态
Operator Property
通过在类内部声明 property,可以让 operator 拥有参数输入,并且在最后一次操作面板里会出现一个简单地面板,显示所有 property
添加菜单
bpy.types.VIEW3D_MT_object.append(menu_func)
类似于重载 menu 类中的 draw 函数,append 为在 draw 之前运行,prepend 在之后运行,以及 remove
def menu_func(self, context):
self.layout.operator(ObjectCursorArray.bl_idname)
通过 layout.operator 绘制一个操纵 operator 的菜单项