mcpField
B
blender-python-addon

blender-python-addon

github.com/mindrally開発28768 回インストール3 週間前に更新
リポジトリ

blender-python-addon について

`bpy` API を使った Blender アドオン開発のスキルです。構成、UI、安全なシーン操作、登録、テスト、パッケージ化を扱います。

主な機能

  1. 01アドオンのパッケージとマニフェスト構成
  2. 02オペレーター、パネル、プロパティ
  3. 03安全なシーンとメッシュの操作
  4. 04登録とクリーンアップの手順
  5. 05Blender バージョン間のテスト
  6. 06拡張機能とアドオンのパッケージ化

活用シーン

  1. 01新しい Blender アドオンのひな形作成
  2. 02Blender UI への操作と設定の追加
  3. 03登録と解除が適切かの確認
  4. 04インストール用アドオンパッケージの準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mindrally/skills --skill blender-python-addon

インストール後、Claude Code で/blender-python-addonを入力して読み込まれたか確認します。

詳細

Blender Python アドオン開発

このスキルでは、アドオンの構成、オペレーター、パネル、プロパティ、安全なシーン操作、Blender のバージョンをまたいだテストなど、bpy API を使った Blender アドオンの開発方法を説明します。

Blender アドオンの開発ワークフロー

  1. アドオンのひな形を作成する — エントリーポイントとして __init__.py を含むパッケージを作成し、名前、バージョン、対応する Blender のバージョンを記述した blender_manifest.toml(Blender 4.2 以降の拡張機能)または bl_info 辞書(従来のアドオン)を用意します。
  2. データを定義する — 関連する設定をまとめる PropertyGroup クラスを作成し、適切な ID 型に登録します(例:bpy.types.Scene.my_addon = PointerProperty(type=MyAddonSettings))。
  3. オペレーターを実装する — 各ユーザー操作について bpy.types.Operator をサブクラス化します。利用可能かどうかを判定する poll()、対話型のセットアップを行う invoke()、実際の処理を行う execute() を実装します。
  4. UI パネルを作成する — bpy.types.Panel をサブクラス化し、適切なエディター(3D ビューポートのサイドバー、プロパティエディターなど)にオペレーターとプロパティを表示します。
  5. すべてを登録する — すべてのクラスを classes タプルに列挙し、対応する register()/unregister() 関数で登録・解除します。プロパティポインターも、クラスとあわせて登録します。
  6. クリーンなプロファイルでテストする — Blender を --factory-startup で起動し、アドオンをインストールして有効化し、各オペレーターを試します。その後、無効化し、後に何も残っていないことを確認します。
  7. パッケージ化して配布する — アドオンフォルダーを ZIP 化する(または .zip 拡張機能パッケージをビルドする)とともに、Blender の Preferences > Add-ons(または Extensions)パネルから問題なくインストールできることを確認します。

アドオンの構成

  • アドオンのエントリーポイントは __init__.py に置き、互いに対応する明確な register() 関数と unregister() 関数を用意します(登録したものはすべて、逆順に登録解除します)。
  • アドオンが簡単なものより大きくなったら、オペレーター、パネル、プロパティ、プリファレンス、ユーティリティコードを別々のモジュールに分け、__init__.py からインポートして登録します。
  • 対象の Blender バージョンとパッケージ形式に合わせて、bl_info(4.2 より前の従来のアドオン)または blender_manifest.toml(4.2 以降の拡張機能)を使用します。規約を混在させないでください。
  • UI のラベルは簡潔にします。プロジェクトが対応している場合は、bpy.app.translations または "Category"/ラベルの規約を使用して、ユーザー向けのテキストをローカライズできるようにします。

API の使用

  • 操作には bpy.types.Operator、UI レイアウトには bpy.types.Panel、関連する設定のグループ化には bpy.types.PropertyGroup を使用します。
  • すべてのオペレーターに bl_idname(小文字の category.action 形式。例:object.apply_custom_modifier)、bl_label、bl_options(例:{'REGISTER', 'UNDO'})を明示的に定義します。
  • オペレーターを実行可能にする前に poll() でコンテキストを検証します。アクティブなオブジェクト、適切なモード、有効な選択があるかを確認し、エラーを発生させる代わりにオペレーターボタンをグレー表示にします。
  • 対話型のセットアップ(ダイアログの表示、マウス位置の読み取り)には invoke() を、実際の操作には execute() を使用します。追加の対話が不要な場合は、invoke() から self.execute(context) を呼び出します。
  • 成功時は一貫して {'FINISHED'} を、失敗時またはユーザーによる中断時は {'CANCELLED'} を返します。何も返さない None や、認識されない文字列は返さないでください。
  • モディファイアー、シェイプキー、その他の依存関係グラフに基づく結果を含む最終的なシーン状態を読み取る場合は、bpy.context.evaluated_depsgraph_get() と object.evaluated_get(depsgraph) を使用します。
例:オペレーター、パネル、登録
bl_info = {
    "name": "Random Vertex Color",
    "author": "Example",
    "version": (1, 0, 0),
    "blender": (4, 0, 0),
    "category": "Mesh",
}

import bpy
import random


