К содержанию
fohbook/ TouchDesigner
уверенный

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() — программный доступ к ошибкам конкретного узла; основа мониторинга.
рядом по смыслу