TfNotice(通知システム)について
TfNotice とは、「Stage 上のオブジェクトが変更された」といった
指定のイベントに対して通知を行うためのシステムです。
https://openusd.org/dev/api/page_tf__notification.html
まずは最もシンプルなものを試してみます。
from pxr import Tf, Usd
def objectChanged(notice,sender):
print("変更されました!")
stage = Usd.Stage.CreateInMemory()
notice = Tf.Notice.Register(Usd.Notice.ObjectsChanged, objectChanged, stage)
prim = stage.DefinePrim('/sample')
Tf.Notice.Register を使用して、変更があった時に呼び出される関数を登録します。
https://openusd.org/dev/api/class_usd_notice.html
デフォルトで用意されているイベントは、
- LayerMutingChanged
- ObjectsChanged
- StageContentsChanged
- StageEditTargetChanged
- StageNotice
の 5 つです。
サンプルで使用した「ObjectsChanged」は、その名の通り UsdObjects に変化があった時に
引数で指定した関数を実行します。
PySide 使い的には、Signal-Slot に近いですね。
通知情報を取得する
指定のイベントが発生すると、Register で指定した関数が呼び出されます。
呼び出された関数は、Notice と Sender 引数を持ち、実行した時の状況を受け取ることができます。
https://openusd.org/dev/api/class_usd_notice_1_1_objects_changed.html
Notice は、ObjectsChanged オブジェクトが渡され
実行時の状況を取得したり、対象の SdfPath が実行されたのかチェックをしたりする機能が
提供されます。
from pxr import Tf, Usd,Sdf
def objectChanged(notice,sender):
print("InfoOnly")
print(notice.GetChangedInfoOnlyPaths())
print("ReSynced")
print(notice.GetResyncedPaths())
stage = Usd.Stage.CreateInMemory()
notice = Tf.Notice.Register(Usd.Notice.ObjectsChanged, objectChanged, stage)
print(">>CreatePrim")
prim = stage.DefinePrim('/sample')
print(">>CreateAttr")
attr = prim.CreateAttribute('hoge',Sdf.ValueTypeNames.Bool)
print(">>SetAttr")
attr.Set(True)
実行結果がこちら。
ObjectsChanged で変更を受けるばあい、大きく分けると 2 種類 InfoOnly と ReSynced があります。
InfoOnly とは、Prim の構造に変更がなく、アトリビュートの値が変更されたものの SdfPath を取得できます。
対して ReSynced は、Prim を作成したりアトリビュートを追加したりといった
構造の変更があったものの Path が取得できます。
なので、DefinePrim なら 、Prim の SdfPath が表示されるし、Attribute なら PrimPath.AttrName といったアトリビュート
が取得できるし、最後の SetAttr はセットした Path が取得されます。
実行された Stage を取得する
どこで実行されたのかを取得したい場合は、Sender で受け取ります。
from pxr import Tf, Usd,Sdf
def objectChanged(notice,sender):
print(sender)
stage = Usd.Stage.CreateInMemory()
notice = Tf.Notice.Register(Usd.Notice.ObjectsChanged, objectChanged, stage)
print(">>CreatePrim")
prim = stage.DefinePrim('/sample')
Sender は、Register の 3 つ目の引数で指定したオブジェクト(Sender)を取得できます。
そのため、今回だと実行した Stage が取得できます。
通知を終了する
最後に、このままだと永久に通知されてしまうので、通知をやめるようにします。
def objectChanged(notice,sender):
print(sender)
stage = Usd.Stage.CreateInMemory()
notice = Tf.Notice.Register(Usd.Notice.ObjectsChanged, objectChanged, stage)
print(">>CreatePrim")
prim = stage.DefinePrim('/sample')
notice.Revoke()
Register 関数を実行すると、登録した通知のハンドルオブジェクトが帰ってきます。
(おそらくこれをリスナーと呼ぶっぽい?)
終了したいところで Revoke を呼び出すと、通知を終了させることができます。
まとめ
Notice を使用すると、USD のシーングラフの変更に対して、何かしらの関数を実行できることがわかりました。
次回はもう少し詳しい使い方を追ってみようと思います。