comparison infinite_canvas/README.md @ 276:b55c22cff335

Add interactive infinite canvas prototype
author MrJuneJune <me@mrjunejune.com>
date Mon, 17 Aug 2026 16:57:56 -0700
parents
children 8d560f50ed4c
comparison
equal deleted inserted replaced
274:c9be578316a6 276:b55c22cff335
1 # Infinite Canvas
2
3 Native and WebAssembly Raylib 6 prototype for a world-space, immediate-mode
4 infinite canvas.
5
6 ## Build and run
7
8 ```bash
9 # Native development build with Raygui controls
10 bazel run //infinite_canvas:dev
11
12 # Start directly in the ten-browser stress scene
13 INFINITE_CANVAS_BROWSER_STRESS=1 bazel run //infinite_canvas:dev
14
15 # Native build without development UI
16 bazel run //infinite_canvas:app
17
18 # Browser build and local server
19 bazel build //infinite_canvas:infinite_canvas_wasm
20 bazel run //infinite_canvas:serve
21 ```
22
23 Open `http://127.0.0.1:4343/index.html` after starting the server. Pass a
24 different port as an argument only when needed.
25
26 The native development target opens at 1920x1200 and starts with a gallery
27 layout containing one non-overlapping example of every entity type.
28
29 Theme mode defaults to `auto`, which follows the OS light/dark preference at
30 startup. Rendering consumes a shared semantic `Canvas_Theme` palette for the
31 canvas, developer controls, and camera-pinned notifications. Until the planned
32 config file lands, `INFINITE_CANVAS_THEME=light|dark|auto` provides an explicit
33 override. The developer panel also includes a live light/dark mode toggle.
34
35 ## Controls
36
37 - Middle-mouse drag, or Space + left-mouse drag: pan
38 - Mouse wheel: zoom around the cursor
39 - WASD or arrow keys: pan (disabled while a text area has keyboard focus)
40 - Left-mouse drag on an entity: select and move it
41 - `P`: pin or unpin the selected entity in screen space so it remains visible
42 while the camera pans and zooms; pinned entities show a blue pin badge
43 - Development toolbar: spawn/clear entities, reset the camera, or restore the
44 deterministic demo scene
45 - `View camera context`: open a live, scrollable snapshot of entities
46 intersecting the camera viewport and their current semantic values
47 - `10 browser stress scene`: lay out ten compact independent browser views for
48 performance testing
49 - `White`/`Grid`: toggle the optional grid; the default canvas is pure white
50
51 Canvas primitives include shapes, lines, text, buttons, editable text areas,
52 dropdowns, accordions, cards, calendars, switches, tables, notifications,
53 scrollable areas, images, and web content. Accordions
54 expand with eased height, chevron, divider, and content transitions; cards
55 toggle emphasis, calendars select dates, and switches animate their track color
56 and thumb position when toggled. The default browser build embeds
57 `https://mrjunejune.com` in a camera-tracked iframe. Native builds open
58 `https://www.google.com` in a CEF off-screen browser whose pixel buffer is
59 uploaded into a Raylib texture. It remains inside the canvas and participates
60 in pan, zoom, clipping, and entity dragging on Windows, macOS, and Linux. Web
61 views have no simulated browser toolbar: drag their narrow outer edge to move
62 them and drag the bottom-right handle to resize them. Multiple web entities have independent
63 browser instances, URLs, focus, input, and rendering. Browser resources are
64 assigned only to visible entities, off-screen views are suspended, and the
65 native CEF pool supports up to twelve live browsers. Small background views
66 render at a reduced frame rate, larger views receive a moderate frame budget,
67 and the focused view runs at 30 FPS so scenes with ten compact browsers remain
68 responsive without giving every page the maximum rendering budget. Native
69 browser viewport and texture resolution follow the displayed view size in
70 64-pixel buckets, capped at 1280x800, so resized views become sharper without
71 reallocating continuously during a drag.
72
73 Tables support row selection, and notifications behave as bottom-right toast
74 cards: multiple toasts overlap compactly, fan into a spaced stack on hover,
75 and slide/fade away from either Undo or close. Position, size, stack expansion,
76 and dismissal all use eased frame-rate-independent transitions. Scrollable areas consume the
77 mouse wheel without zooming the camera. Image
78 entities render HTTPS URLs or native filesystem paths through CEF; browser
79 builds render URLs or paths available in the Emscripten filesystem. Override
80 the demo image in native development with
81 `INFINITE_CANVAS_IMAGE_SOURCE=/path/to/image.png`.
82
83 The first native build downloads the platform CEF 151 minimal distribution.
84 Linux stages its runtime once under
85 `~/.cache/zenbu/infinite-canvas/cef-151`; application state and the RGBA paint
86 buffer remain owned by the Dowa arena, while CEF owns its browser internals.
87
88 Buttons animate on hover/press and toggle when clicked. Dropdowns open a real
89 option menu with hover and selection states. Selected text areas accept typing,
90 Enter, and Backspace. Dragging still moves every primitive.
91
92 Camera context is derived from the visible world rather than a hidden
93 conversation store. Panning entities outside the viewport removes them;
94 zooming out includes and concatenates newly visible entities. Each entry
95 contains identity, type, placement, pin state, and type-specific state such as
96 text content, dropdown selection, switch value, selected calendar date or table
97 row, scroll position, image source, and browser URL. The current text format is
98 intentionally provisional so it can later be replaced by the final API
99 contract.
100
101 The prototype uses the Inter variable font under the SIL Open Font License.
102
103 ## Memory ownership
104
105 The application creates one Dowa arena. Application state and the fixed-capacity
106 entity array are arena-owned, there are no per-frame first-party allocations,
107 and the arena is released once during native shutdown. Browser lifetime memory
108 is reclaimed with the WebAssembly runtime when the page closes.