@umicat/phaser-sdk 1.0.19 → 1.0.21

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.
@@ -38,6 +38,15 @@ const WORLD_BOUNDS_ALPHA = 0.7;
38
38
  const CAMERA_VIEWPORT_COLOR = 0x4488ee;
39
39
  const CAMERA_VIEWPORT_ALPHA = 0.9;
40
40
  const CAMERA_VIEWPORT_LINE_WIDTH = 2;
41
+ // HUD edit mode — the PLAYER'S SCREEN frame (full game-intrinsic resolution).
42
+ // Brighter/distinct from the world-camera rect: it's the fixed boundary HUD
43
+ // widgets anchor to (Godot's UI viewport rect), not the movable camera view.
44
+ const HUD_SCREEN_COLOR = 0x5bc0ff;
45
+ // World-origin axes (Godot convention): red = X axis (world y=0), green = Y
46
+ // axis (world x=0). Semi-transparent so they read as reference, not content.
47
+ const AXIS_X_COLOR = 0xff5566;
48
+ const AXIS_Y_COLOR = 0x55dd66;
49
+ const AXIS_ALPHA = 0.5;
41
50
  // FB.10 polish — CSS cursor name per tilemap resize handle. Corner handles
42
51
  // get the diagonal arrows (`nwse-resize` ↖↘ for NW/SE, `nesw-resize` ↗↙ for
43
52
  // NE/SW). Edge handles get the axis arrows (ns / ew). Same conventions as
