跳至内容

Blender 3D:从新手到专业/高级教程/Blender 脚本/插件剖析

来自维基教科书,开放的书籍,为开放的世界

一个插件是一个 Python 脚本,它可以以多种方式扩展 Blender 的功能。它可以位于 Blender 用户首选项目录中的一个文件中,也可以存储在 Blender 文档中的一个文本块中。在前一种情况下,插件需要在您想要使用它的每个 Blender 文档中启用,方法是在该文档的用户首选项窗口中的“附加组件”列表中选中其条目中的复选框。在后一种情况下,可以通过在文本编辑器窗口中按  ALT + P  来运行脚本;或者您可以在文本编辑器中选中该脚本的“注册”复选框,使插件在文档加载到 Blender 中时自动启用。

插件脚本通常执行的主要功能是定义一个或多个新的操作符。Blender 中的所有用户界面功能都是由操作符执行的;这些操作符通过与菜单项、按钮或热键关联来调用。每个操作符都是bpy.types.Operator类的子类。您在 Python 中为类提供的名称在定义它的脚本之外是无关紧要的;它将在 Blender 中通过其操作符名称来引用,该名称在文档中必须是唯一的。同样,您的脚本可以通过使用带有操作符名称的 Blender API 函数来调用其他地方定义的操作符。

文本块

[编辑 | 编辑源代码]

Blender 文档可以包含文本块,它们与 3D 场景中的文本对象不同(虽然前者可以转换为后者)。除了生成文本对象外,文本块还可以满足您喜欢的任何目的;例如,使用它将工作流程说明与文档一起传递给同事;在用户打开文档时看到的初始布局中显示版权或帮助消息;或者保存一个 Python 脚本,用户可以运行该脚本来执行与文档相关的某些有用操作。

您的第一个操作符

[编辑 | 编辑源代码]

打开一个新的、空的 Blender 文档。在任何方便的窗口中调出文本编辑器 ;您将看到一个空的灰色矩形。在您开始输入文本之前,需要创建一个文本块;通过点击窗口标题栏中标记为“新建”的大按钮来创建文本块。您一这样做,应该会看到一个弹出菜单出现,列出您文档中的所有文本块,当前(唯一)的条目名为“文本”。您还应该看到一个红色的插入光标出现在左上角,表明您可以开始输入。

与控制台窗口不同,不会自动为您导入任何内容。因此,与其他任何 Python 脚本一样,您需要提及您要访问的每个模块。

您将操作符定义为的子类。bpy.types.Operator。它必须具有一个bl_idname类属性,该属性提供操作符名称,而bl_label提供在空格键菜单中显示的用户可见名称。前者必须具有有效的 Python 语法作为名称,包括一个点;点左边的部分必须是有效操作符类别之一的名称,您可以在控制台窗口中键入

dir(bpy.ops)

来找到它们。

让我们定义一个操作符,它将为文档添加一个新的四面体对象。类定义应该以类似以下内容开头

class MakeTetrahedron(bpy.types.Operator) :
    bl_idname = "mesh.make_tetrahedron"
    bl_label = "Add Tetrahedron"

它必须定义一个invoke方法,该方法以类似以下内容开头

    def invoke(self, context, event) :

invoke方法执行操作符的实际功能;它完成后,必须返回一个字符串集,告诉 Blender 一些事情,例如操作符是否仍在模态状态下执行,或者操作是否已完成,如果是,是否成功。要指示成功完成:在invoke方法的末尾加上以下内容

        return {"FINISHED"}

无论如何,让我们计算四面体顶点的坐标:如果边长为 1 个 Blender 单位,则合适的数值为 。或者用 Python

        Vertices = \
          [
            mathutils.Vector((0, -1 / math.sqrt(3),0)),
            mathutils.Vector((0.5, 1 / (2 * math.sqrt(3)), 0)),
            mathutils.Vector((-0.5, 1 / (2 * math.sqrt(3)), 0)),
            mathutils.Vector((0, 0, math.sqrt(2 / 3))),
          ]

然后我们创建网格数据块,并将其命名为“Tetrahedron”

        NewMesh = bpy.data.meshes.new("Tetrahedron")

用上面的顶点定义和相关的面填充它

        NewMesh.from_pydata \
          (
            Vertices,
            [],
            [[0, 2, 1], [0, 1, 3], [1, 2, 3], [2, 0, 3]]
          )

