dskjal
広告
広告

Blender の RNA プロパティと ID プロパティとの違い

カテゴリ:blender

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 からプロパティの値を読むこともできる。

Driver からプロパティの値を読む

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/

関連記事

Blender 記事の目次


広告
広告

カテゴリ