機械学習基礎理論独習

誤りがあればご指摘いただけると幸いです。数式が整うまで少し時間かかります。リンクフリーです。

勉強ログです。リンクフリーです
目次へ戻る

Blender Addon 開発メモ

はじめに

これは個人用 Blender Addon 開発用のメモ帳です。
基本的には「Blender Python 完全ガイド」という本を参照しています。

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 の回転姿勢などを取得いますが、そんな処理はすべて不要になります。
これに気づいたとき、BlenderAPI って超親切って思いましたね。
それが 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)
目次へ戻る