見出し画像

今日から始める!TouchDesigner UI構築

TouchDesignerは高い柔軟性から、多くのクリエイターに愛用されているビジュアル構築ツールです。しかし、アウトプットだけを重視すると、実際の運用で必要となるUIの操作性や視認性が後回しになりがち。
本記事ではメディアプレイヤーの作成を例に、あらゆるプロジェクトへ応用できるUI構築の実践テクニックを解説します。
デザインと機能を両立させるノウハウを、初心者の方にもわかりやすく紹介しているので、ぜひ参考にしてみてください!

本記事はTouchDesigner Advent Calendar 2024の16日目の記事です。

今回のゴール

メディアプレイヤー

  • 選択した映像を再生・停止できる

  • 各クリップのサムネイルを表示する

サンプルプロジェクト

TouchDesigner 2023.11340で作成しています。

概要:忙しい人はここだけでOK!

Container COMPによるレイアウト設計

  • Layout Modeの使い分け(Fixed, Fill など)やMargin/Spacingの設定が重要。

  • ChildrenのAlignをTop to BottomやLeft to Rightに切り替え、パネル内のUI要素を並べる。

  • Lookで薄く色を付けておくと配置が分かりやすい。

  • 幅やマージンは 8の倍数 を使うとレイアウトを管理しやすい。

replicator COMPの活用

  • 同じパーツの大量複製に最適。オペレーター数が動的に増減するケースにも対応しやすい。

  • folder DAT と組み合わせることで、フォルダ内のファイルをまとめてUIに反映可能。

  • me.parent().digitsが便利。

  • replicator callbacks を用いて、複製直後にdisplayをOnにしたり、CHOPへ自動接続するなど処理を仕込める。

Button Groupとラジオボタン化

  • Button Group DATopFind DAT を活用し、ボタン同士の連動を作成(ラジオボタン形式)。

  • fan CHOP を使って選択中ボタンのインデックスを取得し、ファイル選択やプレビュー表示を連動させる。

UIパーツのカスタマイズ

  • TouchDesignerの Palette にある BasicWidgets(masterButton など)を使うと、デフォルトButtonより柔軟なカスタマイズが可能。

  • LookやBorder設定、Face Color、フォントなどを組み合わせて、使いやすく見栄えのいいボタンを作る。

サムネイルの作成

  • Movie File In TOP を使いつつ、メモリ効率のために低解像度読み込み&Playをオフに。

  • インデックス位置をトリムして、黒や単色シーンが目立たないフレームをサムネイルにする。

プレビュー画面と操作部の実装

  • OPviewer COMP とレイアウト設定(Fixed Aspectで16:9など)で画面プレビューを配置。

  • info CHOP で動画の再生状況(index_fraction)を取得し、シークバー風に表示。

  • materialDesignIcons フォントを活用し、再生・停止ボタンなどをアイコンベースで作成。

パネルのレイアウト

TouchDesignerでUIを作成する際、最初に重要なのは「全体像をざっくりとイメージすること」です。細かい部分に取り掛かる前に、まずは全体のレイアウトを設計しましょう。

Container COMP

UIを作成する際には主にContainer COMP を使用します。

最低限知っておきたいContainer COMP の重要パラメータ

  • Layout:パネルの配置やサイズ等を設定する

    • Width / Height:パネルの 幅 / 高さ

    • HorizontalMode / Vertical Mode:パネルの 幅 / 高さ をどのように決めるか

      • Fixed Width / Height:上述のWidth / Height の値に準じる

        • 幅や高さを数値指定したいときに使う

        • デフォルトだとこれ

        • 修正しにくくなるのであまり使いたくない

      • Fill:親要素のサイズに準じる

        • 基本これを使用している

        • 同階層に子要素が複数ある場合は等幅で分割される

        • 分割される割合を別途指定することもできる

          • Horizontal / Vertical Fill Weight

    • Align Order:他の子要素に対する並び順の優先順位

      • 同階層に子要素が複数ある場合に数字が若い順に上位に来る

      • -1等の負の数を設定することもできる(0より優先される)

        • 優先度をさらに高めたい場合に活用するテクニック

      • 同じ優先度のものが複数ある場合はオペレーターの名前順になる

  • Children:自身の子要素をどのように配置するかを設定する

    • Align:子要素をどのように配置するか

      • None:並べずに重ねる

      • Top to Bottom:上から下に並べる

      • Left to Right:左から右に並べる

    • Spacing:子要素同士の隙間

    • Margin:親要素に対するマージン(隙間)

