TouchDesignerで作ったVJ用UIを振り返る

この記事は[TouchDesigner Advent Calendar 2022](https://qiita.com/advent-calendar/2022/touchdesigner)の16日目の記事なのに、既に12/17です。すみません

# はじめに
TouchDesignerでたまにVJするので去年あたりから自分用のUIを作り直しています。
[以前TouchDesigner Advent Calendarで書いたもの](https://qiita.com/satzz/items/1d45e773f1e262f982ed)を参考にしたという人がいて「へ〜誰の役に立つかわからないもんだな」と思ったので、今年は現場を乗り切るのにやってよかったTIPSや現状のオレオレ構成をざっくり書いてみます。

何年経ってもよくわからないまま使っており、最適解というより自分はこうやってますってポイントだけ書くので、「あーこのあたり考えておく必要があるのね」とか「あれで済みそうことをやりたいんだな」とかなんとなく察してください。

3年ぶりのQiita投稿...

# 自己紹介

- [satzz](https://twitter.com/satzz) / [Hackmarkt](https://linktr.ee/hackmarkt)
- フリーランスWebエンジニア（frontend/backend）
- [Tunnel Tokyo](https://tunnel-tokyo.jp/)（コワーキングスペース）スタッフ（映像・音響・機材）
- [Ableton Meetup Tokyo](https://ableton-meetup.tokyo/)（ユーザーグループ）スタッフ
- テクノDJ、VJ
- DJイベント主催、外国人アーティストの来日サポート
- VJチームのオーガナイズ 
- サウンドデザインお手伝いなど
etc

# 構成

## 機能を使う状況ごとに整理する
PaletteのDerivative > UI > Basic Widgetsにあるsection Widgetを使って、使わない機能をたたんでおく。ちなみにPaletteずっと無視してたけど、そこにあるものを一度眺めたり自分のコンポーネントをしまっておくことでUIの作り直しの助けになった。

Container COMP内で、section Widgetから0/1の状態を取得し、CHOP Executeに渡してparentの高さを変えることでsectionを折りたたむ。

![Screen Shot 2022-12-16 at 18.27.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/79200789-6dee-0491-5d4b-f1c65ebbe098.png)

```python
def onOffToOn(channel, sampleIndex, val, prev):
	op('controls').par.display = 1
	me.parent().par.h = op('height').text
	return

def onOnToOff(channel, sampleIndex, val, prev):
	op('controls').par.display = 0
	op('height').text = me.parent().par.h
	me.parent().par.h = 30
	return
```
Container COMPの挙動が確認できたらコピーして並べる。
![Screen Shot 2022-12-16 at 18.26.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/7102d36f-c042-3c48-fa2d-b5687b779550.png)
まぁ正直、タブ状UIが作れたらそれでもよいと思う。
ここからは各sectionに入れている機能を挙げる。section名は適当。
![Screen Shot 2022-12-16 at 18.23.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/247fe630-9f50-76fc-7d4a-343ea0ae3bde.png)

## Window
performウィンドウを開くボタン、MacのScreen Saver/Screen Lockを切り忘れないためのblinkなど地味な機能。頻繁には使わない。
![Screen Shot 2022-12-16 at 18.36.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/b409f18d-7551-f30f-742f-f2d93f00778e.png)

## Pref
Preferenceというあまり意味のない名前はさておき、現場でのテスト中に、壁や装飾を見ながら最終的な絵の出る位置とサイズを調整する機能を現状は置いている。
Basic Widgets > slider2D Widgetでtransform X/Y, scale X/Yを調整する。
これも最初に調整したらあとでいじることは少ない。
![Screen Shot 2022-12-16 at 18.40.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/2b659a7f-a143-c699-de2e-09dc346fe396.png)

## Audio

マイクから音を拾ってaudio reactiveな絵を作りたいときに、音声のinput gainを調整する機能。Basic Widgets > Core > masterKnobが割と省スペースなのでちょうどよいサイズに調整して使っている。イベント中を通じて当然出音は変わるので、割と頻繁にいじる。

![Screen Shot 2022-12-16 at 18.45.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/00368f28-59b3-b090-fdd5-7d69de8107f2.png)

## Artist

イベント名や出演者名などのテキストをエフェクトをかけてさくっと出す機能。文字数によってサイズ調整もできるようにしている。

![Screen Shot 2022-12-16 at 18.50.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/f239af34-c965-6568-3725-0207c9352695.png)

## Scenes

自分で作ったコンポーネントの切り替えを行う。ここは自分のスタイルを出すところなので簡単に増やせるようにした。PaletteのTools にある[sceneChanger](https://derivative.ca/UserGuide/Palette:sceneChanger
)をうまく使うとリソースを節約できるのだが、sceneの削除したときの挙動がどうも不安定な気がする。要検証。

![Screen Shot 2022-12-16 at 18.51.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/f086df2a-93dc-99e7-aee2-3cc7b9f01416.png)

## Effects

絵にかけるエフェクトを調整する。

![Screen Shot 2022-12-16 at 18.55.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/33b16063-d3a7-c887-27e8-7cd0f074f376.png)

## Videos

背景の動画素材のファイルの切り替えを行う。
![Screen Shot 2022-12-17 at 22.09.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/2c97172b-f6f7-ca61-d77b-0e79d613b3b6.png)
このContainerのAlignはGrid Rowsが便利。
![Screen Shot 2022-12-17 at 21.51.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/52613e10-48bc-7918-eb7f-f8bacc1423f5.png)
素材のPanel CHOPのクリックをCHOP Executeへ渡し、欲しいコンポーネントの素材だけ再生する。
sceneChangerとやりたいことは似てる。
```python
def onOffToOn(channel, sampleIndex, val, prev):
	print("onOffToOn", channel, sampleIndex, val)
	moviesNum = int(op('info1')['length'])

	for i in range(0,moviesNum):
		opName = "bg" + str(i) 
		op(opName+ '/movie').par.play = 0
		print(opName, "off")

	opName = "bg" + str(sampleIndex)
	op("selectView").par.top = opName + "/out1"
	op(opName+ '/movie').par.play = 1
	print(opName, "on")

	return
```

![Screen Shot 2022-12-17 at 21.14.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/c5ac5593-d70c-2a06-70e3-262d5e6d4dd1.png)

素材の追加、もとい、素材が並んだネットワークが地獄である。

## Master

最終的にかけるマスターのエフェクトを置いている。明るさの調整やモノクロなど。（Ableton LiveのMaster Trackみたいな？）

![Screen Shot 2022-12-17 at 21.20.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/52dbcc30-6c20-4908-71c3-fdbd0ac7e2aa.png)
# 課題
もらった現場をこなしながら自分で必要な機能を考えてUIを育てていく感じで上記のようになってきたが、プレビューしたい、素材やシーン追加を楽にやりたいといろいろ課題もあり、この少ない機能だけでもネットワークや階層が複雑化してきた。またリファクタして作り直したい気持ちがある。
![Screen Shot 2022-12-17 at 20.44.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281/ad121081-396b-06a2-14e3-2ef66cdcc85a.png)
※これはごく一部

うまく作り直せたら数年後のアドベントカレンダーで書く。
# 参考情報
- [TDSWの動画](https://www.youtube.com/c/TDSW-online): TDSWのイベントや配信がなかったらTDやろうと思わなかったと思う。
- [Higaさんの資料など](http://satoruhiga.com/TDWS2019/day16/): 基本的なUIの作り方などはここで勉強した気がする。
- [ビジュアルクリエイターのためのTOUCHDESIGNERバイブル](https://amazon.co.jp/dp/441661991X
): 作例がいっぱいあるのでステップアップにおすすめ。
# おわりに
「このレベルだったら苦労してTouchDesignerでやる必要はなくVJソフト使えばいいじゃん」って話ですが、やっぱり自分でhackしていくのがTDのかわいさって感じがしますね。Advent Calendarの他の記事も勉強になります！

筆者は大型LEDが使える大崎の[Tunnel Tokyo](https://tunnel-tokyo.jp/)でスタッフやってる（audio visualをはじめイベントのサポートも）ので、お立ち寄りの際は是非。

Happy TouchDesigner Life!