Blender 3D:第四单元:与高级教程起飞
Addons will commonly do more than unconditionally perform a single action; the user may be able to control their actions in various ways. We can add controls for adjusting settings to our addon panel, and associate these with custom
properties
that we define for the current scene; Blender will then take care of updating the property values as the user operates those controls, and our operator’s
invoke
routine can fetch those property values when it runs.
::添加程序通常不仅仅是无条件执行单个操作;用户可能能够以各种方式控制其操作.我们可以在添加程序面板中添加调整设置的控制,并将其与我们为当前场景定义的自定义属性关联起来;然后,Blender会在用户操作这些控制时更新属性值,并且运营商的调用程序可以在运行时获取这些属性值.
Defining A Property
::定义一个财产
Properties need to be defined at the same time our custom classes get registered. We previously did this in top-level statements, but now let’s gather it all together into a
register
method, like this:
::属性需要在我们自定义类注册的同时定义. 我们以前在顶级语句中做过,但现在让我们把它全部汇集到一个注册方法中,像这样:
def register() : bpy.utils.register_class(MakeTetrahedron) bpy.utils.register_class(TetrahedronMakerPanel) bpy.types.Scene.make_tetrahedron_inverted = bpy.props.BoolProperty \ ( name = "Upside Down", description = "Generate the tetrahedron upside down", default = False ) #end register
Here we are attaching the property as a new attribute of Blender’s
Scene
class; Python lets us assign new attributes to just about any object, and Blender takes full advantage of that. Note that the property must be created using one of the property-definition routines provided in
bpy.props
: choose the one that matches the type of property you want to create. Here we are defining a simple true/false toggle, which the user will control via a checkbox. Whatever name you use for your custom class attribute, an instance of that class will have an attribute with the same name, holding the actual value for that property.
::在这里,我们将属性作为Blender的Scene类的新属性附加;Python让我们对几乎任何对象赋予新的属性,而Blender充分利用了这一点.请注意,该属性必须使用bpy.props中提供的属性定义例程之一创建:选择与您想要创建的属性类型匹配的属性.在这里,我们定义了一个简单的true/false切换,用户将通过一个选框控制.无论您为自定义类属性使用什么名字,该类的实例都将具有具有相同名字的属性,并保持该属性的实际值.
The
name
will be used as the name of a control for examining or changing this property, while the
description
will appear as a tooltip when the user hovers the mouse over the control. The
default
is used as the initial value of the property.
::名称将被用作检查或更改该属性的控件名称,而描述将作为工具提示显示,当用户在控件上移动鼠标时.默认值被用作属性的初始值.
Note also I tried to use a name,
make_tetrahedron_inverted
, which is less likely to clash with names defined by other addons or parts of Blender.
::我试图使用一个名字, make_tetrahedron_inverted, 这不太可能与其他添加程序或Blender的部分定义的名称发生冲突.
Let’s also add an
unregister
method, which undoes everything that
register
does. This won’t actually be used for now, but it will become relevant later when we extract the addon for separate installation:
::让我们添加一个取消注册的方法,它会取消注册所做的一切. 这一方法现在实际上没有用,但当我们提取附加程序以进行单独安装时,它将变得相关:
def unregister() : bpy.utils.unregister_class(MakeTetrahedron) bpy.utils.unregister_class(TetrahedronMakerPanel) del bpy.types.Scene.make_tetrahedron_inverted #end unregister
To make the checkbox appear, add the following line to our panel’s
draw
routine:
::为了让选框出现,请在我们的面板的抽象程序中添加以下行:
TheColumn.prop(context.scene, "make_tetrahedron_inverted")
The first argument to the
prop
method must be an instance of the class to which we attached our property definition above; in this case, it is the current scene.
::prop方法的第一个参数必须是我们上面附加的属性定义的类的实例; 在这种情况下,它是当前的场景.
Finally, we need to finish off our script with the following bit of boilerplate which will invoke our registration routine in the situations (like the Text Editor) where Blender doesn't do it for us:
::需要在Blender不为我们做的事情时 (如文字编辑器) 调用注册程序:
if __name__ == "__main__" : register() #end if
Using The Property
::使用该财产
Now we actually need to use the property in our operator’s
execute
routine. We’ll use it to negate a scale factor which will be applied to the Z coordinate of the vertices of the tetrahedron:
::现在我们需要在运算符的执行程序中使用该属性. 我们将用它来否定一个规模因子,
Scale = -1 if context.scene.make_tetrahedron_inverted else 1
But only the last vertex has a nonzero Z coordinate, so this is the only one that needs a change in its computation:
::只有最后一个顶点的坐标不是零,所以它是唯一需要改变计算的顶点:
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, Scale * math.sqrt(2 / 3))), ]
To recap all our changes, here is the complete updated script:
::为了回顾所有变化, 以下是完整的更新脚本:
import math import bpy import mathutils class TetrahedronMakerPanel(bpy.types.Panel) : bl_space_type = "VIEW_3D" bl_region_type = "TOOLS" bl_context = "objectmode" bl_category = "Create" bl_label = "Add Tetrahedron" def draw(self, context) : TheColumn = self.layout.column(align = True) TheColumn.prop(context.scene, "make_tetrahedron_inverted") TheColumn.operator("mesh.make_tetrahedron", text = "Add Tetrahedron") #end draw #end TetrahedronMakerPanel class MakeTetrahedron(bpy.types.Operator) : bl_idname = "mesh.make_tetrahedron" bl_label = "Add Tetrahedron" bl_options = {"UNDO"} def invoke(self, context, event) : Scale = -1 if context.scene.make_tetrahedron_inverted else 1 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, Scale * math.sqrt(2 / 3))), ] NewMesh = bpy.data.meshes.new("Tetrahedron") NewMesh.from_pydata \ ( Vertices, [], [[0, 1, 2], [0, 1, 3], [1, 2, 3], [2, 0, 3]] ) NewMesh.update() NewObj = bpy.data.objects.new("Tetrahedron", NewMesh) context.scene.objects.link(NewObj) return {"FINISHED"} #end invoke #end MakeTetrahedron def register() : bpy.utils.register_class(MakeTetrahedron) bpy.utils.register_class(TetrahedronMakerPanel) bpy.types.Scene.make_tetrahedron_inverted = bpy.props.BoolProperty \ ( name = "Upside Down", description = "Generate the tetrahedron upside down", default = False ) #end register def unregister() : bpy.utils.unregister_class(MakeTetrahedron) bpy.utils.unregister_class(TetrahedronMakerPanel) del bpy.types.Scene.make_tetrahedron_inverted #end unregister if __name__ == "__main__" : register() #end if
As before, execute the script with ALT + P . Check the Tool Shelf in the 3D View, and your panel should now look like this:
::像之前一样,使用ALT+P执行脚本. 在3D视图中检查工具架,您的面板现在应该看起来像这样:

Try executing it with and without the checkbox checked, and you should end up with two tetrahedra pointing in opposite directions.
::试着在没有勾选的框中执行它, 你应该得到两个四面体指向相反的方向.