Blender 2.6 の Export plug-in を作る (1)

Blender を使った経験が全く無いので練習兼ねてプラグイン作ります。

Blender

Blender 2.65 を install 。
Script は python 3.3 で、plug-in (addon) もこれで記述するようです。

Scripts Development

本体に DirectX .x や fbx など多くの exporter addon が含まれているので、これらのスクリプトが参考になります。

Windows だとこの辺に入っています。
C:\Program Files\Blender Foundation\Blender\2.65\scripts\addons

●Python Console

Blender 上の 3D View など、Window を Python Console に切り替えられます。
直接コマンドを実行して動作確認ができるので便利です。

●スクリプトの置き場所

addon として作成した script は下記の場所に入れておきます。

◎ Windows 7/8

 C:\Users\<ユーザー名>\AppData\Roaming\Blender Foundation\Blender\2.65\scripts\addons

◎ MacOS X

 /Users/<ユーザー名>/Library/Application Support/Blender/2.65/scripts/addons

Add-Ons
Configuration & Data Paths

上記場所に入れたスクリプトでは最低限 bl_info の定義が必要です。
User Preferences の Addons を開くときに、フォルダ内の python ファイルから bl_info を検索して定義内容を取り込んでいるようです。
bl_info がなかったり定義にミスがあるとエラーになります。

Script meta informations

# test.py (Preference に列挙されるための最小限)

bl_info= {
  "name": "Test",
  "category": "Import-Export",
}

print( "on load message" );

●スクリプトの読み込み&実行

Blender のメニューから addon を有効にします。

   File → User Preferences … → Addons

上記の Addon スクリプト置き場に入っていて、かつ bl_info が定義されていればここに列挙されます。
左サイドの Categories で絞り込むと見つけやすくなります。
上の test.py なら “Import-Export” に入ります。

test.py である「Import-Export: Test」のチェックボックスを On にすると script が読み込まれて走ります。
ただし上の test.py は class を定義しておらず、内容が不完全なのでエラーになります。

●エラーコンソール

addon としてロードした script の print 出力 (stdout) は、
Blender 内の Python Console には表示されません。
エラーなどのログを見るにはコンソールを開きます。

Windows の場合、メニューの “Window” から

   Window → Toggle System Console

Maya でも別ウィンドウになっているあれ (Output Window) と同じです。

MacOS X/Linux の場合上記のメニューがないのでコマンドラインから起動します。
Finder からではなく、ターミナルを開いて blender コマンドを直接実行します。

$ /Applications/Blender/blender.app/Contents/MacOS/blender

The Console Window

これで上記 test.py を読み込もうとすると “on load message” が表示されたあと
エラーが出ていることを確認できます。

●コマンドの追加と実行

addon はコマンドの class を定義してシステムに登録する必要があります。

Preferences Addons のチェックボックスの on/off で script 内の
register()/unregister() が呼び出されています。
このタイミングで class を登録を行います。

# test.py (2)
import bpy

bl_info= {
  "name": "Test",
  "category": "Import-Export",
}

class ExportTest( bpy.types.Operator ):
    bl_label= 'export test'
    bl_idname= 'export.test_a6'

    def execute( self, context ):
        print( "exec-command" )
        return {'FINISHED'}

def unregister():
    bpy.utils.register_module(__name__)

def register():
    bpy.utils.unregister_module(__name__)

定義クラスは bl_label, bl_idname が必須で、bl_idname が識別子になっています。
(2) の test.py は Preferences Addos で正しくロードできます。

Preferences Addos の “Import-Export: Test” のチェックを入れると
register() が呼び出されて bl_idname で指定したコマンド名が有効になります。

Python Console を開いて export.test_a6() が実行できることを確認できます。
(↓太字は出力結果)

>>> bpy.ops.export.test_a6()
exec-command
{'NIFISHED'}

●Export Menu に追加する

付属の scripts/addons/io_scene_fbx を参考にしました。
io_export_direct_x.py の方は ExportHelper を使わずに実装されているようです。

# io_export_test_a6.py
import bpy
from bpy_extras.io_utils import ExportHelper

bl_info= {
  "name": "Export Test a6",
  "category": "Import-Export",
}

class ExportTestA6( bpy.types.Operator, ExportHelper ):
    bl_label= 'export test a6'
    bl_idname= 'export.test_a6'
    filename_ext= '.txt' # ←必須

    def execute( self, context ):
        print( 'file=' + self.filepath )
        return  {'FINISHED'}


def menu_func(self, context):
    self.layout.operator( ExportTestA6.bl_idname, text="Export Test a6 (.txt)" )

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

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

register()/unregister() の中で class だけでなく menu_func も登録しています。
この menu_func() はメニューの

   File → Export

のサブメニューを開くタイミングで呼ばれるようです。
self.layout.operator() の最初の引数が実行する class id、text が Menu のラベルです。
例えば menu_func() を

def menu_func(self, context):
    self.layout.operator( "export_scene.fbx", text="Export Test a6?" )

と書き換えると File → Export →「Export Test a6?」の選択で fbx の
export を呼び出せます。

●Export 時のオプション

Export 実行時に左側のサイドバーでオプション選択ができます。
例えば選択されたオブジェクトだけ Export したり、Axis を変更したりなど。
このようなプロパティは Export class に追加しておきます。

~

class ExportTestA6( bpy.types.Operator, ExportHelper ):
    bl_label= 'export test a6'
    bl_idname= 'export.test_a6'
    filename_ext= '.txt'

    # ↓追加
    flag_selected= BoolProperty( name= "Selected Objects",
                description= "Export selected objects",
                default= False )

    def execute( self, context ):
        print( 'file=' + self.filepath )
        print( 'flag=', self.flag_selected )
        return  {'FINISHED'}

~

これで File → Export →「Export Test a6」を選択すると、
Export ファイル選択画面となり、左サイドバーから「Selected Objects」の
チェックが可能となります。

右上の「export test a6」ボタンを押すと、コンソール出力で
入力したファイル名と “Selected Objects” のチェック状態が読み取れている事がわかります。

まだ必要最小限ですが addon 登録周りの挙動がわかったので、
次は内部データのアクセスを行います。