はじめてのBlenderアドオン開発
Last Update: 2023.3.1
Blender 2.7
はじめてのBlenderアドオン開発
Blender 2.7
Last Update: 2023.3.1
2-1. アドオン開発の基礎を身につける
1-5節 ではアドオンを作成し、作成したアドオンをインストール&アンインストールしましたが、ソースコードの解説を一切行っていませんでした。 本節では 1-5節 よりも実用的なアドオンのサンプルを紹介し、そのソースコードを解説します。
1-5節 で紹介したアドオンは、アドオンを有効化または無効化した時にコンソールウィンドウへメッセージを出力する機能のみを持つアドオンでした。 これをアドオンと呼ぶのには寂しい気がしますので、本節ではより実用的な機能を持ったアドオンを作ります。
最初に、本節で作成するアドオンの仕様を決めます。 アドオンのソースコードを用いた初めての解説となるので、本節のサンプルの仕様は以下のように単純なものにしました。
[3Dビュー] エリアのメニューの [追加] > [メッシュ] > [ICO球] を実行した時の動作を確認します。
1 | [3Dビュー] エリアのメニューから、[追加] > [メッシュ] > [ICO球] を実行します。 |
2 | 3Dカーソルを中心としたICO球が作成されます。 |
仕様を満たすようにアドオンを作成します。
ソースコードの解説は後ほど行いますので、ここでは 1-5節 を参考にして以下のソースコードを入力し、ファイル名を sample_2_1.py
として保存してください。
import bpy # アドオン開発者に対して用意しているAPIを利用する
# アドオンに関する情報を保持する、bl_info変数
bl_info = {
"name": "サンプル2-1: オブジェクトを生成するアドオン",
"author": "Nutti",
"version": (2, 0),
"blender": (2, 75, 0),
"location": "3Dビュー > 追加 > メッシュ",
"description": "オブジェクトを生成するサンプルアドオン",
"warning": "",
"support": "TESTING",
"wiki_url": "",
"tracker_url": "",
"category": "Object"
}
# オブジェクト(ICO球)を生成するオペレーション
class CreateObject(bpy.types.Operator):
bl_idname = "object.create_object"
bl_label = "球"
bl_description = "ICO球を追加します"
bl_options = {'REGISTER', 'UNDO'}
# メニューを実行した時に呼ばれる関数
def execute(self, context):
bpy.ops.mesh.primitive_ico_sphere_add()
print("サンプル2-1: 3DビューにICO球を生成しました。")
return {'FINISHED'}
# メニューを構築する関数
def menu_fn(self, context):
self.layout.separator()
self.layout.operator(CreateObject.bl_idname)
# アドオン有効化時の処理
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_mesh_add.append(menu_fn)
print("サンプル2-1: アドオン「サンプル2-1」が有効化されました。")
# アドオン無効化時の処理
def unregister():
bpy.types.INFO_MT_mesh_add.remove(menu_fn)
bpy.utils.unregister_module(__name__)
print("サンプル2-1: アドオン「サンプル2-1」が無効化されました。")
# メイン処理
if __name__ == "__main__":
register()
アドオンの動作を確認してからソースコードの解説した方が理解が深まりますので、作成したアドオンを使ってみましょう。
1-5節 を参考にして、作成したアドオンを有効化します。
アドオンを有効化すると、コンソールウィンドウに以下の文字列が出力されるはずです。
サンプル2-1: アドオン「サンプル2-1」が有効化されました。
アドオン有効化後、[3Dビュー] エリアのメニューに [追加] > [メッシュ] > [球] が追加されていることを確認します。
以下の手順に従って、アドオンの機能を使ってみます。
1 | 追加されたメニュー [追加] > [メッシュ] > [球] を実行すると、3Dカーソルを中心としたICO球が作成されます。 さらに、コンソールウィンドウには以下の文字列が出力されます。 サンプル2-1: 3DビューにICO球を生成しました。 |
1-5節 を参考に、アドオンを無効化します。
アドオンを無効化すると、コンソールウィンドウに以下の文字列が出力されます。
サンプル2-1: アドオン「サンプル2-1」が無効化されました。
アドオンの動作が確認できたところで、作成したアドオンのソースコードを解説します。
Blenderのアドオンを開発するためには、bpy
モジュールと呼ばれるBlenderが提供するAPIをまとめたモジュールをインポートし、APIを利用できるようにする必要があります。
以下のコードにより、bpyモジュールをインポートすることができます。
import bpy # アドオン開発者に対して用意しているAPIを利用する
作成したソースコードがBlenderのアドオンであることをBlender本体に認識させるためには、bl_info
と呼ばれる変数を作成する必要があります。
# アドオンに関する情報を保持する、bl_info変数
bl_info = {
"name": "サンプル2-1: オブジェクトを生成するアドオン",
"author": "Nutti",
"version": (2, 0),
"blender": (2, 75, 0),
"location": "3Dビュー > 追加 > メッシュ",
"description": "オブジェクトを生成するサンプルアドオン",
"warning": "",
"support": "TESTING",
"wiki_url": "",
"tracker_url": "",
"category": "Object"
}
bl_info
はディクショナリ型の変数で、以下のようなキーと値を定義する必要があります。
キー | 値の型 | 値の説明 |
---|---|---|
name |
文字列 | アドオンの名前 |
author |
文字列 | アドオンの作者 |
version |
タプル | アドオンのバージョン |
blender |
タプル | アドオンが動作するBlender本体の最古のバージョン で、ここに指定されたバージョンより古いBlenderでアドオンをインストールすると警告が出る |
location |
文字列 | アドオンが提供する機能が存在する場所 |
description |
文字列 | アドオンの説明文 |
warning |
文字列 | アドオン使用時の注意点、バグ情報等 |
support |
文字列 | アドオンのサポートレベル |
wiki_url |
文字列 | アドオンに関連する情報が得られるサイトのURL(ドキュメントサイト) |
tracker_url |
文字列 | アドオンのサポートサイトのURL |
category |
文字列 | アドオンのカテゴリ |
各キーに設定した値について、Blenderにどのように反映されるかを説明します。
アドオンを有効化/無効化する時に利用する [ユーザ設定] ウィンドウに表示される情報は、以下の bl_info
変数のキーに指定された値に基づいています。
name
author
version
location
description
warning
wiki_url
tracker_url
本節で作成したアドオンについて、上記のキーに設定した値がどのようにBlenderに反映されるかを見ていきます。
以下の図では、bl_info
変数に指定された値と表示内容の対応関係を示しています。 warning
, wiki_url
, tracker_url
については、本節のサンプルでは未設定のため表示されていません。
本節で作成したサンプルは warning
, wiki_url
, tracker_url
を設定していませんが、もしこれらのキーについて値を設定した場合に [ユーザ設定] ウィンドウへどのように反映されるかを確認するため、ソースコードの bl_info
を以下のように書き換えます。
# アドオンに関する情報を保持する、bl_info変数
bl_info = {
"name": "サンプル2-1: オブジェクトを生成するアドオン",
"author": "Nutti",
"version": (2, 0),
"blender": (2, 75, 0),
"location": "3Dビュー > 追加 > メッシュ",
"description": "オブジェクトを生成するサンプルアドオン",
"warning": "本アドオンはサンプルです",
"support": "TESTING",
"wiki_url": "https://github.com/nutti/Introduction-to-Addon-Development-in-Blender/wiki",
"tracker_url": "https://github.com/nutti/Introduction-to-Addon-Development-in-Blender",
"category": "Object"
}
ソースコードを書き換えてファイルを保存しアドオンを有効化すると、[ユーザ設定] ウィンドウのアドオン情報にボタンと警告マークが表示されます。
[ドキュメント編集] ボタンをクリックすると、wiki_url
に指定したURLが開きます。 アドオンのドキュメントや本アドオンの最新情報が得られるサイトのURLを wiki_url
に設定します。 本節のサンプルでは、本書のWebページ版が公開されているURLを設定しました。
[バグを報告] ボタンをクリックすると、tracker_url
に指定したURLが開きます。 アドオンのバグを報告するサイトを持つ方が、ユーザからのフィードバックを得たい場合に設定しておくと良いかと思います。 今回は本書のソースコードを公開しているサイトのURLを設定しました。
これから、bl_info
のキーに設定する値について説明します。
アドオン名を指定します。
基本的にアドオン名は自由に決めて良いですが、アドオンの機能に関連した名前をつけるようにします。 また、ユーザがアドオン名とアドオンのソースコードを対応付けやすくするため、アドオン名とユーザに提供するソースコードのファイル名は互いに連想できるものにしましょう。
アドオンの開発者を指定します。
アドオンの開発が複数人で行われている場合、開発への貢献度順に名前を指定します。 例えば Hoge
がアドオンのメイン部を作成し、その後 Piyo
がアドオンのバグを修正した場合は、以下のように指定します。
"author": "Hoge, Piyo"
アドオンのバージョンを以下のフォーマットで示します。
(メジャーバージョン, マイナーバージョン)
正式リリース前はメジャーバージョンを 0
とし、アップデートの度にマイナーバージョンを増やします。 メジャーバージョンは正式リリース時に 1
とし、以降はアドオンのUIなどに影響する大きな修正を行う時に増やします。 機能追加などの修正の場合は正式リリース前と同様に、マイナーバージョンを増やしていきます。 なおメジャーバージョンを増やした時は、マイナーバージョンを 0
に戻します。
例えば、正式リリース直後に初めて細かい修正を加えた時に version
に指定する値は (1, 1)
となります。
アドオンの機能を使うためのUIが存在する場所を指定します。 例えば [3Dビュー] エリアの [追加] > [メッシュ] に追加する場合は、3Dビュー > 追加 > メッシュ
と記載します。
アドオンが持つ機能を記載します。
表示できるスペースが非常に少ないことから簡潔に記載することを目指すべきですが、もしアドオンが多くの機能を持つ場合などで記載内容が長くなる場合は location
と同様 "See Add-ons Preferences" などと記載し、Add-ons Preferencesに記載すると良いと思います。
本項目を指定すると、警告アイコンと warning
に指定した文字列が [ユーザー設定] ウィンドウのアドオン情報に表示されるようになります。 本項目は、アドオンが正式リリース前のテスト中であることを示す場合や、機能の一部に不具合があることがわかっている時に指定します。
アドオンのチュートリアルなど、アドオンに関するドキュメントが存在するWebページのURLを指定します。 Blender公式のWikiページにアドオンのドキュメントを公開している場合は、Blender公式のWikiページ(https://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts)を指定することができます。
アドオンに不具合があることが発覚した時、ユーザが開発者へ不具合の報告をするためのWebページのURL(https://developer.blender.org/maniphest/task/create/?project=3&type=Bug)を指定します。 サポートレベルがOfficialまたはContribであればD.B.Oのバグ報告ページを指定することになりますが、個別にサポートページを持つ場合は各自が持つサポートページを指定しても良いです。
bl_info
に指定可能な、アドオンのサポート情報について説明します。
アドオンが動作する最古のバージョンを以下の形式で指定します。
(メジャーバージョン, マイナーバージョン, 0)
Blenderのバージョンが2.70であれば、blender
に指定する値は (2, 70, 0)
となります。
基本的にアドオンを開発したBlenderのバージョンを指定しておけば良いと思います。 アドオンを更新した時に、修正時に使用したBlenderと開発時に使用したBlenderのバージョンが異なる場合は、blender
も一緒に修正することを忘れないようにしましょう。
なお、指定したバージョンよりも古いバージョンのBlenderでアドオンを有効化すると警告メッセージが表示されます。
実際、どのような警告メッセージが表示されるか確認してみましょう。 blender
に (2, 76, 0)
を指定してアドオンを有効化すると、以下のように警告メッセージが表示されます。
blender
に指定したバージョンよりも古いバージョンのBlender上でもアドオン自体に問題がなければ、アドオンを使い続けることができるかもしれません。 しかし、開発者が設定したサポート範囲を超えての利用となるため、問題が発生してもサポートを受けられなくなる可能性が高いです。
アドオンのサポートレベルを以下の3つから選択します。
1-2節 で説明したアドオンのサポートレベルを参考に設定してください。
設定値 | ユーザ設定ウィンドウ上の表示 | 値の意味 |
---|---|---|
OFFICIAL |
公式 | Blenderが公式にサポートするアドオンです。サポートレベルがReleaseのアドオンに対して設定します。 |
COMMUNITY |
コミュニティ | Blenderが公式にサポートしないアドオンです。サポートレベルがContribまたはExternalのアドオンに対して設定します。 |
TESTING |
テスト中 | テスト中のアドオンに対して設定します。機能が不完全な場合やテスト中の場合に、アドオンの動作が不安定な場合に設定します。 |
[ユーザ設定] ウィンドウでは、インストールされたアドオンについてサポートレベルでフィルタリングして表示することができます。 例えば [ユーザ設定] ウィンドウの [サポートレベル] にて [テスト中] ボタンのみを選択状態にすることで、support
に TESTING
が設定されたアドオンのみを表示することができます。
本書で紹介する全てのサンプルのアドオンは、support
に TESTING
が設定されています。 [テスト中] ボタンのみを選択することで、サンプルのアドオンをすぐに見つけることができます。
機能の種類によって、アドオンをカテゴリとして分類できます。 category
には、アドオンが属するカテゴリを指定します。
カテゴリ一覧は [ユーザ設定] ウィンドウの [カテゴリー] から確認できます。 アドオンのカテゴリは英語で指定する必要があるため、Blenderを日本語化している方は一度英語に戻し、カテゴリの正式名称を確認 しましょう。
既存のカテゴリに分類できない場合は、新たなカテゴリを作ることもできます。 category
に Sample
を指定すると、右図に示すように新たなカテゴリとして Sample
が追加されていることがわかります。
bl_info
は必ずしも必要な情報ではなく、あくまでアドオンの情報をユーザ設定ウィンドウに表示するために利用するための変数です。 bl_info
がなくても、ソースコードを実行してアドオンの機能を利用することはできます。bl_info
を設定しないとユーザ設定ウィンドウにアドオンが表示されず、コンソールウィンドウに警告メッセージが表示されてしまいます。 Blender公式のアドオン開発のガイドラインにも、アドオン開発時は bl_info
を設定するように書かれていますので、特別な理由がない限り変数 bl_info
を定義するようにしましょう。
アドオンからBlenderに対して何かしらの操作を行うためには、オペレータクラスを作成し具体的な処理を定義する 必要があります。 オペレータクラスは、bpyモジュールが提供するクラスである、bpy.types.Operator
を継承して作成します。
ここではオペレータクラスの作成方法を紹介します。 最初に、オペレータクラスのクラス変数の宣言例を以下に示します。
# オブジェクト(ICO球)を生成するオペレーション
class CreateObject(bpy.types.Operator):
bl_idname = "object.create_object"
bl_label = "球"
bl_description = "ICO球を追加します"
bl_options = {'REGISTER', 'UNDO'}
オペレータクラスには、以下のようなクラス変数を含める必要があります。
クラス変数 | 型 | 値の説明 |
---|---|---|
bl_idname |
文字列 | Blender内部で使用するID |
bl_label |
文字列 | メニュー登録時に、メニューの項目に表示する文字列 |
bl_description |
文字列 | メニュー登録時に、メニューの項目に表示する説明文 |
bl_options |
集合型 | 処理の属性 |
bl_idname
にはBlender内部で使用するIDを設定します。 bl_idname
は自由に決めても良いですが、<アドオンのカテゴリ>.<任意の文字列>
のように指定し、Blender内で唯一の文字列 である必要があります。 本節のサンプルでは、作成するアドオンのカテゴリが OBJECT
であることから、IDを object.create_object
としました。
bl_options
には、オペレータクラスの処理の属性を、集合型で指定します。 本節のサンプルでは、メニューへ登録するための REGISTER
と、エラー発生時に処理実行前の状態へ戻すことを可能にするための UNDO
を指定しました。
bl_idname
、bl_label
、bl_description
に指定した値は、図のように追加したメニューの項目から確認することができます。
続いて、メニューを実行した時に呼ばれるメソッドを作成します。
# メニューを実行した時に呼ばれる関数
def execute(self, context):
bpy.ops.mesh.primitive_ico_sphere_add()
print("サンプル2-1: 3DビューにICO球を生成しました。")
return {'FINISHED'}
メニューを実行した時には、execute
メソッドが呼ばれます。 このため、execute
メソッドにはメニューを実行した時の処理を記述します。
execute
メソッドが呼ばれると、以下の引数がBlender本体から渡されてきます。 なお、本節のサンプルではこれらの引数を利用しないため、特に意識する必要はありません。
引数 | 型 | 値の説明 |
---|---|---|
self |
呼びだされた execute メソッドを定義しているクラス |
オペレータクラスのインスタンス |
context |
bpy_types.Context |
execute メソッド実行時のコンテキスト |
execute
メソッドの処理を解説します。
最初に、bpy.ops.mesh.primitive_ico_sphere_add
関数を呼んでいます。 これはBlenderが提供しているAPIの1つで、3DビューエリアにICO球を生成します。 この関数には複数の引数を渡すことができますが、本節のサンプルでは引数を指定していないため、3Dカーソルの位置にICO球が生成されます。
bpy.ops.mesh.primitive_ico_sphere_add
関数は以下の引数を渡すことができます。
引数 | 型 | 値の説明 |
---|---|---|
size |
浮動小数点数 | 生成するICO球のサイズ |
location |
タプル | 生成時のICO球の座標 |
rotation |
タプル | 生成時のICO球の回転角 |
ソースコードを改造し、bpy.ops.mesh.primitive_ico_sphere_add
関数に引数を指定して実行してみましょう。
ICO球生成時のサイズが2.0倍、生成時の座標が(x, y, z) = (5.0, -5.0, 0.0)、生成時の回転角(ラジアン)が(x, y, z) = (0.79, 0.0, 1.57)のICO球を作成するように、execute
メソッドを以下のように書き換えます。
# メニューを実行した時に呼ばれる関数
def execute(self, context):
bpy.ops.mesh.primitive_ico_sphere_add(size=2.0, location=(5.0, -5.0, 0.0), rotation=(0.79, 0.0, 1.57))
print("サンプル2-1: 3DビューにICO球を生成しました。")
return {'FINISHED'}
アドオンを有効化し、[3Dビュー] エリアのメニューから [追加] > [メッシュ] > [球] を実行すると、右図のように指定した引数に応じてICO球が生成されます。
bpy.ops.mesh.primitive_ico_sphere_add
関数がICO球を作成する関数であると書きましたが、どのようにしてこの関数がICO球を作成する関数であることを知ることができたのでしょうか?続いて print
関数が呼ばれますが、print
関数は引数に指定した文字列をコンソールウィンドウに表示する関数です。
最後に return
で値を返しますが、execute
メソッドで返す値は以下のいずれかになります。 本節のサンプルでは処理が正常に終了したことを示す FINISHED
を返しています。
戻り値 | 値の説明 |
---|---|
FINISHED |
execute メソッドで行った処理を確定します。オペレーションが成功した時に指定します。 |
CANCELLED |
execute メソッドで行った処理を取り消します。オペレーションが失敗した時に指定します。 |
PASS_THROUGH |
オペレーションにより発行されたイベントを無視します。モーダルモード中に本処理のみならず、他の処理にもイベントを通知する時に指定します。 |
RUNNING_MODAL |
モーダルモードに移行します。 |
ここでは FINISHED
と、エラーが発生した時にメソッドで行った処理を取り消す CANCELLED
を覚えておけばよいと思います。
オペレータクラスを作成しただけでは、メニューなどのUIには登録されません。 メニューへ登録するためには、メニューへ登録するための処理を記述する 必要があります。
最初に、メニューに登録時に呼ばれるメニュー構築関数 menu_fn
を作成します。 menu_fn
関数は、後で解説するアドオン有効化・無効化時に呼ばれる関数の中で利用します。
# メニューを構築する関数
def menu_fn(self, context):
self.layout.separator()
self.layout.operator(CreateObject.bl_idname)
メニューの編集は、self.layout
を用いて行います。
self.layout.operator
関数の引数に CreateObject.bl_idname
を指定することで、作成したオペレータクラスの処理をメニューに登録することができます。
さらに本節のサンプルでは、新たに作成するメニュー項目と既存のメニュー項目とを分けるためのセパレータ(メニュー項目を区切る横線)を追加しています。 セパレータの追加は、self.layout.separator
関数で行うことができます。
アドオン有効化時には、register
関数が呼ばれます。
# アドオン有効化時の処理
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_mesh_add.append(menu_fn)
print("サンプル2-1: アドオン「サンプル2-1」が有効化されました。")
bpy.utils.register_module
関数 は、引数に指定したモジュールを登録してBlender内で使えるようにするための関数です。 引数に __name__
を指定することで、ファイル内の全てのモジュールを登録することができます。
bpy.types.INFO_MT_mesh_add.append
関数に、メニューを構築する関数である menu_fn
関数を指定することで、[3Dビュー] エリアのメニューである [追加] > [メッシュ] に項目を追加することができます。
bpy.types.INFO_MT_mesh_add
は、bpy.types.INFO_MT_mesh_add.append
関数を確認した時と同様に、[3Dビュー] エリアのメニュー [追加] > [メッシュ] をマウスオーバーすることで確認することができます。 ここで、もしマウスオーバーした際にサブメニューが開いてしまって確認できない場合は、キーボードの左キーを押すことで確認することができるようになります。
最後に print
関数で、アドオンが有効化されたことをコンソールウィンドウへ出力します。
アドオン無効化時には、unregister
関数が呼ばれます。
# アドオン無効化時の処理
def unregister():
bpy.types.INFO_MT_mesh_add.remove(menu_fn)
bpy.utils.unregister_module(__name__)
print("サンプル2-1: アドオン「サンプル2-1」が無効化されました。")
bpy.types.INFO_MT_mesh_add.remove
関数に、メニューを構築する関数である menu_fn
関数を指定することで、[3Dビュー] エリアのメニューである [追加] > [メッシュ] からメニューを削除することができます。
bpy.utils.unregister_module
関数は、引数に指定したモジュールを削除してBlenderからの利用を禁止する関数です。 アドオン有効化時に bpy.utils.register_module
関数の引数に指定したものと同様、引数に __name__
を指定することでファイル内の全てのモジュールを削除できます。
最後に print
関数で、アドオンが無効化されたことをコンソールウィンドウへ出力します。
最後に、メイン処理について説明します。
[テキストエディター] エリアのメニューである [テキスト] > [スクリプト実行] を実行した時に呼ばれる処理がメイン処理です。
|
メイン処理では、アドオンの登録処理のみ行っています。
アドオンであればメイン処理は必要な処理ではありませんが、慣習として書くことが多いので本サンプルでも記載しています。
# メイン処理
if __name__ == "__main__":
register()
ICO球を3Dビューエリア上に生成するアドオンを作成し、アドオンのソースコードを解説しました。
本節で紹介したサンプルはシンプルな機能しか持たないアドオンでしたが、覚えることが多く混乱された方も多いと思います。 しかし、アドオン開発に必要な知識をここでしっかりと理解しておくことで、次節以降の内容をスムーズに理解できると思います。 本節で説明したことを理解してから次節に進むようにしてください。 なおこの時点で完全に理解できていない状態で先に進めてしまっても、わからなくなった場合に本節に戻ってきて復習するのも良いと思います。
bpy
モジュールをインポートする必要があるbl_info
変数は、アドオンに関する情報をBlenderに伝えるために指定する変数であるbpy.types.Operation
クラスを継承したオペレータクラスの execute
メソッドに記述するregister
関数はアドオン有効化時に呼ばれる関数であり、モジュールの登録やメニューの構築を行う処理を記述するunregister
関数はアドオン無効化時に呼ばれる関数であり、モジュールの削除や構築したメニューの破棄を行う処理を記述する