v0.4.0 — preview-mode UX overhaul
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-modeargv flag was wrong (CLI doesn't have it); now wires through theLABELLE_PREVIEWenv var.- Cold
zig buildcan take 30–60s; the 2s connect timeout was firing before the engine even started. Bumped to 60s. - macOS libc
setenvmutations don't propagate toposix_spawn-spawned children — switched to explicitSpawnOptions.environ_mapclone + add. - Added
Preview.sendFrameAccept()so the engine's frame_state transitions out of.offeredandpublishFrame*calls succeed. markCrashedlogs 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→.crashedimmediately 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.Whelpers, ECHILD handling, rotating-buffer helper dedup.
Full Changelog: v0.3.0...v0.4.0