Preferences の設定
Interface > Display & gt; Developer Extras と Python Tooltips にチェックを入れる

これにより、できることを紹介します。(正しくないと思うけど、自分が気づいたことだけ)
Contoroller にホバーしたときに、それに関する変数情報が取得できる。

インデックスが見れるようになる。
選択状態に応じて、インデックスが変わる。

printの内容を見る
Window > Toggle System Console で System Console を起動する。

print method を呼び出すと、System Console に出力される。

active collection の取得方法
import bpy active_collection = bpy.context.view_layer.active_layer_collection.collection print(f"Active Collection:\n{ActiveCollection} {type(active_collection)}")
3D Cursor の location の取得方法
import bpy print(bpy.context.scene.cursor.location)
View の回転姿勢の取得方法
import bpy print(bpy.context.space_data.region_3d.view_rotation) # Quaternion
オペレータプロパティが初回表示されるタイミングとコンボボックスの中身が変わったタイミングを取得する
調べたがやり方が分からなかった。
ので、クラスにメンバ作ってフラグのようにしてみた。良いかどうかわからないが、正しく動作するようだ。
class ADD_MESH_OT_tile_polygons(bpy.types.Operator): .... last_align = "" .... def execute(self, context): if self.last_align == "": # on initialize ... if self.align != self.last_align: # on initialize or on change align ... ... self.last_align = self.align
3D Cursor の回転姿勢は matrix から取得したほうが良い
3D Cursor の Rotation Mode が XYZ で Rotation Euler が変更されている時、Rotation Quaternion が更新されているとは限らない。
以下の実験を行った。
・初期状態
・Rotation Mode は XYZ Euler のまま Rotation Euler X を 37 に変更
・Rotation Quaternion をログ出力 print(context.scene.cursor.rotation_quaternion)
・Rotation Mode を XYZ Euler から Quaternion に変更
・Rotation Mode を Quaternion から XYZ Euler に変更(この時角度は一切変更していない)
・Rotation Quaternion をログ出力 print(context.scene.cursor.rotation_quaternion)

以上より、パネルで 3D Cursor の Rotation を変更する場合、Rotation mode が変更されたときに、その Rotation が更新されることが分かる。
現在の 3D Cursor の回転姿勢は Rotation Quaternion から取得できるとは限らないことが分かった。
Rotation Axis Angle, Rotation Euler も同様である。
ではどうすればよいか。
現在の 3D Cursor の回転姿勢は matrix から取得すればよい。
以下は、現在の 3D Cursor の matrix を 3x3 の行列に変換(回転成分だけを抽出)し、オイラー角に変換するプログラムです。
euler = context.scene.cursor.matrix.to_3x3().to_euler('XYZ')
ちなみに公式のマニュアルを見てみると、

こんな感じで書かれており、常に最新の行列のようなので、現在の 3D Cursor の回転姿勢は matrix を参照するのが良いと思われる。
3D Cursor の回転姿勢のまとめ
# Quaternion context.scene.cursor.rotation_quaternion # Axis Angle context.scene.cursor.rotation_axis_angle # Euler context.scene.cursor.rotation_euler # Rotation Mode # "QUATERNION" or "AXIS_ANGLE" or "XYZ" or "XZY" or "YXZ" or "YZX" or "ZXY" or "ZYX" context.scene.cursor.rotation_mode # 4x4 Matrix -> 3x3 Matrix context.scene.cursor.matrix.to_3x3()
状態によって、入力項目を Disabled にする
draw関数で以下のようにやればよい。
def draw(self, context): layout = self.layout layout.use_property_split = True layout.use_property_decorate = False # No animation. column = layout.column(align=True) if self.gap < 0.5: column.enabled = False column.prop(self, "start_y") column.prop(self, "end_y")
このようにすると、イベント受け取って、Disabled を入れ替えているような動きができる。
IntVectorProperty は size 必須
size プロパティは必須のようだ。指定しないとそこでエラーが出て、それ以下のコードは無視される。
他の VectorProperty も同様。
range: IntVectorProperty( name = "", description = "", default = (-1, 2), min = -20, max = 20, size=2 ) # type: ignore
Mesh追加のAddonを書くなら、AddObjectHelper、object_data_add は必須
Mesh 追加の Addon にとってほぼ共通の処理があります。
下記画像の赤で囲った箇所です。

これを既存の Cube などと同じ振る舞いをするように自分で実装すると意外と大変であることに気づきます。
本記事の前半で、3D Cursor や View の回転姿勢などを取得いますが、そんな処理はすべて不要になります。
これに気づいたとき、Blender の API って超親切って思いましたね。
それが AddObjectHelper、object_data_add を使うと簡単に実装できます。
AddObjectHelper は自身が作成するオペレータクラスの継承元のクラスで、これを継承するだけで、赤色で囲ったプロパティが定義、表示されます。
今回のサンプルプログラムでは省略しますが、通常は draw 関数を定義します。
この辺は 有名 Addon の Extra Mesh Objects の Menger Sponge のソースが参考になります。
ソースの場所は、C:\Users\USER\AppData\Roaming\Blender Foundation\Blender\4.2\extensions\blender_org\extra_mesh_objects\add_menger_sponge.py です。
点と面から mesh を作成し、object_data_addに渡すだけで、オブジェクトモードの時は object 新規作成、編集モードの時は object に mesh が追加されます。
三角形を1つ作成する AddOn のサンプルプログラムを書いておきます。
import bpy from bpy_extras.object_utils import ( AddObjectHelper, object_data_add, ) bl_info = { "name": "Test", "author": "your name", "version": (1, 0, 0), "blender": (4, 2, 0), "location": "3D Viewport > Add > Mesh", "description": "Test add-on", "warning": "", "support": "COMMUNITY", "doc_url": "", "tracker_url": "", "category": "Add Mesh" } class MESH_OT_test(bpy.types.Operator, AddObjectHelper): bl_idname = "mesh.test" bl_label = "Test" bl_description = "Test addon" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): vertices = [(0, 0, 0), (1, 0, 0), (1, 1, 0)] faces = [(0, 1, 2)] mesh = bpy.data.meshes.new(name='Test') mesh.from_pydata(vertices, [], faces) object_data_add(context, mesh, operator=self) return {'FINISHED'} def menu_register_func(cls, context): cls.layout.separator() cls.layout.operator(MESH_OT_test.bl_idname, icon='PLUGIN') classes = [ MESH_OT_test, ] def register(): for c in classes: bpy.utils.register_class(c) bpy.types.VIEW3D_MT_mesh_add.append(menu_register_func) def unregister(): bpy.types.VIEW3D_MT_mesh_add.remove(menu_register_func) for c in reversed(classes): bpy.utils.unregister_class(c)