【笔记-Blender】插件开发

BDFFZI / 2024-01-14 / 原文

【笔记-Blender】插件开发

前置工作

  • 打开设置“界面-开发选项”:
    这样可以通过对功能按钮的右键菜单直接复制或查看其源码,以及快速跳转到API手册。
  • 打开设置“界面-Python工具提示”:
    这样可以通过界面的悬停菜单直接查看该条目在代码中的表示方式。
  • 通过命令提示符打开Blender(也可通过“窗口-切换系统控制台”打开):
    这样可以利用python的print函数打印信息并显示在黑窗中(blender控制台不支持显示)。

编码环境

在内置环境中快速实现小功能,然后在外部环境组合成完整插件。

Blender内置环境

Blender自带Python解析器并会配置好相关环境,所以在此编写的代码可以直接运行,能很方便的进行一些代码片段的测试或快速执行一些临时操作。

不要在内置环境中执行注册类等操作,因为相比外部插件的方式,二次访问这些类会更困难,导致会出现无法取消和多次注册的问题。

  • Blender的Python控制台:
    自动引入所有模块,支持代码补全提示,常用于快速测试一些单行代码的可用性。
  • Blender的文本编辑器:
    无法进行代码补全,但弥补了控制台的单行代码缺陷,通常两者配合使用。

外部环境

需要自己配置开发环境,写完后还要再通过安装插件的方式嵌入Blender,整体流程肯定也没内置环境快。但若要做一个完整的插件,考虑代码量,资源文件,编辑器集成等,肯定还是在外单开一个项目更合适,具体开发时还可以内外环境配合使用。

目前市面上也有很多编辑器插件支持Blender的开发,比如VSCode内就有,可以实现自动打包并导入插件到Blender,大幅提升开发效率,可以基本实现和内置一样。

关键概念

编码原理

所有功能或数据都被用Python封装,我们包括编辑器都只是调用这些函数。

Blender的核心代码是用C++写,但其中很多常见操作都被封装成了Python函数,而Blender编辑器就相当于是调用这些函数的一个可视化入口,而我们所写的Blender脚本也是一样,只是换成了用代码的方式调用,这点可以通过Python的工具提示功能看出来。

除此之外,很多数据也被用Python进行了封装,精准控制网格的每个顶点或图像的每个像素都是完全可以的,这也正是脚本占优的地方,使用Blender编辑器只能靠官方提供的方式处理数据,很多冷门点的操作都没有,这时换成脚本就可以完美解决了。

资源处理

所有资源都存在集合中,包括对象的生命周期也完全由对集合的增删控制。

Blender中的各种资源都是一个个对象,而所有的对象都被存在了一个个集合里,并且这集合完全管理这些物体的生命周期,这意味着创建或删除物体的方式不再是常规的new,delete这些,而是要使用这些集合的函数在里面添加和移除对象。

访问属性

所有资源的属性包括自定义属性在代码中都有对应,可以利用Python工具提示查看。

所有图像界面上的设置在代码中都有对应的属性,可用利用Python工具提示很容易的看到这些,除此之外基本上每个资源都有额外的自定义属性功能,同样可以在代码中索引访问。

访问功能

所有界面上的功能都一定对应着代码中的一个运算符,借此可以像图像界面上一样调用这些功能。

Blender中所有可调用的功能都是一个运算符,如果创建了一个UI按钮,按钮所能绑定的事件也必须是运算符,而运算符需要继承实现并注册,虽然有些繁琐,但也因此所有UI上的可用功能在代码中也都可以调用对应的运算符实现。

部分运算符需要在特定的环境下才能运行,否则会抛出异常,对于这种特殊的运算符可以调用它的poll函数进行判断,来确定当前环境是否可以调用。

如果启用了“界面-开发选项”功能,那可以通过“帮助-操作项信息一览”菜单项创建一个包含所有运算符及其默认参数的文本文件,然后可以用Blender的文本编辑器查阅,这样可以很方便的了解到内置运算符及其调用方式。

代码集成

通过继承实现编辑器提供的接口类并注册的方式来将代码集成到编辑器中。

如果想把自己代码做成插件,集成到Blender编辑器中而不是一次性运行,那必须以下几个方法来实现(更具体的说是必须要继承对应的Blender类,并注册到编辑器才行)。

  • 通过定义渲染引擎。
  • 通过定义运算符。
  • 通过定义菜单、标题和面板。
  • 通过将新按钮插入到现有菜单、标题和面板中。

常用属性

注意:以下仅列出关键字,具体使用应查看官方文档

空间

bpy.data #当前项目里所有的资源,对应“大纲视图-Blender文件”界面。
bpy.context #当前编辑环境,如选中的物体,正在使用的编辑模式等。
bpy.ops #blender自带的所有运算符
bpy.utils #可选的杂项实用程序,不是blender内部数据处理的必须渠道,一般用其的注册功能较多。
bpy.props #用于实现自定义属性,必须使用在blender原生的物体上

bpy.types.Operator #运算符基类
bpy.types.Panel #UI面板基类
bpy.types.UILayout #绘制UI的工具类

函数

# 自定义类的注册和取消
bpy.utils.register_class
bpy.utils.unregister_class
# 简易消息弹窗
def ShowMessageBox(message = "", icon = 'INFO'):
    def draw(self, context):
        self.layout.label(text=message)
    bpy.context.window_manager.popup_menu(draw, title = icon, icon = icon)
# 自定义属性显示
# 1. 使用类似反射机制,参数是为反射服务,这和一般的IMMUI参数不一样,注意别填错
# 2. 属性必须是自定义属性
bpy.types.UILayout.prop(包含该属性的物体,该属性的字段名)

参考资料

Blender官方API文档