Marketplace
Plugins
A plugin is a single script file that extends DMXexpress: paint a new effect layer, add your own window of controls, or restyle the whole console. Download one below, drop it on the app's Plugins window, and it is live — no restart, no compiler.
Download
Grab a .rhai file from the registry below — or from any GitHub link someone shares on the forum.
Drop it in
In DMXexpress, open Plugins from the toolbar and drag the file onto the window — or press Open folder and copy it there, then Reload all.
Enable it
Tick the plugin in the list. Layers start mixing immediately, windows appear under its Window toggle, and looks restyle the console. Untick or Remove any time.
Plugins are sandboxed, but read them anyway
Scripts run inside the app's sandbox: no file, network, or system access, and a runaway loop is stopped by an operation budget. Still, a plugin does drive your rig's DMX output — skim any script before running it in front of an audience.
Registry
Browse plugins.
Community plugins are reviewed before they appear here. The three starters ship inside DMXexpress — download them here anyway if you deleted yours.
Share yours
Submit a plugin.
Host the .rhai file anywhere public — a GitHub repository or release
works perfectly — then submit the direct link. Submissions are held for review
before they appear in the registry.
For developers
Write a plugin in an afternoon.
Plugins are Rhai scripts — one file, four optional functions, headers at the top. If you can write a for-loop, you can write a light show.
The shape of a plugin
//! name: Wave Floor
//! version: 1.0
//! author: you
//! description: A sine wave across every dimmer.
//! blend: highest // mix | highest | add
fn controls() {
[
#{ kind: "slider", id: "rate", label: "Rate", min: 0.1, max: 4.0, value: 1.0 },
#{ kind: "button", id: "kick", label: "KICK" },
]
}
// Called ~40x a second while enabled. Return [address, value] pairs.
fn frame(t, rig, state) {
let out = [];
for f in rig {
if f.dimmer > 0 {
let v = (1.0 + sin(t * state.rate + f.x)) / 2.0;
out.push([f.dimmer, (v * 255.0).to_int()]);
}
}
out
}
// A window button was pressed. Stash anything you like in state.
fn button(id, t, state) {
if id == "kick" { state.kicked_at = t; }
state
}
The four hooks
| Function | What it does |
|---|---|
controls() | Declares the plugin's window: sliders, checkboxes, buttons, labels. Values arrive in state. |
frame(t, rig, state) | Called every tick. Returns [address, value] pairs painted onto the plugin's own mixer layer. |
button(id, t, state) | Runs when a window button is pressed; return the new state map. |
theme() | Returns #RRGGBB strings for accent, surface, text — a console re-tint while enabled. |
Each rig entry
| Field | Meaning |
|---|---|
i, name | Fixture index and display name |
addr, channels | 1-based base address and channel count |
dimmer red green blue white | Absolute address of that channel, 0 if the fixture has none |
x y z | Stage position in metres — fan effects across space |
Rules of the sandbox
- No file, network, or process access — scripts only compute values
- An operation budget stops infinite loops with an error, not a hang
- Errors park the hook and show in the Plugins window; fix and press Reload
print("...")goes to the app's Log windowhsv(h, s, v)is built in and returns[r, g, b]