[Blender] Blenderプラグインの作り方

# Blenderプラグインとは
Blenderは機能を拡張するため、さまざまなAPIを公開しています。APIを利用することで、例えば「現在選択されている面」「オブジェクトの頂点の位置」など、Blenderが内部で使用しているデータを取得することができます。APIから取得できる情報は様々で、公開されているAPIは例えば以下から確認することができます。
http://www.blender.org/documentation/blender_python_api_2_67_release/contents.html

# プラグインの作成に必要なこと
APIはPythonベースであり、ユーザ向けのものではないため以下の知識が必要です。
一見するとかなり敷居が高そうに見えますが、実際はBlenderを作って何かしら作品を作ったことのある人なら何とかなると思います。逆に、3D関連のプログラミングに慣れている方にとっては、簡単かもしれません。

* Pythonの知識（入門レベルでも問題ないでしょう）
* モデリングやCGなどの3DCGの知識（UV座標・法線などの基本的な知識は最低限必要です）
* 数学・物理の知識（物理演算などのプラグインを作成する場合に必要です）
* 英語（リファレンスや開発者サイトはすべて英語ですが、高校レベルの英語力があれば問題ないでしょう）

# サンプルプラグイン
Blenderの簡単なサンプルプラグインです。

```py3:skeleton.py
# Blender内部のデータ構造にアクセスするために必要
import bpy

# プラグインに関する情報
bl_info = {
    "name" : "Hoge Plugin",             # プラグイン名
    "author" : "Piyo",                  # 作者
    "version" : (0,1),                  # プラグインのバージョン
    "blender" : (2, 6, 5),              # プラグインが動作するBlenderのバージョン
    "location" : "UV Mapping > Hoge",   # Blender内部でのプラグインの位置づけ
    "description" : "Hoge Fuga Piyo",   # プラグインの説明
    "warning" : "",
    "wiki_url" : "",                    # プラグインの説明が存在するWikiページのURL
    "tracker_url" : "",                 # Blender Developer OrgのスレッドURL
    "category" : "UV"                   # プラグインのカテゴリ名
}

# メニュー
class CHoge(bpy.types.Operator):
    
    bl_idname = "uv.hoge"               # ID名
    bl_label = "Hoge Menu"              # メニューに表示される文字列
    bl_description = "Hoge Piyo"        # メニューに表示される説明文
    bl_options = {'REGISTER', 'UNDO'}

    # 実際にプラグインが処理を実施する処理
    def execute(self, context):
        return {'FINISHED'}             # 成功した場合はFINISHEDを返す

# メニューを登録する関数
def menu_func(self, context):
    self.layout.operator("uv.hoge")     # 登録したいクラスの「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()
```

# サンプルプラグインの解説
## bpyモジュールのimport

Blenderの内部データにアクセスするためには、bpyと呼ばれるモジュールをインポートする必要があります。

```py3:skeleton_1.py
# Blender内部のデータ構造にアクセスするために必要
import bpy
```

## プラグインに関する情報（bl_info）

プラグインに関する情報を記述します。ソースコードのコメントがそのまま説明となっているため、ここでは特に何も説明しません。プラグインをblenderのwikiに公開したい場合は、WikiページのURLやBlender Deverloper OrgのURLを記載したほうが良いでしょう。ただし個人で利用する場合は、locationやcategoryのみ気をつければ問題ないです。参考までに私が作成したプラグインのWikiページとBlender Developer OrgのURLを以下に示しておきます。
[Wiki] http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/UV/Copy_Paste_UVs
[Blender Developer Org] https://developer.blender.org/T38460

```py3:skeleton_2.py
# プラグインに関する情報
bl_info = {
    "name" : "Hoge Plugin",             # プラグイン名
    "author" : "Piyo",                  # 作者
    "version" : (0,1),                  # プラグインのバージョン
    "blender" : (2, 6, 5),              # プラグインが動作するBlenderのバージョン
    "location" : "UV Mapping > Hoge",   # Blender内部でのプラグインの位置づけ
    "description" : "Hoge Fuga Piyo",   # プラグインの説明
    "warning" : "",
    "wiki_url" : "",                    # プラグインの説明が存在するWikiページのURL
    "tracker_url" : "",                 # Blender Developer OrgのスレッドURL
    "category" : "UV"                   # プラグインのカテゴリ名
}
```

## メニュー用のクラス

実際にプラグインの処理を記載するクラスで、単一のメニュー項目を作成します。bpy.types.Operatorクラスを継承する必要があります。executeメソッドに実行したい処理を記述し、成功した場合は「FINISHED」を戻り値として返す必要があります。他に戻り値として指定できるものとして、エラーが生じた場合に操作を打ち切る「CANCELLED」などがあるります。詳しくは以下を参照してください。
http://www.blender.org/documentation/blender_python_api_2_67_1/bpy.types.Operator.html

```py3:skeleton_3.py
# メニュー
class CHoge(bpy.types.Operator):
    
    bl_idname = "uv.hoge"               # ID名
    bl_label = "Hoge Menu"              # メニューに表示される文字列
    bl_description = "Hoge Piyo"        # メニューに表示される説明文
    bl_options = {'REGISTER', 'UNDO'}

    # 実際にプラグインが処理を実施する処理
    def execute(self, context):
        return {'FINISHED'}             # 成功した場合はFINISHEDを返す
```