マージンやスペースを適切に設定すると良い感じになります。
関係が近い要素は近づけ、関係が遠い要素は離しましょう。

また、こだわりがなければサイズやマージンは8の倍数に設定することをお勧めします。
これにはいくつかのメリットがあり、

  • 多くのディスプレイは解像度が8の倍数になっているため綺麗に割り切れることが多い

  • マージンを10にするか11にするか(それとも12?13?)だと迷いが生まれるが、8にするか16にするかだと判断が速いから

等があげられます。おすすめです。

Lookで色を付けるとわかりやすい

ボタン等のUIパーツがない状態でパネルを配置していると、なにがどこに配置されているのかが分からなくなります。
そういう時には、LookタブのBackground Color と、BackgroundAlphaを設定すると、並び順やサイズが正しく設定されているかを確認することが出来ます。

Lookの設定例

レイアウトしてみる

レイアウトの設定例
project1の子階層
  • project1:container COMP

    • Children

      • Align:Top to Bottom

      • Margin:8, 8, 8, 8

  • layout:container COMP

    • Layout

      • HorizontalMode:Fill

      • Vertical Mode:Fill

    • Children

      • Align:Left to Right

  • select_buttons:container COMP

    • Layout

      • HorizontalMode:Fill

      • Vertical Mode:Fill

  • preview:container COMP

    • Layout

      • HorizontalMode:Fill

      • Horizontal Fill Weight:2

      • Vertical Mode:Fill

      • Align Order:1

  • footer:text COMP

    • Layout

      • HorizontalMode:Fill

      • Height:24

      • Align Order:1

replicator COMP の実践的な使い方

UIを作成していると、同じパーツがたくさん必要になることがよくあります。
今回の場合は、各クリップを選択するボタンがそれにあたります。

Container COMP を複製しながら作成しても良いですが、変更が生じた際に複製しなおさなければならなかったり、途中で要素数を動的に変更したい場合等に対応できません。

そのようなときに、TouchDesignerでは replicator COMP を使用します。
これを機に使い方を覚えてしまいましょう。

まずは先ほど作成した select_buttons オペレーターに入ってください。

folder DAT

特定のフォルダのファイルをを一括で読み込みたいときにはfolder DATを使用します。

folder DAT の設定
  • Folder

    • Root Folder:動画ファイルがあるパスを設定

Basic Widgets

通常GUIを作成する際はbuttonCOMPや、sliderCOMPを使用するかと思うのですが、実はデフォルトのそれらのCOMPはあまり使い勝手がよくありません。

PaletteのBasicWidgetsに便利にカスタマイズされたUIパーツ集があるので、そちらを使います。

button COMP と masterButton の比較

button COMP
masterButton

masterButtonでは、デフォルトでOnの時とOffの時の色やテキストをそれぞれ設定することが出来ます。また、他にもフォント等の様々なパラメータを下の階層に入らずに設定することが出来ます。

masterButtonをPaletteから配置したら、(後続の処理のために)masterButton1にリネームしておきましょう。
また、パラメータも設定します。

  • Layout

    • HorizontalMode:Fill

    • Height:24

replicator COMP

replicator COMP
  • Replicator

    • Replication Method:By Number

      • 複製する方法:数字

    • Number of Replicants:op('folder1').numRows - 1

      • 複製する数:op('folder1')の行数-1

        • タイトル行を抜くため-1している

    • Master Operator:masterButton1

      • 複製元にするオペレータ:masterButton1

    • Layout:Vertical

      • 複製したオペレータのレイアウト:垂直

      • グリッドより縦に並んでた方が見やすい気がするので垂直にしています。グリッドのままでも問題ありません。

ここまで設定出来たら親COMPのselect_buttonsオペレータを

  • Children

    • Align:Top to Bottom

に設定します。

select_buttonsオペレータ

Master Operator は非表示

