Every control
Each control is one call. It appears on a plate, in the order you make it, and hands back an object you can ask.
In JavaScript the last thing a control takes is its options, in braces: dial("speed", 0, 10, 3, { step: 1 }). In Python they are given by name: dial("speed", 0, 10, 3, step=1). An option with a capital in JavaScript has an underscore in Python: onChange is on_change.
Every control takes x and y (to place it by hand: its top left corner), colour, and size, share and span, which are in Laying out a panel. Every control has value, label, remove() and place(x, y).
dial
const speed = dial("speed", 0, 10, 3) // from 0 to 10, starting at 3
const pitch = dial("pitch", 100, 2000, 440, { log: true, unit: "Hz" })A dial is a number between two ends. speed.value is the number now, and setting it turns the dial. In a sum the dial stands for its number.
| Option | What it does |
|---|---|
step | The dial moves in steps of this size: step: 1 gives whole numbers |
unit | Words after the number: "Hz", "%" |
log | Turned by ratio and not by amount, as a pitch is: each part of the turn multiplies |
digits | How many digits after the point are shown |
size | How big the dial is: "small", "large", so many times the usual size (1.5), or a size in points (a number over 4) |
onChange (on_change) | A function called with the new value when a hand changes it |
dial(label, target, "setting") makes a dial that is a setting of something else: see Tying a control to a synth.
slider
const size = slider("size", 10, 150, 60)
const height2 = slider("height", 0, 100, 50, { vertical: true })The same as a dial, as a slider, with the same options. vertical stands it upright.
button
const fire = button("fire")
let shots = 0
function update(dt) {
if (fire.pressed) {
shots += 1
playSound("laser")
}
}
function draw() {
background("black")
text("Shots " + shots, width / 2, height / 2, "white", 40, "centre")
}fire.pressed is true once for each press: ask it in update. fire.held is true for as long as the button is down. A second value is a function to call on each press: button("reset", startAgain).
toggle
const mute = toggle("mute") // off to begin with
const grid = toggle("grid", true) // on to begin withA switch. mute.on is true or false, and so is mute.value. In Python if mute: asks it.
select
const level = select("level", ["easy", "medium", "hard"], "medium")One of a list, stepped through with the arrows at its sides. level.value is the choice and level.index is its place in the list, from 0.
select(label, target, "setting") takes the choices from the target, and keeps up when they change: a list of MIDI devices, or a synth's wave, where "sample" is a choice only once the synth has a sample. { style: "rotary" } makes it a rotary (style="rotary").
rotary
const mode = rotary("mode", ["easy", "medium", "hard"], "medium")
const lead = makeSynth("lead")
rotary("reverb", lead, "reverbType") // the choices come from the synthA knob that clicks between a few choices, with a notch for each and their names round it where there is room. Drag to turn it from notch to notch, or tap a name. It holds at each notch until you have gone most of the way to the next, then clicks over.
mode.value is the choice and mode.index its place, as with a select.
The choice is written under the knob only where no names are round it. showValue: true or false says otherwise (show_value in Python).
keyboard
const lead = makeSynth("lead")
const piano = keyboard(lead, { octave: 4, octaves: 2 })A piano keyboard along the bottom, which plays what it is given. piano.notes is the notes held now, as numbers where 60 is middle C.
| Option | What it does |
|---|---|
octave | The octave its first key is in. 4 starts at middle C |
octaves | How many octaves it shows |
keys | false turns the computer's keys off for it |
hints | false hides the letters on the keys |
height | How tall it is, which is kept to whatever the room |
animate | false: the keys jump to a new octave, and do not slide |
onNoteOn (on_note_on) | A function called with the note and how hard, when a key goes down |
onNoteOff (on_note_off) | A function called with the note, when a key comes up |
With the computer's keys, A S D F G H J are the white keys and W E T Y U the black ones; Z and X step down and up an octave.
The arrows above the keys step an octave too, again and again while one is held, and the keys slide there. A finger on the strip between the arrows drags the keys sideways, and they settle on a whole octave. A keyboard never shows so many octaves that a key is too narrow to play.
A keyboard with no synth is a way to read notes for anything:
let last = "nothing yet"
keyboard(null, { onNoteOn: (note) => { last = "note " + note } })
function draw() {
background("midnightblue")
text(last, width / 2, 80, "white", 30, "centre")
}scope
const graph = scope("height")
let t = 0
function update(dt) {
t += dt
graph.push(Math.sin(t * 2) * 100)
}A line of numbers, live. What it is given decides what it draws:
| Given | It draws |
|---|---|
| A label, or nothing | What you push: one more point each time, to draw any value over time |
| A synth | The wave the synth is making |
| A function that returns a list | That list, asked for every frame |
Options: min and max (the bottom and top of the picture), width, height, and points (how many points it keeps).
meter
const level = meter("speed")
level.value = 0.7A level from 0 to 1 as a bar of lights. Set level.value yourself, or give it a synth and it shows how loud the synth is.
label
label("Ball")
const size = dial("size", 5, 80, 30)
row() // the plates after this start a new line
label("World")
const gravity = dial("gravity", 0, 2000, 900)Words. A label made just before some controls is their heading, on the plate they share, and they are kept together.
group, row, column, grid, page, spacer and wrap
These say what goes with what. They are in Laying out a panel, with pictures.
| JavaScript | Python | What it does |
|---|---|---|
group("filter", () => { … }) | with group("filter"): | A plate with a title, and the controls on it |
row(() => { … }) | with row(): | Controls in a line. row() with nothing in it starts a new line |
column(() => { … }) | with column(): | Controls one under another |
grid(3, () => { … }) | with grid(3): | Three to a line, in columns that line up |
page("fx") | page("fx") | A page of controls with a tab. page() ends the pages |
spacer() | spacer() | All the room that is left over, so what follows is pushed to the far end |
wrap() | wrap() | If this line has to be split, split it here |
layout, room, theme and over
layout says where the plates go, how big they are and how they wrap, and gives back the width, height and scale the layout came to. room() is the rectangle no control is on (x, y, width, height), for the scene to draw in. Both are in Laying out a panel.
theme sets the colours, and in JavaScript over(x, y) says whether a control is at a point. They are in Layout and touch.
More controls
There are more, each on a page of its own kind. They are made and laid out like the ones above, and take the same options.
For any program
| JavaScript | Python | What it is |
|---|---|---|
number(label, min, max, start), stepper(…) | the same | A number box with − and +, which can be typed into |
textBox(label, text) | text_box(label, text) | One line of text to type |
readout(label, () => value) | readout(label, lambda: value) | Shows a value or a message, and takes no hand |
checkbox(label, on) | checkbox(label, on) | A box that is ticked |
choose(label, choices), radio(label, choices) | the same | One of a few, all in sight: side by side, or one under another |
dropdown(label, choices) | dropdown(label, choices) | One of a long list, which opens over the controls |
xyPad(label, target, "across", "up") | xy_pad(…) | A square where one finger sets two numbers |
colourPicker(label, colour), colorPicker(…) | colour_picker(…), color_picker(…) | A patch of colour that opens a picker |
progress(label, value) | progress(label, value) | A bar that fills, from 0 to 1 |
light(label, on), busy(label) | the same | A light, and a ring that goes round while something is happening |
rangeSlider(label, min, max, [low, high]) | range_slider(…) | A slider with two handles |
fader(…) | fader(…) | A slider that stands upright, with the look of a mixing desk's |
For games
| JavaScript | Python | What it is |
|---|---|---|
joystick() | joystick() | A stick for a thumb: stick.x and stick.y, each from -1 to 1 |
dpad() | dpad() | A pad of arrows: pad.left, pad.right, pad.up, pad.down |
actionButton("A") | action_button("A") | A round button for a thumb |
For music
| JavaScript | Python | What it is |
|---|---|---|
envelope(label, target) | envelope(label, target) | The shape of a note as a graph whose corners you drag |
stepGrid(label, steps, rows) | step_grid(…) | A grid of steps, each on or off, a row for each sound |
pads(label, names, target) | pads(label, names, target) | Pads to hit, several at once |
pitchWheel(…), modWheel(…), wheel(…) | pitch_wheel(…), mod_wheel(…), wheel(…) | A wheel that rolls back, and ones that stay |
tranceGate(label, target) | trance_gate(…) | The editor for a synth's trance gate: the steps that open and shut its sound in time |
arpPattern(label, target) | arp_pattern(…) | The editor for a synth's arpeggio pattern, as a grid of notes |
steps(label, 16) | steps(label, 16) | A lane of steps, for anything |
drumSeq(label, drums, target) | drum_seq(…) | A drum sequencer that plays by itself |
A control for anything
A control can be tied to any object, not only a synth. With nothing else to go on it reads and writes the property you name, so the range is given:
const ball = { radius: 40 }
dial("size", ball, "radius", { min: 5, max: 120 })
function draw() {
background("midnightblue")
circle(width / 2, height / 2, ball.radius, "gold")
}toggle(label, target, "setting") and select(label, target, "setting") tie a switch and a list the same way.