.. _pme-scripting:
================
スクリプティング
================
PMEは、Blenderの `Python API `_ を使用した高度なカスタマイズと自動化を可能にします。
この記事では、PMEのスクリプティング機能の概要と、組み込まれたグローバル変数と関数について説明します。
.. NOTE: RTDでのページ内目次のために必要。furo または book テーマでは不要のためコメントアウト
.. .. contents::
.. :local:
.. :depth: 2
.. :class: this-will-duplicate-information-and-it-is-still-useful-here
.. important::
通常の Command / Custom とメニューの Poll は **1行のコード** を入力します。
長い処理や再利用する処理は外部の Python ファイルへ分け、コード欄には短い呼び出しを書きます。
AI が生成するコードにも、この入力先ごとの形式が適用されます。
入力先ごとの仕様と書き方は :doc:`command_text` を参照してください。
このページは関数・変数と引数を調べる API リファレンスです。
--------------
チュートリアル
--------------
- **動画**: `Introduction to Scripting with Python in Blender (vimeo.com) `_
- **動画**: `Task Automation with Python Scripting in Blender (youtube.com) `_
- `Python for Non-Programmers (python.org) `_
- `Blender Python API `_
- `Blender/Python Quickstart `_
----------------
グローバル変数
----------------
PMEの各スロットエディタ内で利用できる変数です。
.. list-table::
:header-rows: 1
:widths: 25 75
* - **変数**
- **説明**
* - ``menu``
- アクティブなメニューの名前
* - ``slot``
- アクティブなスロットの名前
* - ``C``
- `bpy.context `_
* - ``D``
- `bpy.data `_
* - ``O``
- `bpy.ops `_
* - ``T``
- `bpy.types `_
* - ``P``
- `bpy.props `_
* - ``L``
- 現在の `UILayout `_ オブジェクト
.. code-block:: python
L.box().label(text="My Label")
* - ``E``
- 現在の `Event `_ オブジェクト
.. code-block:: python
E.ctrl and E.shift and message_box("Ctrl+Shift Pressed")
* - ``U``
- ユーザーデータ保存用の `pme.UserData <#pme.UserData>`_ インスタンス
.. code-block:: python
U.foo = "value"
U.update(foo="value1", bar="value2")
U.foo
U.get("foo", "default_value")
---------------
グローバル関数
---------------
PMEのスロットエディタ内で利用できる関数です。コマンドタブとカスタムタブで利用できる関数が異なります。
.. _pme-common-functions:
共通関数
************
.. py:function:: execute_script(path, **kwargs)
外部のPythonスクリプトを実行します。
:param str path: スクリプトファイルパス。相対パス(``pie_menu_editor`` フォルダから、推奨)または絶対パス。
:param kwargs: スクリプトに渡される追加のキーワード引数。
:return: スクリプト内の ``return_value`` またはデフォルトで ``True``。
.. warning::
- 信頼できるソースのスクリプトのみ配置・実行してください
- 実行前に内容を確認し、必要に応じてバックアップやテスト環境で検証してください
- ファイル操作や設定変更など、環境に影響する処理が含まれる場合があります
**スクリプト内で利用可能な変数**:``kwargs``、``__file__``、``return_value``、PMEのすべてのグローバル変数
**使用例**::
# 基本的な実行と戻り値
execute_script("scripts/hello_world.py", msg="Hello World!")
message_box(execute_script("scripts/get_message.py"))
# scripts/hello_world.py
message_box(kwargs["msg"])
# scripts/get_message.py
return_value = "Hi!"
# パラメータを使用した処理
# scripts/process_data.py
kwargs = locals().get("kwargs", {})
result = my_function(kwargs.get("param1"), kwargs.get("param2", "default"))
return_value = result
# 呼び出し
result = execute_script("scripts/process_data.py", param1=200, param2="Hello")
# カスタムタブでのUI描画
# scripts/custom_ui.py
msg = kwargs.get("msg", pme.context.text or "Default Message")
box = L.box()
box.label(text=msg, icon=pme.context.icon, icon_value=pme.context.icon_value)
# 呼び出し
execute_script("scripts/custom_ui.py", msg="カスタムメッセージ")
.. py:function:: props(name=None, value=None)
PMEプロパティの値を取得または設定します。
:param str name: プロパティの名前。
:param value: プロパティの新しい値。
:return: ``name`` が ``None`` の場合はPMEプロパティコンテナ、``name`` のみが指定された場合はプロパティ値、値を設定する場合は ``True``。
**例**::
# 文字列記法を使用してプロパティ値を取得
value = props("MyProperty")
# 代替: 属性記法を使用してプロパティを取得
value = props().MyProperty # props()はプロパティコンテナを返す
# 文字列記法を使用してプロパティ値を設定
props("MyProperty", value)
# 代替: 属性記法を使用してプロパティを設定
props().MyProperty = value # props()はプロパティコンテナを返す
.. py:function:: paint_settings()
コンテキストに応じたペイント設定を取得します。
:return: 現在のペイント設定、またはペイントモードでない場合は ``None``。
**例**::
ps = paint_settings(); ps and L.template_ID_preview(ps, 'brush')
.. py:function:: find_by(collection, key, value)
``collection`` 内で ``key`` が ``value`` と等しい最初のアイテムを検索します。
:return: 見つかった場合はコレクションアイテム、そうでなければ ``None``。
**例**::
m = find_by(C.active_object.modifiers, "type", 'SUBSURF')
.. py:function:: setattr(object, name, value)
Pythonの組み込み :func:`setattr` と同じですが、設定後に ``True`` を返します。
:return: ``True``
.. _pme-command-tab-functions:
コマンドタブ関数
*******************
.. py:function:: open_menu(name, slot=None, **kwargs)
名前を指定してメニュー、パイメニュー、ポップアップダイアログを開くか、スタックキー、スティッキーキー、モーダルオペレーター、またはマクロオペレーターを実行します。
:param str name: メニューの名前。
:param slot: スタックキー実行のためのスロットのインデックスまたは名前。
:param kwargs: ローカル変数として使用されるモーダル/マクロオペレーターの引数。
:return: 対象メニューが存在し、現在のコンテキストで利用可能な場合は ``True``。対象が存在しない、無効化されている、Poll によりブロックされている、または指定スロットが見つからない場合は ``False``。
**例**::
# アクティブオブジェクトのタイプに応じてメニューを開く:
open_menu("Lamp Pie Menu" if C.active_object.type == 'LAMP' else "Object Pie Menu")
# Ctrl修飾キーに応じて"My Stack Key"スロットを呼び出す:
open_menu("My Stack Key", "Ctrl slot" if E.ctrl else "Shift slot")
.. py:function:: toggle_menu(name, value=None)
メニューを有効または無効にします。
:param str name: メニューの名前。
:param bool value: 有効にする場合は ``True``、無効にする場合は ``False``、トグルする場合は ``None``。
:return: メニューが存在する場合は ``True``、そうでなければ ``False``。
.. py:function:: tag_redraw(area=None, region=None)
UIエリアまたはリージョンを再描画します。
:param str area: 再描画する :attr:`Area.type `。``None`` の場合はすべてのエリアを再描画。
:param str region: 再描画する :attr:`Region.type `。``None`` の場合はすべてのリージョンを再描画。
:return: ``True``
.. py:function:: close_popups()
すべてのポップアップダイアログを閉じます。
:return: ``True``
.. py:function:: overlay(text, **kwargs)
オーバーレイメッセージを描画します。
:param str text: 表示するメッセージ。
:param kwargs:
- ``alignment``: ``['TOP', 'TOP_LEFT', 'TOP_RIGHT', 'BOTTOM', 'BOTTOM_LEFT', 'BOTTOM_RIGHT']`` のいずれか。デフォルトは ``'TOP'``。
- ``duration``: 表示時間(秒)。デフォルトは ``2.0``。
- ``offset_x``: 水平オフセット。デフォルトは ``10`` ピクセル。
- ``offset_y``: 垂直オフセット。デフォルトは ``10`` ピクセル。
:return: ``True``
**例**::
overlay('Hello PME!', offset_y=100, duration=1.0)
.. py:function:: message_box(text, icon='INFO', title="Pie Menu Editor")
メッセージボックスを表示します。
:param str text: 表示するメッセージ。
:param str icon: アイコン名(例: 'INFO', 'ERROR', 'QUESTION' など)。
:param str title: ウィンドウタイトル。
:return: ``True``
.. py:function:: confirm_box(message, func=None, icon='QUESTION', width=0)
コマンドスロットから確認ダイアログを表示します。
:param str message: 表示するメッセージ。
:param func: 真偽値を1引数で受け取る任意のコールバック。OK時は ``True``、キャンセル時は ``False`` が渡されます。
:param str icon: Blenderのアイコン名。デフォルトは ``'QUESTION'``。
:param int width: ダイアログの幅(ピクセル)。``0`` はBlenderのデフォルト幅を使用します。
:return: ``None``。ユーザーが確定・キャンセルする前に戻ります。
確認後の処理はコールバック内に記述してください。``confirm_box()`` の後のコードは
確認を待たずに進みます。戻り値はユーザーの回答ではありません。
**用例1: 確認後に現在のエリアを閉じる**::
confirm_box(
"Close this area?",
func=lambda ok: bpy.ops.screen.area_close() if ok else None,
)
**用例2: 確認後にPMEのMacroを実行する**::
confirm_box(
"Run this macro?",
func=lambda ok: open_menu("My Macro") if ok else None,
)
``My Macro`` は、作成済みで有効なMacroの名前に置き換えてください。
このCommandは対象Macroの外に置きます。確認ダイアログはMacroの後続ステップを
一時停止せず、同じMacroを指定すると再びそのMacroを呼び出します。
どちらの用例もキャンセル時には何も実行しません。処理はコールバック時に利用可能な
コンテキストで実行され、通常のオペレーターやメニューのPoll条件に従います。
コールバックはダイアログ間で共有されるため、確認ダイアログは同時に1つだけ開いてください。
.. py:function:: input_box(func=None, prop=None)
入力ボックスを表示します。
:param func: 入力値で呼び出す関数。
:param str prop: 編集するプロパティへのパス。
:return: ``True``
**例**::
# オブジェクトの名前を変更:
input_box(prop="C.active_object.name")
# 入力値を表示:
input_box(func=lambda value: overlay(value))
.. _pme-custom-tab-functions:
カスタムタブ関数
*********************
.. py:function:: draw_menu(name, frame=True, dx=0, dy=0)
別のポップアップダイアログまたはパイメニュー内にポップアップダイアログを描画します。
:param str name: メニュー(ポップアップダイアログ)の名前。
:param bool frame: フレームを描画するかどうか。
:param int dx: 水平オフセット。
:param int dy: 垂直オフセット。
:return: 対象メニューが存在し、現在のコンテキストで利用可能な場合は ``True``。対象が存在しない、無効化されている、または Poll によりブロックされている場合は、何も描画せず ``False``。
.. py:function:: operator(layout, idname, text="", icon='NONE', emboss=True, icon_value=0, **kwargs)
:meth:`UILayout.operator() ` と似ていますが、オペレータープロパティの設定が可能です。
:param layout: :class:`UILayout ` インスタンス。
:param str idname: オペレーターの識別子。
:return: :class:`OperatorProperties ` オブジェクト。
**例**::
operator(L, "wm.context_set_int", "Material Slot 1",
data_path="active_object.active_material_index", value=0)
# 以下と同じ:
# op = L.operator("wm.context_set_int", text="Material Slot 1")
# op.data_path = "active_object.active_material_index"
# op.value = 0
.. py:function:: custom_icon(filename)
カスタムアイコンに関連付けられた整数値を取得します。
:param str filename: ``pie_menu_editor/icons/`` にある拡張子なしのアイコンファイル名。
:return: カスタムアイコンの整数値。
**例**::
L.label(text="My Custom Icon", icon_value=custom_icon("p1"))
.. py:function:: panel(pt, frame=True, header=True, expand=None, area=None, root=False, poll=True, layout=None)
IDによってパネルを描画します。
:param pt: パネルクラスまたはパネルクラス名の文字列。文字列の場合は、 ``bpy.types`` から対応するクラスを検索します。
:type pt: Union[str, Type]
:param bool frame: パネルをフレームで囲むかどうかを制御。``True`` の場合、``layout.box()`` を使用。``False`` の場合、``layout.column()`` を使用。
:param bool header: パネルヘッダーの表示スタイルを制御。
:param expand: パネルの初期展開状態を制御。``True`` : 展開された状態で開始、``False`` : 折りたたまれた状態で開始、``None`` : 前回の状態を保持。
:type expand: Optional[bool]
:param area: パネルを描画する際に想定する :attr:`Area.type ` (例: ``'VIEW_3D'``, ``'PROPERTIES'`` )。
ポップアップダイアログや別エディタ上から ``VIEW3D_PT_*`` のようなエディタ固有パネルを描画したい場合に指定します。
パネル側の ``poll`` / ``draw`` が期待する ``space_data`` を解決できるようになります。
``None`` または ``'CURRENT'`` を指定すると現在のコンテキストを維持します。
:type area: Optional[str]
:param bool root: ``True`` にすると、追加の ``box()`` / ``column()`` で包まず、現在の ``pme.context.layout`` に直接パネルを描画します。
``True`` の場合、``frame`` と ``layout`` の指定は無視されます。レイアウトのネストを減らしたいときに使用します。
:param bool poll: パネルの ``poll`` メソッドを実行するかどうかを制御。``True`` の場合、パネルの表示条件をチェック。
:param layout: カスタムレイアウトを指定。
:type layout: Optional[Any]
:return: True
:rtype: bool
**例**::
panel("MATERIAL_PT_context_material", True, True, True)
# パネルサイズを変更
L.scale_x = 0.8; panel("USERPREF_PT_interface", layout=L.box())
# ポップアップダイアログから 3D ビューのパネルを描画
panel("VIEW3D_PT_tools_meshedit_options", area='VIEW_3D')
# 外側の box / column を付けずに描画
panel("MATERIAL_PT_context_material", root=True)
----
------------------
自動実行スクリプト
------------------
PME では、Blender 起動時に自動的に実行される Python スクリプトを作成できます。
`autorun` は通常の Python module import ではなく、PME の実行 namespace 上で ``exec(...)`` されます。
探索先は次の 2 系統です。
- システム側: bundled ``assets/scripts/autorun``
- ユーザー側: :ref:`user_resources` の ``scripts/autorun``
起動時は **システム側が先、ユーザー側が後** の順に走査されます。
ユーザー側には、以下の形でファイルを置けます。
- 直接 ``.py`` ファイル
- スクリプトを含むフォルダ
- シンボリックリンク
.. note::
`autorun` script では ``pme`` と ``bpy`` は既にグローバル変数として注入されています。
そのため、PME の `autorun` / `execute_script()` 用スクリプトでは、
通常 ``import pme`` や ``import bpy`` は不要です。
ただし、そのファイルを Blender Text Editor から単独実行したり、
通常の Python module として再利用したりする用途まで想定する場合は、
必要に応じて通常の import を追加してください。
.. warning::
- 信頼できるソースのスクリプトのみ配置・実行してください
- 実行前に内容を確認し、必要に応じてバックアップやテスト環境で検証してください
- ファイル操作や設定変更など、環境に影響する処理が含まれる場合があります
---------------------------------
カスタムグローバル関数の追加
---------------------------------
`autorun` の代表的な使い方は、Command タブや Custom タブから再利用する
補助関数を起動時に登録しておくことです。手順は次の 2 つです。
1. :ref:`user_resources` の ``scripts/autorun`` に ``.py`` を置く
2. ``pme.context.add_global()`` を使用して関数を登録
最小例:
.. code-block:: python
def hello_world():
message_box("Hello World")
pme.context.add_global("hello", hello_world)
登録された関数 ``hello()`` は以下で利用可能になります:
- コマンドタブ
- カスタムタブ
- ``execute_script()`` で実行される外部ファイル
もう少し実用的な例:
.. code-block:: python
def active_object_name(default="No Active Object"):
obj = C.active_object
return obj.name if obj else default
def show_active_object_name():
overlay(active_object_name())
return True
pme.context.add_global("active_object_name", active_object_name)
pme.context.add_global("ao_name", active_object_name) # 短い別名として登録
pme.context.add_global("show_active_object_name", show_active_object_name)
登録後は PME 内の各スクリプトから次のように呼べます。
.. code-block:: python
# Command tab
show_active_object_name()
.. code-block:: python
# Custom tab
L.label(text=ao_name(), icon='OBJECT_DATA')
.. seealso::
- :ref:`user_resources`
- :ref:`boot_options` - ``import pme`` が必要な外部スクリプト向け
-----------------
PMEコンポーネント
-----------------
PMEは、よく使用される関数、変数、およびユーザー定義の追加項目へのアクセスを提供するグローバルコンテキストを維持します。
このコンテキストは、2つの主要なインターフェースからアクセス可能です:
.. py:class:: pme.context
.. py:attribute:: globals
:type: dict
PMEのグローバルコンテキスト辞書へのアクセス。以下を含みます:
- 組み込みショートカット(``C``, ``D``, ``O``, ``L`` など)
- 登録されたカスタム関数と値
- ユーザーデータストレージ(``U``)
.. code-block:: python
from pie_menu_editor import pme
# 外部スクリプトからグローバルにアクセス
g = pme.context.globals
props = g.get('props')
user_data = g.get('U')
.. py:method:: add_global(key, value)
グローバルコンテキストにカスタム関数または値を登録します。
:param str key: アイテムにアクセスするための名前
:param value: 登録する関数または値
:rtype: None
.. code-block:: python
# 関数を登録
def my_tool():
bpy.ops.mesh.select_all(action='TOGGLE')
pme.context.add_global("toggle_select", my_tool)
# 定数を登録
pme.context.add_global("MAX_ITEMS", 10)
# コマンドタブ経由でPMEメニューからアクセス:
# toggle_select()
# MAX_ITEMS
.. py:class:: pme.UserData
Blenderセッション中に持続するユーザー定義データのための柔軟なストレージ。
.. py:method:: get(name, default=None)
保存された値を取得します。
:param str name: データキー
:param default: キーが存在しない場合に返す値
:return: 保存された値またはデフォルト値
.. py:method:: update(**kwargs)
複数の値を一度に更新します。
.. code-block:: python
U = pme.context.globals['U'] # UserDataインスタンスを取得
U.update(tool_state="active", count=5)
print(U.tool_state) # "active"