@codexo/exojs-tilemap 0.15.2 → 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
package/dist/esm/TileMap.js
CHANGED
|
@@ -1,361 +1,405 @@
|
|
|
1
|
-
import { validatePositiveInteger } from
|
|
2
|
-
import { TileMapView } from
|
|
1
|
+
import { validatePairedDimensions, validatePositiveInteger } from "./types.js";
|
|
2
|
+
import { TileMapView } from "./TileMapView.js";
|
|
3
3
|
|
|
4
|
+
//#region src/TileMap.ts
|
|
4
5
|
/**
|
|
5
|
-
|
|
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
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
6
|
+
* A generic, format-independent tile map.
|
|
7
|
+
*
|
|
8
|
+
* Owns a finite grid of {@link TileLayer}s and a shared set of {@link TileSet}s.
|
|
9
|
+
* Tile data is stored in compact chunked arrays - no per-tile heap objects.
|
|
10
|
+
*
|
|
11
|
+
* The map does NOT own tileset textures (those are Loader-owned) and does
|
|
12
|
+
* NOT own SceneNode children - see {@link import('./TileMapNode').TileMapNode},
|
|
13
|
+
* which owns those.
|
|
14
|
+
*
|
|
15
|
+
* Multiple tilesets are supported: each cell stores a packed tileset index
|
|
16
|
+
* and local tile ID, so different tilesets may have different tile dimensions.
|
|
17
|
+
*
|
|
18
|
+
* @advanced
|
|
19
|
+
*/
|
|
20
|
+
var TileMap = class {
|
|
21
|
+
/** Map name (debug). */
|
|
22
|
+
name;
|
|
23
|
+
/** Map width in tiles, or `undefined` if unbounded. */
|
|
24
|
+
width;
|
|
25
|
+
/** Map height in tiles, or `undefined` if unbounded. */
|
|
26
|
+
height;
|
|
27
|
+
/** Tile width in pixels. */
|
|
28
|
+
tileWidth;
|
|
29
|
+
/** Tile height in pixels. */
|
|
30
|
+
tileHeight;
|
|
31
|
+
/** Pixel width, or `undefined` if unbounded. */
|
|
32
|
+
get pixelWidth() {
|
|
33
|
+
return this.width === void 0 ? void 0 : this.width * this.tileWidth;
|
|
34
|
+
}
|
|
35
|
+
/** Pixel height, or `undefined` if unbounded. */
|
|
36
|
+
get pixelHeight() {
|
|
37
|
+
return this.height === void 0 ? void 0 : this.height * this.tileHeight;
|
|
38
|
+
}
|
|
39
|
+
/** `true` if this map has a fixed width/height; `false` if unbounded. */
|
|
40
|
+
get bounded() {
|
|
41
|
+
return this.width !== void 0 && this.height !== void 0;
|
|
42
|
+
}
|
|
43
|
+
/** Default chunk width for layers. */
|
|
44
|
+
chunkWidth;
|
|
45
|
+
/** Default chunk height for layers. */
|
|
46
|
+
chunkHeight;
|
|
47
|
+
/** Map class/type string (Tiled `class`; may be empty). */
|
|
48
|
+
class;
|
|
49
|
+
/** Map background colour as `0xRRGGBB`, or `null`. Informational. */
|
|
50
|
+
backgroundColor;
|
|
51
|
+
/** Tile draw order (Tiled `renderorder`). Informational. */
|
|
52
|
+
renderOrder;
|
|
53
|
+
/** Map-level properties (immutable). */
|
|
54
|
+
properties;
|
|
55
|
+
_tilesets;
|
|
56
|
+
_layers = [];
|
|
57
|
+
_layerById = /* @__PURE__ */ new Map();
|
|
58
|
+
_objectLayers = [];
|
|
59
|
+
_imageLayers = [];
|
|
60
|
+
_documentOrder = [];
|
|
61
|
+
_revision = 0;
|
|
62
|
+
_destroyed = false;
|
|
63
|
+
/**
|
|
64
|
+
* @throws When dimensions or other options are invalid.
|
|
65
|
+
*/
|
|
66
|
+
constructor(options) {
|
|
67
|
+
validatePairedDimensions(options.width, options.height, "TileMap", "map");
|
|
68
|
+
validatePositiveInteger(options.tileWidth, "map.tileWidth");
|
|
69
|
+
validatePositiveInteger(options.tileHeight, "map.tileHeight");
|
|
70
|
+
const chunkWidth = options.chunkWidth ?? 32;
|
|
71
|
+
const chunkHeight = options.chunkHeight ?? 32;
|
|
72
|
+
validatePositiveInteger(chunkWidth, "chunkWidth");
|
|
73
|
+
validatePositiveInteger(chunkHeight, "chunkHeight");
|
|
74
|
+
this.name = options.name ?? "TileMap";
|
|
75
|
+
this.width = options.width;
|
|
76
|
+
this.height = options.height;
|
|
77
|
+
this.tileWidth = options.tileWidth;
|
|
78
|
+
this.tileHeight = options.tileHeight;
|
|
79
|
+
this.chunkWidth = chunkWidth;
|
|
80
|
+
this.chunkHeight = chunkHeight;
|
|
81
|
+
this.class = options.class ?? "";
|
|
82
|
+
this.backgroundColor = options.backgroundColor ?? null;
|
|
83
|
+
this.renderOrder = options.renderOrder ?? "right-down";
|
|
84
|
+
this._tilesets = options.tilesets ? [...options.tilesets] : [];
|
|
85
|
+
this.properties = options.properties ? Object.freeze({ ...options.properties }) : Object.freeze({});
|
|
86
|
+
if (options.layers) for (const layer of options.layers) this._addLayer(layer);
|
|
87
|
+
if (options.objectLayers) this._objectLayers.push(...options.objectLayers);
|
|
88
|
+
if (options.imageLayers) for (const layer of options.imageLayers) this._addImageLayer(layer);
|
|
89
|
+
this._documentOrder.push(...this._buildDocumentOrder(options.documentOrder));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Validate an explicit `documentOrder` option against current tile/image
|
|
93
|
+
* layer membership and resolve it to layer instances, or compute the
|
|
94
|
+
* fallback order (tile layers in insertion order, then image layers) when
|
|
95
|
+
* omitted. The order stores instance references - not ids - so a
|
|
96
|
+
* cross-kind id collision in a fallback map can never resolve to the
|
|
97
|
+
* wrong layer.
|
|
98
|
+
* @throws Per the validation rules documented on {@link
|
|
99
|
+
* TileMapOptions.documentOrder}.
|
|
100
|
+
*/
|
|
101
|
+
_buildDocumentOrder(documentOrder) {
|
|
102
|
+
if (!documentOrder) return [...this._layers, ...this._imageLayers];
|
|
103
|
+
const tileIds = new Set(this._layers.map((l) => l.id));
|
|
104
|
+
const imageIds = new Set(this._imageLayers.map((l) => l.id));
|
|
105
|
+
for (const id of tileIds) if (imageIds.has(id)) throw new Error(`Layer ID ${id} exists as both a tile layer and an image layer in map "${this.name}"; documentOrder cannot disambiguate them.`);
|
|
106
|
+
const seen = /* @__PURE__ */ new Set();
|
|
107
|
+
for (const id of documentOrder) {
|
|
108
|
+
if (!tileIds.has(id) && !imageIds.has(id)) throw new Error(`documentOrder references unknown layer ID ${id} in map "${this.name}".`);
|
|
109
|
+
if (seen.has(id)) throw new Error(`documentOrder lists layer ID ${id} more than once in map "${this.name}".`);
|
|
110
|
+
seen.add(id);
|
|
111
|
+
}
|
|
112
|
+
const totalLayers = tileIds.size + imageIds.size;
|
|
113
|
+
if (seen.size !== totalLayers) {
|
|
114
|
+
for (const id of [...tileIds, ...imageIds]) if (!seen.has(id)) throw new Error(`documentOrder is missing layer ID ${id} in map "${this.name}".`);
|
|
115
|
+
}
|
|
116
|
+
const instanceCount = this._layers.length + this._imageLayers.length;
|
|
117
|
+
if (documentOrder.length !== instanceCount) throw new Error(`documentOrder has ${documentOrder.length} entries but map "${this.name}" has ${instanceCount} tile/image layer instances; check for a duplicate image-layer ID.`);
|
|
118
|
+
return documentOrder.map((id) => {
|
|
119
|
+
const layer = this._layerById.get(id) ?? this._imageLayers.find((imageLayer) => imageLayer.id === id);
|
|
120
|
+
if (!layer) throw new Error(`documentOrder references layer id ${id}, but map "${this.name}" has no tile or image layer with that id.`);
|
|
121
|
+
return layer;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/** Immutable list of tilesets available to this map. */
|
|
125
|
+
get tilesets() {
|
|
126
|
+
return this._tilesets;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Add a tileset. Tilesets must have unique names.
|
|
130
|
+
* @throws If a tileset with the same name already exists, or the map is destroyed.
|
|
131
|
+
*/
|
|
132
|
+
addTileset(tileset) {
|
|
133
|
+
this._checkDestroyed();
|
|
134
|
+
if (this._tilesets.some((ts) => ts.name === tileset.name)) throw new Error(`Tileset "${tileset.name}" already exists in map "${this.name}".`);
|
|
135
|
+
this._tilesets.push(tileset);
|
|
136
|
+
this._revision++;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get a tileset by name, or undefined.
|
|
140
|
+
*/
|
|
141
|
+
getTileset(name) {
|
|
142
|
+
return this._tilesets.find((ts) => ts.name === name);
|
|
143
|
+
}
|
|
144
|
+
/** Immutable snapshot of layers (ordered). */
|
|
145
|
+
get layers() {
|
|
146
|
+
return this._layers;
|
|
147
|
+
}
|
|
148
|
+
_addLayer(layer) {
|
|
149
|
+
if (this._layerById.has(layer.id)) throw new Error(`Layer ID ${layer.id} already exists in map "${this.name}".`);
|
|
150
|
+
this._layerById.set(layer.id, layer);
|
|
151
|
+
this._layers.push(layer);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Add a layer after construction. Appended to the end of {@link
|
|
155
|
+
* renderableLayers}'s document order.
|
|
156
|
+
* @throws If a layer with the same ID already exists.
|
|
157
|
+
*/
|
|
158
|
+
addLayer(layer) {
|
|
159
|
+
this._checkDestroyed();
|
|
160
|
+
this._addLayer(layer);
|
|
161
|
+
this._documentOrder.push(layer);
|
|
162
|
+
this._revision++;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get a tile layer by ID.
|
|
166
|
+
*/
|
|
167
|
+
getTileLayerById(id) {
|
|
168
|
+
return this._layerById.get(id);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Get a tile layer by name. Returns the first match in insertion order.
|
|
172
|
+
*/
|
|
173
|
+
getTileLayer(name) {
|
|
174
|
+
return this._layers.find((l) => l.name === name);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Remove a layer by ID. The layer is destroyed and spliced out of {@link
|
|
178
|
+
* renderableLayers}'s document order.
|
|
179
|
+
* @returns true if the layer was found and removed.
|
|
180
|
+
*/
|
|
181
|
+
removeLayer(id) {
|
|
182
|
+
this._checkDestroyed();
|
|
183
|
+
const layer = this._layerById.get(id);
|
|
184
|
+
if (!layer) return false;
|
|
185
|
+
this._layers.splice(this._layers.indexOf(layer), 1);
|
|
186
|
+
this._layerById.delete(id);
|
|
187
|
+
const orderIndex = this._documentOrder.indexOf(layer);
|
|
188
|
+
if (orderIndex !== -1) this._documentOrder.splice(orderIndex, 1);
|
|
189
|
+
layer.destroy();
|
|
190
|
+
this._revision++;
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
/** Immutable snapshot of object layers (insertion order). */
|
|
194
|
+
get objectLayers() {
|
|
195
|
+
return this._objectLayers;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Add an object layer after construction.
|
|
199
|
+
* @throws If the map is destroyed.
|
|
200
|
+
*/
|
|
201
|
+
addObjectLayer(layer) {
|
|
202
|
+
this._checkDestroyed();
|
|
203
|
+
this._objectLayers.push(layer);
|
|
204
|
+
this._revision++;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Get an object layer by name (first match in insertion order), or undefined.
|
|
208
|
+
*
|
|
209
|
+
* Supply an {@link ObjectSchema} type argument `S` to obtain a typed view of
|
|
210
|
+
* the layer - `getObjectLayer<LevelObjects>('Entities')` returns an
|
|
211
|
+
* `ObjectLayer<LevelObjects>` whose {@link ObjectLayer.byType} / {@link
|
|
212
|
+
* ObjectLayer.where} accessors narrow `properties`. The schema is a static
|
|
213
|
+
* developer promise only; no runtime validation is performed and the call
|
|
214
|
+
* remains fully back-compatible when omitted.
|
|
215
|
+
*/
|
|
216
|
+
getObjectLayer(name) {
|
|
217
|
+
return this._objectLayers.find((layer) => layer.name === name);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Get an object layer by ID.
|
|
221
|
+
*
|
|
222
|
+
* Supply an {@link ObjectSchema} type argument `S` to obtain a typed view of
|
|
223
|
+
* the layer, as with {@link getObjectLayer}.
|
|
224
|
+
*/
|
|
225
|
+
getObjectLayerById(id) {
|
|
226
|
+
return this._objectLayers.find((layer) => layer.id === id);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Remove an object layer by ID.
|
|
230
|
+
* @returns true if the layer was found and removed.
|
|
231
|
+
*/
|
|
232
|
+
removeObjectLayer(id) {
|
|
233
|
+
this._checkDestroyed();
|
|
234
|
+
const index = this._objectLayers.findIndex((layer) => layer.id === id);
|
|
235
|
+
if (index === -1) return false;
|
|
236
|
+
this._objectLayers.splice(index, 1);
|
|
237
|
+
this._revision++;
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
/** Immutable snapshot of image layers (insertion order). */
|
|
241
|
+
get imageLayers() {
|
|
242
|
+
return this._imageLayers;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Add an image layer after construction. Appended to both {@link
|
|
246
|
+
* imageLayers} and the end of {@link renderableLayers}'s document order.
|
|
247
|
+
* @throws If an image layer with the same ID already exists. An ID shared
|
|
248
|
+
* with a *tile* layer is permitted - the two kinds keep separate ID
|
|
249
|
+
* spaces, and all internal bookkeeping is instance-based.
|
|
250
|
+
*/
|
|
251
|
+
addImageLayer(layer) {
|
|
252
|
+
this._checkDestroyed();
|
|
253
|
+
this._addImageLayer(layer);
|
|
254
|
+
this._documentOrder.push(layer);
|
|
255
|
+
this._revision++;
|
|
256
|
+
}
|
|
257
|
+
/** Shared by the constructor and {@link addImageLayer}: enforce ID uniqueness within the image-layer kind. */
|
|
258
|
+
_addImageLayer(layer) {
|
|
259
|
+
if (this._imageLayers.some((existing) => existing.id === layer.id)) throw new Error(`Image layer ID ${layer.id} already exists in map "${this.name}".`);
|
|
260
|
+
this._imageLayers.push(layer);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Get an image layer by name (first match in insertion order), or undefined.
|
|
264
|
+
*/
|
|
265
|
+
getImageLayer(name) {
|
|
266
|
+
return this._imageLayers.find((layer) => layer.name === name);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Get an image layer by ID.
|
|
270
|
+
*/
|
|
271
|
+
getImageLayerById(id) {
|
|
272
|
+
return this._imageLayers.find((layer) => layer.id === id);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Remove an image layer by ID. Spliced out of {@link renderableLayers}'s
|
|
276
|
+
* document order.
|
|
277
|
+
* @returns true if the layer was found and removed.
|
|
278
|
+
*/
|
|
279
|
+
removeImageLayer(id) {
|
|
280
|
+
this._checkDestroyed();
|
|
281
|
+
const layer = this._imageLayers.find((l) => l.id === id);
|
|
282
|
+
if (!layer) return false;
|
|
283
|
+
this._imageLayers.splice(this._imageLayers.indexOf(layer), 1);
|
|
284
|
+
const orderIndex = this._documentOrder.indexOf(layer);
|
|
285
|
+
if (orderIndex !== -1) this._documentOrder.splice(orderIndex, 1);
|
|
286
|
+
this._revision++;
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Tile and image layers combined into a single document order (see {@link
|
|
291
|
+
* TileMapOptions.documentOrder}), maintained live as membership changes.
|
|
292
|
+
* Reflects `addLayer` / `addImageLayer` / `removeLayer` /
|
|
293
|
+
* `removeImageLayer` calls made after construction. Holds instance
|
|
294
|
+
* references, so entries stay correct even when a tile layer and an image
|
|
295
|
+
* layer share an id in a fallback-ordered map. Object layers are
|
|
296
|
+
* data-only and never appear here.
|
|
297
|
+
*/
|
|
298
|
+
get renderableLayers() {
|
|
299
|
+
return this._documentOrder;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Create a new {@link TileMapView} that groups this map's layers into
|
|
303
|
+
* independently placeable band / layer scene nodes for interleaving
|
|
304
|
+
* application actors between tile layers.
|
|
305
|
+
*
|
|
306
|
+
* Each call returns a fresh, independent view - the map does **not** cache a
|
|
307
|
+
* single global view, so multiple coexisting views of the same map are
|
|
308
|
+
* allowed. The view references this map but never owns it: destroying the
|
|
309
|
+
* view frees only its generated layer/band nodes - never the map, its layers,
|
|
310
|
+
* tileset textures, or any application actors.
|
|
311
|
+
*
|
|
312
|
+
* @advanced
|
|
313
|
+
*/
|
|
314
|
+
createView(options) {
|
|
315
|
+
return new TileMapView(this, options);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Get a resolved tile from a given layer at tile coordinates.
|
|
319
|
+
* Convenience for `map.getTileLayerById(id)?.getTileAt(tx, ty)`.
|
|
320
|
+
* Returns null for an empty cell, out-of-bounds, or missing layer.
|
|
321
|
+
*/
|
|
322
|
+
getTileAt(layerId, tx, ty) {
|
|
323
|
+
const layer = this._layerById.get(layerId);
|
|
324
|
+
if (!layer) return null;
|
|
325
|
+
return layer.getTileAt(tx, ty);
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Set a tile on a given layer at tile coordinates.
|
|
329
|
+
* Convenience for `map.getTileLayerById(id)?.setTileAt(tx, ty, tile)`.
|
|
330
|
+
* @throws If the layer does not exist, coordinates are out of bounds,
|
|
331
|
+
* or the tile reference is invalid.
|
|
332
|
+
*/
|
|
333
|
+
setTileAt(layerId, tx, ty, tile) {
|
|
334
|
+
const layer = this._layerById.get(layerId);
|
|
335
|
+
if (!layer) throw new Error(`Layer ${layerId} not found in map "${this.name}".`);
|
|
336
|
+
layer.setTileAt(tx, ty, tile);
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Clear a tile on a given layer at tile coordinates.
|
|
340
|
+
* Convenience for `map.getTileLayerById(id)?.clearTileAt(tx, ty)`.
|
|
341
|
+
* @throws If the layer does not exist or coordinates are out of bounds.
|
|
342
|
+
*/
|
|
343
|
+
clearTileAt(layerId, tx, ty) {
|
|
344
|
+
const layer = this._layerById.get(layerId);
|
|
345
|
+
if (!layer) throw new Error(`Layer ${layerId} not found in map "${this.name}".`);
|
|
346
|
+
layer.clearTileAt(tx, ty);
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Convert a tile coordinate to the pixel position of its top-left corner
|
|
350
|
+
* in map-local space (ignoring layer offsets).
|
|
351
|
+
*/
|
|
352
|
+
tileToPixel(tx, ty) {
|
|
353
|
+
return {
|
|
354
|
+
x: tx * this.tileWidth,
|
|
355
|
+
y: ty * this.tileHeight
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Convert a pixel position in map-local space to the tile coordinate
|
|
360
|
+
* that contains it. Uses `floor`. May return coordinates outside map bounds.
|
|
361
|
+
*/
|
|
362
|
+
pixelToTile(px, py) {
|
|
363
|
+
return {
|
|
364
|
+
tx: Math.floor(px / this.tileWidth),
|
|
365
|
+
ty: Math.floor(py / this.tileHeight)
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Monotonic map revision counter. Increments on structural changes only
|
|
370
|
+
* (add/remove layer, add tileset). Cell mutations are tracked per-chunk
|
|
371
|
+
* and per-layer; the renderer reads chunk-level revisions directly.
|
|
372
|
+
* @advanced
|
|
373
|
+
*/
|
|
374
|
+
get revision() {
|
|
375
|
+
return this._revision;
|
|
376
|
+
}
|
|
377
|
+
/** Whether the map has been destroyed. */
|
|
378
|
+
get destroyed() {
|
|
379
|
+
return this._destroyed;
|
|
380
|
+
}
|
|
381
|
+
_checkDestroyed() {
|
|
382
|
+
if (this._destroyed) throw new Error(`TileMap "${this.name}" has been destroyed.`);
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Destroy the map and all owned layers and chunk storage.
|
|
386
|
+
*
|
|
387
|
+
* Is idempotent. Does NOT destroy tileset textures (Loader-owned) or
|
|
388
|
+
* any SceneNodes (those do not exist yet in this slice).
|
|
389
|
+
*/
|
|
390
|
+
destroy() {
|
|
391
|
+
if (this._destroyed) return;
|
|
392
|
+
this._destroyed = true;
|
|
393
|
+
for (const layer of this._layers) layer.destroy();
|
|
394
|
+
this._layers.length = 0;
|
|
395
|
+
this._layerById.clear();
|
|
396
|
+
this._objectLayers.length = 0;
|
|
397
|
+
this._imageLayers.length = 0;
|
|
398
|
+
this._documentOrder.length = 0;
|
|
399
|
+
this._tilesets.length = 0;
|
|
400
|
+
}
|
|
401
|
+
};
|
|
359
402
|
|
|
403
|
+
//#endregion
|
|
360
404
|
export { TileMap };
|
|
361
|
-
//# sourceMappingURL=TileMap.js.map
|
|
405
|
+
//# sourceMappingURL=TileMap.js.map
|