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 mathsscript.lua (Lua)
Familiar web-style scripting, flexible in/out portsutility.javascript (JavaScript)
Python with libraries, files, or shell commandsutility.script (Python)
A generative drawing canvas (Processing-style)script.p5 (p5.js)
Live-coded, ever-shifting video textureseffect.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_0in_3) and four number outputs (out_0out_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.

ParameterTypeDefault
codeString"function execute(inputs, ct..."
in_0Number
in_1Number
in_2Number
in_3Number

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.

ParameterTypeDefault
codeString"def execute(inputs, cx): ..."
input_countNumber1
output_countNumber1
allow_shellBooleanfalse
in_0Number
in_1Number
in_2Number
in_3Number
in_4Number
in_5Number
in_6Number
in_7Number

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.

ParameterTypeDefault
codeString"p.draw = function() { bac..."
widthNumber512
heightNumber512
opacityNumber1

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.

ParameterTypeDefault
codeString"osc(10, 0.1, 1.2).out(o0)"
widthNumber512
heightNumber512
opacityNumber1

Tips for all scripting nodes

See also