Help us understand the problem. What is going on with this article?

[Blender] Blenderのスクリプトを複数ファイルに分割する

More than 5 years have passed since last update.

最初は機能も限られていてサイズも小さかったBlenderスクリプトのソースファイルが、機能の追加と共にサイズが巨大化してきていませんか?
そんな時は複数のソースファイルに分割しましょう。
とは言っても、Blenderのスクリプトってどうやって分割したら良いかわからない方もいると思うので、Blenderのスクリプトの分割の仕方をまとめておきます。

ファイル分割前のソース

ファイルを分割する前のサンプルソースファイルを示します。
あくまで例ですので、あまりソースの内容は深く考えていません。

all_in_one.py
import bpy

bl_info = {
# ...
}

class Operator_1(bpy.types.Operator):
    bl_idname = "uv.operator_1"
    bl_label = "Operator 1"
    file_name = "hoge.blend"

    def execute(self, context):
        return{'FINISHED'}

class Operator_2(bpy.types.Operator):
    bl_idname = "uv.operator_2"
    bl_label = "Operator 2"

    def execute(self, context):
        self.report({'INFO'}, Operator_1.file_name)
        return{'FINISHED'}



def menu_func(self, context):
    self.layout.separator()
    self.layout.menu(Operator_1.bl_idname)
    self.layout.menu(Operator_2.bl_idname)


def register():
    bpy.utils.register_module(__name__)
    bpy.types.VIEW3D_MT_uv_map.append(menu_func)

def unregister():
    bpy.utils.unregister_module(__name__)
    bpy.types.VIEW3D_MT_uv_map.remove(menu_func)


if __name__ == "__main__":
    register()

ファイル分割後のソース

クラスごとにファイルを分割したファイルを示します。
このサンプルでは、すべてのファイルが同一ディレクトリに置かれている必要があります。
また、スクリプトが最初に読み込まれる時の処理を記載したファイル名は、__init__.pyとしなくてはなりません。
__init__.pyの最初に分割したファイルを読み込む処理がありますが、その他は分割しない場合と比べて特に変わったところはありません。
この部分の説明、実を言うとPythonのパッケージと同じであるので、Pythonを知っている人にとっては非常に馴染みのあるものとなっています。

op1.py
import bpy

class Operator_1(bpy.types.Operator):
    bl_idname = "uv.operator_1"
    bl_label = "Operator 1"
    file_name = "hoge.blend"

    def execute(self, context):
        return{'FINISHED'}
op2.py
import bpy
from . import op1

class Operator_2(bpy.types.Operator):
    bl_idname = "uv.operator_2"
    bl_label = "Operator 2"

    def execute(self, context):
        self.report({'INFO'}, op1.Operator_1.file_name)
        return{'FINISHED'}
__init__.py
bl_info = {
# ...
}

if "bpy" in locals():
    import imp
    imp.reload(op1)
    imp.reload(op2)
else:
    from . import op1
    from . import op2

import bpy

def menu_func(self, context):
    self.layout.separator()
    self.layout.menu(op1.Operator_1.bl_idname)
    self.layout.menu(op2.Operator_2.bl_idname)


def register():
    bpy.utils.register_module(__name__)
    bpy.types.VIEW3D_MT_uv_map.append(menu_func)

def unregister():
    bpy.utils.unregister_module(__name__)
    bpy.types.VIEW3D_MT_uv_map.remove(menu_func)


if __name__ == "__main__":
    register()

最後に

Blenderスクリプトでファイルを分割する方法を示しました。
Blenderは1つのスクリプトの機能をパッケージのように扱っていると考えれば、Pythonのパッケージの作り方と同じと言えます。
そのため記事にするまでもなかったのかもしれませんが、Blenderスクリプトを作成する方々の参考になればと思います。

参考情報

nutti
同人ゲーム開発、Blenderアドオン開発、DTM
https://colorful-pico.net
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away