11. Wasm canvases#
In this chapter you run small interactive programs in the Viewer: a Wasm guest that draws on a canvas and takes touch, mouse and keys. mpmux runs it itself, on the desktop and on Android, without a browser and without a web engine. An agent can write one to show you something you can play with: a simulation, a plot you can scrub, a small game.
This is experimental: the API may still change.
Run one#
mpmux-cli media show life.wasm
The guest starts in the Viewer and draws at the display's pace while it animates. Tap or click the canvas to give it the keys; tap the terminal to take them back. At the bottom of the canvas, a small graph shows how long each frame took (min, average and max over the last frames, and how many drawing operations the last one made).
A guest runs only while the Viewer shows it. Showing the same file again starts it anew.
The examples#
contrib/wasm-canvas holds a template and examples. Build them once:
cd contrib/wasm-canvas
cargo build --release --target wasm32-unknown-unknown --examples
Then show the folder's README in the Viewer and tap an example's name:
mpmux-cli media show README.md
media show sends the files a document links to along with it, so the
README works as a launcher. The guest runs in the README's place; Back
returns to the list.
| Example | Shows |
|---|---|
shapes |
every drawing call once: a reference card |
life |
Conway's Game of Life; drag to draw cells |
paint |
finger painting with smoothed strokes |
plot |
three signals scrolling by, with a crosshair |
snake |
the game: arrow keys, WASD or swipes |
stopwatch |
arcs and text; tap to start and stop |
stuck |
a guest that hangs on purpose: the Viewer stops it |
The same works from a page: an HTML file in the Viewer that links to a
.wasm file it carries (<a href="guests/life.wasm">) runs the guest in
the page's place.
Write one#
A guest is a WebAssembly module, written in Rust, Zig, C or WAT. It exports a few functions, and mpmux calls them:
| Export | Called |
|---|---|
frame(time: f64, width: f32, height: f32) -> i32 |
to draw one frame; time is seconds since the start. Return 1 to be called again on the next display frame, 0 to wait for input. |
pointer(kind: i32, x: f32, y: f32) |
optional: 0 down, 1 move, 2 up, in canvas points |
key(code: i32, down: i32) |
optional: a key while the canvas has the keys. Characters come as their code point (letters lower case), the rest as codes in canvas::key (arrows, Enter, Escape, ...). |
It draws by calling mpmux's functions (module mpmux; colors are
0xRRGGBBAA):
| Call | Draws |
|---|---|
clear(rgba) |
fills the canvas |
fill_rect, fill_rounded_rect, fill_circle, line |
shapes |
text(x, y, size, rgba, ptr, len) |
UTF-8 text from the guest's memory |
begin_path, move_to, line_to, quad_to, cubic_to, close_path |
a path |
fill_path(rgba), stroke_path(width, rgba) |
the path, filled or outlined |
log(ptr, len) |
a line in mpmux's log |
The template's src/canvas.rs wraps these for Rust, with helpers for
polygons, arcs, a random number generator and colors. Copy the folder, keep
canvas.rs, and write your own frame and pointer in src/lib.rs.
Limits#
A guest gets nothing but its canvas: no files, no network, no clock but
time. Its module is at most 8 MB and its memory at most 16 MB; a frame
draws at most 50 000 operations.
A frame that takes longer than 2 seconds stops the guest, and the Viewer says so; the rest of mpmux stays responsive, because the guest runs on a thread of its own. To see how long a guest's frames take before you show it:
cargo run --release -p mpmux-wasm-canvas --example measure -- guest.wasm
The runtime is the mpmux-wasm-canvas crate, on Makepad's stitch
interpreter. Its documentation (crates/mpmux-wasm-canvas/src/lib.rs) is
the full API.
For agents#
The mpmux media skill (installed by mpmux-cli agents install) tells an agent when a
guest fits and how to show one. To offer several guests at once, write a
Markdown document that links to them by relative path and show the
document.
Next#
Chapter 12 shows how to plan and share the work with your agent.