TouchDesigner Overview
How Lightpath uses TouchDesigner, the component contract, and the shared patterns every output and plugin follows.
Lightpath is built and tested against TouchDesigner 2023.12600. Other versions may work, but we recommend staying on this build. Download from Derivative.
On client machines that don't need network editing, Lightpath can run against TouchPlayer instead of TouchDesigner. Choose which one Lightpath launches on the Settings → TouchDesigner page.
TouchDesigner is the engine that produces every pixel Lightpath puts on screen. Lightpath wraps a TouchDesigner project, loads outputs and plugins into it dynamically, routes content through them, and exposes their parameters to the web UI.
You author the TouchDesigner side as .tox files following a small
contract. There are two kinds:
- Outputs are the destinations — the components that take a final composed texture and push it somewhere physical: a pixel-mapped LED sculpture, a projection mapped surface, a video wall over NDI, etc. One output per physical destination in the install.
- Plugins are the supporting cast. They come in three flavors:
- Sources generate textures — patterns, audio reactivity, media playback, shader visuals.
- Effects transform textures — blurs, color shifts, masks, geometric distortions.
- System plugins don't render anything; they send control signals or expose shared data other plugins react to (sensors, cameras, APIs). One instance per install.
A Lightpath look picks a source, stacks effects on it, and routes the result to one or more outputs.
This page covers the shared concepts — custom parameters, file paths — that apply to both outputs and plugins. The dedicated guides drill into each:
Custom parameters
Lightpath surfaces TouchDesigner custom parameters to the user interface, but only ones on specific parameter pages. There are three pages it cares about: Look, Config, and Status.
Look parameters
Any parameter on a page named Look is exposed per-look. Operators tune these in the look editor; each look stores its own values. Switching looks switches the values.
Use Look params for things an operator should be able to vary across looks — pattern speed, blur radius, mix amount, color shift, fit mode.
Note: Look parameters are not available for System plugins, since they are install-level instances. Their state doesn't change per look, so a Look page wouldn't have anywhere to land.
Config parameters
Any parameter on a page named Config is exposed at the project level — one value for the whole project, same across every look, every schedule event, every operator action.
Use Config params for things tied to the install rather than the look — network targets, monitor indexes, sample rates, file paths, default behaviors.
Config parameters show up in several places:
- Outputs page — each output's edit panel surfaces that output's config params alongside its other settings. Edit values and save new defaults that restore on project load.
- Plugins page — same pattern for sources, effects, and system plugins: each plugin's config params live next to the plugin itself.
- Actions — an action step can change a config param value.
- Logic — rules can read config param values as conditions.
- Kiosk — config params can appear as user-facing controls on the Kiosk page.
Status parameters
Any parameter on a page named Status is exposed to Lightpath as read-only state. The values stream live from TouchDesigner and appear in the TouchDesigner device on the Devices page — grouped by the component that exposes them — so operators can see at a glance what each component is doing.
Use Status params for things Lightpath should observe, not control — connection state of a remote service, last-received message timestamps, error counts, signal-presence booleans, current mode strings. They're read-only in the UI; nothing the user does in Lightpath writes back to them.
Status params also feed the Alerts system: every Status parameter becomes a selectable target in the alert rule editor, so you can notify operators when (for example) a connection goes offline or an error count climbs.
Status pages work on outputs and system plugins — the singleton components in a project. Source and effect plugins don't support Status pages, since each look can wire them in different combinations and there's no single "the source's status" to point at.
Managed parameters
Lightpath looks for a specific set of specially-named parameters on your component and manages them itself — writing, toggling, or pulsing them at the right moments. You don't wire these up to anything; exposing one is how you opt in to its behavior. We recommend grouping them on a page named Managed to keep them out of the operator's way, but the page name is only convention — Lightpath finds them by name.
| Parameter | Applies to | What Lightpath does with it |
|---|---|---|
Resolution1 / Resolution2 (Int) | Sources | Writes the output's render resolution onto the pair so the source cooks at the right size. Required for sources — drive your source's internal cook rate off these. Aliases accepted, first match wins: Resolutionw/Resolutionh, Resolutionx/Resolutiony, Res1/Res2, Resw/Resh. |
Thumbnail (Toggle) | Sources, effects, outputs | Sets it On while capturing the picker thumbnail, Off afterward. Key showcase values off it (via parameter expressions) so a component that's pass-through at its defaults still renders something recognizable in the picker. See Thumbnails. |
Onload / Ondestroy (Pulse) | All | Pulses Onload just after the component is placed and cooking, Ondestroy just before teardown — the pulse-parameter form of the lifecycle hooks. |
Enable (Toggle) | Outputs | Uses this toggle to disable rendering for secondary instances of an output. See The Enable toggle. |
The Thumbnail and Onload/Ondestroy behaviors can also be handled
as extension methods (BeforeThumbnail/AfterThumbnail,
OnLoad/OnDestroy) if you'd rather write Python than wire a pulse —
see Lifecycle hooks.
Which components support which pages
| Component | Look | Config | Status | Managed |
|---|---|---|---|---|
| Output | ✓ | ✓ | ✓ | ✓ |
| Source plugin | ✓ | ✓ | — | ✓ |
| Effect plugin | ✓ | ✓ | — | ✓ |
| System plugin | — | ✓ | ✓ | ✓ |
Need your own custom parameters that Lightpath neither exposes nor
touches — purely internal plumbing for your component? Put them on any
page other than Look, Config, or Status and Lightpath leaves them
alone. Internal is the recommended name for these.
Refreshing the parameter schema
Lightpath detects schema changes — parameters added or removed on a
.tox while it's running — and re-scans automatically. Value
changes are streamed live; you don't need to do anything for either.
In the rare case Lightpath and TouchDesigner look out of sync (a rename that auto-detection missed, a refresh that didn't land), the TouchDesigner settings page has a Sync data button in the Process Status section that forces a full re-scan.
Thumbnails
Sources and effects show up in the UI with a thumbnail, and Lightpath generates them automatically. There are two ways to shape what that image looks like.
Provide the image
Add a TOP named thumbnail inside a source COMP and Lightpath
saves that as the thumbnail. Lock it to ship a
fixed, hand-authored preview — a logo, a representative still — or leave
it live to present a differently-composed frame than your working
output. With no thumbnail TOP, Lightpath captures the first Out TOP.
Showcase mode
A straight capture often doesn't represent a component well:
- Interactive sources and effects that react to live sensor input — audio, camera, MIDI, OSC — capture as flat or empty when nothing's coming in. Feeding fake data during capture makes them show off what they do.
- Pass-through effects sit at neutral defaults — a blur at radius 0, a hue shift of 0 — so the capture looks identical to the input and tells the operator nothing.
Expose a Thumbnail Toggle on the Managed page and key your
showcase values off it with parameter expressions so the capture shows
what the component actually does:
# On a Blur effect's Filter Size parameter (expression mode):
20 if parent().par.Thumbnail else parent().par.Blur
# On a Color effect's Hue Shift parameter:
0.3 if parent().par.Thumbnail else parent().par.Hueshift
# On an audio-reactive source, feed a synthetic level while capturing:
0.8 if parent().par.Thumbnail else op('audio_in')['level']Lightpath sets the toggle On while capturing and Off afterward. Sources that react to input need it as much as effects do; outputs use it when the thumbnail should render differently than the live output.
If the prep needs real logic rather than a parameter expression, an
extension can implement BeforeThumbnail(target) /
AfterThumbnail(target) instead — fired around the capture just
like the toggle, with target the TOP being captured.
Lifecycle hooks
Your component can react to being loaded or torn down. Hooks are optional; most sources and effects built from a template need none. Reach for one when a component has to do work a plain parameter can't express: connecting to an external service, allocating resources, starting or stopping a stream, opening a window.
There are two ways to handle a hook — pick whichever suits the component. The contract is identical for every component type (output, source, effect, system plugin): Lightpath fires both the same way, on all of them.
- An extension method — add an extension to the COMP with a
capitalized method matching the hook name (
OnLoad,OnDestroy). Best when the component requires complex logic best encapsulated in an extension. - A pulse parameter — add a pulse custom parameter on the
Managed page named after the hook (
Onload,Ondestroy) and handle it in a parameter execute DAT. Best when you'd rather keep things simple.
If a component defines both for the same hook, the extension method wins and the pulse is left alone — so use one per hook.
OnLoad
Fires once the component is in place and cooking. Use it for setup that can't happen during cook: connecting to an API, allocating resources, resetting state, opening a window.
OnDestroy
Fires just before the component is torn down — a look change, slot clear, plugin reload, or output removal. Use it for cleanup: closing connections, stopping streams, releasing handles, closing a window.
Example
A component that opens a session with an external device on load and closes it on teardown, using the extension-method tier:
class MyExt:
def __init__(self, ownerComp):
self.ownerComp = ownerComp
def OnLoad(self):
# Just placed — tell the device we're live.
self.ownerComp.op('webclient').request(
'http://192.168.1.50/api/session', 'POST',
data='{"state": "live"}')
def OnDestroy(self):
# About to be torn down — close the session cleanly.
self.ownerComp.op('webclient').request(
'http://192.168.1.50/api/session', 'DELETE')The pulse-parameter equivalent: add an Onload (and/or Ondestroy)
pulse parameter on the Managed page and do the same work from the
COMP's parameter execute DAT onPulse callback.
Accessing project files
When your output or plugin needs to reference external assets — 3D
models, images, spreadsheets, etc. — store them inside your
project folder and reference them via the project path shortcut.
If you add a 3D model at
my_cool_project/outputs/My_Output/model.obj, you can load it in
TouchDesigner with the path:
project/outputs/My_Output/model.objThis path resolves correctly across machines and project locations because TouchDesigner reads it relative to the loaded project root. Don't use absolute filesystem paths — they break the moment the project moves.
Saving toxes
Lightpath includes two keyboard shortcuts for saving .tox files from inside the
TouchDesigner editor. Both flash the network background green when the
save completes — quick visual confirmation that the file was written.
- alt+e — Save the currently selected COMP to its
externaltoxpath. If the COMP has never been saved (noexternaltoxset), a folder picker opens once; the chosen<folder>/<comp name>.toxbecomes the COMP'sexternaltoxfor every subsequent save. - alt+shift+e — Save the COMP whose network you're currently inside — i.e. the parent of the network editor's view. Same save semantics as alt+e. Useful when you're working inside a component and want to save the component itself without dropping back out to its parent.
Where to go next
- Making an Output — wire a new fixture, video wall, projector, or screen into Lightpath.
- Making Plugins — author a source, effect, or system plugin that any output can use.

