この記事はTouchDesigner Advent Calendar 2022の12日目の記事です。
株式会社レイという映像機材を扱う会社でエンジニアをしています。
TouchDesignerで映像オペレーションをする上でのUIを構築することになりました。
これまでちゃんとUIを組んだことが無かったので、今回は学習の共有です。
UI構築の経緯
現在弊社ではスイッチャーやメディアサーバの他にV出しにはRolandのPR-800HD、VJ的にレイヤーで出す時はRosolumeのArenaなどを使ったりします。
PRはシンプルで使いやすいのですが、4KのV出しができません。Arenaはアウトプットの切り出しが簡単でLED出しの時に便利なのですが、TDと併用になると最初からTDで完結できるのでは?と思いました。
また今後TDを使った汎用的な演出や仕組みを開発した時に、それを組み込むベースとなり自分以外のオペレータ(非TDエンジニア)も違和感無く使えるシステムが必要と考え、今回のUI構築となりました。
完成のイメージ
UIを作る上でのポイント
個人的には以下の3つがポイントと考えました。
- Panels系COMPの挙動・機能理解
- CloneとExternalを利用した静的複製
- ReplicatorCOMPによる動的複製
1. Panels系COMPの挙動・機能理解
1-1. 親子関係を作る上での使い分け
UIを作る時はCOMPのPanels系を階層化するかオペレータの上下のワイヤーを繋げて親子関係を作ります。
シンプルなUIな場合は、Base COMPでオペレータをまとめる時のように階層構造で問題無いです。しかし複雑なUIを作ろうとすると、階層がどんどん深くなってメンテナンス性が最悪になります。
極力ワイヤーで親子にしつつ、細かすぎるパーツや後述の複製が発生する場合は階層化します。
(現在構築途中のNetwork Editor画面)
1-2. 各UIパーツをキレイにレイアウトする
基本的には子のLayoutのModeをFill
にして、親のChildrenのAlign
を指定すればキレイになります。
子の位置を整頓したい場合
⇒ Justify Horizontal/Vertical
を指定
パーツとパーツの間に隙間を空けたい場合
⇒ Spacing
とMargin
パーツを正確な比率(7:3など)に整頓したい場合
⇒ 子のModeをAnchors
に設定、対応させたいCOMP同士をReferenceで紐づける
1-3. パーツごとに特定の機能を付与する
アプリケーション「らしい」振る舞いをするには、これらの実装が必要です。
-
ドラッグ&ドロップ
Drag/DropのDrag/Drop Script
を設定することで、動画のセットなどができます。
詳しくはJoe君がアドベントカレンダー20日目の記事で解説してくれます(丸投げ) -
右クリックでメニュー表示
Info CHOP
やPanel CHOP
を使って操作を検出することで、メニュー表示などができます。 -
MIDIやOSCと紐づける際のTIPS
MIDIコンとTD上の数値を紐付けた際に、数値だけ何らかの理由で変えた場合コントローラと数値の間に差が生まれてしまい、操作した際にガクッとなってしまいます。これを避けるため、Bind CHOP
のChannel Pickup
をOnにすることで、コントローラが同じ値になるまで数値が変化しないようにすることができます。
1-4. 結局「Widget COMP」って何?
半自動的かつ一括でCOMPのParameterをUI化する時に使います。
PalleteからbasicWidgets
とautoUI
、さらにUI化したいCustom Componentが設定されたCOMPとUIを表示するためにContainer COMPを用意します。autoUI
のUIとCustom COMPのところに上記の2つを紐付けてGenerate UIをPulseすると、UIが生成されます。
便利と言えば便利ですが、現状Widget COMP単体ではContainer COMPと挙動が基本変わらないことと、自分でパーツごとの見た目や機能は制御したいので使いません。
2. CloneとExternalを利用した複製
2-1. Clone機能の基本とOperatorのImmutable化
UIを作る際に、共通して同じ見た目・機能を持ったパーツを複数作ることになるのが通常だと思います。
しかしパーツごとに独立したCOMPにしてしまうと、後から変更を加える時個別に1つずつ変えなければいけなくなってしまいます。この問題を解決するのがClone
という機能です。
Clone先のCOMPのCommonタブにあるEnable Cloning
をOnにし、Clone元となるCOMPをClone Master
に設定することで、Clone元の変更が一括でClone先に反映されます。またClone元のCOMP内にあるオペレータのClone Immune
フラグを立てることで、そのオペレータのParameterをユニークにすることができます。
2-2. 複製したパーツに異なる見た目・機能を設定する
上記のようにImmuneにすることでCOMP内のParameterをユニークにしても良いのですが、実際の運用上は別の方法を採用しています。CloneにはClone元のCOMP自体のParametersは変更されないという仕様があります。この仕様を生かして、ユニークにしたいParameterをCustom Componentに設定してあげる方が参照先が一元化されて、後から調整しやすいです。
個別化してしまうと結局まとめて変更したい時に面倒ではと思うかもしれませんが、Custom Component自体は共通化されているので、変更したいCOMPを複数選択して1か所変更すれば一括で変えられます。これも先述の親子関係を極力階層で作らない/Custom Componentでユニーク化するという2点のメリットです。
2-3. Operatorのコンポーネント化とExternalによる共通化
作成したUIやパーツを別プロジェクトで使いたい場合があると思います。
その時は使用したいオペレータを右クリックし、Save Component .tox
でtoxファイルとして保存します。このtoxを参照させたいオペレータのCommonタブにあるExternal .tox
に設定することで、Cloneと同じように元のtoxと共通化されます。
ただtox化した時、toxの変更を参照元に反映させようと思うと一々Saveし直すのが面倒です。その問題を解決するのがSatoru Higaさんの「ExternalToxSaver」です。Gumroadにて3ドルで購入できます。
3. Replicator COMPによる動的複製
3-1. Replicator COMP機能の基本
Replicator COMPのOperator Prefix
で複製したいオペレータを指定、Replication Method
をBy Number
にしてNumber of Replicants
で数値を設定することで、その数値分だけ指定したオペレータが複製されます。
またReplicator COMPのcallbacksの中でc.outputConnectors[{OUT}].connect({IN})
と記述することで複製時に元のオペレータのOUTを特定のオペレータ(例えばSwitch TOPなど)にINにすることが出来ます。
def onReplicate(comp, allOps, newOps, template, master):
sw = op('switch1')
for c in newOps:
c.outputConnectors[1].connect(sw)
#c.display = True
#c.render = True
#c.par.display = 1
#c.par.clone = comp.par.master
pass
return
CHOPの場合はSelect CHOP
のCHOPs
に{Operator Prefix}*/out{num}
という形で記述することで、callbacksに書かなくともOUTの数値をまとめることが出来ます。
3-2. 特定のOperatorのParameterUIを動的に複製する
Parameter COMPを使えば簡単にオペレータのParameterをUI化することができます。この時、CommonタブのParameterは不要な場合がほとんどだと思います。TIPSとしてはPage Scope
に^Common
と記述する事で、CommonタブだけをUI化から外すことができます。
ただこの方法だと、UIの見た目がParameter COMPに依存してしまいますし、実際にUI化したいParameterは決まっていることが想定されます(すべての読み込んだ動画にLevel TOPのOpacityのparameterを付けたいなど)。
なので、Cloneを使った複製の時と同様、UI化したいParameterをCustom Componentとして設定し、その値をParameter DAT
などで取得、Replicator COMPのTemplate DAT table
の設定とcallbacksの組み合わせによって、UIを生成します。こうすることでCloneを使うにしろReplicatorを使うにしろ、ワークフローとフォーマットが共通化できます。
※この辺りは今度追記します。。
3-3. CloneとReplicatorCOMPの使い分け
結論だけ言うと、複製するUIを静的(決まった数・形式)に変更する場合はClone、動的(柔軟に増減する)な場合はReplicatorという使い分けになると思います。
終わりに
UIに関する記事は数多くあり、焼き増しの内容も多かったかと思います。
本来はアルファ版まで出来たものをこの記事のタイミングで公開する予定だったのですが、間に合わず初歩的な内容に終始してしまいました。
また開発途中のシステムとUIが出来た際には、そこから得た知見を共有したいと思います。
参考サイト