Python в TouchDesigner
Где живёт код, как обратиться к сети, что делать нельзя и почему скрипт на каждом кадре — плохая идея.
TouchDesigner несёт встроенный Python (в актуальных сборках — 3.11) и
модуль td, через который доступна вся сеть.
Где писать код
| Место | Для чего |
|---|---|
Textport (Alt+T) |
Проверить строчку, посмотреть ошибку |
| Text DAT | Модуль с функциями, вызываемыми откуда угодно |
| Script DAT / Script CHOP / Script SOP | Оператор, содержимое которого считает Python |
| Колбэки (Execute DAT и другие) | Реакция на события — Скрипты и колбэки |
| Параметр в режиме Expression | Однострочные выражения — Ссылки |
| Extensions | Классы, живущие вместе с компонентом — Extensions |
Базовые обращения
op('noise1') # оператор
op('noise1').par.period = 4 # параметр
op('noise1').par.period.expr = "absTime.seconds" # выражение
op('constant1')['chan1'] # канал CHOP
op('table1')[0, 'name'] # ячейка DAT
op('geo1').par.display = 0
ops('render*') # список по шаблону
parent() # родительский компонент
me # сам оператор
project.folder # папка проекта
absTime.seconds # время с запуска
Создание и удаление узлов:
n = parent().create(noiseTOP, 'noise_new')
n.nodeX, n.nodeY = 200, 0
n.par.period = 3
op('noise_old').destroy()
Запуск отложенно
run("op('a').par.Reset.pulse()", delayFrames=1)
run("me.fetch('go')", delayMilliSeconds=500)
run с задержкой — способ выполнить действие после текущего кука.
Многие «странные» ошибки («изменил структуру сети во время кука») лечатся
именно этим.
Хранение состояния
Не держите состояние в глобальных переменных модуля — они переживут не то, что вы думаете. Используйте:
me.store('counter', 0) # хранилище оператора
me.fetch('counter', 0) # с значением по умолчанию
или собственные параметры компонента, или Extensions.
Чего делать не надо
Execute DAT с обработчиком onFrameStart, внутри которого перебирается
сеть, — прямой путь к падению кадров. Python в TouchDesigner работает в
главном потоке: пока он считает, не считается ничего.
Правильнее:
- значения — CHOP и экспорт, а не скрипт;
- реакция на изменение — колбэк, а не опрос;
- тяжёлые вычисления — отдельный поток (
Thread Manager) или отдельный процесс (Engine COMP); - обход сети — один раз при старте, результат в таблицу.
Отладка
print()уходит в Textport.debug()печатает с именем оператора и номером строки — удобнее.- Ошибки видны в Textport и в
Error DAT, который можно поставить в служебную панель и показывать на площадке. op('...').errors()и.warnings()— программный доступ к ошибкам конкретного узла; основа мониторинга.