第14回: Python深堀りとDAT操作
本日のtoeファイル ← ダウンロードしておいてください
DATの使い方
/project1/DAT_BASIC を参照

一番基本的な2つのDATを紹介します。 両方ともViewer Activeの状態にするとキーボードからの入力で文字を入力できます。
Test DAT
単純に文字情報を入力できます。
Table DAT
Excelのような縦横にわけられたテーブルを扱うことができます
Pythonの実行
TouchDesignerはPythonと密接に連動しています。Pythonを実行するには通常 Textport and DATs Window か Test DAT を使います。また、Pythonから出力された情報は Textport and DATs Window に表示されます
Text DAT からPythonを実行するには3つの方法があります。
- Viewer Activeの状態を抜けて、オペレーターを右クリック >
Run Script - オペレーターの名前 (例えば
text1) が表示されている所を右クリック >Run Script - オペレーターを右ドラッグなどで選択しておいて
Ctrl+R
Ctrl+R のショートカットを使うのが一番作業効率的が高いと思います
外部のテキストエディタを利用する
Pythonスクリプトを書くにあたって、TouchDesignerの Text DAT はお手軽なのですが不便なこともあります。Preferences メニュー > DATs タブ > Text Editor をを指定することで、好きなテキストエディタを使うことができます。
外部のテキストエディタを使うことで、コードを書く際に書式を間違っていた時にエラーを出してくれたり、その他色々な便利な機能があるのでなるべく外部エディタを使ったほうがいいでしょう。
おすすめは Visual Studio Code です。この授業では主にvscodeを使う前提ですすめていきたいと思います。
Preference > DATs > Table Editor のほうも指定していると、Table DAT を開いた時にも外部エディタで開いてくれます。この場合、テーブルは タブ文字 区切りのテキストとして表現されます。エディタの設定でスペースが入ってしまう場合は設定を切り替えてタブ文字が入るようにしてください。空白文字を表示するオプションを有効にしておくと、タブ文字とスペースの見分けがつくようになるので便利です。
余談
最近のVisual Studio Codeの更新で、Windows環境の場合インストールされる所が隠しフォルダになってしまい場所がわかりにくくなってしまいました。。 %HOME%AppData\Local\Programs\Microsoft VS Code\Code.exe を指定するとうまくいきます。
op() を理解する
/project1/WORK_WITH_OP を参照
チャンネルのリファレンスなどを作るときに op('null1') のようなものがよく出てきました。これは一体なんなのでしょうか?
例えば、text1 を見てみましょう。
print( op('constant1') )
これを Run Script で実行すると、
/project1/WORK_WITH_OP/constant1
と表示されます。パスが表示されただけ?と思うかもしれませんが、実際には text1 のPythonオブジェクトの内容を表示しています。どういうことかと言うと、たとえば
print( op('constant1').__class__ )
と書かれた text2 を実行してみてください。すると、
<class 'td.constantCHOP'>
と表示されたはずです。.__class__ は、Pythonの機能で、オブジェクトはどのクラスのオブジェクトか?を問い合わせるものです。つまり、op('constant1') から返ってくる値は td.constantCHOP クラスだ、ということです。
Pythonや他のプログラム言語をやったことがある人はピンとくるかもしれませんが、TouchDesignerでは、GUI上のオペレーターとオペレーターのPythonオブジェクトが1対1で対応しています。op() は、与えられた文字列から現在いる場所のオペレーターを検索して、そのオペレーターのPythonオブジェクトを返す、という機能です。
同様にして、me もよく出てきました。自分自身のPythonオブジェクトを取得します。なので、me.parent() とすると、自分の親階層のPythonオブジェクトを取得できます。
また、取得できるのはPythonオブジェクトなので、Pythonの機能である help() 関数を使うとヘルプドキュメントを出力することができます。
Pythonのヘルプは、パラメーターウィンドウのPythonヘルプボタンでも見ることができます。これはWebブラウザで当該オペレーターのリファレンスが見れるので通常はこちらを使うといいでしょう。ただ、help() 関数はネットワークがつながっていない環境でもドキュメントを見ることができるので、一応覚えておくといいと思います。
オペレーターのPythonオブジェクトをいじる
/project1/OPERATOR_OBJECT を参照
では、次に Text DAT からPython経由で Text TOP のパラメーターを変更してみましょう。例えばこうなります。
o = op('text2')
o.par.text = 'hey'
最初の o = op('text2') で、text2 のオペレーターのPythonオブジェクトを変数o として定義しました。こうしておくと、毎回 op('text2) のように書かないでもよくなるので便利です。
次の o.par.text = 'hey' では、↑ で取得した Text TOP のオペレーターの、text パラメーターを書き換えています。これはパラメーターリファレンスとは逆の操作です。単純に出したい文字列を .par.text に代入することでパラメーターが書き替えできます。
text3 では、もうすこしPythonらしい機能を使っています
import random
o = op('text2')
o.par.text = random.choice(['i', 'my', 'me', 'mine'])
import random は、Python標準の random モジュールを読み込む、という宣言です
9.6. random — 擬似乱数を生成する — Python 3.6.5 ドキュメント
random モジュールには色々な乱数に関わる機能がありますが、この例ではその中の random.choice を使っています。random.choice は、引数に渡された配列 (今回の場合だと配列 ['i', 'my', 'me', 'mine']) からランダムに一つ選んだ値を返す、という機能があります。なので、text3 を実行するたびに Text TOP の文字が変更されることになるはずです。
どのようなパラメーターがあるのはか、前述のPythonヘルプボタンを押すことで確認できます。例えば Text TOP の場合はこちら → textTOP Class - Derivative
テーブルを使う
/project1/TABLE を参照

テーブルの形を持ったDATに対しては、dat_operator[タテのインデックス, ヨコのインデックス] という角カッコを使った指定で内容を取り出せます。インデックスの指定は 0 始まりです。
t = op('table1')
print( t[0, 0] )
print( t[1, 0] )
print( t[0, 1] )
なので ↑ のスクリプトの出力は 1, 4, 2 となります
テーブル特有の機能として、縦、または横の一番最初の要素を検索のキーとして使うこともできます。↓ の例だと r = t.row('row1') という部分で、row1 で初まっている行を取得しています。取得された列の先頭には row1 が入っているため、r[1] が t[0, 1] と同じ要素をさすものになります。同様にして列を選択するには .col() を使います。
t = op('table2')
r = t.row('row1')
print( r )
print( r[1] )
オペレーターとの連携
/project1/CHANGE_IMAGE1 を参照

Filder DAT を使うと、指定したフォルダ以下のファイルを検索してテーブルにしてくれます。このテーブルを使って、サンプルイメージフォルダにある画像を表示してみましょう。text1 がそれです。
o = op('folder1')
n = 6
r = o.row(n)
op('FILENAME').text = r[0]
op('PATH').text = r[1]
r = o.row(n) の所で、n に指定した行を取得しています。この例だと n は6なので、6行目です。返ってきた行の値の0番目がファイル名、1番目がファイルのパスなので、それぞれの文字列を PATH, FILENAME の Text DAT に入れています。
そして、PATH、FILENAME の値をそれぞれ Movile File In TOP Text TOP で利用しています。n の値を変更してスクリプトを走らせると画像が変わっていくのがわかると思います
text3 では、random.randrange を使って実行のたびにランダムに画像が変更されるようになっています
import random
o = op('folder1')
n = random.randrange(1, o.numRows)
r = o.row(n)
op('FILENAME').text = r[0]
op('PATH').text = r[1]
DATの実行イベント
/project1/EXECUTES を参照

Execute系のDATを使うと、様々なタイミングのイベントでスクリプト実行することができます。それぞれのオペレーターで実行して欲しいタイミングのパラメーターのトグルをOnにすると、def onイベント名(): の関数が実行されるようになります。
Execute DAT- ファイルの起動終了時やオペレーターの作成時、フレームの開始終了時など
OP Execute DAT- オペレーターのcook(計算)の前後、オペレーターの状態が変更された時など
Parameter Execute DAT- パラメーターの変更時など
CHOP Execute DAT- CHOPの値が変化した時など
DAT Execute DAT- DATの値が変化した時など
画像をスライダで切り替える
/project1/CHANGE_IMAGE2 を参照

今までは Text DAT に書かれたスクリプトは Run Script で実行してきました。ですが、 Pythonからでも別の Text DAT の内容を実行できます。op('TARGET_TEXT_DAT_NAME').run() のような形です。
.run(1, 2, 3) のように、引数を渡すこともできます。その場合実行される側の Text DAT からは args を使って引数を受け取れます。
/project1/CHANGE_IMAGE2 の例では、まず op('CHANGE_IMAGE').run(変更したい画像のインデックス) となるような仕組みをあらかじめ作ってから、CHOP Execute DAT を使ってインデックスの値を変更しています。
一定の処理の内容を Text DAT にまとめておくことで関数呼出のような感じでネットワークを操作することができ、処理の見通しがよくなります
まとめ
今回はDAT、Pythonの導入あたりをやってきました。TouchDesignerはスクリプトを使わなくても結構いい所までいける環境だと思いますが、ある程度複雑なことをやろうとするとさすがに文字ベースの言語で組んだほうが楽になるシチュエーションもあります。Pythonを完璧に理解する必要はないですが、基本の部分だけでも覚えてしまうとよいと思います!
授業中でPythonの基本についてやる時間はとれない(し、自分が教えても微妙…)と思うので各自でお願いします!
初心者向けにはこちらがいいかな → みんなのPython 第4版
こちらは読んだことないけど評判よさそう → スラスラわかるPython
来週は Script SOP、Script CHOP、GLSL TOP あたりですかね~、、、