Introduction
::引言

An  addon  is a Python script that can extend the functionality of Blender in various ways. It can reside in a file within your Blender user preferences directory, or it can be stored in a text block within the Blender document. In the former case, the addon needs to be  enabled  in each Blender document where you want to use it, by ticking the checkbox in its entry in the Add-Ons list in the User Preferences window for that document. In the latter case, the script can be run by pressing  ALT + P  in the Text Editor window; or you can tick the “Register” checkbox for that script in the Text Editor, to have the addon be automatically enabled as soon as the document is loaded into Blender.
::附加程序是Python脚本,可以以各种方式扩展Blender的功能.它可以位于您的Blender用户偏好目录中的文件中,也可以存储在Blender文档中的文本块中.在前一种情况下,需要在每个Blender文档中启用附加程序,您需要在该文档的用户偏好窗口中选择附加程序列表中的选项框.在后一种情况下,脚本可以通过按ALT + P在文本编辑器窗口中运行;或者您可以在文本编辑器中选择该脚本的"注册"选项框,以便在文档被加载到Blender后,自动启用附加程序.

The main thing an addon script typically does is define one or more new  operators . All the user-interface functions in Blender are performed by operators; these are invoked by being associated with menu items, buttons or hotkeys. Each operator is a subclass of the  bpy.types.Operator  class. The name you give your class in Python is immaterial outside the script where it is defined; it will be referred to from the rest of Blender via its  operator name , which must be unique within the document. In the same way, your script can invoke other operators defined elsewhere via Blender API functions that take their operator name.
::添加脚本通常的主要作用是定义一个或多个新的操作符. Blender 中的所有用户界面函数都是由操作符执行的;这些函数通过与菜单项,按或热键相关联而被调用.每个操作符都是 bpy.types.Operator 类的子类.您在 Python 中给类的名称在定义的脚本之外是无关紧要的;它将通过其操作符名称从Blender 的其余部分引用,该操作符名称必须在文档中是唯一的.同样,您的脚本可以通过使用其操作符名称的 Blender API 函数调用其他定义的操作符.

Text Blocks
::文字块

A Blender document can contain  text blocks , which are not the same as  text objects  in a 3D scene (though the former can be converted to the latter). Besides generating text objects, a text block can serve any purpose you like; for example, use it to pass workflow instructions to a colleague along with the document; display a copyright or help message in the initial layout that a user sees on opening the document; or hold a Python script that can be run by the user to perform some useful action related to the document.
::混合器文档可以包含文本块,这些块与3D场景中的文本对象不同 (尽管前者可以转换为后者).除了生成文本对象外,文本块可以用于您喜欢的任何目的;例如,使用它将工作流指令传递给文档中的同事;在用户打开文档时看到的初始布局中显示版权或帮助消息;或者持有Python脚本,用户可以运行它来执行与文档相关的有用操作.

Your First Operator
::您的第一位操作员

Open a new, empty Blender document. Bring up the Text Editor   in any convenient window; you will see an empty, grey rectangle. Before you can type in text, you need to create a text block; do so by clicking the large button labeled “New” in the window header. As soon as you do this, you should see a popup menu appear listing all the text blocks in your document, with the current (only) entry named “Text”. You should also see a red insertion cursor appear at the top left, indicating that you can start typing.
::打开一个新的,空的Blender文档. 在任何方便的窗口中打开文本编辑器;您将看到一个空的,灰色的矩形. 在您可以输入文本之前,您需要创建一个文本块;通过点击窗口标题中的标签为"新"的大按来实现这一点. 您一旦这样做,您应该看到一个弹出菜单显示文本中的所有文本块,当前 (仅) 条目名为"文本". 您还应该看到一个红色插入光标出现在左上方,表明您可以开始输入.

Unlike the Console Window, nothing is automatically imported for you. So as in any other Python script, you need to mention every module you want to access.
::与控制台窗口不同,没有什么是自动导入的.所以就像任何其他Python脚本一样,你需要提到你想要访问的每个模块.

You define your operator as a subclass of a subclass of the  bpy.types.Operator . It must have a  bl_idname  class attribute which gives the operator name, while  bl_label  gives the user-visible name that appears in the spacebar menu. The former must have valid Python syntax for a name, including a single dot; the part to the left of the dot must be the name of one of the valid categories of operators, which you can find by typing
::您将操作符定义为bpy.types.Operator的子类的子类.它必须有一个bl_idname类属性,它给出操作符名称,而bl_label给出在空格菜单中显示的用户可见名称.前者必须具有有效的Python语法,包括一个单点;点的左侧部分必须是有效的操作符类别之一的名称,您可以通过键入找到

dir(bpy.ops)

into the Console Window.
::进入控制台窗口.

Let’s define an operator that will add a new tetrahedron object to the document. The class definition should start something like this:
::让我们定义一个运算符,它将为文档添加一个新的四面体对象. 类定义应该像这样开始:

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

It has to define an  invoke  method, which starts off like this:
::它必须定义一个调用方法, 开始的方法是这样的:

    def invoke(self, context, event) :

The  invoke  method performs the actual function of the operator; after it has finished, it must return a value which is a set of strings, telling Blender things like whether the operator is still executing in a modal state, or whether the operation has finished, and if so whether it was successful or not. To indicate successful completion: end the  invoke  method with this:
::调用方法执行操作符的实际功能;完成后,它必须返回一个字符串集的值,告诉Blender操作符是否仍在模态中执行,或者操作是否已经完成,如果是这样,它是否成功完成.为了表示成功完成:用以下方法结束调用方法:

        return {"FINISHED"}