## プラグインのインストール・アンインストール時の処理

プラグインをインストールしたときに実行される処理を「register」関数、アンインストールしたときに実行される処理を「unregister」関数に記述します。bpy.utils.register_moduleとbpy.utils.unregister_moduleでプラグインの登録を行います。bpy.types.VIEW3D_MT_uv_map.appendとbpy.types.VIEW3D_MT_uv_map.removeは「UV Map」のメニューに項目を追加・削除するものです。登録したいクラス内で定義された「bl_idname」をself.layout.operatorの引数に渡した処理を記載した関数を作成（ここではmenu_func）し、bpy.types.VIEW3D_MT_uv_map.appendの引数に渡すことで、「UV Map」のメニューにbl_labelで指定された項目が追加されます。bpy.types.VIEW3D_MT_uv_map.removeの引数に渡すと追加した項目が削除されます。

```py3:skeleton_4.py
# メニューを登録する関数
def menu_func(self, context):
    self.layout.operator("uv.hoge")     # 登録したいクラスの「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)
```

## main関数

main関数では、register関数を呼び出すだけでよいです。

```py3:skeleton_5.py
# メイン関数
if __name__ == "__main__":
    register()
```

# サンプルプラグインの実行

上記のサンプルプラグインを実際に動作させてみましょう。プラグインのインストールの手順は以下のとおりです。なお、インストール手順についてはBlenderのWikiページにも記載されています。
http://wiki.blender.org/index.php/Doc:JA/2.6/Manual/Extensions/Python/Add-Ons

1. 「File」-「User Preferences」を選択します
2. 「Addons」タブを選択します
3. 「Install from File...」ボタンを押します
4. インストールしたいプラグインを選択します
5. インストールされたプラグインの横のチェックボックスをオンにします
6. 「Edit Mode」で「U」を押します
7. 「Hoge Menu」と表示されていることを確認します
8. 「Hoge Menu」をクリックすると処理が実行されます（今回の場合は特に何も処理を行っていないので、何も起こりません）

# 実行結果

インストールが無事完了すれば、各画面で以下のように確認することができます。

## 「User Preferences」-「Addons」
![20140905224305.jpg](https://qiita-image-store.s3.amazonaws.com/0/38888/58d608fe-f059-c5d5-eb8a-497e77d361b1.jpeg)
## 「Edit Mode」の「U」メニュー
![20140905224318.jpg](https://qiita-image-store.s3.amazonaws.com/0/38888/da59926b-0c8c-052b-8392-c3d2f026ec73.jpeg)

# Blenderプラグイン開発に関するQiita記事

私がBlenderプラグインを開発していく際にポイントとなったことを他のQiita記事で紹介しています。合わせて参考にしてみてください。

## Blender APIを深く知りたい方向けの記事

* [[Blender] プラグインでサブメニューを作成する方法](http://qiita.com/nutti/items/3f75f34adab99a805a35)
* [[Blender] オブジェクトの頂点・辺・面の選択順序を取得する方法](http://qiita.com/nutti/items/384109ec6ed6d4a2e9f9)
* [[Blender] ユーザがツールシェルフのオプションからプラグインを制御できるようにするための方法](http://qiita.com/nutti/items/ea4f4b0c3cfa90c88a58)
* [[Blender] EnumPropertyの選択項目を動的に設定する方法](http://qiita.com/nutti/items/9ec0a61d182350e44319)
* [[Blender] Blenderのスクリプトを複数ファイルに分割する](http://qiita.com/nutti/items/35e7f79f8683fc79eda8)
* [[Blender] Blenderスクリプトでマウスやキーボードのイベントを扱う方法](http://qiita.com/nutti/items/aeb2cd47d704d2368f19)
* [[Blender] スクリプトの内部からOpenGLを利用する](http://qiita.com/nutti/items/835b745257a79ed215e8)
* [[Blender] スクリプト内部で自作の機能にショートカットキーを割り当てる](http://qiita.com/nutti/items/e29226ff8bd7a7e770aa)
* [[Blender] スクリプト内からテキスト描画モジュールを利用する](http://qiita.com/nutti/items/82aebaaab0060b470257)

## Blenderプラグインを公開したい人向けの記事

* [[Blender] BlenderプラグインをBlender本体に取り込んでもらうまでの流れ](http://qiita.com/nutti/items/a63eb404a506c2081be2)
* [[Blender] Blenderスクリプトを多言語対応させる方法](http://qiita.com/nutti/items/adcf4feb45135d649105)

## Blenderプラグインの開発環境を向上したい人向けの記事

* [[Blender] Blenderスクリプトのデバッグ環境（Eclipse+PyDev）を整える](http://qiita.com/nutti/items/643aeff33228d37c1fda)
* [[Blender] Blenderに標準で備わっているPython Consoleのショートカットキー一覧](http://qiita.com/nutti/items/69e16b6a897011db1075)


# Blenderプラグイン開発チュートリアル

Blenderプラグインをこれから開発したい人向けに、初心者向けのチュートリアルを作成中です。
もし興味がありましたら、こちらもぜひ参考にしてみてください。

https://www.gitbook.com/book/nutti/introduction-to-add-on-development-in-blender/details

# 参考文献

* https://developer.blender.org/
* http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts
* http://www.blender.org/documentation/blender_python_api_2_65_9/contents.html
* http://matosus304.blog106.fc2.com/blog-entry-257.html