diff --git a/docs/editor.md b/docs/editor.md index 16a7908..ef3e78f 100644 --- a/docs/editor.md +++ b/docs/editor.md @@ -2,13 +2,15 @@ The `/simulator` page uses CodeMirror for editing and a locally hosted MicroPython WASM worker for simulation. It loads the saved project on startup and runs it automatically. With Auto-run enabled, source changes restart the simulation after a 650 ms pause in typing. Stop disables automatic simulation; Run, F5, or Command/Ctrl+Enter runs the current project manually. +The page shows a browser-only guide above the workspace and a physical-badge guide above the connection tools. Run and Auto-run never write to a connected badge; Upload or Install sends changes explicitly. The guides stay visible without expanding a help panel. Full screen hides the setup text to preserve editing space while keeping the connection and upload tools available. + Projects contain an `__init__.py` entry point, companion Python and text files, and binary assets. The file sidebar lets users switch between files, edit text, preview images, and add files. Each simulation stages the complete project in the virtual filesystem, sets its working directory and import path, and executes the entry point using its actual filename. A fresh worker terminates the previous program and resets its virtual state. The display receives RGBA framebuffer messages. Pointer and keyboard controls release held buttons when focus changes, and execution pauses in hidden tabs. The Apps collection uses the same installable-app selection rules as `/apps`. `public/editor-apps/catalog.json` records the bundled public `badger/home` revision and lists every project file. Run `npm run sync:editor-apps` to refresh these apps, including modules and assets. The sync also bundles the `menu` launcher as the catalog's `launcher` entry; it is not listed as an editable app. ## About page simulator -On wide screens, the working badge sits beside the hardware specifications. Narrow screens put the badge first. `src/lib/badge-controls.ts` supplies the approved control names and SVG icons to both the About page buttons and `badge-control-symbols.astro`. The shared 3D view draws these same SVGs beside the five physical buttons and the existing Home touchpad; clicking a symbol uses its existing input bit. Both model hosts include the SVG source component, so the editor's 3D model gets the same markings without changing its separate page controls. No case-model rebuild is required. +On wide screens, the working badge sits beside the hardware specifications. Narrow screens put the badge first. `src/lib/badge-controls.ts` supplies the approved control names and SVG icons to `badge-controls.astro` and `badge-control-symbols.astro`. Both About and the Developer Simulator use the same 52-pixel page buttons, 24-pixel icons, and responsive control groups. The shared 3D view draws these same SVGs beside the five physical buttons and the existing Home touchpad; clicking a symbol uses its existing input bit. Both model hosts include the SVG source component. No case-model rebuild is required. `/about-badge/` boots the Mona OS 4.0 menu in the same worker and renders it on the editor's 3D badge model (`initBadgeModel`). Zooming moves the orbit target toward the badge screen as the camera closes in, and back to the model centre when zoomed out. `npm run sync:editor-apps` bundles the menu from `badger/home` `badge/apps/menu` as the catalog `launcher`. Each device `.mpy` module is replaced by its `src/.py` source, because the simulator cannot load `.mpy` files. `launcher.stock` lists the stock apps, taken from the menu's `anim/.bin` icons. The page stages only the menu at `/system/apps/menu` and the stock apps at `/system/apps/`. `src/lib/badge-firmware-compat.ts` registers stand-ins for firmware-frozen modules that are missing from the vendored runtime (`aye_arr` and `badgeware.ir`) in `sys.modules`. `public/simulator/filesystem/sparkle.py` replaces the firmware's Sparkle supervisor: `request_local_show()` wraps the next `run` call to draw the local show's bouncing Invertocat and case lights, with the Bluetooth mesh shimmed out. Three SELECT presses or the 10-minute timeout end the show and call `machine.reset()`. It also patches newer firmware APIs: `display.set_async`, `machine.reset_cause`, and the three-argument `missing_details.show`. Both this page and editor simulations use it; no extra files are staged. IR does nothing in the simulator. A Python launcher in `src/lib/badge-os-simulator.ts` replicates `badge/main.py`: it runs the menu, launches the selected app, and returns to the menu when HOME is pressed or the app calls `reset()` or fails. This loop is needed because `machine.reset()` and pin IRQs are inert in the simulator. The page shows the badge photo until the 3D model has loaded and the first frame renders. If the browser lacks module workers, WebAssembly, WebGL, or `ImageData`, or the simulator or model errors or times out, the worker stops and the photo remains. The Examples collection includes all 36 examples from the simulator's categorized manifest at revision `eb3b3fbf27e6e61635aef5de11ab17e6303e8c20`. `public/editor-examples/` includes their original source, manifest categories and descriptions, required images and fonts, and MIT notice. Run `npm run sync:editor-examples` to restore them from that pinned revision. Update `simulatorRevision` in `scripts/editor-example-source.mjs` only when updating the bundled runtime and its provenance notices together. Opening an example creates an editable `example-` app with an `__init__.py` entry point. References to bundled `/system/assets/` files become app-local asset paths, so first installs include those dependencies and avoid collisions with existing badge app names. diff --git a/src/components/badge-controls.astro b/src/components/badge-controls.astro new file mode 100644 index 0000000..50023ec --- /dev/null +++ b/src/components/badge-controls.astro @@ -0,0 +1,30 @@ +--- +import { badgeControls } from '@/lib/badge-controls' + +interface Props { + disabled?: boolean +} + +const { disabled = false } = Astro.props +const groups = [badgeControls.slice(0, 3), badgeControls.slice(3)] +--- + +
+ {groups.map(group => ( +
+ {group.map(({ icon: Icon, name, bit }) => ( + + ))} +
+ ))} +
+ + diff --git a/src/components/badge-os-simulator.astro b/src/components/badge-os-simulator.astro index 0c86e76..e8db306 100644 --- a/src/components/badge-os-simulator.astro +++ b/src/components/badge-os-simulator.astro @@ -1,11 +1,8 @@ --- import { Maximize, Minus, Plus, RotateCw, ScanSearch } from 'lucide-react' import BadgeControlSymbols from '@/components/badge-control-symbols.astro' +import BadgeControls from '@/components/badge-controls.astro' import BadgeImage from '@/components/badge-image.astro' -import { badgeControls } from '@/lib/badge-controls' - -const badgeButtons = badgeControls.slice(0, 3) -const sideButtons = badgeControls.slice(3) ---
@@ -35,21 +32,8 @@ const sideButtons = badgeControls.slice(3)
-
-
- {badgeButtons.map(({ icon: Icon, name, bit }) => ( - - ))} -
-
- {sideButtons.map(({ icon: Icon, name, bit }) => ( - - ))} -
+
+
Use the controls above, or use the arrow keys to move, Enter to select, and Esc for Home. Drag the badge to rotate it; scroll or use +/− to zoom; use Rotate to flip it; device tilt controls motion. MonaOS 4.0 and stock apps run in the browser. HTTP requests depend on CORS, and socket apps such as Camera and Copilot require a physical badge. @@ -81,7 +65,6 @@ const sideButtons = badgeControls.slice(3) .badge-os-key:disabled { opacity: 0.4; } .badge-os-key:focus-visible { outline: 2px solid hsl(var(--primary)); outline-offset: 2px; } .badge-os-key[data-pressed='true'] { color: hsl(var(--primary)); border-color: hsl(var(--primary)); background: hsl(var(--primary) / 0.1); transform: translateY(1px); box-shadow: inset 0 1px 3px rgb(0 0 0 / 0.6); } - .badge-os-control { display: grid; width: 3.25rem; height: 3.25rem; place-items: center; } .badge-os-tool { display: inline-flex; width: auto; align-items: center; gap: 0.5rem; padding: 0 0.75rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.12em; } .badge-os-tool[aria-pressed='true'] { color: hsl(var(--primary)); border-color: hsl(var(--primary) / 0.6); } @media (max-width: 480px) { .badge-os-tool { padding: 0 0.5rem; letter-spacing: 0.08em; } } diff --git a/src/pages/simulator.astro b/src/pages/simulator.astro index 817e5de..988f246 100644 --- a/src/pages/simulator.astro +++ b/src/pages/simulator.astro @@ -1,6 +1,7 @@ --- import Layout from '@/layouts/Layout.astro' import BadgeControlSymbols from '@/components/badge-control-symbols.astro' +import BadgeControls from '@/components/badge-controls.astro' import { Code2, Play, Square, Upload, Download, FolderOpen, Terminal, Cpu, Usb, RefreshCw, ArrowRight, Undo2, Redo2, Grid2X2, Maximize, Minimize, X, Search, Trash2, Plus, RotateCw } from 'lucide-react' --- @@ -8,6 +9,11 @@ import { Code2, Play, Square, Upload, Download, FolderOpen, Terminal, Cpu, Usb,

Developer Simulator

+
+

Use the browser

+

No badge is needed. Select Apps or Examples, or select New app. Edit the code, then select Run to test it in the browser. With Auto-run selected, the preview updates as you edit. Run does not change files on a connected badge.

+
+
@@ -75,9 +81,8 @@ import { Code2, Play, Square, Upload, Download, FolderOpen, Terminal, Cpu, Usb,
Your code starts here.

Loading 3D view… You can use the simulator now.

-
-
{[['A',16],['B',8],['C',4]].map(([label,bit]) => )}
-
{[['↑',2],['↓',1],['⌂',32]].map(([label,bit]) => )}
+
+
Drag to rotate · Scroll to zoomModel source ↗
@@ -86,7 +91,7 @@ import { Code2, Play, Square, Upload, Download, FolderOpen, Terminal, Cpu, Usb, {[['←',256],['↑',2048],['↓',4096],['→',512],['Select',1024],['Back',8192]].map(([label,bit]) => )}
-

Badge: arrow keys, Space or Enter to select, Escape for Home. Gamepad: WASD to move, J to select, K to go back, U for Menu. Keyboard controls work while the simulator is focused. In full screen, Escape exits full screen; use the ⌂ button for Home.

+

Badge: arrow keys, Space or Enter to select, Escape for Home. Gamepad: WASD to move, J to select, K to go back, U for Menu. Keyboard controls work while the simulator is focused. In full screen, Escape exits full screen; use the Home button for Home.

@@ -106,6 +111,16 @@ import { Code2, Play, Square, Upload, Download, FolderOpen, Terminal, Cpu, Usb,

Edit apps on your badge

No badge connected
+
+

Use desktop Chrome or Edge.

+
    +
  1. Connect the badge to your computer with a USB data cable. Quickly press RESET twice. Wait for USB Disk Mode on the screen and the BADGER drive on your computer.
  2. +
  3. Select Connect badge. Choose the BADGER drive itself and allow access.
  4. +
  5. To edit an installed app, select Choose badge app. To install your current project, leave it open in the editor.
  6. +
  7. Edit the code, then select Upload or Install. Wait for confirmation.
  8. +
  9. Select Disconnect, then eject BADGER from your computer. Wait for the drive to disappear before unplugging. If the badge does not restart on its own, press RESET. Open the app on the badge to test it.
  10. +
+
@@ -121,10 +136,6 @@ import { Code2, Play, Square, Upload, Download, FolderOpen, Terminal, Cpu, Usb,
-
- USB setup -

Connect over USB, double tap the reset button to open disk mode, then choose the BADGER volume with Connect badge. Select an app to edit its files.

-
@@ -215,6 +226,7 @@ import { Code2, Play, Square, Upload, Download, FolderOpen, Terminal, Cpu, Usb, .fullscreen-exit { display: none; } #badge-editor[data-fullscreen='true'] { position: fixed; inset: 0; z-index: 100; display: flex; flex-direction: column; height: 100dvh; width: 100%; max-width: none; margin: 0; border: 0; border-radius: 0; box-shadow: none; background: hsl(var(--background)); } #badge-editor[data-fullscreen='true'] #badge-connection { flex-shrink: 0; margin: 0 0 0.75rem; border: 0; border-radius: 0; box-shadow: none; } + #badge-editor[data-fullscreen='true'] #usb-help { display: none; } #badge-editor[data-fullscreen='true'] #editor-workspace { display: flex; flex-direction: column; flex: 1; min-height: 0; border: 0; border-radius: 0; box-shadow: none; } #badge-editor[data-fullscreen='true'] .editor-toolbar { flex-shrink: 0; } #badge-editor[data-fullscreen='true'] .editor-split { flex: 1; min-height: 0; grid-template-rows: minmax(0, 1fr) minmax(0, 1fr); }