TouchDesignerでのPython入門（応用編）

# この記事について
TouchDesignerやってるけどPythonほとんど書いたことない私さのかずや(Twitter:@sanokazuya0306)が理解を深めるためにつくった、TouchDesignerでPython書けるようになりたい人用のメモ。

基礎編はこちら：[TouchDesignerでのPython入門（基礎編）](https://qiita.com/sanokazuya0306/private/d733b17854a566801d00)

## TouchDesignerで本気でPythonやるぞマン各位へ
TouchDesigner野郎にはおなじみ、リファレンス鬼のMatthew Raganパイセンが超詳細なリファレンスまとめてらっしゃいます。
[Python in TouchDesigner | Matthew Ragan](https://matthewragan.com/teaching-resources/touchdesigner/python-in-touchdesigner/)
これを読めばたぶんマスターできる。すごいなMatthew。
なのでMatthewリファレンスからかいつまんで記します。

## 応用編について
if文（条件分岐）とかfor文（繰り返し）的な処理の方法と、具体的にif文とfor文使って処理する方法をやっていきます。**全然応用じゃねえな！**

## エディタ設定
本題の前に。TouchDesignerでテキストを扱うためのDATは、**実は外部エディタが使える。**
Preferences→DATs→Text Editor から設定可能。
<img width="483" alt="スクリーンショット_2017-12-02_17_05_28.png" src="https://qiita-image-store.s3.amazonaws.com/0/77925/f45a9952-1b97-5394-4d2b-4ae661631027.png">
わたしはAtomです

# if文（条件分岐）の基本的な書き方
こちらの一部抜粋。
[Python in TouchDesigner | Logic | TouchDesigner | Matthew Ragan](https://matthewragan.com/2015/10/22/python-in-touchdesigner-logic-touchdesigner/)

```python:if_example
my_int1 = 5
print('my_int1 is %d' % my_int1)

if my_int1 >= 6:
	print( 'This number is greater than 6')

else:
	print( 'This number is less than 6')
```

これをRunすると結果はこうなる。

<img width="244" alt="スクリーンショット 2017-12-02 17.12.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/77925/c7fc1600-66ec-b767-48fd-0cb7fde70793.png">

# for文（繰り返し）の基本的な書き方
こちらがとてもていねい。
[Python in TouchDesigner | For Loop | TouchDesigner | Matthew Ragan](https://matthewragan.com/2016/07/06/python-in-touchdesigner-for-loop-touchdesigner/)
↑めっちゃ丁寧に書いててしゅげー

超抜粋。

```python:for_example
loop_count  = 10

print( "This is our first loop" )
for item in range( loop_count ):
    print( item )
```

結果はこんな感じ。
<img width="272" alt="スクリーンショット 2017-12-02 17.46.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/77925/da065e9f-e824-af8d-ec4a-d573cba2c458.png">


# 例：画像Nodeを増減させる
[Python in TouchDesigner | Op Class | TouchDesigner | Matthew Ragan](https://matthewragan.com/2016/07/06/python-in-touchdesigner-op-class-touchdesigner/)
こちらからひとつ例を拝借。

```Python:op_test
# create a new variable called new_op
# this is also a copy of the operator out 1
new_op = parent().copy( op( 'moviefilein1' ) )

# since we've defind our new op with the variable
# name new_op we can continue to use this name
# our next step will be to give it a name
new_op.name = 'moviefilein_new_op'

# finally we're going to change the location of
# our new operator. In this example we want it
# created at a location in relation to our original
# operator. We start by finding the original operator's
# y position, and then subtract 200
new_op.nodeY = op( 'moviefilein1' ).nodeY - 100
```

適当に画像をいれて`moviefilein1`を用意して、これをRunさせるとこうなる。

![1512224140262.gif](https://qiita-image-store.s3.amazonaws.com/0/77925/60c7f6b2-8914-d719-23fd-919ad46fbecf.gif)
[綿貫くん](https://twitter.com/watakemi725)が増殖しますね

これを、**if文とfor分を使って、増えたり減ったりするようにしてみる。**

```python:op_test2
# moviefileinをすべて取得
m = parent().ops('moviefilein*')

# moviefileinの数
check = len(m)

# moviefileinが1個なら
if check == 1:

	# 繰り返し処理(moviefilein2から10まで)
	for i in range(2, 11):

		# コピー元のOPをmoviefilein1にする
		new_op = parent().copy( op( 'moviefilein1' ) )

		# iが5以下のときは1段め
		if i <= 5:
			# つくったnodeの位置を横にずらす
			new_op.nodeX = op( 'moviefilein'+str(i-1) ).nodeX + 150
		# iが6以上のときは2段めへ
		else:
			# つくったnodeの位置を縦にずらし、横にもずらす
			new_op.nodeY = op( 'moviefilein1' ).nodeY - 130
			new_op.nodeX = op( 'moviefilein1' ).nodeX + 150 * (i-6)

# moviefileinが10個なら
if check == 10:

	# 繰り返し処理(moviefilein2から10まで)
	for i in range(2, 11):
		# OPを削除
		op( 'moviefilein'+str(i) ).destroy()
```

これでRunを繰り返すとこうなる。

![1512228693749.gif](https://qiita-image-store.s3.amazonaws.com/0/77925/85e07e88-c163-91cf-ac17-e88a64cdb85f.gif)
[綿貫くん](https://twitter.com/watakemi725)がたくさん増えたり減ったりしますね

## 応用
Constantで数を変えられるようにしてみる。

```Python:op_test3
import math
num = int(op('constant1')[0])

# moviefileinをすべて取得
m = parent().ops('moviefilein*')

# moviefileinの数
check = len(m)

# moviefileinが1個なら
if check == 1:

	# 繰り返し処理(moviefilein2からnumまで)
	for i in range(2, num+1):

		# コピーするためのOPをmoviefilein1にする
		new_op = parent().copy( op( 'moviefilein1' ) )

		# 5ずつ縦に並べるためにi-1を5で割って切り捨てた数かける
		new_op.nodeY = op( 'moviefilein1' ).nodeY - 130 * math.floor((i-1)/5)
		# i-1を5で割ったあまりのぶんだけ横にずらす
		new_op.nodeX = op( 'moviefilein1' ).nodeX + 150 * ((i-1)%5)

if check == num:

	# 繰り返し処理(moviefilein2からnumまで)
	for i in range(2, num+1):
		# OPを削除
		op( 'moviefilein'+str(i) ).destroy()
```

![1512277198726.gif](https://qiita-image-store.s3.amazonaws.com/0/77925/b82a15c8-d3e0-7495-f91e-66cfba07b223.gif)
[綿貫くん](https://twitter.com/watakemi725)が200個出てきます

buttonで動くようにもできる。
CHOPから動かすときは**CHOP Execute DAT**が便利。

<img width="986" alt="スクリーンショット 2017-12-03 14.03.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/77925/6d274c6a-8428-d090-2dcb-1208ebe76491.png">

COHPにbuttonから出したnullをセット。

```python:chopexec1
# me - this DAT
#
# channel - the Channel object which has changed
# sampleIndex - the index of the changed sample
# val - the numeric value of the changed sample
# prev - the previous sample value
#
# Make sure the corresponding toggle is enabled in the CHOP Execute DAT.

import math
num = int(op('constant1')[0])

# moviefileinをすべて取得
m = parent().ops('moviefilein*')

# moviefileinの数
check = len(m)

def onOffToOn(channel, sampleIndex, val, prev):
	# 繰り返し処理(moviefilein2からnumまで)
	for i in range(2, num+1):

		# コピーするためのOPをmoviefilein1にする
		new_op = parent().copy( op( 'moviefilein1' ) )

		# 5ずつ縦に並べるためにi-1を5で割って切り捨てた数かける
		new_op.nodeY = op( 'moviefilein1' ).nodeY - 130 * math.floor((i-1)/5)
		# i-1を5で割ったあまりのぶんだけ横にずらす
		new_op.nodeX = op( 'moviefilein1' ).nodeX + 150 * ((i-1)%5)

	return

def whileOn(channel, sampleIndex, val, prev):
	return

def onOnToOff(channel, sampleIndex, val, prev):
	# 繰り返し処理(moviefilein2からnumまで)
	for i in range(2, num+1):
		# OPを削除
		op( 'moviefilein'+str(i) ).destroy()
	return

def whileOff(channel, sampleIndex, val, prev):
	return

def onValueChange(channel, sampleIndex, val, prev):
	return
```
先ほどの個数チェックをボタンのオンオフにセット。`chopexec1`のパラメータの`Off to On`と`On to Off`をどちらもOnにしておく。

![1512277590881.gif](https://qiita-image-store.s3.amazonaws.com/0/77925/6a83e942-8445-4db5-2099-5c0749b3ccd8.gif)
めっちゃラグるけど出せる


### ていうか
こんなめんどいことしなくても**Replicator COMP**でできたわ
![1512230078361.gif](https://qiita-image-store.s3.amazonaws.com/0/77925/b55b5776-d3dd-6c0b-1871-fa7b9a59f730.gif)

ちなみに**Replicator COMPとかOPをたくさん増減させる系は処理が重たくなるのであまり推奨されていないっぽい。**
元ファイルを変える必要がないなら、Translateとかで元ファイルは変えずに映像で処理するほうが懸命…？

## 他の例
2つのCHOPのパラメータ比較してprintする、とかはここにある。
[Python in TouchDesigner | Logic - Part 2 | TouchDesigner](https://youtu.be/GjhI7rhzpzg)
これを応用すれば映像の出し変えとかもいろいろできそう。

# まとめ
見れば見るほどめっちゃむずない！？と感じてしまったので、Matthewパイセンのガチリファレンスでちゃんと勉強してちょっとずつまとめます。
[Python in TouchDesigner | Matthew Ragan](https://matthewragan.com/teaching-resources/touchdesigner/python-in-touchdesigner/)

あくまで入門ということで、**さらなる活用はみなさんどんどんQiitaに上げて頂けたらよいのでしょうか！**きっと喜ぶと思います！おもにぼくが！

それではみなさん埋めてくださったアドカレたのしみにしております！