>  기사  >  백엔드 개발  >  Blender Python 프로그래밍 도입 사례 분석

Blender Python 프로그래밍 도입 사례 분석

王林
王林앞으로
2023-05-12 10:55:051774검색

    Blender Python 프로그래밍

    지원 기능:

    • 사용자 인터페이스에서 편집할 수 있는 모든 데이터(장면, 메시, 입자 등)를 편집합니다.

    • 사용자 기본 설정, 키맵 및 테마를 수정합니다.

    • 자신만의 설정으로 도구를 실행하세요.

    • 메뉴, 헤더, 패널과 같은 사용자 인터페이스 요소를 만듭니다.

    • 새 도구를 만듭니다.

    • 대화형 도구를 만듭니다.

    • Blender와 통합된 새로운 렌더링 엔진을 만듭니다.

    • 데이터 및 해당 속성의 변경 사항을 구독하세요.

    • 기존 블렌더 데이터 내에 새로운 설정을 정의합니다.

    • Python을 사용하여 3D 뷰를 그립니다.

    (여전히) 누락된 기능:

    • 새 공간 유형을 만듭니다.

    • 각 유형에 사용자 정의 속성을 할당합니다.

    데이터 액세스

    Python은 애니메이션 시스템 및 사용자 인터페이스와 동일한 방식으로 Blender의 데이터에 액세스합니다. 이는 버튼을 통해 변경할 수 있는 모든 설정을 Python에서도 변경할 수 있음을 의미합니다.

    현재 로드된 Blender 파일의 데이터에 액세스하는 것은 bpy.data 모듈을 사용하여 수행할 수 있습니다. 이를 통해 라이브러리 데이터에 액세스할 수 있습니다. 예: bpy.data 。这样就可以访问库数据。例如:

    >>> bpy.data.objects
    <bpy_collection[3], BlendDataObjects>
    >>> bpy.data.scenes
    <bpy_collection[1], BlendDataScenes>
    >>> bpy.data.materials
    <bpy_collection[1], BlendDataMaterials>

    访问集合

    您会注意到索引和字符串都可以用来访问集合的成员。与 Python 字典不同,这两种方法都是可用的; 但是,在运行 Blender 时,成员的索引可能会改变。

    list(bpy.data.objects)
    [bpy.data.objects["Cube"], bpy.data.objects["Plane"]]
    >>> bpy.data.objects[&#39;Cube&#39;]
    bpy.data.objects["Cube"]
    >>> bpy.data.objects[0]
    bpy.data.objects["Cube"]

    访问属性

    一旦你有了一个数据块,比如一个材料、对象、集合等,它的属性就可以被访问,就像使用图形界面更改设置一样。事实上,每个按钮的工具提示还显示了 Python 属性,它可以帮助查找在脚本中更改哪些设置。

    bpy.data.objects[0].name
    &#39;Camera&#39;
    >>> bpy.data.scenes["Scene"]
    bpy.data.scenes[&#39;Scene&#39;]
    >>> bpy.data.materials.new("MyMaterial")
    bpy.data.materials[&#39;MyMaterial&#39;]

    对于测试要访问哪些数据,使用 Python Console 是很有用的,它是自己的空间类型。这支持自动完成,为您提供了一种快速探索文件中的数据的方法。

    可以通过控制台快速找到的数据路径示例:

    bpy.data.scenes[0].render.resolution_percentage
    100
    >>> bpy.data.scenes[0].objects["Torus"].data.vertices[0].co.x
    1.0

    数据创建/删除

    当你熟悉其他 Python API 时,你可能会惊讶于 bpy API 中新的数据块不能通过调用类来创建:

    bpy.types.Mesh()
    Traceback (most recent call last):
      File "<blender_console>", line 1, in <module>
    TypeError: bpy_struct.__new__(type): expected a single argument

    用户不能在 Blender 数据库(bpy.data访问的那个)外的任何地方新建数据,因为这些数据是由 Blender 管理的(保存、加载、撤销、追加等)。

    而只能使用以下方法进行数据增删:

    mesh = bpy.data.meshes.new(name="MyMesh")
    >>> print(mesh)
    <bpy_struct, Mesh("MyMesh.001")>
    bpy.data.meshes.remove(mesh)

    自定义属性

    Python 可以访问具有 ID 的任何数据块上的属性。当分配属性时候,如果该属性本不存在,就会新建该属性。

    这些属性同样保存在 Blender 文件中,并随着对象一同继承或者复制。

    bpy.context.object["MyOwnProperty"] = 42
    if "SomeProp" in bpy.context.object:
        print("Property found")
    # Use the get function like a Python dictionary
    # which can have a fallback value.
    value = bpy.data.scenes["Scene"].get("test_prop", "fallback value")
    # dictionaries can be assigned as long as they only use basic types.
    collection = bpy.data.collections.new("MyTestCollection")
    collection["MySettings"] = {"foo": 10, "bar": "spam", "baz": {}}
    del collection["MySettings"]

    但是,这些自定义属性的值必须是基本的 Python 数据类型。如:

    • int/float/string

    • int/ float 的数组

    • 字典(仅支持字符串键,值也必须是基本类型)

    自定义属性在 Python 外部同样有效。它们可以通过曲线设置动画或在驱动路径中使用。

    上下文 Context

    能够直接通过名称或列表访问数据非常有用,但更常见的是根据用户的选择进行操作。这些上下文信息始终可从 bpy.context 中获得。

    常用案例:

    >>> bpy.context.object
    >>> bpy.context.selected_objects
    >>> bpy.context.visible_bones

    请注意,上下文是只读的。这些值不能直接修改,尽管可以通过运行 API 函数或使用数据 API 进行更改。

    因此这样会引发错误bpy.context.object = obj

    但是这样会正常工作:bpy.context.scene.objects.active = obj

    运算符 Operators (Tools)

    Operators 通常是用户从按钮、菜单项或快捷键访问的工具。从用户的角度来看,它们是一个工具,但是 Python 可以通过 bpy.ops 模块访问、设置并运行他们。

    举例:

    bpy.ops.mesh.flip_normals()
    {&#39;FINISHED&#39;}
    >>> bpy.ops.mesh.hide(unselected=False)
    {&#39;FINISHED&#39;}
    >>> bpy.ops.object.transform_apply()
    {&#39;FINISHED&#39;}

    Operator Cheat Sheet 给出了 Python 语法中所有操作符及其默认值的列表,以及生成的文档。这是一个了解 Blender 所有操作符的好方法。

    Operator Poll()

    许多的 Operators 都有自己的 Poll() 方法,该方法能检查现在的 Blender 上下文是否满足该 Operator 运行的条件。不满足时,直接调用该 Operator 将会产生错误。所以在操作一个 Operators 的时候,建议先用一下方式检查 context

    if bpy.ops.view3d.render_border.poll():
        bpy.ops.view3d.render_border()
    import bpy
    def main(context):
        for ob in context.scene.objects:
            print(ob)
    class SimpleOperator(bpy.types.Operator):
        """Tooltip"""
        bl_idname = "object.simple_operator"
        bl_label = "Simple Object Operator"
        @classmethod
        def poll(cls, context):
            return context.active_object is not None
        def execute(self, context):
            main(context)
            return {&#39;FINISHED&#39;}
    def register():
        bpy.utils.register_class(SimpleOperator)
    def unregister():
        bpy.utils.unregister_class(SimpleOperator)
    if __name__ == "__main__":
        register()
    # test call
    bpy.ops.object.simple_operator()
    import bpy
    class HelloWorldPanel(bpy.types.Panel):
        """Creates a Panel in the Object properties window"""
        bl_label = "Hello World Panel"
        bl_idname = "OBJECT_PT_hello"
        bl_space_type = &#39;PROPERTIES&#39;
        bl_region_type = &#39;WINDOW&#39;
        bl_context = "object"
        def draw(self, context):
            layout = self.layout
            obj = context.object
            row = layout.row()
            row.label(text="Hello world!", icon=&#39;WORLD_DATA&#39;)
            row = layout.row()
            row.label(text="Active object is: " + obj.name)
            row = layout.row()
            row.prop(obj, "name")
            row = layout.row()
            row.operator("mesh.primitive_cube_add")
    def register():
        bpy.utils.register_class(HelloWorldPanel)
    def unregister():
        bpy.utils.unregister_class(HelloWorldPanel)
    if __name__ == "__main__":
        register()

    Accessing Collections

    컬렉션의 구성원에 액세스하는 데 인덱스와 문자열을 모두 사용할 수 있다는 것을 알 수 있습니다. Python 사전과 달리 두 가지 방법을 모두 사용할 수 있지만 Blender를 실행할 때 멤버의 인덱스가 변경될 수 있습니다.

    >>> C.object.rotation_mode = &#39;AXIS_ANGLE&#39;
    # setting multiple camera overlay guides
    bpy.context.scene.camera.data.show_guide = {&#39;GOLDEN&#39;, &#39;CENTER&#39;}
    # passing as an operator argument for report types
    self.report({&#39;WARNING&#39;, &#39;INFO&#39;}, "Some message!")
    >>> bpy.context.object
    bpy.data.objects[&#39;Cube&#39;]

    속성 액세스
    • 재료, 개체, 컬렉션 등과 같은 데이터 블록이 있으면 그래픽 인터페이스를 사용하여 설정을 변경하는 것처럼 해당 속성에 액세스할 수 있습니다. 실제로 각 버튼의 도구 설명에는 스크립트에서 어떤 설정이 변경되었는지 찾는 데 도움이 될 수 있는 Python 속성도 표시됩니다.

      >>> C.scene.objects
      bpy.data.scenes[&#39;Scene&#39;].objects
      bpy.context.object.matrix_world @ bpy.context.object.data.verts[0].co
      # modifies the Z axis in place.
      bpy.context.object.location.z += 2.0
      # location variable holds a reference to the object too.
      location = bpy.context.object.location
      location *= 2.0
      # Copying the value drops the reference so the value can be passed to
      # functions and modified without unwanted side effects.
      location = bpy.context.object.location.copy()

      어떤 데이터에 접근하고 싶은지 테스트하려면 자체 공간 유형인 Python 콘솔을 사용하는 것이 유용합니다. 이는 자동 완성을 지원하여 파일의 데이터를 빠르게 탐색할 수 있는 방법을 제공합니다.
    • 콘솔을 통해 빠르게 찾을 수 있는 데이터 경로의 예:

      obj = bpy.context.object
      obj.location[2] = 0.0
      obj.keyframe_insert(data_path="location", frame=10.0, index=2)
      obj.location[2] = 1.0
      obj.keyframe_insert(data_path="location", frame=20.0, index=2)

      데이터 생성/삭제🎜🎜다른 Python API에 익숙해지면 bpy API의 새 데이터 블록을 호출하여 생성할 수 없다는 사실에 놀랄 수 있습니다. 클래스:🎜
      obj = bpy.context.object
      obj.animation_data_create()
      obj.animation_data.action = bpy.data.actions.new(name="MyAction")
      fcu_z = obj.animation_data.action.fcurves.new(data_path="location", index=2)
      fcu_z.keyframe_points.add(2)
      fcu_z.keyframe_points[0].co = 10.0, 0.0
      fcu_z.keyframe_points[1].co = 20.0, 1.0
      🎜사용자는 Blender 데이터베이스(bpy.data에서 액세스하는 데이터) 외부 어디에서나 새 데이터를 생성할 수 없습니다. 이 데이터는 Blender에서 관리(저장, 로드, 실행 취소, 추가 등)되기 때문입니다. ). 🎜🎜그리고 데이터는 다음 방법을 통해서만 추가 및 삭제할 수 있습니다: 🎜rrreeerrreee🎜사용자 정의 속성🎜🎜Python은 ID가 있는 모든 데이터 블록의 속성에 액세스할 수 있습니다. 속성을 할당할 때 해당 속성이 없으면 생성됩니다. 🎜🎜이러한 속성은 블렌더 파일에도 저장되며 개체와 함께 상속되거나 복사됩니다. 🎜rrreee🎜그러나 이러한 사용자 정의 속성의 값은 🎜 기본 Python 데이터 유형이어야 합니다. 예: 🎜🎜🎜🎜int/float/string🎜🎜🎜🎜int/ float (문자열 키만 지원되며 값도 기본 유형이어야 함) 🎜🎜🎜🎜사용자 정의 속성은 Python 외부에서도 유효합니다. 곡선을 통해 애니메이션화하거나 구동 경로에 사용할 수 있습니다. 🎜🎜Context Context🎜🎜 이름이나 목록으로 데이터에 직접 액세스할 수 있다는 것은 매우 유용하지만 더 일반적으로는 사용자 선택에 따라 수행됩니다. 이 컨텍스트 정보는 <code>bpy.context에서 항상 사용할 수 있습니다. 🎜🎜일반적인 경우: 🎜rrreee🎜🎜컨텍스트는 읽기 전용이라는 점에 유의하세요🎜. 이 값은 API 기능을 실행하거나 데이터 API를 사용하여 변경할 수 있지만 직접 수정할 수는 없습니다. 🎜🎜이렇게 하면 🎜오류가 발생합니다🎜: bpy.context.object = obj🎜🎜그러나 이것은 잘 작동합니다: bpy.context.scene.objects.active = obj 🎜🎜연산자(도구)🎜🎜연산자는 일반적으로 사용자가 버튼, 메뉴 항목 또는 단축키를 통해 액세스하는 도구입니다. 사용자 관점에서 볼 때 이는 도구이지만 Python은 bpy.ops 모듈을 통해 액세스, 설정 및 실행할 수 있습니다. 🎜🎜예: 🎜rrreee🎜연산자 치트 시트는 생성된 문서뿐만 아니라 Python 구문과 해당 기본값의 모든 연산자 목록을 제공합니다. 이는 Blender의 모든 연산자에 대해 배울 수 있는 좋은 방법입니다. 🎜

      Operator Poll()

      🎜많은 Operator에는 현재 Blender 컨텍스트가 Operator 실행 조건을 충족하는지 확인할 수 있는 자체 Poll() 메서드가 있습니다. 만족스럽지 않은 경우 교환원에게 직접 전화하면 오류가 발생합니다. 따라서 Operator를 운영할 때 🎜권장🎜 먼저 다음과 같은 방법으로 컨텍스트를 확인하세요. 🎜rrreee🎜Python을 Blender에 통합하는 방법🎜🎜Python 스크립트는 다음과 같은 방법으로 Blender와 통합할 수 있습니다. 🎜🎜 🎜 🎜렌더링 엔진을 정의합니다. 🎜🎜🎜🎜연산자를 정의합니다. 🎜
    • 通过定义菜单,标题和面板。

    • 通过将新按钮插入现有菜单,标题和面板

    在 Python 中,这是通过定义一个类来完成的,该类是现有类型的子类。

    Blender 官方文档中提供了实例的类模板。如:

    示例运算符

    import bpy
    def main(context):
        for ob in context.scene.objects:
            print(ob)
    class SimpleOperator(bpy.types.Operator):
        """Tooltip"""
        bl_idname = "object.simple_operator"
        bl_label = "Simple Object Operator"
        @classmethod
        def poll(cls, context):
            return context.active_object is not None
        def execute(self, context):
            main(context)
            return {&#39;FINISHED&#39;}
    def register():
        bpy.utils.register_class(SimpleOperator)
    def unregister():
        bpy.utils.unregister_class(SimpleOperator)
    if __name__ == "__main__":
        register()
    # test call
    bpy.ops.object.simple_operator()

    一旦这个脚本运行,SimpleOperator 在 Blender 中注册,可以从 Operator Search 中调用或添加到工具栏中。

    运行脚本:

    • 启动 Blender 并切换到脚本工作区。

    • 单击文本编辑器中的 New 按钮以创建新的文本数据块。

    • 从上面并将其粘贴到文本编辑器中。

    • 单击 Run Script 按钮。

    • 将光标移至 3D 视口,打开运算符搜索菜单,输入 “Simple”。

    • 点击搜索中找到的 “SimpleOperator” 项目。

    示例面板

    面板注册为一个类,就像操作符一样。请注意用于设置它们所显示的上下文的额外 bl_ 变量。

    import bpy
    class HelloWorldPanel(bpy.types.Panel):
        """Creates a Panel in the Object properties window"""
        bl_label = "Hello World Panel"
        bl_idname = "OBJECT_PT_hello"
        bl_space_type = &#39;PROPERTIES&#39;
        bl_region_type = &#39;WINDOW&#39;
        bl_context = "object"
        def draw(self, context):
            layout = self.layout
            obj = context.object
            row = layout.row()
            row.label(text="Hello world!", icon=&#39;WORLD_DATA&#39;)
            row = layout.row()
            row.label(text="Active object is: " + obj.name)
            row = layout.row()
            row.prop(obj, "name")
            row = layout.row()
            row.operator("mesh.primitive_cube_add")
    def register():
        bpy.utils.register_class(HelloWorldPanel)
    def unregister():
        bpy.utils.unregister_class(HelloWorldPanel)
    if __name__ == "__main__":
        register()

    运行脚本:

    • 启动 Blender 并切换到脚本工作区。

    • 单击文本编辑器中的 New 按钮以创建新的文本数据块。

    • 从上面并将其粘贴到文本编辑器中。

    • 单击 Run Script 按钮。

    要查看结果:

    • 选择默认立方体。

    • 点击按钮面板中的对象属性图标(最右边;出现为一个小立方体)。

    • 向下滚动查看名为 “Hello World Panel” 的面板。

    • 更改对象名称也会更新 Hello World Panel 的 name:字段。

    请注意通过代码定义的行分布以及标签和属性。

    数据类型

    Blender 定义了许多 Python 类型,但也使用 Python 本机类型。

    原生类型

    在简单的情况下,将数字或字符串作为自定义类型会很麻烦,因此可以将它们作为普通的 Python 类型进行访问。

    • Blender float / int / boolean-> float / int / boolean

    • Blender 枚举器->字符串

    >>> C.object.rotation_mode = &#39;AXIS_ANGLE&#39;
    • Blender枚举器(多个)->字符串集

    # setting multiple camera overlay guides
    bpy.context.scene.camera.data.show_guide = {&#39;GOLDEN&#39;, &#39;CENTER&#39;}
    # passing as an operator argument for report types
    self.report({&#39;WARNING&#39;, &#39;INFO&#39;}, "Some message!")

    内部类型

    用于 Blender 数据块和 Blender 集合: bpy.types.bpy_struct

    用于包含 collections/meshes/bones/scenes 等属性的数据。

    包装 Blenders 数据的主要类型有 2 种,

    • 一种用于数据块(内部称为 bpy_struct

    >>> bpy.context.object
    bpy.data.objects[&#39;Cube&#39;]
    • 另一种用于属性。

    >>> C.scene.objects
    bpy.data.scenes[&#39;Scene&#39;].objects

    Mathutils 类型

    用于表示向量,四元数,euler,矩阵和颜色类型等,可从 mathutils 模块访问它们。

    一些属性,如 bpy.types.Object.location, bpy.types.PoseBone.rotation_eulerbpy.types.Scene.Cursor_location 可以作为特殊的数学类型访问,这些类型可以一起使用并以各种有用的方式进行操作。

    例如,矩阵向量的乘法

    bpy.context.object.matrix_world @ bpy.context.object.data.verts[0].co

    注意:mathutils 类型保留对 Blender 内部数据的引用,这样更改就可以应用回来。

    举个例子

    # modifies the Z axis in place.
    bpy.context.object.location.z += 2.0
    # location variable holds a reference to the object too.
    location = bpy.context.object.location
    location *= 2.0
    # Copying the value drops the reference so the value can be passed to
    # functions and modified without unwanted side effects.
    location = bpy.context.object.location.copy()

    动画

    有两种方法可以通过 Python 添加关键帧。

    • 第一种是直接通过键属性,这类似于用户从按钮插入关键帧。

    • 您也可以手动创建曲线和关键帧数据,然后将路径设置为属性。

    这是这两种方法的示例。这两个示例都在活动对象的 Z 轴上插入关键帧。

    简单的例子:

    obj = bpy.context.object
    obj.location[2] = 0.0
    obj.keyframe_insert(data_path="location", frame=10.0, index=2)
    obj.location[2] = 1.0
    obj.keyframe_insert(data_path="location", frame=20.0, index=2)

    使用低级功能:

    obj = bpy.context.object
    obj.animation_data_create()
    obj.animation_data.action = bpy.data.actions.new(name="MyAction")
    fcu_z = obj.animation_data.action.fcurves.new(data_path="location", index=2)
    fcu_z.keyframe_points.add(2)
    fcu_z.keyframe_points[0].co = 10.0, 0.0
    fcu_z.keyframe_points[1].co = 20.0, 1.0

    위 내용은 Blender Python 프로그래밍 도입 사례 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제