Skip to content

v0.4.0 — preview-mode UX overhaul

Choose a tag to compare

@apotema apotema released this 17 May 02:49
· 60 commits to main since this release

Minor release covering six PRs of Play-in-Editor (preview-mode) work since v0.3.0. The editor's Game View tab is now a stable surface for the running game, with the build-phase progress visible inline and crashes surfaced immediately instead of after a 60s wait.

Highlights

Game View tab (#128 / #129)

The preview viewport is no longer a popup — it's a TabBar tab alongside Scene/Prefab editors. Close it, reopen it from the Build menu, drag it around the docking layout. The render-target redirect (Path A IOSurface ring on macOS) is aware of the tab's resize and rebinds attachments without dropping frames.

Scene picker for Run (#132 / #134)

Build → Run preview now opens a picker showing every scene in the project. Selection is wired through labelle run --scene=<name> so the engine boots into the chosen scene instead of the default. The picker remembers the last selection per project.

Preview spawn fixes (#130, #135)

  • --preview-mode argv flag was wrong (CLI doesn't have it); now wires through the LABELLE_PREVIEW env var.
  • Cold zig build can take 30–60s; the 2s connect timeout was firing before the engine even started. Bumped to 60s.
  • macOS libc setenv mutations don't propagate to posix_spawn-spawned children — switched to explicit SpawnOptions.environ_map clone + add.
  • Added Preview.sendFrameAccept() so the engine's frame_state transitions out of .offered and publishFrame* calls succeed.
  • markCrashed logs the reason + first 512 bytes of captured stderr.

Live stderr tail + early-crash detection (#127, #136 → #138)

  • Compiler Output panel is force-opened on each Run and live-tails the subprocess's stderr. Rotating 16 KiB buffer so the recent tail (where build errors land) is what's visible, not the first 16 KiB of zig progress noise.
  • Non-blocking waitpid(WNOHANG) integration: build/launch failures transition .listening/.connecting → .crashed immediately with the exit code or signal, instead of waiting for the 60s connect-timeout backstop. One final stderr drain on reap surfaces the compile error.

Project version pin preservation (#125 / #126)

project.labelle save no longer overwrites loaded core_version / engine_version / gfx_version / assembler_version with the gui's defaults. External projects pinned to specific upstream versions round-trip cleanly.

Verified

  • zig build test — 197/197.
  • zig build gui-test-build — clean.
  • Live macOS smoke against flying-platform-labelle: game pixels flow into the Game View tab via the IOSurface zero-copy path end-to-end.

Paired downstream

  • labelle-assembler v0.25.0 — window.hideWindow() during preview so closing the standalone window can't kill the subprocess.
  • labelle-engine v1.37.5 — Path A getIOSurfaceAt / signalSlotReady.

Follow-up

  • #139 — review-feedback deferrals: shared cap constant, idiomatic std.posix.W helpers, ECHILD handling, rotating-buffer helper dedup.

Full Changelog: v0.3.0...v0.4.0