Mesh.from_pydata方法目前在 Blender API 中没有很好的文档,但它的第一个参数是Vector定义顶点的数组,第二个参数是边定义的数组,第三个参数是面定义的数组。每个边或面都定义为一个顶点索引列表(边中每个列表有 2 个元素,面中每个列表有 3 个或 4 个元素),以通常的 Python 风格从 0 开始,是您传递的顶点定义数组中的索引。请注意,您传递的是边定义或面定义,而不是两者:另一个应该作为空列表传递。如果此函数使用不正确,会导致 Blender 崩溃。

我们还需要添加以下内容,告诉Blender网格已更改并需要更新(就好像它自己无法弄清楚一样)。

        NewMesh.update()

(省略此操作会导致一个轻微的怪癖:右键单击新创建的四面体不会像其他对象一样以橙色突出显示其轮廓,但如果您进入对象的编辑模式并再次退出,问题就会消失。)

现在创建对象数据块(我也给它命名为“四面体”),并将其链接到网格。

        NewObj = bpy.data.objects.new("Tetrahedron", NewMesh)

但是,在将对象链接到场景之前,用户将看不到它。

        context.scene.objects.link(NewObj)

回顾一下,这是完整的脚本。

import math
import bpy
import mathutils

class MakeTetrahedron(bpy.types.Operator) :
    bl_idname = "mesh.make_tetrahedron"
    bl_label = "Add Tetrahedron"
    def invoke(self, context, event) :
        Vertices = \
          [
            mathutils.Vector((0, -1 / math.sqrt(3),0)),
            mathutils.Vector((0.5, 1 / (2 * math.sqrt(3)), 0)),
            mathutils.Vector((-0.5, 1 / (2 * math.sqrt(3)), 0)),
            mathutils.Vector((0, 0, math.sqrt(2 / 3))),
          ]
        NewMesh = bpy.data.meshes.new("Tetrahedron")
        NewMesh.from_pydata \
          (
            Vertices,
            [],
            [[0, 2, 1], [0, 1, 3], [1, 2, 3], [2, 0, 3]]
          )
        NewMesh.update()
        NewObj = bpy.data.objects.new("Tetrahedron", NewMesh)
        # Blender 2.79: context.scene.objects.link(NewObj)
        context.collection.objects.link(NewObj)
        return {"FINISHED"}
    #end invoke
#end MakeTetrahedron

bpy.utils.register_class(MakeTetrahedron)

注意添加了register_class调用,以使Blender将您的操作符添加到其内置集合中。

现在通过键入 ALT + P 执行您的脚本。如果一切顺利,不应该发生任何事情;Blender 将定义该类并将其注册为您请求的新操作符,准备使用。

如果您遇到任何语法错误,Blender 应该会在弹出窗口中显示这些错误;返回并更正它们,并使用 ALT + P 重新执行脚本。

调用您的操作符

[edit | edit source]

我们还没有(尚未)为该操作符定义任何用户界面;那么我们如何调用它呢?很简单。

转到 3D 视图窗口。删除默认立方体以避免它遮挡物体,然后按 SPACE (Blender 2.8 和 Blender 3 中为 F3)。这将打开一个可搜索菜单,其中包含为当前文档定义的每个操作符。在搜索框中,键入您为bl_label属性(键入“tetra”可能就足够了)。这将限制菜单仅显示包含该字符串的项目,其中应包括您的操作符的名称;使用 LMB 单击此操作符或突出显示它并按 ENTER 。如果一切顺利,您应该看到四面体对象出现!。如果它没有出现,请确保在“首选项编辑器”的“界面/显示”中选中“开发者附加功能”框。

如果您遇到错误

[edit | edit source]

如果编译或运行脚本时出现任何错误,Blender 应该会在弹出窗口中显示此错误。例如,以下简单的单行脚本

raise RuntimeError("Uh-oh")

显示此弹出窗口

完整的 Python 回溯消息将写入标准错误,并且看起来像这样

Traceback (most recent call last):
  File "/Text", line 1, in <module>
RuntimeError: Uh-Oh!

在 Linux/Unix 系统上,如果您从命令行调用 Blender,则该消息将出现在终端会话中;否则,如果您从 GUI 启动 Blender,则该消息将附加到您的~/.xsessionerrors文件。在 Windows 上,该消息出现在控制台窗口中。

华夏公益教科书