Animation COMP w/o Animation Editor

# はじめに
この記事ではAnimation Editorを使用せずにAnimation COMPのアニメーションを作成する方法について紹介します。Animation COMPの基本的な使い方については[こちら](https://qiita.com/takashi_kawamura/items/1af840ee5482dbddd8d7)が参考になります。

# Animation COMPの仕組み
Animation COMPの中を見ると次のようなTable DATが用意されています。
![Animation COMP](https://i.gyazo.com/10c603565f7598518dfe200c5e4b355e.png)

Animation Editorからアニメーションを作成すると、”channels” と “keys” というTable DATに値が追加されていることがわかります。
![Animation Editorからアニメーションを作成する](https://i.gyazo.com/ada303cf347a168b1b206c78c1122d11.gif)

もう少し細かくchannels と keys の中身を見てみます。

## channels

| 項目 | 説明 |
| --- | --- |
| name | チャンネル名 |
| id | 識別子 |
| left | Extend Left |
| right | Extend Right |
| default | Default Value |
| keys | 参照先DAT |
| liner | Animation Editorで使用するパラメータ：色(R) |
| lineg | Animation Editorで使用するパラメータ：色(G) |
| lineb | Animation Editorで使用するパラメータ：色(B) |
| picked | Animation Editorで使用するパラメータ：選択中 |
| display | Animation Editorで使用するパラメータ：表示中 |
| template | Animation Editorで使用するパラメータ：表示中（編集不可） |

![channels](https://i.gyazo.com/c2e6d17d396981e493cc695291c782de.png)

## keys

| 項目 | 説明 |
| --- | --- |
| id | 識別子 |
| x | キーフレームの位置 |
| y | キーフレームの値 |
| inslope | 接線のパラメーター（左） |
| inaccel |  |
| expression | イージング関数 |
| outslope | 接線のパラメーター（右） |
| outaccel |  |

![keys](https://i.gyazo.com/acd0eb5fcb591c43095f447d90a4499d.png)

以上、この２つのテーブルのお作法に則りながらTable DATを作成してみます。


# 例）時系列データ(.csv)をAnimation COMPで再生する
センサー等で計測したデータを受信してビジュアライズするようなプロジェクトにおいて、事前に計測したデータ(.csv)を元にAnimation COMPで値を再生できるようなシミュレーターを作ってみます。（ここからは細かい設定や実装についてはかなり省略しているため「こんな風にできるんだぁ」程度に流し見してください:bow:）

## 1. データを準備する
例）感情分析ソフト（仮）の計測結果.csv
![感情分析結果.csv](https://i.gyazo.com/f6e5e51ac90985375931274c61ed70cf.png)

### channels
![channelsを準備する](https://i.gyazo.com/9d993d589337e8696f01939b00ea62f8.png)

以下のようにScript DATでパラメーターを設定します。

- Timestamp 以外のラベルを `name` として設定する
- `id` はラベルごとに順番に採番する
- `left` `right` = hold
- `default` = 0
- `keys` = keys
- `liner`,`lineg`,`lineb` は好みで
- `picked`,`display`,`template` = 0

```python
# me - this DAT
# scriptOp - the OP which is cooking
#
# press 'Setup Parameters' in the OP to call this function to re-create the parameters.
import colorsys

def onSetupParameters(scriptOp):
	return

# called whenever custom pulse parameter is pushed
def onPulse(par):
	return

def onCook(scriptOp):
    # ➁ Channelsのラベル
	scriptOp.copy(scriptOp.inputs[0])
	
    # ⓵ CSVのラベル
	name = scriptOp.inputs[1]

	for i in range(1,name.numCols):
		color = colorsys.hsv_to_rgb(i / name.numCols, 1, 1)
        # ⓷ パラメーターを追加する（例：happiness, 1, hold, hold, 0, keys, 1.0, 0.857142, 0.0, 0, 0, 0）
		scriptOp.appendRow([name[0,i], i, 'hold', 'hold', 0, 'keys', color[0], color[1], color[2], 0, 0, 0])
		
	return
```

すると...

![channels](https://i.gyazo.com/63f5c49617fceca41161f54fdbf94c7d.png)

### keys

- Timestamp (frame) を元に各キーフレームの位置を決定し、チャンネルごとに値を設定する
- センサー値は補間しないので `expression` は constant()

![keys](https://i.gyazo.com/7d442f9781b7439ba7447ec09584db33.png)


``` set_keyframe.py
# keysをリセットします
keys = op('keys')
keys.par.dims = True
keys.par.dims = False

# animation COMP
animOp = me.parent()

# csvのデータ
dataOp = op('data')

# 計測の開始を先頭データに合わせるためのオフセット値
time_offset = dataOp[1, 0]

for i in range(1, dataOp.numRows):	
	# キーフレームの位置
	position = float(dataOp[i, 0]) - float(time_offset)
	
    # 各ラベルごとにキーフレームを追加する
	for j in range(1, dataOp.numCols):
		channel = dataOp[0,j]
		value = dataOp[i,j]				
		animOp.setKeyframe(position, channel=channel, value=value, function='constant()')
```

実行すると...
![keys](https://i.gyazo.com/7843bc0322dc8fcdc80a821a6f45a4bf.png)

Animation Editor上でも確認することができます。
![出力結果](https://i.gyazo.com/86b7d6ea64afcf58875e39cc121904a3.png)


## 2. データを再生する
![データを再生する](https://i.gyazo.com/35b9ea0df2d215200f69e8c866406345.gif)

# 最後に

今回はcsv形式のデータをAnimation COMPで扱えるようにTable DATを変換しただけですが、他にもkeysのTable DATを工夫することで、入力された値に応じてアニメーションの尺を変えたり、条件に応じてアニメーションを分岐するといったことも可能になりそうです。

# 追記
csvのデータの数が増えると負荷がかかるためTimestamp以外のデータをCHOPに変換し、TimestampからインデックスのみをAnimation COMPで作成するなど対策が必要そうでした。