class MESH_OT_random_vertex_color(bpy.types.Operator):
    """Assign a random color to the active vertex color layer"""

    bl_idname = "mesh.random_vertex_color"
    bl_label = "Randomize Vertex Colors"
    bl_options = {"REGISTER", "UNDO"}

    @classmethod
    def poll(cls, context):
        obj = context.active_object
        return (
            obj is not None
            and obj.type == "MESH"
            and obj.mode == "OBJECT"
            and obj.data.color_attributes.active_color is not None
        )

    def execute(self, context):
        obj = context.active_object
        color_layer = obj.data.color_attributes.active_color
        for data in color_layer.data:
            data.color = (random.random(), random.random(), random.random(), 1.0)
        obj.data.update()
        self.report({"INFO"}, f"Randomized colors on '{obj.name}'")
        return {"FINISHED"}


class VIEW3D_PT_random_vertex_color(bpy.types.Panel):
    bl_label = "Vertex Color Tools"
    bl_idname = "VIEW3D_PT_random_vertex_color"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_category = "Tool"

    def draw(self, context):
        layout = self.layout
        layout.operator(MESH_OT_random_vertex_color.bl_idname, icon="COLOR")


classes = (
    MESH_OT_random_vertex_color,
    VIEW3D_PT_random_vertex_color,
)


def register():
    for cls in classes:
        bpy.utils.register_class(cls)


def unregister():
    for cls in reversed(classes):
        bpy.utils.unregister_class(cls)


if __name__ == "__main__":
    register()

データとプロパティ

  • モジュールレベルの変数に場当たり的なグローバル状態を詰め込むのではなく、PropertyGroup クラスを通じてカスタムプロパティを登録してください。こうした変数はファイルの再読み込み後に保持されず、アンドゥにも対応していません。
  • アドオンの設定(API キー、既定のパス、ファイルをまたいで保持される UI の切り替え設定)は、bl_idname がアドオンのモジュール名と一致する AddonPreferences サブクラスに保存してください。
  • PointerProperty、CollectionProperty と、型を明示したプロパティ(StringProperty、FloatProperty、BoolProperty など)を使用し、ツールチップと Python API が自己説明的になるよう、name= と description= を明示してください。
  • unregister() の際に、カスタムプロパティ、bpy.app.handlers のエントリ、タイマー、キーマップをクリーンアップしてください。bpy.types.* クラスやハンドラーリストに追加したものは、すべて明示的に削除する必要があります。

安全性とパフォーマンス

  • オブジェクトの削除やファイルの上書きなど、破壊的なシーン操作は、ユーザーが明示的に操作しない限り実行しないでください。破壊的な操作をファイルの読み込み時に無断で自動実行してはいけません。
  • モーダルオペレーターで UI スレッドをブロックしないでください。時間のかかる処理では、タイトなループの代わりに context.window_manager.event_timer_add() とモーダル状態マシンを使用してください。
  • メッシュの編集はまとめて行い、メッシュデータをプログラムで編集する場合は、構造的な変更のために mesh.vertices を一つずつループするのではなく、bmesh モジュール(bmesh.from_edit_mesh、bmesh.new())を使用してください。
  • 大規模なシーンを繰り返し走査したり、draw() メソッド内でコストの高いデータを再計算したりしないでください。draw() は UI が再描画されるたびに実行されるため、結果をキャッシュし、基になるデータが変わったときにのみキャッシュを無効化してください。
  • ファイルパスは設定可能にし、OS 固有のパスをハードコードするのではなく、Blender のパスユーティリティ(bpy.path.abspath、bpy.utils.resource_path)を使って解決してください。

テストとデバッグ

  • 他のアドオンへの隠れた依存を見つけるため、クリーンな Blender プロファイル(blender --factory-startup)と、パフォーマンスやデータ形状の問題を見つけるための代表的な本番シーンの両方でテストしてください。
  • アドオンモジュールをインポートし、register() を呼び出し、各コアオペレーターを bpy.ops 経由で実行した後、エラーや状態の残留なしに unregister() を呼び出すスモークテストを追加してください。
  • ユーザー向けのオペレーターのフィードバックには、コンソールを見ないユーザーがほとんどであるため、コンソールへの出力ではなく、self.report({'ERROR'}, "message") または {'WARNING'}/{'INFO'} を使用してください。
  • Blender 3.x と 4.x の間の API 変更など、バージョン固有の API の違いは、小さなヘルパー関数の中に分離してください。そうすれば、アドオンの他の部分にバージョンチェックを散在させずに済みます。

よくある間違い

  • unregister() でクラス、ハンドラー、タイマー、キーマップの登録解除を忘れ、アドオンを無効にした後に Blender の状態を壊してしまう。
  • Panel.draw() メソッド内で Blender のデータ(オブジェクトの追加、メッシュデータの変更)を変更する。draw() ではデータの読み取りと UI のレイアウトのみを行う必要があります。
  • context を先に確認せず、アクティブオブジェクト、空でない選択状態、または特定のモード(Object/Edit/Sculpt)が存在すると仮定する。
  • 開発者のマシンにしか存在しないアセットの絶対パスをハードコードし、相対パスや bpy.utils.resource_path を使用しない。

コメント