select_buttonsオペレータを見てみると、動画ファイルが3つしかないはずなのに、ボタンが4つ表示されています。
これは、Master Operatorも表示されてしまっているためです。
そこで、Master OperatorのPanelのdisplayをOffにし、非表示にしておきましょう。
(Number of Replicants を op('folder1').numRows - 2にしてReplicants Suffix Start を2にする方法もありますが、それだとファイルが0個の時にもボタンが残ってしまうため個人的には非推奨です。)
ですが、このままではreplicatorで複製した際に、複製したオペレーターも非表示になってしまします。

replicator callbacks

そこで使用するのが replicator COMPの下にくっついているreplicator callbacksです。

replicator callbacks

なにやら文字がたくさん書いてあってとっつきにくいですが、使い方を覚えればとても便利です。

replicator callbacksは、replicator COMPを使用してオペレーターを複製した際にその複製したオペレーターに対してどのような処理を行うかを書くことが出来ます。

早速使ってみましょう。

コメントアウトされている(#が先頭についている)

c.par.display = 1

上記の行の先頭の#を削除し、コメントアウトを解除してください。

この状態で再度複製すると、displayがonになった状態で複製されます。

これは、オペレーターが複製された後に、
複製されたオペレーターのdisplayパラメータに1を代入
という処理が行われたためです。

複製した際に自動で接続

もっとダイナミックな処理も書くことが出来ます。

後段にmerge CHOP を配置し、

c.outputConnectors[0].connect(op('merge1'))

と記述してください。

入力後のreplicator callbacks

そして、再度複製してみると、複製したオペレーターが自動的にmerge1オペレーターに接続されたと思います。

複製するとmerge1オペレーターに自動的に接続される

この処理はreplicator COMPを使用する際はほとんどセットで使用するため、是非どこかに保存しておいてください。

Button Group

現状、これらのボタンはそれぞれ独立して動作しています。
しかし、メディアプレイヤーとして使用する場合は、あるボタンが押された場合それまで選択されていたボタンの選択は解除されなければなりません。
このようなボタンをラジオボタンといいます。

ラジオボタンを作成する際にはButton Groupというものを設定する必要があります。

今回はopFind DATと組み合わせて使ってみましょう。

まず、opFind DAT を配置し、FamiliesをPanel COMPのみOnにします。
次にColumnsをPathのみに設定します。

opFind DAT

設定出来たらmasterButton1オペレーターのButton Group DAT にopfind1を設定します。ButtonのTypeをRadio Button に変更し再び複製します。

先ほどまで独立して動作していたボタンがラジオボタンとして機能するようになりました。

fan CHOP

merge CHOP からの入力をインデックスに変換するためにfan CHOP を使用します。Operation を Fan In に設定することで、複数チャンネルの入力をインデックスに変換することが出来ます。

2番目(indexが1)のボタンが押されていることが分かる

null CHOP に接続し、select DAT で選択したファイルを抽出します。

押されたボタンのファイルを選択

me.parent().digits

次に、ボタンの見た目を設定していきます。

まずOnの時とOffの時のカラーを好きに変更してください。
次に、LookでBorderを設定して下さい。

Border A Alphaに、

me.par.Value0

と記述してください。ボタンがOnの時だけ枠線がつきます。

ボタンの設定例
  • Panel

    • Display:Off

      • パネルの非表示

  • Look

    • Border A:好きな色

      • 枠線の色

    • Border A Alpha:me.par.Value0

      • 枠線の透明度

    • Left/ Right/ Bottom/ Top Border:Border A

    • Border Over Childrn:On

      • 枠線を前面に表示

  • Button

    • Off Face Color:0, 0, 0, 0

      • Offの時のボタンの色

      • Background TOP を表示したいため透明にしておく

    • On Face Color:0, 0, 0, 0.8

      • Onの時のボタンの色

      • Background TOP を暗くしたいため、黒を透明度0.8にしておく

    • Off Font Color:1, 1, 1, 1

      • Offの時の文字色

    • On Font Color:好きな色

      • Onの時の文字色

    • Align Horizontal:Left

      • 水平方向の整列:左寄せ

    • Offset:4, 0

      • 文字のオフセット

次に、ボタンのテキストをファイル名にします。
ボタンの中の階層に入りin DAT を配置します。
1階層上のfolder1オペレーターを入力し、
select DATを繋ぎ設定します。

  • Select

    • Include First Row:On

      • 先頭行を含む

      • ラベルを表示しておきたいのでOnにする

    • Select Rows:by Index

      • 選択形式

      • インデックスによる選択

    • End Row Index:-1

      • 終了行のインデックス

      • -1に設定することで、開始行で選択した行のみを抽出することが出来る

    • Start Row Index:me.parent().digits

      • 開始行のインデックス

この記述もreplicator COMP を使用する際に頻出です。
親オペレーターのdigits(末尾の数字)を参照します。
replicator COMP で複製されたオペレーターは末尾の数字が連番で複製されるため、このような処理をすることですべてのファイルを個別に抽出することが出来ます。

selectDATの設定

null DAT を接続し、オペレーター名を movie_info としてください。
様々な箇所に参照するようなオペレーターは名前を付けておくと処理の流れが追いやすくなります。
また、参照先の"op('movie_info')[1, 'name']"のような記述を見るだけで、映像の情報の名前を参照しているんだなと分かります。
("op('null')[0, 1]"では何を参照しているかわからないので、参照元のノードを確認しに行く必要があります。)

1階層上に戻ってボタンのラベルを設定します。

ボタンラベルの設定
  • Button

    • Off Label:op('./movie_info')[1, 'name']

      • ボタンがOffの時のラベル

      • op('./movie_info')のように書くと1階層下のオペレータを参照できる

      • table DAT class のオペレーターは[1, 'name']のように、数字で指定するとインデックス、文字を指定するとラベルで参照してくれる

    • On Label:me.par.Buttonofflabel

      • On の時と Off の時でラベルを変える必要がないので自身のOff Labelを参照しておく

サムネイルの作成

次にサムネイルを作成していきます。

映像を選ぶ際に便利なサムネイルですが、いくつか注意すべき点があります。
TouchdesignerのTOPは配置するだけでGPUのメモリを消費するので、無計画に配置しすぎるとメモリを圧迫し、著しくパフォーマンスの低下を引き起こす場合があります。
そこで、出来るだけ低い解像度で読み込む必要があります。
また映像が再生されてしまうのも毎フレームデコードが行われ、パフォーマンスの低下を招くためPlayをオフにしておきます。

以上の点に注意してこのようなサムネイルを作成してみました。

サムネイルの実装例
  • Movie File In TOP:moviefilein1

    • Play

      • File:op('movie_info')[1, 'path']

      • Reload:On

      • Play:Off

    • Common

      • Output Resolution:Fit Resolution

      • Resolution:me.parent().width, 100

  • ramp TOP:ramp1

    • Ramp

      • 右半分が不透明になるように設定

      • 色は白

    • Output

      • Operation:Atop

      • Swap Order:On

  • constant TOP:constant1

    • Constant

      • Alpha:0

    • Common

      • Resolution:me.parent().width, me.parent().height

  • over TOP:over1

    • Transform

      • Pre-Fit Overlay:Native Resolution

      • Justify Horizontal:Right

  • null TOP:bg

select_buttons

かなりいい感じになってきました!

しかし、よく見てみると2番目や7番目のサムネイルが黒くなってしまっています。
これは動画の開始フレームが黒のためです。
汎用素材ではあまりありませんが、MVやポン出しの素材では黒(等の単色)からフェードインで映像が始まることも少なくありません。
そこで、動画の再生してから20%程度の部分をサムネイルとして読み込みましょう。

Movie File In TOPで、TrimタブのTrimをOnにして、Trim Startを0.2にして複製しなおします。
左が開始フレームで、右が開始後20%部分のサムネイルです。右の方が視認性がかなり向上しているのではないでしょうか?

サムネイルの比較

また、大量のreplicatorを複製する際に、フリーズしてしまうことがあるかもしれませんが、replicator COMPの、Incremental UpdateをOnにし、数を1にすると、1フレームに1個づつ複製され、負荷が分散されるのでフリーズを軽減することが出来ます。

プレビュー画面と操作部

映像選択部分が完成したので、次はプレビュー画面と再生ボタン等の操作部を作っていきましょう。

現在の状態

パネル右側のオレンジ色の部分を作成していきます。

preview

select_buttonsパネルで選択した動画のパスを、in/out DAt を使用してpreviewパネルに入れます。
Movie File In TOP にパスを参照させnull TOP を繋いでおきます。

movie file in TOP

次にパネルに表示するためにOPviewer COMP を配置し、null TOPを参照します。
ファイル名を表示するためにtext COMPも配置して、ファイル名を参照させておきましょう。
親コンテナのChildrenのAlignをTop to Bottom に設定し、SpacingとMarginをそれぞれ16に設定しましょう。
また、先ほど配置した2つのCOMPのレイアウトを適切に設定しましょう。

この時の、OPviewer COMP のレイアウトですが

  • Layout

    • Horizontal Mode:Fill

    • Fixed Aspect:Use Horizontal

    • Aspect Ratio:16/9

に設定すると、横幅が親コンテナいっぱいになり、アスペクト比が16:9のビューワーを作成することが出来ます。

OPviewer COMP のレイアウト

info CHOPから情報を反映

動画の再生位置を表示するためのインジケーターを作成しましょう。

info CHOP を使えば、参照したオペレーターの様々な情報を取得することが出来ます。

info CHOP

動画の再生位置は index_fraction にあたるので、Scopeでindex_fractionを指定しましょう。
後段にnull CHOP を接続しておきます。

次に表示部分を作成します。
OPviewer COMP を配置し、レイアウトを設定します。
次に表示用のrectangle TOP を配置しnullTOPに接続しておきます。

インジケーター表示部分

rectangle TOP のパラメーターを以下のように設定します。

  • Rectangle

    • Size:op('null3')['index_fraction'], 1, Fraction

      • 幅に先ほど取得したindex_fractionを参照させる

    • Justify Horizontal:Left

    • fill color:好きな色

  • Common

    • Resolution

      • op('opviewer2').width

      • op('opviewer2').height

全体

materialDesignIcons

次に再生と頭出しのボタンを作成します。
先ほど同様にmasterButton をPaletteから2つ配置しましょう。
上位のcontainer COMPを作成し接続しておきます。
それぞれのレイアウトを適切に設定します。

レイアウトの設定例

上のボタンが頭出し、下のボタンを再生停止のボタンとしましょう。

中間のレイアウト全体図

この時点でこのようなレイアウトになっているかと思います。
頭出しと、再生停止ボタンを「CUE UP」「PLAY/STOP」のように書いても良いですが、今回は materialDesignIcons を使って、アイコンで表現したいと思います。

Palette > Tools > materialDesignIcons を選択し、ネットワークエディタの適当な場所に配置してください。

materialDesignIconsパネル

このようなアイコンがたくさん並んだパネルが表示されると思います。
これらは、materialDesignIcons というもので、アイコンをフォントとして提供しているものになります。TouchDesignerには、デフォルトでmaterialDesignIcons のフォントが入っているので、text TOP や、text COMP等で簡単に利用することが出来ます。

試しに、masterButton のフォントをmaterialDesignIconsに変更し、テキストを chr(0xF0663) に変更してみましょう。
これは、先ほどのmaterialDesignIconsパネルをアクティブにし、使いたいアイコンをクリックするとクリップボードにそのアイコンの文字コードがコピーされます。

アイコンの設定例

このように、簡単にアイコンを設定することが出来ます。

あとは、再生停止ボタンも同様に設定し、出力をMovie File In TOP に割り当てます。
最後にパフォーマンス表示用のフッターを設定したり、プレビュー用で設定していた各container COMP のLookを調整して完成です!

完成!

まとめ

今回はTouchDesignerのUI構築について少し実践的な内容を紹介しました。
TouchDesignerのUIに関する記事は基礎的なものが多い印象があるので、こうした実用的なテクニックを整理できてよかったと思います。
今回紹介したテクニックは、どんなプロジェクトにも応用可能です。
ぜひ自身の作品に取り入れて、より快適でかっこいいUIを追求してみてください!

最後まで読んでいただきありがとうございます!
今回の内容には入りきらなかったのですが、シークバーまで実装したものを置いておきます。

いいなと思ったら応援しよう!