[TouchDesigner] COMP内の動作について


## はじめに

TouchDesignerのとあるプロジェクトでEventCHOPが発火していないという現象がありました。

原因がさっぱりだったのですが、先日参加させていただいた、TouchDesignerもくもく会にて、@komakinex さんに質問したところ、「明日Derivative社の人と会うので聞いてみます。」ということでわざわざ掛け合ってくださりました。本当に感謝。。:bow:
そして解決に至りましたので共有いたします。



## 現象

以前、TouchDesignerでモーショングラフィックスをビートに合わせてランダムなポジションに出すというものを作りました。

簡略化したものが以下になります。（[プロジェクトzip](shugohirao.com/room/td/td_NullCookAlways.zip)）

![td_NullcookAlways01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109091/26eaf92c-4365-0424-0f0b-c944402dba3e.png)
![td_NullcookAlways02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109091/35340e32-0c0e-5f39-6fb4-24e9080fda3e.png)


一応上記オペレータ群をざっくり説明すると、
(余談なので、ざっと飛ばし読みしていただけると、、:pray:)

1. モーショングラフィックスごとに、再生スタート(pulse)、座標(xyz)、スケール(scl)、回転(rot)をもたせたtoxを作ります。
2. mgListにモーショングラフィックスごとに生成したtoxをおいておきます。
3. pulseTransformでpulseを与えるごとにランダムでxyz座標とscale, rotationを出力します。
4. EventCHOPを使い、EventCallbackDATのなかから、先程生成したランダムなパラメータをmgList内のBaseCOMPに代入+再生スタートのpulseを送る。

といった流れで、ビートに合わせたモーショングラフィックスの自動生成を行っています。
正直、同時に同じグラフィックを出せないとか、いろいろと不十分な点があるので、満足なシステムとは言えません。
TOPのインスタンシングっていいやり方あるのかな。。

※当初いろいろ目論見があってEventCHOP使ってましたが、よくよく考えれば上記の内容だとEventCHOPを使う必要もないのかもですね。。



さておき、
ここで予期せぬ問題として、階層を移動するとなぜかEventCHOPが動いておらず、
ビートごとに生成されるはずのモーショングラフィックスも表示されないという問題がありました。

**event1_callbacks**のなかで`print('newMG')`などとし、
Textportで確認すると、エディタ上で同階層を開いている場合は想定通りメッセージがBeatごとに発火されていますが、階層を移動すると、どういうわけかTextportにもメッセージが表示されませんでした。



## 原因

原因としては、**COMPの中身は階層が変わると動作が止まる**という仕様のためでした。
処理負荷を軽減するためこの仕様になっているそうです。
*仕様なのでどうしようもない。*　（というダジャレが脳裏をよぎりました。）

私がちらっと確認したところだと、
EventCHOPのほか,LFOやClockなど階層が変わると動作していないオペレータがいくつかありました。



## 解決

####NullChop - Always

じゃあどうすんのかという話で、教えていただいた解決策としては、
nullCHOPのAlwaysという設定にする。というもの。

EventCHOPなど、常に更新させたい値の入ったオペレーターをnullCHOPを繋ぎ、**CookType**をAlwaysにします。
![td_NullcookAlways05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109091/e749698b-eb95-025d-b13c-1115308e430d.png)


こんな設定、さっぱり気付かなかった。
この設定をすることで、階層を移動しても常にオペレータが更新されるようになるようです。

当然、Alwaysにすることで常に処理がかかるため、多用すると重くなる可能性もあるので注意です。



**Bind**

ついでに、@komakinexさんに教えていただいたことで、
バージョン2019.20140から、ExportとReferenceの他に**Bind**という機能が追加されました。
Referenceなどだと、参照する側の値(expressionを書く側)を変更すると、Referenceが外れてしまっていましたが、このBind機能を使うと、参照される側(もととなる値)はもちろん、参照する側を変更しても値が反映されるようになっています。

今回のように、BaseCompにまとめて利用する場合は、CustomParameterでCookTypeを切り替えられるようにしておくと、後々のデバッグなどで活きてくるかもしれません。
そんなときに、Bind機能はBaseCOMPからも内部のオペレータからも操作できるので非常に便利です！
文字に起こしてもこの便利さ伝わる気しませんが、実際使ってみるとありがたみ感じます。:pray:

![td_NullcookAlways03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109091/971e8985-d8bc-149a-a10b-45b03416e50e.png)
![td_NullcookAlways04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109091/3fb0ff4a-8ae8-1056-1dc4-413d945c47c0.png)

**Probe**

そしてまたついでに、Probeによる確認方法も教えていただきました。
Probeについてはちょうど先日 @satoruhiga さんの記事でも書かれていました。
https://qiita.com/satoruhiga/items/1f9cdd309f65f769c3c3#probe
オペレータの動作確認をする際にもProbeは活躍しそうです。


#### その他の対策

- OutChopなどで無理やり同階層に持ってきて更新をかけるようにする。
  （当初これでむりくり解決していました。）
- opViewerなどで停止しているオペレータを同階層で表示させるようにする。
（おもしろいのはこのときActiveでなくても更新されるけど、Viewをオフにすると更新されない。）
  
  

## おわりに

気軽に質問できる環境って素晴らしい。

僕が参加したのはたまたま第一回でしたが、今後も開催されるということだったので、次回も都合が合えば是非参加したいです。
[TDSW](https://tdsw.co/)が一時活動停止している状況を鑑みての開催だったそうです。
こういったコミュニティを絶やさないためにも、みなさんももしよろしければぜひ。

TouchDesignerもくもく会
https://techlab-tdmokumoku01.peatix.com/