@codexo/exojs-tilemap 0.15.3 → 0.16.0
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 +33 -26
- package/dist/esm/ChunkSource.d.ts +33 -0
- package/dist/esm/ChunkSource.d.ts.map +1 -0
- package/dist/esm/ChunkStreamer.d.ts +98 -0
- package/dist/esm/ChunkStreamer.d.ts.map +1 -0
- package/dist/esm/ChunkStreamer.js +201 -0
- package/dist/esm/ChunkStreamer.js.map +1 -0
- package/dist/esm/ImageLayer.d.ts +11 -3
- package/dist/esm/ImageLayer.d.ts.map +1 -0
- package/dist/esm/ImageLayer.js +71 -64
- package/dist/esm/ImageLayer.js.map +1 -1
- package/dist/esm/ImageLayerNode.d.ts +89 -0
- package/dist/esm/ImageLayerNode.d.ts.map +1 -0
- package/dist/esm/ImageLayerNode.js +205 -0
- package/dist/esm/ImageLayerNode.js.map +1 -0
- package/dist/esm/MapObject.d.ts +70 -0
- package/dist/esm/MapObject.d.ts.map +1 -0
- package/dist/esm/MapObject.js +34 -0
- package/dist/esm/MapObject.js.map +1 -0
- package/dist/esm/MapObjectSpawner.d.ts +133 -0
- package/dist/esm/MapObjectSpawner.d.ts.map +1 -0
- package/dist/esm/MapObjectSpawner.js +147 -0
- package/dist/esm/MapObjectSpawner.js.map +1 -0
- package/dist/esm/MapSpawnSession.d.ts +53 -0
- package/dist/esm/MapSpawnSession.d.ts.map +1 -0
- package/dist/esm/MapSpawnSession.js +88 -0
- package/dist/esm/MapSpawnSession.js.map +1 -0
- package/dist/esm/MapWorld.d.ts +134 -0
- package/dist/esm/MapWorld.d.ts.map +1 -0
- package/dist/esm/MapWorld.js +150 -0
- package/dist/esm/MapWorld.js.map +1 -0
- package/dist/esm/MapWorldRuntime.d.ts +182 -0
- package/dist/esm/MapWorldRuntime.d.ts.map +1 -0
- package/dist/esm/MapWorldRuntime.js +261 -0
- package/dist/esm/MapWorldRuntime.js.map +1 -0
- package/dist/esm/ObjectLayer.d.ts +93 -7
- package/dist/esm/ObjectLayer.d.ts.map +1 -0
- package/dist/esm/ObjectLayer.js +184 -167
- package/dist/esm/ObjectLayer.js.map +1 -1
- package/dist/esm/SampledChunkSource.d.ts +43 -0
- package/dist/esm/SampledChunkSource.d.ts.map +1 -0
- package/dist/esm/SampledChunkSource.js +48 -0
- package/dist/esm/SampledChunkSource.js.map +1 -0
- package/dist/esm/TileAnimator.d.ts +12 -2
- package/dist/esm/TileAnimator.d.ts.map +1 -0
- package/dist/esm/TileAnimator.js +154 -165
- package/dist/esm/TileAnimator.js.map +1 -1
- package/dist/esm/TileChunk.d.ts +30 -5
- package/dist/esm/TileChunk.d.ts.map +1 -0
- package/dist/esm/TileChunk.js +190 -188
- package/dist/esm/TileChunk.js.map +1 -1
- package/dist/esm/TileChunkNode.d.ts +18 -3
- package/dist/esm/TileChunkNode.d.ts.map +1 -0
- package/dist/esm/TileChunkNode.js +104 -85
- package/dist/esm/TileChunkNode.js.map +1 -1
- package/dist/esm/TileLayer.d.ts +104 -24
- package/dist/esm/TileLayer.d.ts.map +1 -0
- package/dist/esm/TileLayer.js +511 -469
- package/dist/esm/TileLayer.js.map +1 -1
- package/dist/esm/TileLayerNode.d.ts +52 -11
- package/dist/esm/TileLayerNode.d.ts.map +1 -0
- package/dist/esm/TileLayerNode.js +224 -166
- package/dist/esm/TileLayerNode.js.map +1 -1
- package/dist/esm/TileMap.d.ts +96 -31
- package/dist/esm/TileMap.d.ts.map +1 -0
- package/dist/esm/TileMap.js +401 -357
- package/dist/esm/TileMap.js.map +1 -1
- package/dist/esm/TileMapBand.d.ts +42 -29
- package/dist/esm/TileMapBand.d.ts.map +1 -0
- package/dist/esm/TileMapBand.js +151 -158
- package/dist/esm/TileMapBand.js.map +1 -1
- package/dist/esm/TileMapNode.d.ts +34 -18
- package/dist/esm/TileMapNode.d.ts.map +1 -0
- package/dist/esm/TileMapNode.js +122 -109
- package/dist/esm/TileMapNode.js.map +1 -1
- package/dist/esm/TileMapView.d.ts +108 -47
- package/dist/esm/TileMapView.d.ts.map +1 -0
- package/dist/esm/TileMapView.js +385 -338
- package/dist/esm/TileMapView.js.map +1 -1
- package/dist/esm/TileSet.d.ts +15 -6
- package/dist/esm/TileSet.d.ts.map +1 -0
- package/dist/esm/TileSet.js +161 -181
- package/dist/esm/TileSet.js.map +1 -1
- package/dist/esm/WangSet.d.ts +5 -4
- package/dist/esm/WangSet.d.ts.map +1 -0
- package/dist/esm/WangSet.js +70 -78
- package/dist/esm/WangSet.js.map +1 -1
- package/dist/esm/WorkerSampledChunkSource.d.ts +95 -0
- package/dist/esm/WorkerSampledChunkSource.d.ts.map +1 -0
- package/dist/esm/WorkerSampledChunkSource.js +117 -0
- package/dist/esm/WorkerSampledChunkSource.js.map +1 -0
- package/dist/esm/autoTile.d.ts +10 -5
- package/dist/esm/autoTile.d.ts.map +1 -0
- package/dist/esm/autoTile.js +164 -205
- package/dist/esm/autoTile.js.map +1 -1
- package/dist/esm/chunkGeometry.d.ts +8 -7
- package/dist/esm/chunkGeometry.d.ts.map +1 -0
- package/dist/esm/chunkGeometry.js +83 -94
- package/dist/esm/chunkGeometry.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +26 -15
- package/dist/esm/nodeBounds.d.ts +20 -0
- package/dist/esm/nodeBounds.d.ts.map +1 -0
- package/dist/esm/nodeBounds.js +40 -0
- package/dist/esm/nodeBounds.js.map +1 -0
- package/dist/esm/pixelSnap.d.ts +4 -3
- package/dist/esm/pixelSnap.d.ts.map +1 -0
- package/dist/esm/pixelSnap.js +18 -16
- package/dist/esm/pixelSnap.js.map +1 -1
- package/dist/esm/public.d.ts +23 -3
- package/dist/esm/public.d.ts.map +1 -0
- package/dist/esm/tileCollision.d.ts +190 -0
- package/dist/esm/tileCollision.d.ts.map +1 -0
- package/dist/esm/tileCollision.js +367 -0
- package/dist/esm/tileCollision.js.map +1 -0
- package/dist/esm/tileWord.d.ts +12 -0
- package/dist/esm/tileWord.d.ts.map +1 -0
- package/dist/esm/tileWord.js +16 -0
- package/dist/esm/tileWord.js.map +1 -0
- package/dist/esm/tilemapExtension.d.ts +4 -3
- package/dist/esm/tilemapExtension.d.ts.map +1 -0
- package/dist/esm/tilemapExtension.js +47 -47
- package/dist/esm/tilemapExtension.js.map +1 -1
- package/dist/esm/tilemapSerializers.d.ts +5 -4
- package/dist/esm/tilemapSerializers.d.ts.map +1 -0
- package/dist/esm/tilemapSerializers.js +48 -41
- package/dist/esm/tilemapSerializers.js.map +1 -1
- package/dist/esm/types.d.ts +34 -18
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +111 -120
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/webgl2/WebGl2TileChunkRenderer.d.ts +50 -2
- package/dist/esm/webgl2/WebGl2TileChunkRenderer.d.ts.map +1 -0
- package/dist/esm/webgl2/WebGl2TileChunkRenderer.js +366 -332
- package/dist/esm/webgl2/WebGl2TileChunkRenderer.js.map +1 -1
- package/dist/esm/webgl2/shaders/tile-chunk.frag.js +6 -0
- package/dist/esm/webgl2/shaders/tile-chunk.frag.js.map +1 -0
- package/dist/esm/webgl2/shaders/tile-chunk.vert.js +6 -0
- package/dist/esm/webgl2/shaders/tile-chunk.vert.js.map +1 -0
- package/dist/esm/webgpu/WebGpuTileChunkRenderer.d.ts +70 -4
- package/dist/esm/webgpu/WebGpuTileChunkRenderer.d.ts.map +1 -0
- package/dist/esm/webgpu/WebGpuTileChunkRenderer.js +496 -383
- package/dist/esm/webgpu/WebGpuTileChunkRenderer.js.map +1 -1
- package/dist/esm/webgpu/shaders/tile-chunk.wgsl.js +6 -0
- package/dist/esm/webgpu/shaders/tile-chunk.wgsl.js.map +1 -0
- package/package.json +8 -15
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/register.d.ts +0 -1
- package/dist/esm/register.js +0 -25
- package/dist/esm/register.js.map +0 -1
|
@@ -1,170 +1,228 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { assertPixelSnapMode } from
|
|
3
|
-
import {
|
|
1
|
+
import { TileChunkNode } from "./TileChunkNode.js";
|
|
2
|
+
import { assertPixelSnapMode } from "./pixelSnap.js";
|
|
3
|
+
import { aggregateChildLocalBounds } from "./nodeBounds.js";
|
|
4
|
+
import { PixelSnapMode } from "@codexo/exojs/renderer-sdk";
|
|
5
|
+
import { Container } from "@codexo/exojs";
|
|
4
6
|
|
|
7
|
+
//#region src/TileLayerNode.ts
|
|
5
8
|
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
9
|
+
* A scene node that renders one generic {@link TileLayer} as a
|
|
10
|
+
* {@link Container} of per-chunk {@link TileChunkNode} drawables.
|
|
11
|
+
*
|
|
12
|
+
* Each non-empty loaded chunk becomes one child positioned at its pixel
|
|
13
|
+
* origin, so the engine's existing per-node culling drops individual chunks and
|
|
14
|
+
* the render-plan optimiser batches them by tileset texture. The layer's pixel
|
|
15
|
+
* `offset` is applied to this node's transform; `visible` and `opacity` are
|
|
16
|
+
* read live from the runtime layer on every frame (no rebuild required).
|
|
17
|
+
*
|
|
18
|
+
* A `parallax` factor other than `1` makes this node's rendered position
|
|
19
|
+
* camera-dependent, resolved per frame in {@link _collectContent} by patching
|
|
20
|
+
* the node position against the camera centre, then restoring it - the cull
|
|
21
|
+
* test runs before that patch, so a bounded layer with parallax would be
|
|
22
|
+
* culled at its static base-offset bounds while actually rendering elsewhere.
|
|
23
|
+
* Such a layer therefore opts out of view culling (`cullable = false`), same
|
|
24
|
+
* as an unbounded layer (exactly like {@link import('./ImageLayerNode').ImageLayerNode}).
|
|
25
|
+
*
|
|
26
|
+
* The node references - but never owns - the {@link TileLayer}: destroying it
|
|
27
|
+
* frees its chunk nodes and their cached geometry but leaves the layer, map,
|
|
28
|
+
* and Loader-owned textures intact.
|
|
29
|
+
*
|
|
30
|
+
* Structural changes made via `_adoptChunk`/`_evictChunk` (chunk streaming)
|
|
31
|
+
* are picked up incrementally as they happen, without a full rebuild.
|
|
32
|
+
* {@link TileLayerNode.refresh} remains available for callers that mutate
|
|
33
|
+
* chunk structure by other means (e.g. a bulk edit that bypasses
|
|
34
|
+
* `_adoptChunk`/`_evictChunk`) and need a full resync. In-place tile edits to
|
|
35
|
+
* existing chunks are picked up automatically via chunk revisions.
|
|
36
|
+
*
|
|
37
|
+
* @advanced
|
|
38
|
+
*/
|
|
39
|
+
var TileLayerNode = class extends Container {
|
|
40
|
+
_layer;
|
|
41
|
+
_cullChunks;
|
|
42
|
+
_chunkNodes = [];
|
|
43
|
+
_syncedOpacity = -1;
|
|
44
|
+
_syncedTint = void 0;
|
|
45
|
+
_pixelSnapMode = PixelSnapMode.None;
|
|
46
|
+
_baseOffsetX;
|
|
47
|
+
_baseOffsetY;
|
|
48
|
+
/**
|
|
49
|
+
* Bound once so `TileLayer._addStructuralListener`/`_removeStructuralListener`
|
|
50
|
+
* add and remove the SAME function reference. Incrementally adds/removes
|
|
51
|
+
* the `TileChunkNode` child for exactly the chunk that changed - never
|
|
52
|
+
* triggers a full {@link refresh}, so every other chunk node's
|
|
53
|
+
* revision-cached geometry survives untouched.
|
|
54
|
+
*/
|
|
55
|
+
_onStructuralChange = (event) => {
|
|
56
|
+
const existingIndex = this._chunkNodes.findIndex((n) => n.chunkX === event.cx && n.chunkY === event.cy);
|
|
57
|
+
const existing = this._chunkNodes[existingIndex];
|
|
58
|
+
if (existing) {
|
|
59
|
+
this._chunkNodes.splice(existingIndex, 1);
|
|
60
|
+
this.removeChild(existing);
|
|
61
|
+
existing.destroy();
|
|
62
|
+
}
|
|
63
|
+
if (event.chunk === null || event.chunk.empty) return;
|
|
64
|
+
const node = this._createChunkNode(event.chunk);
|
|
65
|
+
this._chunkNodes.push(node);
|
|
66
|
+
this.addChild(node);
|
|
67
|
+
this._applyTint(node);
|
|
68
|
+
};
|
|
69
|
+
constructor(layer, options) {
|
|
70
|
+
super();
|
|
71
|
+
this._layer = layer;
|
|
72
|
+
this._cullChunks = options?.cullable ?? true;
|
|
73
|
+
this._baseOffsetX = layer.offsetX;
|
|
74
|
+
this._baseOffsetY = layer.offsetY;
|
|
75
|
+
this.setPosition(layer.offsetX, layer.offsetY);
|
|
76
|
+
this._buildChunkNodes();
|
|
77
|
+
if (!this._layer.bounded || layer.parallaxX !== 1 || layer.parallaxY !== 1 || layer.parallaxScale !== 1) this.cullable = false;
|
|
78
|
+
this._layer._addStructuralListener(this._onStructuralChange);
|
|
79
|
+
}
|
|
80
|
+
/** The runtime layer this node renders. */
|
|
81
|
+
get layer() {
|
|
82
|
+
return this._layer;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Render-only pixel-snap mode applied to every chunk node in this layer (and
|
|
86
|
+
* to chunks rebuilt later by {@link refresh}). Each chunk's rendered origin is
|
|
87
|
+
* snapped to the active render target's device-pixel grid; because chunk
|
|
88
|
+
* origins are integer multiples of the integer tile pitch from the same layer
|
|
89
|
+
* origin, the whole grid stays exact and adjacent chunks cannot drift apart.
|
|
90
|
+
*
|
|
91
|
+
* Purely visual: tile data, the layer offset, chunk content revisions, and
|
|
92
|
+
* culling bounds are never changed. `PixelSnapMode.Geometry` and `PixelSnapMode.Position` both resolve
|
|
93
|
+
* to coherent origin snapping for tile chunks (chunk quads are already on the
|
|
94
|
+
* integer pixel grid by construction). Setting the current value is a no-op;
|
|
95
|
+
* an invalid value throws and leaves the prior mode unchanged.
|
|
96
|
+
*
|
|
97
|
+
* @default PixelSnapMode.None
|
|
98
|
+
* @stable
|
|
99
|
+
*/
|
|
100
|
+
get pixelSnapMode() {
|
|
101
|
+
return this._pixelSnapMode;
|
|
102
|
+
}
|
|
103
|
+
set pixelSnapMode(mode) {
|
|
104
|
+
if (mode === this._pixelSnapMode) return;
|
|
105
|
+
assertPixelSnapMode(mode);
|
|
106
|
+
this._pixelSnapMode = mode;
|
|
107
|
+
for (const chunk of this._chunkNodes) chunk.pixelSnapMode = mode;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Rebuild the chunk-node children from the layer's current loaded chunks.
|
|
111
|
+
* Call after structural mutation that creates or empties chunks. In-place
|
|
112
|
+
* tile edits to existing chunks do not need a refresh.
|
|
113
|
+
*/
|
|
114
|
+
refresh() {
|
|
115
|
+
const previous = [...this._chunkNodes];
|
|
116
|
+
this.removeChildren();
|
|
117
|
+
this._chunkNodes.length = 0;
|
|
118
|
+
for (const child of previous) child.destroy();
|
|
119
|
+
this._syncedOpacity = -1;
|
|
120
|
+
this._syncedTint = void 0;
|
|
121
|
+
this._buildChunkNodes();
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
/** The chunk render nodes owned by this layer node, in build order. @internal */
|
|
125
|
+
get chunkNodes() {
|
|
126
|
+
return this._chunkNodes;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Recomputed lazily on read, so it writes `_localBounds` directly rather than
|
|
130
|
+
* going through `_setLocalBounds`: an invalidating write inside a getter
|
|
131
|
+
* would re-dirty the node on every read.
|
|
132
|
+
*/
|
|
133
|
+
getLocalBounds() {
|
|
134
|
+
const bounds = this._localBounds;
|
|
135
|
+
const { pixelHeight, pixelWidth } = this._layer;
|
|
136
|
+
if (pixelWidth !== void 0 && pixelHeight !== void 0) bounds.set(0, 0, pixelWidth, pixelHeight);
|
|
137
|
+
else if (this._chunkNodes.length > 0) aggregateChildLocalBounds(this._chunkNodes, bounds);
|
|
138
|
+
return bounds;
|
|
139
|
+
}
|
|
140
|
+
/** @internal */
|
|
141
|
+
_collectContent(builder) {
|
|
142
|
+
if (!this._layer.visible) return;
|
|
143
|
+
this._syncTint();
|
|
144
|
+
const layer = this._layer;
|
|
145
|
+
const patchesPosition = layer.parallaxX !== 1 || layer.parallaxY !== 1;
|
|
146
|
+
const patchesScale = layer.parallaxScale !== 1;
|
|
147
|
+
if (patchesPosition || patchesScale) {
|
|
148
|
+
const camCenter = builder.view.center;
|
|
149
|
+
const prevX = this.x;
|
|
150
|
+
const prevY = this.y;
|
|
151
|
+
const prevScaleX = this.scale.x;
|
|
152
|
+
const prevScaleY = this.scale.y;
|
|
153
|
+
if (patchesPosition) {
|
|
154
|
+
this.x = this._baseOffsetX + camCenter.x * (1 - layer.parallaxX);
|
|
155
|
+
this.y = this._baseOffsetY + camCenter.y * (1 - layer.parallaxY);
|
|
156
|
+
}
|
|
157
|
+
if (patchesScale) this.setScale(prevScaleX * layer.parallaxScale, prevScaleY * layer.parallaxScale);
|
|
158
|
+
try {
|
|
159
|
+
super._collectContent(builder);
|
|
160
|
+
} finally {
|
|
161
|
+
if (patchesPosition) this.setPosition(prevX, prevY);
|
|
162
|
+
if (patchesScale) this.setScale(prevScaleX, prevScaleY);
|
|
163
|
+
}
|
|
164
|
+
} else super._collectContent(builder);
|
|
165
|
+
}
|
|
166
|
+
destroy() {
|
|
167
|
+
this._layer._removeStructuralListener(this._onStructuralChange);
|
|
168
|
+
const children = [...this._chunkNodes];
|
|
169
|
+
this._chunkNodes.length = 0;
|
|
170
|
+
super.destroy();
|
|
171
|
+
for (const child of children) child.destroy();
|
|
172
|
+
}
|
|
173
|
+
_buildChunkNodes() {
|
|
174
|
+
const layer = this._layer;
|
|
175
|
+
for (const chunk of layer.loadedChunks()) {
|
|
176
|
+
if (chunk.empty) continue;
|
|
177
|
+
const node = this._createChunkNode(chunk);
|
|
178
|
+
this._chunkNodes.push(node);
|
|
179
|
+
this.addChild(node);
|
|
180
|
+
}
|
|
181
|
+
this._syncTint();
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Construct one configured {@link TileChunkNode} for `chunk` - shared by
|
|
185
|
+
* the initial bulk build ({@link _buildChunkNodes}) and the incremental
|
|
186
|
+
* structural-listener handler, so a future constructor argument or
|
|
187
|
+
* per-node setting only needs to be added in one place.
|
|
188
|
+
*/
|
|
189
|
+
_createChunkNode(chunk) {
|
|
190
|
+
const layer = this._layer;
|
|
191
|
+
const node = new TileChunkNode(chunk, layer.tilesets, layer.tileWidth, layer.tileHeight, layer.chunkWidth, layer.chunkHeight);
|
|
192
|
+
node.cullable = this._cullChunks;
|
|
193
|
+
if (this._pixelSnapMode !== PixelSnapMode.None) node.pixelSnapMode = this._pixelSnapMode;
|
|
194
|
+
return node;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Compute and apply this layer's live tint (opacity as alpha, `tintColor`
|
|
198
|
+
* as RGB multiply) to a single chunk node. Used both by {@link _syncTint}'s
|
|
199
|
+
* bulk pass and by the structural-listener handler for a freshly-added
|
|
200
|
+
* node - a node added between two "nothing changed" full syncs must still
|
|
201
|
+
* receive the current tint, which a change-detection-guarded bulk pass
|
|
202
|
+
* alone would skip.
|
|
203
|
+
*/
|
|
204
|
+
_applyTint(node) {
|
|
205
|
+
const tintColor = this._layer.tintColor;
|
|
206
|
+
const r = tintColor === null ? 255 : tintColor >> 16 & 255;
|
|
207
|
+
const g = tintColor === null ? 255 : tintColor >> 8 & 255;
|
|
208
|
+
const b = tintColor === null ? 255 : tintColor & 255;
|
|
209
|
+
node.tint.set(r, g, b, this._layer.opacity);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Propagate the layer's live opacity and tint colour onto every chunk
|
|
213
|
+
* render tint if either changed since the last call. Opacity drives the
|
|
214
|
+
* tint alpha; `tintColor` (`0xRRGGBB`) multiplies the RGB (white = no tint).
|
|
215
|
+
*/
|
|
216
|
+
_syncTint() {
|
|
217
|
+
const opacity = this._layer.opacity;
|
|
218
|
+
const tintColor = this._layer.tintColor;
|
|
219
|
+
if (opacity === this._syncedOpacity && tintColor === this._syncedTint) return;
|
|
220
|
+
for (const child of this._chunkNodes) this._applyTint(child);
|
|
221
|
+
this._syncedOpacity = opacity;
|
|
222
|
+
this._syncedTint = tintColor;
|
|
223
|
+
}
|
|
224
|
+
};
|
|
168
225
|
|
|
226
|
+
//#endregion
|
|
169
227
|
export { TileLayerNode };
|
|
170
|
-
//# sourceMappingURL=TileLayerNode.js.map
|
|
228
|
+
//# sourceMappingURL=TileLayerNode.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TileLayerNode.js","sources":["../../../src/TileLayerNode.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TileLayerNode.js","names":[],"sources":["../../src/TileLayerNode.ts"],"sourcesContent":["import type { ReadonlyRectangle } from '@codexo/exojs';\nimport { Container } from '@codexo/exojs';\nimport { PixelSnapMode, type RenderPlanBuilder } from '@codexo/exojs/renderer-sdk';\n\nimport { aggregateChildLocalBounds } from './nodeBounds';\nimport { assertPixelSnapMode } from './pixelSnap';\nimport type { ReadonlyTileChunk } from './TileChunk';\nimport { TileChunkNode } from './TileChunkNode';\nimport type { ChunkStructuralEvent, TileLayer } from './TileLayer';\n\n/**\n * Options for a {@link TileLayerNode}. All optional; reserved for forward\n * compatibility.\n * @advanced\n */\nexport interface TileLayerNodeOptions {\n /**\n * Whether the layer's chunk nodes participate in per-chunk view culling.\n * Defaults to `true`. Disable only for tiny, always-on-screen layers where\n * the per-chunk bounds test is pure overhead.\n */\n readonly cullable?: boolean;\n}\n\n/**\n * A scene node that renders one generic {@link TileLayer} as a\n * {@link Container} of per-chunk {@link TileChunkNode} drawables.\n *\n * Each non-empty loaded chunk becomes one child positioned at its pixel\n * origin, so the engine's existing per-node culling drops individual chunks and\n * the render-plan optimiser batches them by tileset texture. The layer's pixel\n * `offset` is applied to this node's transform; `visible` and `opacity` are\n * read live from the runtime layer on every frame (no rebuild required).\n *\n * A `parallax` factor other than `1` makes this node's rendered position\n * camera-dependent, resolved per frame in {@link _collectContent} by patching\n * the node position against the camera centre, then restoring it - the cull\n * test runs before that patch, so a bounded layer with parallax would be\n * culled at its static base-offset bounds while actually rendering elsewhere.\n * Such a layer therefore opts out of view culling (`cullable = false`), same\n * as an unbounded layer (exactly like {@link import('./ImageLayerNode').ImageLayerNode}).\n *\n * The node references - but never owns - the {@link TileLayer}: destroying it\n * frees its chunk nodes and their cached geometry but leaves the layer, map,\n * and Loader-owned textures intact.\n *\n * Structural changes made via `_adoptChunk`/`_evictChunk` (chunk streaming)\n * are picked up incrementally as they happen, without a full rebuild.\n * {@link TileLayerNode.refresh} remains available for callers that mutate\n * chunk structure by other means (e.g. a bulk edit that bypasses\n * `_adoptChunk`/`_evictChunk`) and need a full resync. In-place tile edits to\n * existing chunks are picked up automatically via chunk revisions.\n *\n * @advanced\n */\nexport class TileLayerNode extends Container {\n private readonly _layer: TileLayer;\n private readonly _cullChunks: boolean;\n private readonly _chunkNodes: TileChunkNode[] = [];\n private _syncedOpacity = -1;\n private _syncedTint: number | null | undefined = undefined;\n private _pixelSnapMode: PixelSnapMode = PixelSnapMode.None;\n private readonly _baseOffsetX: number;\n private readonly _baseOffsetY: number;\n\n /**\n * Bound once so `TileLayer._addStructuralListener`/`_removeStructuralListener`\n * add and remove the SAME function reference. Incrementally adds/removes\n * the `TileChunkNode` child for exactly the chunk that changed - never\n * triggers a full {@link refresh}, so every other chunk node's\n * revision-cached geometry survives untouched.\n */\n private readonly _onStructuralChange = (event: ChunkStructuralEvent): void => {\n const existingIndex = this._chunkNodes.findIndex(n => n.chunkX === event.cx && n.chunkY === event.cy);\n\n const existing = this._chunkNodes[existingIndex];\n\n if (existing) {\n this._chunkNodes.splice(existingIndex, 1);\n this.removeChild(existing);\n existing.destroy();\n }\n\n if (event.chunk === null || event.chunk.empty) {\n return;\n }\n\n const node = this._createChunkNode(event.chunk);\n\n this._chunkNodes.push(node);\n this.addChild(node);\n this._applyTint(node);\n };\n\n public constructor(layer: TileLayer, options?: TileLayerNodeOptions) {\n super();\n\n this._layer = layer;\n this._cullChunks = options?.cullable ?? true;\n this._baseOffsetX = layer.offsetX;\n this._baseOffsetY = layer.offsetY;\n\n this.setPosition(layer.offsetX, layer.offsetY);\n this._buildChunkNodes();\n\n if (!this._layer.bounded || layer.parallaxX !== 1 || layer.parallaxY !== 1 || layer.parallaxScale !== 1) {\n this.cullable = false;\n }\n\n this._layer._addStructuralListener(this._onStructuralChange);\n }\n\n /** The runtime layer this node renders. */\n public get layer(): TileLayer {\n return this._layer;\n }\n\n /**\n * Render-only pixel-snap mode applied to every chunk node in this layer (and\n * to chunks rebuilt later by {@link refresh}). Each chunk's rendered origin is\n * snapped to the active render target's device-pixel grid; because chunk\n * origins are integer multiples of the integer tile pitch from the same layer\n * origin, the whole grid stays exact and adjacent chunks cannot drift apart.\n *\n * Purely visual: tile data, the layer offset, chunk content revisions, and\n * culling bounds are never changed. `PixelSnapMode.Geometry` and `PixelSnapMode.Position` both resolve\n * to coherent origin snapping for tile chunks (chunk quads are already on the\n * integer pixel grid by construction). Setting the current value is a no-op;\n * an invalid value throws and leaves the prior mode unchanged.\n *\n * @default PixelSnapMode.None\n * @stable\n */\n public get pixelSnapMode(): PixelSnapMode {\n return this._pixelSnapMode;\n }\n\n public set pixelSnapMode(mode: PixelSnapMode) {\n if (mode === this._pixelSnapMode) {\n return;\n }\n\n assertPixelSnapMode(mode);\n this._pixelSnapMode = mode;\n\n for (const chunk of this._chunkNodes) {\n chunk.pixelSnapMode = mode;\n }\n }\n\n /**\n * Rebuild the chunk-node children from the layer's current loaded chunks.\n * Call after structural mutation that creates or empties chunks. In-place\n * tile edits to existing chunks do not need a refresh.\n */\n public refresh(): this {\n const previous = [...this._chunkNodes];\n\n this.removeChildren();\n this._chunkNodes.length = 0;\n\n for (const child of previous) {\n child.destroy();\n }\n\n this._syncedOpacity = -1;\n this._syncedTint = undefined;\n this._buildChunkNodes();\n\n return this;\n }\n\n /** The chunk render nodes owned by this layer node, in build order. @internal */\n public get chunkNodes(): readonly TileChunkNode[] {\n return this._chunkNodes;\n }\n\n /**\n * Recomputed lazily on read, so it writes `_localBounds` directly rather than\n * going through `_setLocalBounds`: an invalidating write inside a getter\n * would re-dirty the node on every read.\n */\n public override getLocalBounds(): ReadonlyRectangle {\n const bounds = this._localBounds;\n\n // Reading the pixel extents directly (rather than gating on `bounded`)\n // is what narrows them to numbers - `bounded` is a plain boolean getter.\n const { pixelHeight, pixelWidth } = this._layer;\n\n if (pixelWidth !== undefined && pixelHeight !== undefined) {\n bounds.set(0, 0, pixelWidth, pixelHeight);\n } else if (this._chunkNodes.length > 0) {\n aggregateChildLocalBounds(this._chunkNodes, bounds);\n }\n\n return bounds;\n }\n\n /** @internal */\n protected override _collectContent(builder: RenderPlanBuilder): void {\n if (!this._layer.visible) {\n return;\n }\n\n this._syncTint();\n\n const layer = this._layer;\n\n const patchesPosition = layer.parallaxX !== 1 || layer.parallaxY !== 1;\n const patchesScale = layer.parallaxScale !== 1;\n\n if (patchesPosition || patchesScale) {\n const camCenter = builder.view.center;\n const prevX = this.x;\n const prevY = this.y;\n const prevScaleX = this.scale.x;\n const prevScaleY = this.scale.y;\n\n if (patchesPosition) {\n this.x = this._baseOffsetX + camCenter.x * (1 - layer.parallaxX);\n this.y = this._baseOffsetY + camCenter.y * (1 - layer.parallaxY);\n }\n\n if (patchesScale) {\n this.setScale(prevScaleX * layer.parallaxScale, prevScaleY * layer.parallaxScale);\n }\n\n try {\n super._collectContent(builder);\n } finally {\n if (patchesPosition) {\n this.setPosition(prevX, prevY);\n }\n\n if (patchesScale) {\n this.setScale(prevScaleX, prevScaleY);\n }\n }\n } else {\n super._collectContent(builder);\n }\n }\n\n public override destroy(): void {\n this._layer._removeStructuralListener(this._onStructuralChange);\n\n const children = [...this._chunkNodes];\n\n this._chunkNodes.length = 0;\n\n super.destroy();\n\n for (const child of children) {\n child.destroy();\n }\n }\n\n private _buildChunkNodes(): void {\n const layer = this._layer;\n\n for (const chunk of layer.loadedChunks()) {\n if (chunk.empty) {\n continue;\n }\n\n const node = this._createChunkNode(chunk);\n\n this._chunkNodes.push(node);\n this.addChild(node);\n }\n\n this._syncTint();\n }\n\n /**\n * Construct one configured {@link TileChunkNode} for `chunk` - shared by\n * the initial bulk build ({@link _buildChunkNodes}) and the incremental\n * structural-listener handler, so a future constructor argument or\n * per-node setting only needs to be added in one place.\n */\n private _createChunkNode(chunk: ReadonlyTileChunk): TileChunkNode {\n const layer = this._layer;\n const node = new TileChunkNode(chunk, layer.tilesets, layer.tileWidth, layer.tileHeight, layer.chunkWidth, layer.chunkHeight);\n\n node.cullable = this._cullChunks;\n\n if (this._pixelSnapMode !== PixelSnapMode.None) {\n node.pixelSnapMode = this._pixelSnapMode;\n }\n\n return node;\n }\n\n /**\n * Compute and apply this layer's live tint (opacity as alpha, `tintColor`\n * as RGB multiply) to a single chunk node. Used both by {@link _syncTint}'s\n * bulk pass and by the structural-listener handler for a freshly-added\n * node - a node added between two \"nothing changed\" full syncs must still\n * receive the current tint, which a change-detection-guarded bulk pass\n * alone would skip.\n */\n private _applyTint(node: TileChunkNode): void {\n const tintColor = this._layer.tintColor;\n const r = tintColor === null ? 255 : (tintColor >> 16) & 0xff;\n const g = tintColor === null ? 255 : (tintColor >> 8) & 0xff;\n const b = tintColor === null ? 255 : tintColor & 0xff;\n node.tint.set(r, g, b, this._layer.opacity);\n }\n\n /**\n * Propagate the layer's live opacity and tint colour onto every chunk\n * render tint if either changed since the last call. Opacity drives the\n * tint alpha; `tintColor` (`0xRRGGBB`) multiplies the RGB (white = no tint).\n */\n private _syncTint(): void {\n const opacity = this._layer.opacity;\n const tintColor = this._layer.tintColor;\n\n if (opacity === this._syncedOpacity && tintColor === this._syncedTint) {\n return;\n }\n\n for (const child of this._chunkNodes) {\n this._applyTint(child);\n }\n\n this._syncedOpacity = opacity;\n this._syncedTint = tintColor;\n }\n}\n"],"mappings":"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"}
|