Appearance
Script reference
Needs MNodes 1.1.5 or newer
The Script node is new in MNodes 1.1.5. What is marked 1.1.6 on this page is new in MNodes 1.1.6 and does not exist in 1.1.5.
This page lists everything the code of a Script node can use, so you can look it up. How the node works, its settings and longer examples are on the Script node's page, and each part here links to where it is explained.
Inside MNodes, the Reference button on the node shows the ones you use most over the code, each with a button that writes it where the cursor is.
Functions you write
Write these in your code and the Script calls them. Leave out the ones you do not need.
| Function | When it runs | What it is given |
|---|---|---|
onStart() | When the code starts, and again after every edit or Restart. | Nothing. |
onInput(n, value, time) | For every message on In n (In 1 is 1). With CV Inputs on, also each time a CV on In n rises through 0.5. | value: a number, a text, true or false, or undefined for an Event. time (1.1.6): when a CV rose, on the clock now() reads. See CV in. |
onTick(dt) | Tick times a second, when Tick is on in the Inspector. With the picture (1.1.6): once each time the screen refreshes. | dt: the seconds since the last tick. |
onKey(name, down) 1.1.6 | For every key of the computer keyboard pressed and let go. | name: "Left", "Space", "A" and so on. down: true when pressed, false when let go. |
onButton(name, down, pad) 1.1.6 | For every button of a game controller pressed and let go. | name: one of the button names. down: true or false. pad: 1 to 4. |
The node
| Call | What it does |
|---|---|
out(n, value) | Sends value out of Out n: a number, a text, true or false as they are, an array or an object as JSON text. |
out(n) | With no value, sends an Event (a trigger) out of Out n. |
print(...) | Writes a line in the console under the code. Objects are written as JSON. |
time() | The seconds since the code started. |
state | An object kept with the project and across edits: state.count = 3 is still there when the project opens again. |
Keys and game controllers
1.1.6. How to use them in a game: Keys, for a game.
| Call | What it gives |
|---|---|
keyDown(name) | true while that key of the computer keyboard is down. |
gamepad(n) | What game controller n (1 to 4) is doing now. gamepad() is pad 1. |
Key names are the ones the Keyboard node gives: "Left", "Right", "Up", "Down", "Space", "Enter", "Escape", the letters "A" to "Z" and the digits "0" to "9". The Script takes the keys only if its code has onKey or keyDown, and never while you type in a text box.
What gamepad(n) gives back:
| Field | What it is |
|---|---|
connected | true when a controller is there. |
A, B, X, Y | The four buttons on the right: true while held. |
LB, RB | The shoulder buttons. |
Back, Start | The two small buttons in the middle. |
LS, RS | The sticks pressed in. |
Up, Down, Left, Right | The direction pad. |
lx, ly, rx, ry | The left and right sticks, -1 to 1, up and right positive. A stick at rest reads 0. |
lt, rt | The triggers, 0 to 1. |
On Windows any controller that speaks XInput works: Xbox pads and most others. On a Mac, the ones the system knows: Xbox, PlayStation and MFi pads. The controllers are read only while a Script uses them.
CV and MIDI out
1.1.6. Set CV Outputs and MIDI Outputs in the Inspector first. How it works, with an example: CV and MIDI out.
| Call | What it does |
|---|---|
cv(n, value, { at, glide }) | Moves CV n to value and holds it there. glide: slides there over that many seconds. |
note(n, pitch, velocity, length, { at, channel }) | Plays a note out of MIDI n. Pitch 60 is middle C, velocity 1 to 127 (100 if not given), length in seconds (0.25 if not given). |
noteOn(n, pitch, velocity, { at, channel }) | Starts a note that sounds until its noteOff. |
noteOff(n, pitch, { at, channel }) | Ends it. |
cc(n, number, value, { at, channel }) | A controller: number and value, 0 to 127. |
bend(n, value, { at, channel }) | Pitch bend, -1 to 1. |
allNotesOff(n) | Every note of MIDI n off. With no n, of every MIDI output. |
now() | The clock at is on, in seconds. |
transport() | The song: playing, bpm, beat, beatInBar, beatsPerBar and time (now, on the same clock). |
atBeat(beat) | The time a beat falls at, to use as at. |
The options can be left out. at is a time on the clock now() reads: the change lands on that exact sample. Without it, it plays at the start of the next block. channel is 1 to 16 (1 if not given). Each call gives back true when it was sent, or false when it was not, such as an output the node does not have; the console says why, once.
The app window
1.1.6. For the menu of a game made in MNodes. They work only in the standalone app, never in a DAW, and not in the code's first moment and a half. See also the App node.
| Call | What it does |
|---|---|
app.quit() | Leaves MNodes, asking to save first. |
app.fullScreen(on) | true fills the screen, false gives it back, nothing turns it the other way round. |
app.isFullScreen() | true while the window fills the screen. |
app.standalone() | true in the standalone app, false in a DAW. |
app.quit() and app.fullScreen() give back true when they work, or a text that says why not: "standalone only" or "too soon".
Saved games
1.1.8. A game's progress, kept on the computer of whoever plays it and apart from the project: playing never changes the project, and a player who opens the game again, from the library or in a new session, carries on where they left off. How to use it: Saving a game.
| Call | What it does |
|---|---|
save.game(name) | Names the game. Call it once, at the top: its saves are kept under that name. |
save.get(key, otherwise) | What was kept under key, or otherwise when nothing was, as the first time the game is played. |
save.set(key, value) | Keeps a value under key: a number, a text, true or false, or an array or an object of them. Gives back false when it cannot keep it, and the console says why. |
save.remove(key) | Forgets one. |
save.list() | The keys kept, as a list. |
save.clear() | Forgets everything in this save. |
save.slot(name) | Another save of the same game from then on, such as "Slot 2" for a second player. The first is "Slot 1". |
save.slots() | The saves the game has, as a list of their names. |
save.perInstance(true) | In a DAW, each copy of MNodes keeps saves of its own, and finds them again when the session opens. |
save.game(), save.slot() and save.perInstance() with nothing in the brackets say which is in use, and they can go in one line: save.game("Marble Run").slot("Slot 2").
Drawing on a Scene
Wire Out n into a Scene's Objects input, then draw on it from the code. How it works: Drawing on a Scene.
| Call | What it does |
|---|---|
canvas(n) | The Scene that Out n (1 to 8) is wired into. scene(n) is the same. |
c.size(width, height, fit) | The units things are laid out in, fitted to the Scene. fit: "contain" (the default), "stretch" or "cover". |
c.background(colour) | A plain background. It hides the Scene's own picture and its zones. |
c.showCode(on) | Brings the Scene's own picture and zones back under the drawing. |
c.clear() | Takes away everything the Script drew. |
c.find(id) | The object with that id, or null. |
c.on(event, fn), c.off(event, fn) | The mouse on the Scene, heard after its objects and groups. See Events. |
c.theme({...}) | The look of the controls made after it. |
c.add(Kind, {...}) | A control of your own. See Your own control. |
What you can draw
Each maker takes the object's properties and gives the object back. Inside a group, g.rect({...}) and the others put the new object in the group.
| Maker | What it draws | Its own properties |
|---|---|---|
c.rect({...}) | A rectangle | x, y (top left), w, h, radius |
c.circle({...}) | A circle or an ellipse | x, y (middle), r, or rx and ry |
c.arc({...}) | Part of a ring | x, y, r, width, start, end (degrees, 0 at the top, clockwise), cap |
c.line({...}) | A straight line | x1, y1, x2, y2, width, cap ("round", "butt" or "square") |
c.polyline({...}) | Lines through points | points, closed, width, cap |
c.triangle({...}) | A triangle | x1, y1, x2, y2, x3, y3 |
c.polygon({...}) | A filled shape through points | points, counted from its x and y |
c.path({...}) | Any outline, as SVG writes it | d, or points and closed |
c.star({...}) | A star | x, y, r, sides, inner |
c.ngon({...}) | A regular polygon | x, y, r, sides (6) |
c.text({...}) | Text | x, y, text, size, align, baseline, lineHeight, letterSpacing, maxTextWidth (longer text shrinks to fit) |
c.image({...}) | A picture from a file | x, y, w, h, src, fit ("contain" or "cover"), radius |
c.wave({...}) | The sound on the Scene's In A or In B | x, y, w, h, input ("a" or "b"), shows ("wave" or "spectrum"), style ("line", "fill", "bars" or "mirror"), bars, gain, log |
c.group({...}) | A group of objects | x, y, w, h, clip, reveal, revealFrom |
points is [[x, y], ...] or [x, y, x, y, ...]. What each property means in detail: the makers' table.
Properties every object takes
| Property | What it does |
|---|---|
fill | Its colour, a gradient or a pattern. |
stroke, strokeWidth | Its outline, and how thick. |
glow, glowColor | A soft light round it. |
shadow | A shadow under it: a colour, or { color, x, y, blur }. false takes it away. |
blur | Softens its edges. |
trail | Where it has been fades behind it over so many seconds. |
opacity | 0 (not seen) to 1. |
rotation, scale, scaleX, scaleY, originX, originY | Turned (degrees, clockwise) and sized round its middle, or round the point originX and originY say (0 to 1 across it). |
visible | false hides it and what it holds. |
blend | "add" adds its light to what is under it. |
cursor | The pointer over it: "pointer", "grab", "crosshair", "text", "move", "ns-resize", "ew-resize" or "none". |
tooltip | A text shown when the pointer rests on it. |
interactive | false lets the mouse through. true takes clicks with no handler. |
hitPad | How far round it, in units, the mouse still finds it. |
id | A name to find it with c.find(id). |
parent | The group to put it in, or its id. |
on | Handlers, as { click: fn, drag: fn }. |
bind | Ties a property to the sound, the time or a control. See Following without code. |
Colours are written "#4fd1ff", "#4fd1ff80" (the last two digits its alpha), "rgb(79, 209, 255)", "rgba(79, 209, 255, 0.5)" or a colour's name. A gradient is { from, to, angle }, with radial: true or conic: true. A pattern is { from, to, pattern, size, weight, angle }, the patterns "stripes", "dots", "checker", "grid" and "noise". The details: Properties every object takes.
A place or a size can also be a share, written as a text: "50%", "100% - 20", "50%w", "50%h", "50%min", "50%max", "calc(50%w + 10)".
Changing what is drawn
| Call | What it does |
|---|---|
o.set({...}) | Changes it at once. |
o.get(name) | The last value given to that property. |
o.animate({...}, { duration, ease, delay, repeat, yoyo }, then) | Takes it there over time. A number in place of the options is the duration. Defaults: 0.3 seconds, "outCubic", no delay, no repeat. then() runs when it is over. |
o.stop() | Stops its changes over time where they are. |
o.front(), o.back() | Over, or under, the objects next to it. |
o.on(event, fn), o.off(event, fn) | Listens to the mouse on it, or stops. off with no fn stops them all. |
o.remove() | Takes it away, with everything in it. |
g.clear() | Empties a group. |
g.redraw(fn) | Empties a group and lets fn(g) fill it again. |
Every object also has o.id, o.kind ("rect", "group" and so on), o.parent and o.children.
The easings: linear, inQuad, outQuad, inOutQuad, inCubic, outCubic, inOutCubic, inSine, outSine, inOutSine, inExpo, outExpo, inOutExpo, inBack, outBack, inOutBack, outElastic and outBounce.
Events
o.on(event, fn) calls fn(e). The mouse events: enter, leave, move, press, release, click, doubleclick, dragstart, drag, dragend, wheel and rightclick. Also animationend, when a change over time is over.
| Field of e | What it is |
|---|---|
e.type | The event's name. |
e.x, e.y | Where, in the Scene's units. |
e.world 1.1.8 | Over a 3D view or a solid in it: the point of its world under the pointer, on the flat plane where z is 0, as { x, y, z }. |
e.u, e.v | Where on the object, 0 to 1 across it. |
e.dx, e.dy | How far a drag moved since the last one. |
e.totalX, e.totalY | How far since the press. |
e.delta | How far the wheel turned. |
e.shift, e.ctrl, e.alt | Whether those keys were held. |
e.target | The object. |
e.canvas | The Scene it happened on. |
e.stop() | Stops it going on to the groups the object is in and to c.on. |
Following without code
bind: { property: [source, from, to, options] } moves a property on every frame, while the code does nothing. How it works: Following the sound with no code.
| Source | What it follows (0 to 1) |
|---|---|
levelA, levelB | How loud the Scene's In A or In B is. |
bass, mid, treble | In A's lows, mids and highs. |
P1 to P60 | The Scene's P controls. |
time | The Scene's clock, 0 to 1 over and over, as many times a second as the fourth number says. |
| a zone's name | That zone's value. "Pad.y" is the Y of an XY pad. |
| Option | What it does |
|---|---|
decimals, prefix, suffix | For text: how the number is written. |
rate | How many times a second time goes round. |
smooth | Glides after the source over that many seconds, instead of jumping. |
o.set({ bind: null }) lets every bind of the object go.
3D
c.view3d({...}) puts a 3D world on the Scene, and the makers below put things in it. In the world, y is up, x across and z towards you. How it works: In three dimensions.
Each maker matches a Scene node, linked in the table, and most of that node's settings are a property here with the same meaning. To see the exact names, build it with the node, right-click the node and use Copy as Script.
| Maker | What it makes | Its own properties |
|---|---|---|
c.view3d({...}) | A 3D view, with its camera (3D View) | x, y, w, h, radius, yaw, pitch, distance, tx, ty, tz, fov, ortho, orbit, fill, ambient, environment, showEnvironment, intensity, envYaw, exposure, bloom, bloomThreshold, bloomSize, focus, focusDistance, focusRange, tiltShift, ao, aoRadius, saturation, contrast, warmth, vignette, edges, edgeWidth, edgeColor, temporal, fog, fogColor, fogStart, fogHeight, fogFade, hideLabels |
v.box(), v.sphere(), v.cylinder(), v.cone(), v.torus(), v.plane() | A solid (3D Shape) | w, h, d (1 each, a plane 4 by 4), r (0.5), tube (0.18), segments, mirror (a plane) |
v.mesh() | A model from a file (3D Model) | src (an OBJ or glTF file), w, h, d, animation, animationTime |
v.light() | A light (3D Light) | type ("directional", "point", "spot", "panel" or "environment"), intensity (1), fill, r (10), w, h (a panel), tx, ty, tz, cone, soft, shadows, blur (1.5) |
v.group() | A group that moves and turns together (3D Group) | label |
v.clones() | Copies of what it holds (3D Clones) | count (8), layout, spacing (1.2), columns, r (2), turns, turnEach, riseEach, growEach, jitter, seed, spectrum, input |
v.particles() | Sparks, fire, snow (3D Particles) | rate (40), life (2), speed (2), spread (25), gravity, drag, size (0.12), sizeEnd, fill, colorEnd, glow, blend, shape, count (400) |
v.join() | What it holds as one solid, merged or melted together (3D Join) | mode ("merge", "blend" or "intersect"), smooth (0.25), detail (64) |
v.subdivide() | What it holds with its faces split, rounded off (3D Subdivide) | levels (2), round (true) |
v.displace() | What it holds with its surface moved out and in (3D Displace) | map ("noise", "waves", "bricks", "tiles", "dimples", "brushed" or a picture's whole path), amount (0.15), levels (2), mid (0.5), mapRepeat (1) |
v.fog() | Fog in the world (3D Fog) | fog (0.07), fogColor, fogStart, fogHeight, fogFade, opacity |
v.sound() 1.1.6 | Where a sound is (3D Sound) | name |
v.listener() 1.1.6 | Where the sound is heard from (3D Listener) | |
v.zone() 1.1.6 | A place that sounds like a room (3D Reverb Zone) | w (10), h (6), d (10), r, roomMix (0.35), roomSize (0.6), roomDecay (0.6), roomDamp (0.3), roomFade (2), roomPreDelay (20 ms) |
The numbers in brackets are what a property is when you do not give it.
What every solid, group and light takes:
| Property | On | What it does |
|---|---|---|
x, y, z | everything | Where it is. |
rotX, rotY, rotZ | solids, groups | Turned round each axis, in degrees. rotation is rotZ. |
scale, scaleX, scaleY, scaleZ | solids, groups | Its size: 2 twice as big. |
fill, opacity | solids | Its colour, and how much shows through. |
metal, rough | solids | 0 plastic to 1 metal; 0 polished to 1 matt (0.5). |
glow, glowColor | solids | The light it gives of its own. |
flat | solids | Each face shaded as one. |
texture, normalMap | solids | A picture on it, and bumps that catch the light: a file's whole path, "image1" or "image2", or a pattern's name. |
tile, tileU, tileV, offsetU, offsetV, bump | solids | How its pictures repeat and slide, and how strong the bumps are. |
Inside a join, a group with cut: true is cut out of the join instead of added to it. A join, subdivide or displace with lookInside: true wears the look of the first solid it holds.
Anything flat made in a 3D world (a text, a circle, a control) is a label, drawn where its group is seen. A particles object has p.burst(n), which makes n at once (20 if not given).
1.1.8. v.pointAt(x, y) turns a point of the Scene, such as a mouse event's e.x and e.y (or the event itself, v.pointAt(e)), into the point of the view's world under it: where the camera's line of sight through that point meets the flat plane where z is 0. It gives { x, y, z }, or null when that line never meets the plane. { y: 0 } uses the ground instead, { x: 2 } or { z: -1 } another plane, and { facing: true } the plane through what the camera looks at, turned to face it. It follows the camera as it is drawn, however it is turned, tilted or zoomed, with or without Orthographic, so a solid can be dragged under the mouse: const p = v.pointAt(e); if (p) bell.set({ x: p.x, y: p.y });
Physics
1.1.6. A solid or a 3D group with body falls, collides and bounces in its view's world. How it works: Physics.
| Property | On | What it does |
|---|---|---|
body | a solid, a 3D group | "dynamic" (falls and is pushed), "static" (stays put) or "kinematic" (goes where its x, y and z say). |
mass | a body | In kilograms. 0, the default: from its size. |
bounce, friction | a body | 0 a thud to 1 a superball; 0 ice to 1 rubber (0.5). |
damping, gravity | a body | How much the air slows it (0.05); how much gravity pulls it (1). |
sensor | a body | Stops nothing, only feels what comes in and goes out. |
upright | a body | Never turns over. |
fast | a body | Does not pass through thin walls when thrown fast. |
collider | a body | "box", "ball", "capsule" or "cylinder" in place of its own shape. |
name | a body | For joints made by nodes to find it. |
| Call | What it does |
|---|---|
v.physics({ gravity, speed, paused, tempo }) | The view's world: how hard everything is pulled down (9.81), how fast its time goes (1), stopped or not. tempo: the BPM it is laid out at; while the transport plays, its time follows the transport's tempo (laid out at 90, it goes a third faster at 120), so a fall that takes a beat takes a beat at any tempo. 0, the default: off. |
v.joint({...}) | Joins body a to body b, or to the world: joint is "hinge", "spring", "rope", "ball", "fixed" or "slider". |
o.push(x, y, z) | Adds to its speed. push({ x, y, z, spinX, spinY, spinZ }) spins it too. |
o.velocity(x, y, z) | Sets its speed. |
o.body() | Where it is and how fast it goes now: { x, y, z, vx, vy, vz, awake }. |
o.restart() | Every dynamic body of its view back where it was put. |
v.ray(from, to) | The first body a straight line meets: { item, id, x, y, z, normal, distance }, or null. |
A joint's properties: a, b, x, y, z, axis ("x", "y" or "z"), min, max, speed, strength, friction, stiffness (2), damping (0.1), length. All of them explained.
| Event | When | Fields |
|---|---|---|
hit | It begins to touch something. | e.other, e.otherId, e.strength (0 to 1), e.speed, e.point, e.normal, e.at |
bodyenter, bodyexit | A body comes into or leaves a sensor. | e.other, e.otherId, e.at |
bodymove | Every frame it moves. | e.point, e.speed |
jointmove | A joint moves. | e.value (a hinge's angle, a slider's place, a spring's length), e.speed |
1.1.8. e.at is when it happened, to a sixtieth of a second, on the clock now() reads, however late the picture was drawn. Give it to a note to play it in time: note(1, 60, 100, 0.3, { at: e.at + 0.05 }). A time that has already gone plays at once, so the 0.05 (50 ms) keeps every hit the same short way behind its moment, an even beat.
Controls
Knobs, sliders and the rest, ready to place in one line each. How they work: Ready-made controls.
| Maker | What it is | Its own options |
|---|---|---|
c.knob({...}) | A knob | size (80) |
c.slider({...}) | A slider | w, h (160 by 28, or 28 by 160 standing up), vertical |
c.button({...}) | A button | w, h (100 by 36), mode ("trigger", the default, or "momentary"), onPress, glissando (a group's name: slide from one momentary button to the next) |
c.toggle({...}) | An on and off switch | w, h (64 by 32) |
c.xy({...}) | A pad with a point to drag; its value is [x, y] | w, h (160 by 160), outX, outY |
c.meter({...}) | A level to watch | w, h (160 by 16, or 16 by 120 standing up), vertical |
c.steps({...}) | A row of cells to turn on and off; its value is the list | count (8), w, h (34 by 34 each), gap (8) |
c.select({...}) | A row of choices, one lit; its value is its number from 0 | options, w, h (70 by 30 each) |
Every control also takes:
| Option | What it does |
|---|---|
x, y | Where it is: its top left, or a knob's middle. |
name | Shown under it, and what its value is kept under with the project. |
label | Shown instead of the name. "" shows none. |
value, default | Where it starts, and what a double-click brings back. |
min, max, step, log | Its range (0 to 1 unless you say), its steps, and a range for frequencies. |
unit, decimals, format | How its value is written. format is a function that gives the text. |
color | Its own accent colour. |
tooltip, id | A text when the pointer rests on it, and a name to find it. |
out | Its value goes out of Out n whenever it changes, and once when the code starts. send: false leaves out that first one. |
input | A message on In n sets it, and goes on out. |
onChange | A function called with each new value. |
param | true makes it one of the Scene's zones: an output of the Scene, and a parameter your DAW can automate. Not for a meter or steps. |
| On the control | What it does |
|---|---|
k.value | Its value, to read or to set: k.value = 0.3. |
k.on("change", fn) | Calls fn with each new value. |
k.group | The group it is drawn in, to move or animate it. |
k.remove() | Takes it away. |
steps.light(i) | Lights cell i as the one playing. |
c.theme({ accent, body, edge, track, text, label, font }) changes the look of the controls made after it. font is the size of their text (12).
Your own control
A class built on canvas.Component, made with c.add(Kind, {...}), takes every option above:
| Part | What it is |
|---|---|
build() | You write it: makes the drawing in this.group, once. |
draw() | You write it: shows this.value. |
this.set(v) | Gives it a new value, kept, sent and drawn as any control's. |
this.group, this.value | Its group, and its value now. |
An example: Ready-made controls.
Limits
| What | How much |
|---|---|
| Inputs, Outputs | 1 to 8 each. |
| CV Outputs, MIDI Outputs | 0 to 8, and 0 to 4. |
| A call | A quarter of a second. One that runs longer is stopped. |
| Starting | The code's top level and onStart have two seconds each. |
canvas(n) | n from 1 to 8. |
gamepad(n) | Pads 1 to 4. |
| Trails | 8 on a Scene. |
| Lights | 32 in a 3D view. |
| A save | 256 KB of what it keeps. |
The code runs in a sandbox: it reaches no network, and no files other than its own saved games.
