Blender の RNA プロパティと ID プロパティとの違い
ID プロパティは生の変数だ。ID プロパティは integer と float と文字列しかサポートしない。
RNA プロパティは ID プロパティのラッパーだ。RNA プロパティを定義すると ID プロパティにさまざまな機能を追加できる。integer をブーリアン型と解釈させたり、数値の最大値・最小値・ステップを設定できたりする。
ID プロパティは .blend ファイルに保存されるが、RNA プロパティ定義は .blend ファイルに保存されない(RNA プロパティのデータは保存される)ので、アドオン(エクステンション)はロード時に毎回 RNA プロパティを定義する必要がある。
例
以下のスクリプトはアクティブオブジェクトに test_id という ID プロパティを作成し -1 を設定する。その後で RNA プロパティで最小値を設定している。
データの設定は data.objects に行っているのに対し、RNA プロパティの定義は types.Object に対して行っていることに注意。
bpy.data.objects['Cube']['test_id'] = -1 bpy.types.Object.test_id = bpy.props.IntProperty(name='test_id', min=0) # この時点では test_id は -1 bpy.data.objects['Cube'].test_id = -1 # この時点では test_id は0 bpy.data.objects['Cube']['test_id'] = -1 # この時点では test_id は -1。インデックスアクセスでは RNA プロパティの恩恵を受けられない
RNA プロパティ
RNA プロパティはアドオン(エクステンション)が使う管理用変数の確保が主な使用方法だ。
class TEST_EXTENSION_Props(bpy.types.PropertyGroup): is_panel_open : bpy.props.BoolProperty(name='is_panel_open', default=True) classes = (TEST_EXTENSION_Props) def register(): for cls in classes: bpy.utils.register_class(cls) bpy.types.Scene.test_extension_props = bpy.props.PointerProperty(type=TEST_EXTENSION_Props) def unregister(): if getattr(bpy.types.Scene, 'test_extension_props', False): del bpy.types.Scene.test_extension_props for cls in reversed(classes): bpy.utils.unregister_class(cls)
RNA プロパティの特徴
RNA は既存のデータ構造を拡張するため、使用前に宣言が必要だ。
bpy.types.Object.myRnaInt = bpy.props.IntProperty( name = "RNA int", min = -100, max = 100, default = 33)
アドオンで RNA プロパティを使う場合は、アンロード時に削除する必要がある。
def unregister(): del bpy.types.Object.myRnaInt
一度定義してしまえばドットを使ってそれにアクセスできる。
cube.myRnaInt = -99
Driver からプロパティの値を読むこともできる。
ポーズボーンにもプロパティを作成できる。これはIK/FK スイッチのようなプロパティを作るのに便利だ。
import bpy bpy.types.PoseBone.ボーン名 = bpy.props.FloatProperty(name='test')
作成したプロパティはリスト表記でアクセスできる。
import bpy bpy.types.PoseBone.Bone = bpy.props.FloatProperty(name='test') bpy.data.objects['Armature'].pose.bones['Bone']['test'] = 0
スクリプトから RNA を作成する際の注意点
スクリプトから作成した RNA(ID)プロパティは値が代入されない限り表示されない。以下のスクリプトを実行しても Custom Properties には何も表示されない。
import bpy bpy.types.Object.my_rna_bool = bpy.props.BoolProperty(name='RNA bool')
適当な値を代入してやれば表示される。
import bpy bpy.types.Object.my_rna_bool = bpy.props.BoolProperty(name='RNA bool') bpy.context.active_object.my_rna_bool = False bpy.context.scene.update()
最後の update() は変更を反映させるために呼び出している。これがないと一度選択を解除してからもう一度選択してやらないとプロパティが表示されない。
RNA プロパティを保存する際の注意点
RNA プロパティの宣言は保存されない。スクリプトから宣言した RNA プロパティを保存して再度開くと、それらはすべて ID プロパティになる。再宣言すれば、それらを RNA プロパティとして扱える。
ID プロパティ
ID プロパティは単体のデータブロックに追加されるため、他の同じ型のデータに影響はない。事前に宣言する必要はなく、値が代入されたときに自動的に作成される。
cube.data["MyIdInt"] = 111
ID プロパティは integer か float か string になる。それ以外の型が代入されると自動的にそれらの型のどれかに変換される。以下のコードは integer の ID プロパティを作成し、1 が代入される。
cube.data["MyIdBool"] = True
スクリプト例
get() を使ってデータを取得すると、プロパティが存在しない場合は None を返す。
cube.data.get('MyIdInt') # 存在しなかった場合のデフォルト値を設定できる cube.data.get('MyIdInt', default=0)
hasattr や getattr でプロパティが存在するか確認できる。
# hasattr はプロパティが存在しない場合は例外を投げる hasattr(cube.data, 'MyIdInt') # getattr は例外が発生しないが、存在しない場合のデフォルト値を指定する getattr(cube.data, 'MyIdInt', 0)
リンク時の動作
リンクしたオブジェクトの RNA プロパティも ID プロパティも変更できない。プロキシを作成すれば RNA プロパティは変更できるが、ID プロパティは変更できない。
外部リンク
RNA properties versus ID properties
How to check if an object has a custom property with python?
https://developer.blender.org/docs/features/core/rna/