@eva/plugin-renderer-tilemap 2.1.0-beta.4 → 2.1.0-beta.6

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/README.md CHANGED
@@ -1,7 +1,100 @@
1
1
 
2
2
  # @eva/plugin-renderer-tilemap
3
3
 
4
+ Eva.js TileMap / TileSet rendering plugin — Godot-style chunked v2 path + Phaser-style v1 path.
5
+
4
6
  More Introduction
5
7
  - [EN](https://eva.js.org)
6
8
  - [中文](https://eva-engine.gitee.io)
7
-
9
+
10
+ ## Behavior contracts
11
+
12
+ ### Tilemap entity is transform-fixed
13
+
14
+ The Tilemap component renders its chunks in a single `Container` mounted under the
15
+ host GameObject's display container. The geometry of chunks is computed once at
16
+ build time from `cellSize`, `mapOrigin`, and the layer's `cellData`. Once built:
17
+
18
+ - **`transform.position`**: respected — moving the host entity translates the
19
+ whole tilemap as expected (PIXI display tree).
20
+ - **`transform.rotation`**: respected — the chunk Container rotates with the host.
21
+ - **`transform.scale`**: respected visually, but chunk geometry itself is not
22
+ recomputed. Cell collision math (e.g. `cullingBoundsHint`) does **not** see
23
+ the host scale.
24
+ - **`transform.size`**: **ignored**. Tilemap chunks are sized from `cellSize`,
25
+ not the host entity size. Resizing the host entity does not resize cells.
26
+
27
+ If you need to resize cells at runtime, update the `cellSize` prop on the
28
+ Tilemap component — the change emits a CHANGE event for which the system
29
+ rebuilds layer chunks. Do not mutate `transform.size` and expect the tilemap
30
+ to reflow.
31
+
32
+ This is intentional. Tilemaps are typically world-fixed terrain; making them
33
+ react to host `transform.size` would require per-frame geometry recomputation,
34
+ which is much more expensive than the current sprite-build path and only
35
+ useful in niche cases (e.g. minimap or auto-fit UI).
36
+
37
+ ### v1 vs v2 paths
38
+
39
+ The system auto-detects path by component props:
40
+
41
+ - `tileset: string` set → v1 path (Phaser-style: single tileset image +
42
+ `layers[].data[][]`).
43
+ - `tilemapRef: string` set → v2 path (Godot-style: external `.tileset.json`
44
+ resource via `RESOURCE_TYPE.TILESET` + chunked `layersV2[].cellData.chunks`).
45
+
46
+ Switching modes on a live entity (e.g. host clears `tileset` and sets
47
+ `tilemapRef`) is handled by `handleChange` with proper teardown of the
48
+ previous mode's containers and animation drivers (see `ensureV1Built` /
49
+ `ensureV2Built`).
50
+
51
+ ### componentObserver watch list
52
+
53
+ The decorator watches `tileset`, `tilemapRef`, and **`layersV2`** with
54
+ `deep: false`. The host must **reassign `component.layersV2 = [...]` with a
55
+ new array reference** for paint-stroke patches to trigger a rebuild —
56
+ mutating the array in place will not fire the observer.
57
+
58
+ ### Hot reload (SSE)
59
+
60
+ When the host PUTs an updated `.tileset.json` to the design server, the
61
+ server emits `tileset.updated` SSE; the host calls `reloadTilesetInRuntime`
62
+ which invalidates the Eva resource cache and toggles `tilemapRef` to force a
63
+ rebuild. See `apps/eva-design/src/app/tileset-hot-reload.ts` (host) +
64
+ `hot-reload.ts:diffTilesetForChunkRebuild` (plugin diff helper).
65
+
66
+ ### Performance probes
67
+
68
+ 20 probe names declared in `probes.ts`. Most are emitted in hot paths (animation
69
+ tick, paint apply, chunk culling, mode-switch failures, animation errors,
70
+ context loss, etc.); the rest are deferred to Cycle 2 (GPU upload, autotile,
71
+ draw calls by atlas, bodies destroyed). Phase B `budgetCoverage` is enforced
72
+ locally via `__tests__/probe-coverage.spec.ts`.
73
+
74
+ ### Animation driver wiring
75
+
76
+ In v2 mode, animated source tiles (with `animation.frames[]`) are registered
77
+ in `record.animatedSpritesByAnimKey` at sprite-build time. The `update()` tick
78
+ walks all `animationDrivers` and applies dirty-frame texture swaps to live
79
+ sprites. In tab-hidden or WebGL-context-lost states, the tick is skipped.
80
+
81
+ ### Physics (stop-gap)
82
+
83
+ ADR-0019 Phase 1 — plugin-matterjs `registerBodySource` integration — is
84
+ deferred. The current path:
85
+
86
+ 1. `physics/tilemap-static-body-host.ts:buildTileMapStaticBodyDefinitions`
87
+ produces `BodyDefinition[]` from a TileSet's `physicsLayers` and a
88
+ chunked cellData snapshot.
89
+ 2. The host (game-side) spawns child GameObjects with `Physics` components
90
+ per definition. The plugin does **not** push bodies into Matter.World
91
+ directly.
92
+ 3. `ADR_0019_NATIVE_REGISTRY_AVAILABLE = false` is a stable flag the host
93
+ can branch on once the matterjs PR lands.
94
+
95
+ ### Mesh rendering path
96
+
97
+ `chunk-mesh.ts:buildChunkMesh` is currently a stub. `ChunkRenderStrategy`
98
+ dispatches dense chunks to the mesh path; the path falls back to sprite
99
+ rendering when `isMeshPathAvailable()` returns false (current default).
100
+ Activation depends on real PIXI Mesh + tile-shader wiring (Cycle 2).