夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

Blenderでテキストフィールドを作成し、入力した文字をコンソールに出力するシンプルなアドオンを作成する

本日はBlender枠です。

現在MixedRealityModelingToolsなるBlenderとUnityで相互に情報をやり取りできるパッケージを作成しています。

今回はBlender側の実装する上での基礎的なコードとしてテキストフィールドを表示して、任意の文字をログに出力するようなことを行います。

目的としてはBlender内で入力した任意の文字列をコード内で使用できることを実装するというところで、今回はprint()でログ出力しますが、変数として格納したstring型のデータとしてあらゆる場面で使用できます。

〇シンプルなアドオン

まずBlenderでのシンプルなアドオンのコードを紹介します。

import bpy

# Define a new operator (action or function)
class HelloWorldOperator(bpy.types.Operator):
    bl_idname = "object.hello_world"
    bl_label = "Hello, World!"

    def execute(self, context):
        self.report({'INFO'}, "Hello, World!")
        return {'FINISHED'}

# Define a new UI panel
class HelloWorldPanel(bpy.types.Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_hello_world"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Tool'

    def draw(self, context):
        layout = self.layout

        # Add the operator to the panel
        layout.operator("object.hello_world")

# Registration
def register():
    bpy.utils.register_class(HelloWorldOperator)
    bpy.utils.register_class(HelloWorldPanel)

def unregister():
    bpy.utils.unregister_class(HelloWorldOperator)
    bpy.utils.unregister_class(HelloWorldPanel)

if __name__ == "__main__":
    register()

こちらのコードは過去の記事で詳しく紹介しています。

redhologerbera.hatenablog.com

今回はこのコードをベースにテキストフィールドを作成していきます。

Blenderでテキストフィールドを作成する。

Blenderでテキストフィールドを追加するためにはStringProperty()を使用します。

テキストフィールドとその機能を定義するためのオペレータとして次のクラスを作成しました。

# Define a new operator to print text
class PrintTextOperator(bpy.types.Operator):
    bl_idname = "object.print_text"  # アドオン内で一意のIDを設定
    bl_label = "Print Text"  #UI上で表示されるラベルを設定します

    text_input: bpy.props.StringProperty(name="Input Text")  # StringPropertyを使用してテキストフィールド用のプロパティを定義

    def execute(self, context):
        print("Input Text:", self.text_input)  # 入力されたテキストをコンソールに出力
        return {'FINISHED'}  # オペレーションの実行が終了したことを示すステータスを返す

このクラスをBlenderでUIとして表示する処理が次です。

    def draw(self, context):
        layout = self.layout

        # Add a text field to the panel
        layout.prop(context.scene, "my_text_input")

        # Add the print operator to the panel
        layout.operator("object.print_text")

ここではlayout.prop()とlayout.operator()の二つを定義しています。

prop()はテキストフィールドを定義します。第一引数のcontext.sceneはプロパティオブジェクト、第二引数がstring型の変数になります。 つまり入力したテキストはmy_text_inputに格納されることになります。

operator()はBlender内でUIとしてのボタンを定義します。 引数内はBlender内のIDでPrintTextOperatorと一致させることで紐づけています。

BlenderのUI側では次のように表示されます。

〇ボタンを押した際の処理

        # Add the print operator to the panel
        layout.operator("object.print_text")

定義されているボタンを押した場合はobject.print_textによって紐づけられているPrintTextOperatorクラスの def execute(self, context):が実行されます。

  def execute(self, context):
        print("Input Text:", self.text_input)  # 入力されたテキストをコンソールに出力
        return {'FINISHED'}  # オペレーションの実行が終了したことを示すステータスを返す

ここでは終了処理のほかに入力された文字をコンソールに出力しています。

〇アドオンとしての登録

最後に定義した各UIやクラスをアドオンとしてBlenderに登録する処理が以下です。

# Registration
def register():
    bpy.utils.register_class(HelloWorldOperator)
    bpy.utils.register_class(PrintTextOperator)
    bpy.utils.register_class(HelloWorldPanel)
    bpy.types.Scene.my_text_input = bpy.props.StringProperty(name="Text Input")

def unregister():
    bpy.utils.unregister_class(HelloWorldOperator)
    bpy.utils.unregister_class(PrintTextOperator)
    bpy.utils.unregister_class(HelloWorldPanel)
    del bpy.types.Scene.my_text_input

registerはBlenderのアドオン登録時、unregisterは登録解除時に実行される関数でそれぞれ、アドオンの定義、解除を行っています。

〇コード全文

import bpy

# Define a new operator (action or function)
class HelloWorldOperator(bpy.types.Operator):
    bl_idname = "object.hello_world"
    bl_label = "Hello, World!"

    def execute(self, context):
        self.report({'INFO'}, "Hello, World!")
        return {'FINISHED'}

# Define a new operator to print text
class PrintTextOperator(bpy.types.Operator):
    bl_idname = "object.print_text"
    bl_label = "Print Text"

    text_input: bpy.props.StringProperty(name="Input Text")

    def execute(self, context):
        print("Input Text:", self.text_input)
        return {'FINISHED'}

# Define a new UI panel
class HelloWorldPanel(bpy.types.Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_hello_world"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Tool'

    def draw(self, context):
        layout = self.layout

        # Add a text field to the panel
        layout.prop(context.scene, "my_text_input")

        # Add the print operator to the panel
        layout.operator("object.print_text")

# Registration
def register():
    bpy.utils.register_class(HelloWorldOperator)
    bpy.utils.register_class(PrintTextOperator)
    bpy.utils.register_class(HelloWorldPanel)
    bpy.types.Scene.my_text_input = bpy.props.StringProperty(name="Text Input")

def unregister():
    bpy.utils.unregister_class(HelloWorldOperator)
    bpy.utils.unregister_class(PrintTextOperator)
    bpy.utils.unregister_class(HelloWorldPanel)
    del bpy.types.Scene.my_text_input

if __name__ == "__main__":
    register()

以上でテキストフィールドの実装とコンソールの出力が行えました。

〇参考

colorful-pico.net