Edited at

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

More than 3 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スクリプトを作成する方々の参考になればと思います。


参考情報