@@ -345,6 +354,14 @@ export class EditorOverlayScene extends Phaser.Scene {
345
354
  // a tilemap resize handle. Done first so cursor reflects the immediate
346
355
  // visual state regardless of which branch we hit below.
347
356
  this.updateResizeCursor(pointer);
357
+ // Coordinate readout — post the cursor's WORLD position so the host can
358
+ // show it in the ruler corner. Cheap; pointermove is frame-throttled.
359
+ {
360
+ const wc = this.pointerCoords(pointer);
361
+ if (typeof window !== 'undefined' && window.parent) {
362
+ window.parent.postMessage({ type: 'umicat:editor:cursorWorld', x: Math.round(wc.x), y: Math.round(wc.y) }, '*');
363
+ }
364
+ }
348
365
  // P1 infinite canvas — pan in progress: translate screen delta into
349
366
  // world delta via the current zoom, set scroll absolute (relative-mode
350
367
  // would accumulate floating-point drift over many move events).
@@ -1741,6 +1758,20 @@ export class EditorOverlayScene extends Phaser.Scene {
1741
1758
  // layers (or the resize-rebuilt layers don't track post-resize
1742
1759
  // container.x/y changes).
1743
1760
  this.syncTilemapLayersFromContainers();
1761
+ // World coordinate-system axes (Godot-style): red X line through world
1762
+ // y=0, green Y line through world x=0 — so the user can see where the
1763
+ // origin (0,0) is and place entities relative to it. Drawn in world space
1764
+ // (pan/zoom with the view); width counter-scaled by zoom so the lines stay
1765
+ // ~1.5px on screen at any zoom. Drawn first so bounds/selection paint over.
1766
+ {
1767
+ const z = this.cameras.main?.zoom || 1;
1768
+ const w = 1.5 / z;
1769
+ const EXT = 100000;
1770
+ this.graphics.lineStyle(w, AXIS_X_COLOR, AXIS_ALPHA);
1771
+ this.graphics.lineBetween(-EXT, 0, EXT, 0);
1772
+ this.graphics.lineStyle(w, AXIS_Y_COLOR, AXIS_ALPHA);
1773
+ this.graphics.lineBetween(0, -EXT, 0, EXT);
1774
+ }
1744
1775
  if (this.worldBounds) {
1745
1776
  // World bounds outline (the visible game frame). Outside-fill grey
1746
1777
  // strips moved to a separate Graphics in the WORLD scene at very
@@ -1774,10 +1805,28 @@ export class EditorOverlayScene extends Phaser.Scene {
1774
1805
  const snap = this.game['__unboxyEditorScaleSnapshot'];
1775
1806
  const intrinsicW = snap?.gameWidth ?? this.game.scale.width;
1776
1807
  const intrinsicH = snap?.gameHeight ?? this.game.scale.height;
1777
- const camW = intrinsicW / worldSceneCam.zoom;
1778
- const camH = intrinsicH / worldSceneCam.zoom;
1779
- this.graphics.lineStyle(CAMERA_VIEWPORT_LINE_WIDTH, CAMERA_VIEWPORT_COLOR, CAMERA_VIEWPORT_ALPHA);
1780
- this.graphics.strokeRect(camX, camY, camW, camH);
1808
+ if (getEditorMode(this.game) === 'hud') {
1809
+ // HUD mode draw the PLAYER'S SCREEN frame at FULL intrinsic size
1810
+ // (1280×720), NOT intrinsic/zoom. HUD widgets are screen-anchored:
1811
+ // `syncHudCameraToEditorCam` maps HUD-intrinsic (0..1280, 0..720) onto
1812
+ // the full-intrinsic span at (gameCam.scroll). The world-camera zoom
1813
+ // shrinks how much WORLD fits, NOT the screen — so drawing the frame at
1814
+ // intrinsic/zoom (the world-camera viewport, as world mode does) made
1815
+ // the frame 3× smaller than the HUD, and widgets sprawled OUTSIDE it
1816
+ // (the "I can't tell where to place HUD" bug). At full intrinsic the
1817
+ // frame is exactly the HUD's bounds → a stable boundary to anchor to.
1818
+ this.graphics.lineStyle(CAMERA_VIEWPORT_LINE_WIDTH + 1, HUD_SCREEN_COLOR, 1);
1819
+ this.graphics.strokeRect(camX, camY, intrinsicW, intrinsicH);
1820
+ }
1821
+ else {
1822
+ // World mode → the camera viewport rect: where the runtime camera
1823
+ // looks + how much it sees (intrinsic/zoom). Small inside a larger
1824
+ // world for farming/RPG; coincides with world bounds for Tetris etc.
1825
+ const camW = intrinsicW / worldSceneCam.zoom;
1826
+ const camH = intrinsicH / worldSceneCam.zoom;
1827
+ this.graphics.lineStyle(CAMERA_VIEWPORT_LINE_WIDTH, CAMERA_VIEWPORT_COLOR, CAMERA_VIEWPORT_ALPHA);
1828
+ this.graphics.strokeRect(camX, camY, camW, camH);
1829
+ }
1781
1830
  }
1782
1831
  const selectedId = getSelection(this.game);
1783
1832
  if (selectedId) {
@@ -867,7 +867,18 @@ export interface EditorTilemapTilePickedMessage {
867
867
  layerId: string;
868
868
  tileIndex: number | null;
869
869
  }
870
- export type EditorSdkToHostMessage = EditorSceneLoadedMessage | EditorSelectionPickedMessage | EditorDragEndMessage | EditorEntityResizedMessage | EditorShortcutMessage | EditorSelectionRectMessage | EditorRulesLoadedMessage | EditorCameraStateMessage | EditorTilemapEditedMessage | EditorTilemapTilePickedMessage;
870
+ /**
871
+ * Cursor world position (editor coordinate readout). Posted on pointer-move
872
+ * while editing so the host can show the cursor's WORLD (x, y) — e.g. in the
873
+ * corner of the rulers. Integers (rounded). Cheap; pointermove is
874
+ * frame-throttled by the browser.
875
+ */
876
+ export interface EditorCursorWorldMessage {
877
+ type: 'umicat:editor:cursorWorld';
878
+ x: number;
879
+ y: number;
880
+ }
881
+ export type EditorSdkToHostMessage = EditorSceneLoadedMessage | EditorSelectionPickedMessage | EditorDragEndMessage | EditorEntityResizedMessage | EditorShortcutMessage | EditorSelectionRectMessage | EditorRulesLoadedMessage | EditorCameraStateMessage | EditorCursorWorldMessage | EditorTilemapEditedMessage | EditorTilemapTilePickedMessage;
871
882
  export type RpcMethod = 'saves.get' | 'saves.set' | 'saves.delete' | 'saves.list' | 'gameData.get' | 'gameData.set' | 'gameData.delete' | 'gameData.list' | 'realtime.getToken' | 'ai.act';
872
883
  export interface SavesGetParams {
873
884
  key: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umicat/phaser-sdk",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "Umicat Phaser 3 SDK — game infrastructure for the Umicat platform",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",