コンテンツにスキップ

List Editingについて

USDのリファレンスを扱っていると、

#usda 1.0

def "sphereA" (
    prepend references = @sphere.usda@
)
{
}

こんなかんじで、 「prepend」という記述があることがあります。
prependとは「付加する」という意味で、文字通りPrimに対して「Referenceを付加」
するという記述になります。
しかしながら、このprependはなくても挙動としては正しく動きます。
では、このprependというのは一体何を意味するのか?
というのが、今回のお題である ListEditing になります。

List Editingとは

ListEditingとは、USDのGlossaryによると

USDが配列値のデータエレメントを読み込むことができる機能です
この機能によって、 コンポジションアーク に対して配列タイプのエレメントを
非破壊的且つ疎らに編集することができます
日本語訳版より引用
https://usd.prisms.xyz/intro/USD-Glossary.html#list-editing

とあるとおり、コンポジションアークによって複数のレイヤー(usdファイル)を合成したときに
配列タイプのアトリビュートなどを非破壊に編集するための機能を指します。

たとえばUSDのリレーションの場合。

def "test"
{
    rel aaa = [<RelA>,<RelB>]

    def "RelA"{}
    def "RelB"{}

}

まずは、ベースでこんな感じの構造があったとします。

HoudiniのSOLARIS上で要素を覗いてみると、
aaのValueには、 test/RelA と test/RelB という2つの要素があるのがわかります。

これに対して test/RelC というPrimをサブレイヤーで rel aaa に「追加したい」とします。

USDの合成は非破壊で行われるので、ベースのUSDではなく
サブレイヤーで合成するシーン側で「 aaa に加える」という処理を
編集できてほしいわけです。
そういう場合、

def "test"
{
    prepend rel aaa = [<RelC>]
    def "RelC"{}
}

このように prepend とつけることで

サブレイヤーで合成した結果をみると、
prepend で追加した要素が、 aaa の先頭に追加されているのがわかります。

このように、配列の要素に対して、「追加」したり「削除」したりできるのが
この List Editing とよばれる「prepend add delete」の効果になります。

prepend append deleteの違い

このListEditingの3つと、それがない場合どういう違いがおきるかというと、

def "test"
{
    rel aaa = [<RelC>]
}

まず、何もつかない場合。


この場合、配列のアトリビュートをそのままあった要素を無視して「上書き」します。

def "test"
{
    append rel aaa = [<RelC>]

    def "RelC"{}

}

次に、append
この場合は、

配列の最後に要素が追加されます。

def "test"
{
    delete rel aaa = [<RelB>]

}

最後にdelete

deleteの場合は、要素が配列から削除されます。

元のレイヤーを編集せず、サブレイヤー側にListEditingを追加することで
非破壊で配列の編集をすることができました。

コンポジションアークでの ListEditing の影響

リレーションの場合は、並び順に影響しましたが
では、コンポジションアークの場合はどうなるでしょうか。

def "test"
(
    prepend references = </RefA>
)
{
}

def "RefA"
{
    string name = "RefA"
}

def "RefB"
{
    string name = "RefB"
}

まずはこんなusdaを用意してみます。

この結果は、 RefAをリファレンスしているので「name」は「RefA」になります。

def "test"
(
    prepend references = </RefB>
)
{
}

このレイヤーに対して、 prepend で RefBを追加するレイヤーを作ってみます。

結果、リファレンスの評価の先頭に RefBがきたので、 nameは「RefB」になりました。

def "test"
(
    append references = </RefB>
)
{
}

対して append した場合。
この場合は、リファレンスの評価順序の末端に RefBが追加されているので

結果は RefA になります。

def "test"
(
    delete references = </RefA>
)
{
}

最後に、 deleteの場合。
この場合は当然のように RefAのリファレンスが消えるので

アトリビュートがなくなりました。

まとめ

こんな感じで、
単純にリファレンスで上書きしていくような場合は prependがあってもなくても
挙動は同じ(ない場合は上書き=最優先扱い)になりますが
deleteを使えばリファレンスは消えるし
複数のリファレンスでコンポジションする場合は
このListEditingの順番に影響されてくるので、注意が必要かもしれません。
(基本サブレイヤーでの順番優先なら気にしなくて良いかもしれない)

あと、
余談ですが、カスタムメタデータの数字・文字列配列もList Editing対応らしいのですが
探しても記述方法がわかりませんでした。
どうやったらいいんだろう...?


最終更新日: 2020-06-08 16:25:21