@unboxy/phaser-sdk 0.2.18 → 0.2.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SDK-GUIDE.md +1 -0
- package/dist/editor/EditorBridge.js +37 -7
- package/package.json +1 -1
package/SDK-GUIDE.md
CHANGED
|
@@ -638,6 +638,7 @@ The `scene-data-architecture` agent skill has the full guidance. The `scene-data
|
|
|
638
638
|
|
|
639
639
|
## Changelog
|
|
640
640
|
|
|
641
|
+
- **0.2.19** — fix: editor `enter` arriving while BootScene is still preloading (the post-flush iframe-rebuild path) had nothing to pause, so the world scene resumed running freely once it started up. Now the bridge re-attempts the pause + scene snapshot for ~3 seconds after enter, catching the scene as it transitions from BootScene → GameScene. Snapshot is also re-posted once a scene file lands in cache. Surfaced when slice-2's auto-flush rebuilt the iframe and the user found the sprite started moving again post-save (2026-05-07).
|
|
641
642
|
- **0.2.18** — added editor bridge (visual editor slice 2). Replaces the slice-1 `unboxy:setEditMode` message with a full editor protocol: `unboxy:editor:enter`/`:exit` (toggles edit mode + launches the overlay scene), `:applyEdit` (mutates a live entity from the host), `:setSelection` (host pushes selection), `:panZoom` (editor camera control), plus SDK→host `:sceneLoaded` (initial snapshot), `:pickEntity` (pointer-down selection), `:dragEnd` (entity dragged to new position). New module `src/editor/` with `EditorOverlayScene` (high-depth Phaser.Scene drawing selection rect + world bounds, capturing pointer events) and `EditorBridge` (postMessage handler + applyEdit logic). New exports: `setupEditorBridge`, `EditorOverlayScene`, `EDITOR_OVERLAY_KEY`, plus all editor protocol types. `setupEditorModeListener` is preserved as a thin wrapper that delegates to the bridge so existing `createUnboxyGame` wiring continues to work. Pairs with home-ui's new Hierarchy + Inspector panels and `useEditorDraft` hook.
|
|
642
643
|
- **0.2.17** — added scene-as-data foundation (visual editor slice 1). New exports: `loadWorldScene`, `preloadManifest`, `getManifest`, `preloadSceneAssets`, `spawnEntity`, `EntityRegistry`, `attachEntityRegistry`, `getEntityRegistry`, `setupEditorModeListener`, `isEditMode`, `parseColor`, `SCHEMA_VERSION`, plus all schema types (`Manifest`, `WorldScene`, `WorldEntity`, `Transform`, `AssetRecord`, etc.). New games that ship with `public/scenes/manifest.json` load entities + camera config from JSON; `GameScene.ts` becomes a generic loader that calls `await loadWorldScene(this, sceneId)`. `createUnboxyGame` now also wires `setupEditorModeListener` so the host (home-ui) can pause active scenes via `postMessage({ type: 'unboxy:setEditMode', enabled: boolean })`. Purely additive — existing scene-as-code games are unaffected. Migration to scene-as-data is opt-in via the `scene-data-migration` agent skill.
|
|
643
644
|
- **0.2.16** — added orientation presets. `createUnboxyGame` now accepts an `orientation: 'portrait' | 'landscape'` option as an alternative to explicit `width`/`height` (TS union — pass one or the other). New exports: `Orientation` type and `ORIENTATION_DIMENSIONS` map (`landscape: 1280×720`, `portrait: 720×1280`). Lets games declare orientation once and have a single source of truth for canvas dimensions.
|
|
@@ -60,6 +60,36 @@ function enterEdit(game) {
|
|
|
60
60
|
if (getEditorState(game).active)
|
|
61
61
|
return;
|
|
62
62
|
setEditorActive(game, true);
|
|
63
|
+
pauseActiveNonEditor(game);
|
|
64
|
+
// Launch the overlay AFTER pausing world scenes so it sits on top in render
|
|
65
|
+
// order (Phaser renders scenes in the order they were started).
|
|
66
|
+
const overlayInit = buildOverlayInit(game);
|
|
67
|
+
if (!game.scene.isActive(EDITOR_OVERLAY_KEY)) {
|
|
68
|
+
game.scene.run(EDITOR_OVERLAY_KEY, overlayInit);
|
|
69
|
+
}
|
|
70
|
+
// Send the initial scene snapshot so home-ui can populate Hierarchy /
|
|
71
|
+
// Inspector without a separate getScene round-trip.
|
|
72
|
+
postSceneSnapshot(game);
|
|
73
|
+
// Race-window catch: when home-ui sends `enter` right after iframe load
|
|
74
|
+
// (which is exactly the auto-flush rebuild path), BootScene may still be
|
|
75
|
+
// in preload / GameScene may not have started, so the synchronous pause
|
|
76
|
+
// above had nothing to pause and the snapshot found no scene file in
|
|
77
|
+
// cache yet. Re-attempt for ~3 seconds. Each attempt is cheap and stops
|
|
78
|
+
// automatically once the user exits edit mode.
|
|
79
|
+
let attempts = 0;
|
|
80
|
+
const reattempt = () => {
|
|
81
|
+
if (!getEditorState(game).active)
|
|
82
|
+
return;
|
|
83
|
+
pauseActiveNonEditor(game);
|
|
84
|
+
if (!hasPostedSnapshot(game))
|
|
85
|
+
postSceneSnapshot(game);
|
|
86
|
+
attempts += 1;
|
|
87
|
+
if (attempts < 30)
|
|
88
|
+
setTimeout(reattempt, 100);
|
|
89
|
+
};
|
|
90
|
+
setTimeout(reattempt, 100);
|
|
91
|
+
}
|
|
92
|
+
function pauseActiveNonEditor(game) {
|
|
63
93
|
for (const scene of game.scene.getScenes(true)) {
|
|
64
94
|
const key = scene.scene.key;
|
|
65
95
|
if (BOOT_SCENE_KEYS.has(key))
|
|
@@ -69,19 +99,14 @@ function enterEdit(game) {
|
|
|
69
99
|
if (scene.scene.isActive())
|
|
70
100
|
scene.scene.pause();
|
|
71
101
|
}
|
|
72
|
-
// Launch the overlay AFTER pausing world scenes so it sits on top in render
|
|
73
|
-
// order (Phaser renders scenes in the order they were started).
|
|
74
|
-
const overlayInit = buildOverlayInit(game);
|
|
75
|
-
game.scene.run(EDITOR_OVERLAY_KEY, overlayInit);
|
|
76
|
-
// Send the initial scene snapshot so home-ui can populate Hierarchy /
|
|
77
|
-
// Inspector without a separate getScene round-trip.
|
|
78
|
-
postSceneSnapshot(game);
|
|
79
102
|
}
|
|
80
103
|
function exitEdit(game) {
|
|
81
104
|
if (!getEditorState(game).active)
|
|
82
105
|
return;
|
|
83
106
|
setEditorActive(game, false);
|
|
84
107
|
setSelection(game, null);
|
|
108
|
+
// Allow next enter to re-post the snapshot (scene file may have changed).
|
|
109
|
+
delete game[SNAPSHOT_POSTED_FLAG];
|
|
85
110
|
if (game.scene.isActive(EDITOR_OVERLAY_KEY)) {
|
|
86
111
|
game.scene.stop(EDITOR_OVERLAY_KEY);
|
|
87
112
|
}
|
|
@@ -116,6 +141,7 @@ function buildOverlayInit(game) {
|
|
|
116
141
|
};
|
|
117
142
|
}
|
|
118
143
|
// --- Snapshot -------------------------------------------------------------
|
|
144
|
+
const SNAPSHOT_POSTED_FLAG = '__unboxyEditorSnapshotPostedFor';
|
|
119
145
|
function postSceneSnapshot(game) {
|
|
120
146
|
const sceneFile = readActiveSceneFile(game);
|
|
121
147
|
if (!sceneFile)
|
|
@@ -125,6 +151,10 @@ function postSceneSnapshot(game) {
|
|
|
125
151
|
sceneId: sceneFile.id,
|
|
126
152
|
sceneFile,
|
|
127
153
|
});
|
|
154
|
+
game[SNAPSHOT_POSTED_FLAG] = sceneFile.id;
|
|
155
|
+
}
|
|
156
|
+
function hasPostedSnapshot(game) {
|
|
157
|
+
return !!game[SNAPSHOT_POSTED_FLAG];
|
|
128
158
|
}
|
|
129
159
|
function readActiveSceneFile(game) {
|
|
130
160
|
// The active world scene cached its scene file in Phaser's JSON cache via
|