← all scripts / norns
norns-hud new
no description yet
install
In maiden's REPL (the >> prompt at the bottom of the editor), run:
;install https://github.com/vehka/norns-hudOr add the splines catalog to maiden and install it from the project manager. Restart norns if the script ships a new engine.
readme from vehka/norns-hud
hud
Text and value editors drawn over a norns script's grid.
- Help on hold: hold a grid key a little longer than usual and the grid shows what it does, or a value.
- Popups: feedback without a keypress:
SAVED,RANDOMISED,120. - Editors: press the meta key (bottom-right by default), then a key, and that key's editor opens: a stepper (−10 −1 … +1 +10) or a row of choices. Meta blinks on the beat while it waits for the key; it stays lit while an editor is open. Press meta again to close.
While the hud is up the script's own LEDs are dimmed and the rows under it are switched off. Text that fits is centred and still; longer text scrolls. Hold text appears on the side of the grid away from your finger, preferring the top.
The font is 3×5 capitals with proportional widths: about four characters fit
on a 16-wide grid, two on an 8×8. Lowercase is drawn as capitals; ♭, ♯ and
° are included.
Use
Copy lib/hud.lua into your script's lib/ folder, then wrap your grid:
local hud = include('lib/hud')
local g = hud.wrap(grid.connect(), {
describe = function(x, y) -- help text for a held key, or nil
if y == 8 and x == 1 then return 'PLAY' end
end,
editor = function(x, y) -- editor for meta + key, or nil
if y == 8 and x == 15 then return hud.param('clock_tempo') end
if y <= 7 then
return hud.stepper{label = 'VEL', min = 0, max = 100,
get = function() return vel[x] end,
set = function(v) vel[x] = v end}
end
end,
})
g.key = function(x, y, z) ... end -- unchanged
g:led(x, y, level); g:refresh() -- unchanged
g:show('SAVED') -- popup
The wrapped grid works like the original: led, all, refresh, key,
cols, rows, rotation, intensity and the rest. It keeps a copy of what
the script draws so it can dim it and restore it afterwards. While nothing is
shown, calls go straight to the grid. The meta key belongs to the hud: the
script doesn't receive its presses and can't light it.
Editor layout (16×8)
rows 1-5 the value; the editor's label first, until a key is pressed
row 6 blank
row 7 stepper: [-10][-1] ▮▮▮▮▮▮▯▯▯▯▯▯ [+1][+10] (tap the bar to jump)
choice: one key per option, the selected one bright
row 8 the script's grid, dimmed; meta lit
While an editor is open, the hud takes every key: row 7 adjusts, a visible key below opens that key's editor instead, meta closes. Keys held before meta was pressed still send their release to the script.
Editors
hud.stepper{label, get, set, min, max, step=1, big=10, format} |
Numbers. format(v) returns the shown text. |
hud.choice{label, options, get, set, format} |
get() returns an index, set(i) takes one. More options than the grid is wide work as a stepper. |
hud.toggle{label, get, set} |
OFF / ON; get() returns a boolean. |
hud.param(id, {label, step, big}) |
Picks one of the above from the param's type: number and control → stepper, option → choice, toggle binary → toggle. Changes go through params, so PSETs, PMAP and param actions stay in step. For controls, ±1 is one fine step (1% of the range by default). |
Every editor has :delta(d), for an encoder.
Methods
g:show(text, opts) |
Popup. text is a string or a function (re-read every frame). opts.time: seconds, nil (default) = long enough to read once, false = until g:hide(). opts.pos: 'auto' (default), 'middle', 'top', 'bottom', or a row number to keep clear of. |
g:hide() |
Remove the popup. |
g:edit(editor) |
Open an editor without meta, e.g. from K2. |
g:close() |
Close the editor and meta mode. |
g:editing() |
The open editor, or nil. |
g:delta(d) |
Nudge the open editor's value; false if none is open. Handy in enc(). |
g:showing() |
true while the hud draws over the grid. |
g:described(x, y) |
true if the key's help text was shown during its latest press. Check it on release to skip the key's action after a help hold. |
g:set(opts) |
Change options. |
g:cleanup() |
Stop the hud's clocks; call from your script's cleanup(). |
hud.width(text) |
Width of text in grid columns. |
Options
| option | default | |
|---|---|---|
describe |
nil |
function(x, y) → text or nil. Re-read every frame while shown. |
editor |
nil |
function(x, y) → editor or nil, for meta + key. |
meta |
bottom-right | {x, y} for the meta key; false for none. Only active when editor is set, unless given explicitly. |
meta_level |
4 |
Meta brightness while the hud is closed. |
hold |
0.5 |
Seconds before a held key's help appears. |
dim |
0.25 |
Brightness of the script's LEDs under the hud; 0 switches them off. |
separator |
'blank' |
Row between text and grid: 'blank', 'line' or 'none'. |
level |
15 |
Text brightness. |
speed |
10 |
Scroll speed in columns per second. |
pause |
0.6 |
Seconds still before scrolling. |
gap |
6 |
Columns between repeats of looping text. |
popup_time |
1.5 |
Seconds a popup that fits stays up. |
fps |
20 |
Frame rate while the hud is up. |
block_covered |
false |
Ignore presses on keys hidden under hold text. |
font |
3×5 | A custom font: {height = n, fallback = '?', glyphs = {[char] = {row strings}}}. |
All key events reach your g.key while the hud is closed, including after a
help hold. Act on release and check g:described(x, y) if a help hold
shouldn't trigger the key (the demo does this).
Demo
hud.lua is a 16-step sequencer with PolyPerc and a cutoff LFO:
- grid rows 1–7: notes (brightness shows velocity)
- row 8: play, randomise, clear, undo · root, scale, LFO rate, cutoff, release · tempo, meta
- hold a row 8 key: what it is and its value
- meta + a step: that step's velocity; meta + a row 8 param key: edit it
- E2 tempo, E3 root (or the open editor's value), K2 save PSET, K3 play/stop
Tests
lua5.3 tests/test_hud.lua
Runs the library against a fake clock, grid and paramset.
discussion
Like this script? React with 👍 or ❤️ below (needs a GitHub account). Reactions count as likes (♥) on splines, updated daily.