Scripting nodes
When a one-line Expression isn't enough, drop in a full scripting node — Lua, JavaScript, Python, or a live-coded visual canvas.
An Expression is perfect for short per-element formulas. But sometimes you want real logic — loops, helper functions, talking to a file, or generating a whole image from code. That's when you reach for a scripting node.
Each one takes code you type (or wire in from upstream), runs it every frame, and hands you back values or an image you can keep using in the graph. Each node also keeps its own private memory, so two copies of the same subgraph don't step on each other.
Which one should I use?
| You want… | Use |
|---|---|
| Fast, lightweight per-frame logic and maths | script.lua (Lua) |
| Familiar web-style scripting, flexible in/out ports | utility.javascript (JavaScript) |
| Python with libraries, files, or shell commands | utility.script (Python) |
| A generative drawing canvas (Processing-style) | script.p5 (p5.js) |
| Live-coded, ever-shifting video textures | effect.hydra (Hydra) |
The first three return numbers. The last two return an image (a colour field) you can feed into materials, post effects, or composite like any other layer.
Lua — fast logic
The quickest scripting node. You write an execute function that receives the inputs and a context, and returns a table of outputs:
function execute(inputs, ctx)
return { out_0 = inputs.in_0 * 2 }
end
It has four number inputs (in_0…in_3) and four number outputs (out_0…out_3). The ctx table gives you playback info: ctx.frame, ctx.time, ctx.fps, ctx.bpm, and ctx.is_playing. Great for snappy maths that runs on every frame.
| Parameter | Type | Default |
|---|---|---|
code | String | "function execute(inputs, ct..." |
in_0 | Number | — |
in_1 | Number | — |
in_2 | Number | — |
in_3 | Number | — |
JavaScript — flexible logic
Web-style scripting with a variable number of ports. Set how many inputs and outputs you want, then write execute:
function execute(inputs, cx) {
return { out_0: inputs.in_0 || 0 };
}
You get up to eight inputs and four outputs (the extra ports appear as you raise the counts). The cx object carries frame, time, fps, bpm, and is_playing. Read whichever inputs you need by name and return only the outputs you set.
Python — libraries, files, and shell
For heavier work. Write an execute function that returns a dictionary:
def execute(inputs, cx):
value = inputs.get("in_0", 0.0)
return {"out_0": value}
Like JavaScript, it has adjustable input and output counts. The cx dictionary gives you frame, time, timeline_frame, canvas_width, canvas_height, and is_playing.
Turn on Allow shell to unlock a shell(command) helper that runs a system command and hands back its output. Because Python can touch your files and run programs, it only runs when the project is trusted.
Python (and especially the shell helper) is gated by trust. If a project isn't trusted, the Python node refuses to run until you grant it. Only trust .dna files from people you know.
| Parameter | Type | Default |
|---|---|---|
code | String | "def execute(inputs, cx): ..." |
input_count | Number | 1 |
output_count | Number | 1 |
allow_shell | Boolean | false |
in_0 | Number | — |
in_1 | Number | — |
in_2 | Number | — |
in_3 | Number | — |
in_4 | Number | — |
in_5 | Number | — |
in_6 | Number | — |
in_7 | Number | — |
p5.js — a generative canvas
A creative-coding sketch that renders to an image. Define a p.draw (and optional p.setup) just like Processing:
p.draw = function() {
background(0);
fill(255);
circle(width/2, height/2, sin(getTime()) * 100 + 150);
}
Set the canvas width and height, and animate with getTime(). The node outputs a colour image you can wire anywhere a raster goes — into a material, a post effect, or straight onto a layer.
| Parameter | Type | Default |
|---|---|---|
code | String | "p.draw = function() { bac..." |
width | Number | 512 |
height | Number | 512 |
opacity | Number | 1 |
Hydra — live-coded visuals
Hydra is a visual synth: short, chainable expressions become endlessly morphing video. The classic starting point:
osc(10, 0.1, 1.2).out(o0)
Set the output width and height and the node renders a live colour image, perfect for backgrounds, textures, and live visuals. Edit the code while it's running and the picture updates.
p5.js and Hydra run their sketches in an embedded browser engine, so they need the desktop app and a moment to warm up on first use. The first frame may lag slightly before the image settles.
| Parameter | Type | Default |
|---|---|---|
code | String | "osc(10, 0.1, 1.2).out(o0)" |
width | Number | 512 |
height | Number | 512 |
opacity | Number | 1 |
Tips for all scripting nodes
The code field can be wired from upstream — feed a text node or file in to drive the script without retyping it.
Each node remembers its own state, so duplicating a subgraph keeps the copies independent.
Reach for Expressions first for short formulas; promote to a scripting node when you need real structure. You can also decompose many nodes into editable Expressions to learn from them.