Anyway, let us compute the coordinates of the vertices for the tetrahedron: with edges with a length of 1 Blender unit, suitable values are  ( 0 , 1 3 , 0 ) ( 1 2 , 1 2 3 , 0 ) ( 1 2 , 1 2 3 , 0 )  and  ( 0 , 0 , 2 3 ) . Or in Python:
::无论如何,让我们计算四面体的顶点坐标:边长为1个混合器单位,合适的值是 (0,-13,0), (1,2,1,2,3,0) 和 (0,0,0,2,3) .

        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))),
          ]

Then we create the mesh datablock, giving it the name “Tetrahedron”:
::然后我们创建一个网格数据块, 给它一个名字:

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

Fill it in with the above vertex definitions and associated faces:
::填写上面的顶点定义和相关面:

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

The  Mesh.from_pydata  method is not currently well documented in the Blender API, but its first argument is an array of  Vector  defining the vertices, the second argument is an array of edge definitions, and the third argument is an array of face definitions. Each edge or face is defined as a list of vertex indices (2 elements in each list for an edge, 3 or 4 for a face), 0-based in usual Python style, being indices into the array of vertex definitions that you passed. Note that you pass  either the edge definitions or the face definitions, but not both : the other one should be passed as the empty list. If this function is not used correctly, it will cause Blender to crash.
::目前Mesh.from_pydata方法在Blender API中没有很好的文档,但它的第一个参数是定义顶点的Vector数组,第二个参数是边界定义的数组,第三个参数是面定义的数组.每个边或面被定义为顶点索引列表 (每个列表中的2个元素为边,面为3或4),以通常的Python风格为0,是你传递的顶点定义数组中的索引.请注意,你传递的是边界定义或面定义,但不是两者:另一个应该被传递为空列表.如果这个函数不被正确使用,它会导致Blender崩.

We also need to add the following, to tell Blender the mesh has changed and needs updating (as if it couldn’t figure it out itself):
::需要更新 (好像它自己也无法弄清楚):

        NewMesh.update()

(Omitting this produces a minor quirk: right-clicking the newly-created tetrahedron does not highlight its outline in orange as with other objects, though the problem goes away if you enter edit mode on the object and exit again.)
:sad如果不这样做,会产生一个小的奇特点:右键点击新创建的四面体不会像其他对象一样以色突出显示其轮,尽管如果进入对象的编辑模式并再次退出,问题就会消失.

Now to create the object datablock (I also give it the name “Tetrahedron”), and link it to the mesh:
::现在创建对象数据块 (我也给它一个名字四面体), 并将其链接到网格:

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

But the object will not appear to the user until it is linked into the scene:
::但对象在与场景连接之前不会出现在用户眼中:

        context.scene.objects.link(NewObj)

To recap, here is the complete script:
::总结一下, 以下是完整的剧本:

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)

Note the addition of the  register_class  call, to make Blender add your operator to its built-in collection.
::让Blender将您的操作符添加到其内置集合中.

Now execute your script by typing  ALT + P . If all goes well  nothing should appear to happen ; Blender will define the class and register it as a new operator as you requested, ready for use.
::现在通过键入ALT+P来执行脚本.如果一切顺利,则似乎没有什么发生; 混合器将定义类并将其注册为您请求的新操作符,即可使用.

If you hit any syntax errors, Blender should display these in a popup window; go back and correct them, and re-execute the script with  ALT + P .
::如果遇到任何语法错误,Blender应该在弹出窗口中显示这些错误;回去纠正它们,并用ALT+P重新执行脚本.

Invoking Your Operator
::调用您的运营商

We haven’t (yet) defined any user interface for this operator; so how do we invoke it? Simple.
::我们还没有为这个操作符定义任何用户界面,那么我们如何调用它? 简单.

Go to a 3D View window. Delete the default cube to avoid it obscuring things, and press  SPACE  (F3 in Blender 2.8, Blender 3). This brings up a searchable menu of every operator defined for the current document. Into the search box, type part or all of the string you defined for the  bl_label  attribute above (typing “tetra” should probably be enough). This will restrict the menu to only showing items that contain that string, which should include the name of your operator; click with  LMB  on this or highlight it and press  ENTER . If all goes well, you should see your tetrahedron object appear!. If it does not appear make sure that in the Preferences Editor, Interface/Display "Developer Extras" box is checked.
::进入3D视图窗口.删除默认立方体以避免它模糊东西,并按空格 (F3在混器2.8,混器3). 这会显示当前文档定义的每个操作者的可搜索菜单. 在搜索框中,输入部分或你定义的bl_label属性的所有字符串 (输入tetra可能足够). 这将限制菜单只显示包含该字符串的项目,其中应包括操作者的名称; 点击此或突出并按ENTER. 如果一切顺利,你应该看到你的四面体对象出现! 如果它没有出现,请确保在编辑器偏好中,界面/显示"开发者额外"框被勾选.

If You Hit An Error
::如果您遇到一个错误

If there is any error compiling or running the script, Blender should display this in a popup. For example, the following simple one-line script
::如果编译或运行脚本时出现任何错误,Blender应该在弹出窗口中显示此错误.例如,以下简单的单行脚本

raise RuntimeError("Uh-oh")

displays this popup:
::显示这个弹出窗口:

The full Python traceback message is written to Standard Error, and looks something like this:
::完整的 Python 追溯消息写成标准错误, 类似于这样:

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

On Linux/Unix systems, the message will appear in the terminal session if you invoked Blender from the command line; otherwise it will be appended to your  ~/.xsessionerrors  file if you launched Blender from a GUI. On Windows the message appears in the console window.
::在Linux/Unix系统中,如果您从命令行调用了Blender,则会在终端会话中显示该消息;否则,如果您从GUI启动了Blender,则将其添加到您的~/.xsessionerrors文件中.在Windows中,该消息会出现在控制台窗口中.


Last modified: Monday, 17 March 2025, 2:41 PM