@codexo/exojs-tilemap 0.13.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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +187 -0
  3. package/dist/esm/TileChunk.d.ts +136 -0
  4. package/dist/esm/TileChunk.js +192 -0
  5. package/dist/esm/TileChunk.js.map +1 -0
  6. package/dist/esm/TileChunkNode.d.ts +59 -0
  7. package/dist/esm/TileChunkNode.js +89 -0
  8. package/dist/esm/TileChunkNode.js.map +1 -0
  9. package/dist/esm/TileLayer.d.ts +229 -0
  10. package/dist/esm/TileLayer.js +450 -0
  11. package/dist/esm/TileLayer.js.map +1 -0
  12. package/dist/esm/TileLayerNode.d.ts +81 -0
  13. package/dist/esm/TileLayerNode.js +142 -0
  14. package/dist/esm/TileLayerNode.js.map +1 -0
  15. package/dist/esm/TileMap.d.ts +178 -0
  16. package/dist/esm/TileMap.js +262 -0
  17. package/dist/esm/TileMap.js.map +1 -0
  18. package/dist/esm/TileMapBand.d.ts +97 -0
  19. package/dist/esm/TileMapBand.js +161 -0
  20. package/dist/esm/TileMapBand.js.map +1 -0
  21. package/dist/esm/TileMapNode.d.ts +71 -0
  22. package/dist/esm/TileMapNode.js +113 -0
  23. package/dist/esm/TileMapNode.js.map +1 -0
  24. package/dist/esm/TileMapView.d.ts +182 -0
  25. package/dist/esm/TileMapView.js +342 -0
  26. package/dist/esm/TileMapView.js.map +1 -0
  27. package/dist/esm/TileSet.d.ts +99 -0
  28. package/dist/esm/TileSet.js +157 -0
  29. package/dist/esm/TileSet.js.map +1 -0
  30. package/dist/esm/chunkGeometry.d.ts +71 -0
  31. package/dist/esm/chunkGeometry.js +98 -0
  32. package/dist/esm/chunkGeometry.js.map +1 -0
  33. package/dist/esm/index.d.ts +1 -0
  34. package/dist/esm/index.js +10 -0
  35. package/dist/esm/index.js.map +1 -0
  36. package/dist/esm/pixelSnap.d.ts +12 -0
  37. package/dist/esm/pixelSnap.js +19 -0
  38. package/dist/esm/pixelSnap.js.map +1 -0
  39. package/dist/esm/public.d.ts +18 -0
  40. package/dist/esm/register.d.ts +1 -0
  41. package/dist/esm/register.js +20 -0
  42. package/dist/esm/register.js.map +1 -0
  43. package/dist/esm/tilemapExtension.d.ts +18 -0
  44. package/dist/esm/tilemapExtension.js +52 -0
  45. package/dist/esm/tilemapExtension.js.map +1 -0
  46. package/dist/esm/types.d.ts +139 -0
  47. package/dist/esm/types.js +121 -0
  48. package/dist/esm/types.js.map +1 -0
  49. package/dist/esm/webgl2/WebGl2TileChunkRenderer.d.ts +39 -0
  50. package/dist/esm/webgl2/WebGl2TileChunkRenderer.js +339 -0
  51. package/dist/esm/webgl2/WebGl2TileChunkRenderer.js.map +1 -0
  52. package/dist/esm/webgpu/WebGpuTileChunkRenderer.d.ts +42 -0
  53. package/dist/esm/webgpu/WebGpuTileChunkRenderer.js +390 -0
  54. package/dist/esm/webgpu/WebGpuTileChunkRenderer.js.map +1 -0
  55. package/package.json +48 -0
@@ -0,0 +1,342 @@
1
+ import { assertPixelSnapMode } from './pixelSnap.js';
2
+ import { TileLayerNode } from './TileLayerNode.js';
3
+ import { TileMapBand } from './TileMapBand.js';
4
+
5
+ /**
6
+ * Groups a {@link TileMap}'s layers into independently placeable scene nodes so
7
+ * application actors can be interleaved **between** tile layers.
8
+ *
9
+ * A view produces exactly one canonical {@link TileLayerNode} per map layer
10
+ * (stable identity, map document order) and, optionally, named {@link TileMapBand}s
11
+ * grouping subsets of those nodes. The application parents the bands / layer
12
+ * nodes wherever it wants — typically as siblings of its own actor containers:
13
+ *
14
+ * ```ts
15
+ * const view = map.createView({ bands: { ground: ['background', 'ground'], roof: ['roofs'] } });
16
+ * worldRoot.addChild(view.band('ground'), actors, view.band('roof'));
17
+ * // or without bands:
18
+ * worldRoot.addChild(view.getLayerNodeById(groundId)!, actors, view.getLayerNodeById(roofId)!);
19
+ * ```
20
+ *
21
+ * **Actors are application-owned siblings.** A `TileMapView` never adopts or
22
+ * destroys actors. The view is a helper, not a scene node — it does not own the
23
+ * world container, the {@link TileMap}, the {@link TileLayer}s, or tileset
24
+ * textures.
25
+ *
26
+ * **Ownership:** the view owns its generated layer nodes and bands. A layer
27
+ * assigned to a band is owned by that band; an unbanded layer is owned by the
28
+ * view directly. {@link TileMapView.destroy} destroys every band and layer node
29
+ * (detaching them from their application parents) but leaves actors, the map,
30
+ * its layers, and Loader-owned textures untouched. There is no map-replacement
31
+ * mutation API: to swap maps, destroy the old view, construct a new one, and
32
+ * re-parent its bands — the actor tree is never involved.
33
+ *
34
+ * @advanced
35
+ */
36
+ class TileMapView {
37
+ _map;
38
+ _cullable;
39
+ /** All canonical layer nodes, in map document order. */
40
+ _layerNodes = [];
41
+ /** Layer id → its canonical layer node. */
42
+ _layerNodeById = new Map();
43
+ /** Bands in definition (insertion) order. */
44
+ _bands = [];
45
+ /** Band name → band. */
46
+ _bandByName = new Map();
47
+ /** Original band definitions (frozen) for re-resolution on refresh. */
48
+ _bandDefs = [];
49
+ /** Layer node → its owning band (absent = view-owned / unbanded). */
50
+ _nodeBand = new Map();
51
+ /** Unbanded layer nodes owned directly by the view, in map document order. */
52
+ _directLayerNodes = [];
53
+ _destroyed = false;
54
+ _pixelSnapMode = 'none';
55
+ /**
56
+ * @param map The runtime map to compose. Referenced, never owned.
57
+ * @param options Band definitions and culling.
58
+ * @throws When a band definition references an unknown/ambiguous layer or
59
+ * assigns a layer twice / to multiple bands.
60
+ */
61
+ constructor(map, options) {
62
+ this._map = map;
63
+ this._cullable = options?.cullable ?? true;
64
+ for (const layer of map.layers) {
65
+ const node = new TileLayerNode(layer, { cullable: this._cullable });
66
+ this._layerNodes.push(node);
67
+ this._layerNodeById.set(layer.id, node);
68
+ }
69
+ if (options?.bands) {
70
+ for (const [name, selectors] of Object.entries(options.bands)) {
71
+ this._defineBand(name, selectors);
72
+ }
73
+ }
74
+ for (const node of this._layerNodes) {
75
+ if (!this._nodeBand.has(node)) {
76
+ this._directLayerNodes.push(node);
77
+ }
78
+ }
79
+ }
80
+ /** The runtime map this view composes. Referenced, never owned. */
81
+ get map() {
82
+ return this._map;
83
+ }
84
+ /** All canonical layer nodes, one per map layer, in map document order. */
85
+ get layers() {
86
+ return this._layerNodes;
87
+ }
88
+ /** The bands, in definition (insertion) order. */
89
+ get bands() {
90
+ return this._bands;
91
+ }
92
+ /** Whether this view has been destroyed. */
93
+ get destroyed() {
94
+ return this._destroyed;
95
+ }
96
+ /**
97
+ * Render-only pixel-snap mode applied to every layer node this view owns (and
98
+ * forwarded to every chunk drawable, current and rebuilt by
99
+ * {@link refreshLayers}). Snaps tile chunk origins to the active render
100
+ * target's device-pixel grid for crisp tiles; with integer tile pitch the grid
101
+ * stays exact and adjacent chunks cannot drift apart. Purely visual — tile
102
+ * data, layer offsets, chunk revisions, and culling are unchanged. Setting the
103
+ * current value is a no-op; an invalid value throws and leaves the prior mode
104
+ * unchanged.
105
+ *
106
+ * @default 'none'
107
+ * @stable
108
+ */
109
+ get pixelSnapMode() {
110
+ return this._pixelSnapMode;
111
+ }
112
+ set pixelSnapMode(mode) {
113
+ if (mode === this._pixelSnapMode) {
114
+ return;
115
+ }
116
+ assertPixelSnapMode(mode);
117
+ this._pixelSnapMode = mode;
118
+ for (const node of this._layerNodes) {
119
+ node.pixelSnapMode = mode;
120
+ }
121
+ }
122
+ /**
123
+ * The canonical layer node for the layer with the given **id**, or
124
+ * `undefined`. Ids are authoritative and unique — this is the unambiguous
125
+ * lookup. The returned node may be reparented into the caller's own
126
+ * containers; the view still tracks it for refresh and destruction.
127
+ */
128
+ getLayerNodeById(id) {
129
+ return this._layerNodeById.get(id);
130
+ }
131
+ /**
132
+ * Every canonical layer node whose layer has the given **name**, in map
133
+ * document order. Layer names are not guaranteed unique, so this returns an
134
+ * array (empty when no layer matches). Prefer {@link getLayerNodeById} when
135
+ * you have the id.
136
+ */
137
+ getLayerNodesByName(name) {
138
+ return this._layerNodes.filter(node => node.layer.name === name);
139
+ }
140
+ /**
141
+ * The band registered under `name`.
142
+ * @throws If no band with that name was defined.
143
+ */
144
+ band(name) {
145
+ const band = this._bandByName.get(name);
146
+ if (!band) {
147
+ throw new Error(`TileMapView has no band named "${name}". Defined bands: ${this._bands.length ? this._bands.map(b => `"${b.name}"`).join(', ') : '(none)'}.`);
148
+ }
149
+ return band;
150
+ }
151
+ /** Whether a band with the given name was defined. */
152
+ hasBand(name) {
153
+ return this._bandByName.has(name);
154
+ }
155
+ /**
156
+ * Rebuild the view after **structural** map changes (layers added to or
157
+ * removed from the map). Ordinary tile edits and chunk creation/removal do
158
+ * NOT need this — those are handled by chunk revisions and
159
+ * {@link TileLayerNode.refresh} respectively.
160
+ *
161
+ * - Removed layers: their generated layer node is detached and destroyed.
162
+ * - Unchanged layers: keep their existing layer node (stable identity).
163
+ * - Added layers: a new layer node is created and assigned to the first band
164
+ * whose definition selects it (by id, or by a currently-unambiguous name),
165
+ * otherwise owned directly by the view.
166
+ * - Every band's children are re-ordered to map document order.
167
+ *
168
+ * Application actors are never touched, and bands keep their placement in the
169
+ * application scene graph.
170
+ *
171
+ * @throws If the view has been destroyed.
172
+ */
173
+ refreshLayers() {
174
+ if (this._destroyed) {
175
+ throw new Error('Cannot refresh a destroyed TileMapView.');
176
+ }
177
+ const currentLayers = this._map.layers;
178
+ const currentIds = new Set();
179
+ for (const layer of currentLayers) {
180
+ currentIds.add(layer.id);
181
+ }
182
+ // 1. Remove nodes whose layer no longer exists.
183
+ for (const node of [...this._layerNodes]) {
184
+ if (!currentIds.has(node.layer.id)) {
185
+ this._removeNode(node);
186
+ }
187
+ }
188
+ // 2. Re-derive the doc-ordered node list, creating + assigning new nodes.
189
+ const newOrder = [];
190
+ for (const layer of currentLayers) {
191
+ let node = this._layerNodeById.get(layer.id);
192
+ if (!node) {
193
+ node = new TileLayerNode(layer, { cullable: this._cullable });
194
+ if (this._pixelSnapMode !== 'none') {
195
+ node.pixelSnapMode = this._pixelSnapMode;
196
+ }
197
+ this._layerNodeById.set(layer.id, node);
198
+ this._assignNewNode(node, layer);
199
+ }
200
+ newOrder.push(node);
201
+ }
202
+ this._layerNodes.length = 0;
203
+ this._layerNodes.push(...newOrder);
204
+ // 3. Re-order each band's children to map document order.
205
+ const documentIndexById = new Map();
206
+ for (const [index, layer] of currentLayers.entries())
207
+ documentIndexById.set(layer.id, index);
208
+ for (const band of this._bands) {
209
+ band._reorder(documentIndexById);
210
+ }
211
+ // 4. Rebuild the unbanded set in doc order.
212
+ this._directLayerNodes.length = 0;
213
+ for (const node of newOrder) {
214
+ if (!this._nodeBand.has(node)) {
215
+ this._directLayerNodes.push(node);
216
+ }
217
+ }
218
+ return this;
219
+ }
220
+ /**
221
+ * Destroy the view: every band and generated layer node is destroyed (and
222
+ * detached from its application parent), freeing cached chunk geometry.
223
+ * Idempotent. Application actors, sibling content, the {@link TileMap}, its
224
+ * {@link TileLayer}s, and Loader-owned tileset textures all survive.
225
+ */
226
+ destroy() {
227
+ if (this._destroyed) {
228
+ return;
229
+ }
230
+ this._destroyed = true;
231
+ for (const band of this._bands) {
232
+ band.destroy();
233
+ }
234
+ for (const node of this._directLayerNodes) {
235
+ node.parent?.removeChild(node);
236
+ node.destroy();
237
+ }
238
+ this._bands.length = 0;
239
+ this._bandByName.clear();
240
+ this._bandDefs.length = 0;
241
+ this._directLayerNodes.length = 0;
242
+ this._layerNodes.length = 0;
243
+ this._layerNodeById.clear();
244
+ this._nodeBand.clear();
245
+ }
246
+ // ── Internals ──────────────────────────────────────────────────────────
247
+ /** Resolve one band definition into a {@link TileMapBand} and record it. */
248
+ _defineBand(name, selectors) {
249
+ const memberIds = new Set();
250
+ for (const selector of selectors) {
251
+ const id = this._resolveSelector(name, selector);
252
+ if (memberIds.has(id)) {
253
+ throw new Error(`TileMapView band "${name}" lists layer ${id} more than once.`);
254
+ }
255
+ const existing = this._layerNodeById.get(id);
256
+ if (existing && this._nodeBand.has(existing)) {
257
+ throw new Error(`TileMapView layer ${id} is assigned to multiple bands ` +
258
+ `("${this._nodeBand.get(existing).name}" and "${name}").`);
259
+ }
260
+ memberIds.add(id);
261
+ }
262
+ // Order members by map document order (membership selects; doc order renders).
263
+ const orderedNodes = this._layerNodes.filter(node => memberIds.has(node.layer.id));
264
+ const band = new TileMapBand(name, orderedNodes);
265
+ for (const node of orderedNodes) {
266
+ this._nodeBand.set(node, band);
267
+ }
268
+ this._bands.push(band);
269
+ this._bandByName.set(name, band);
270
+ this._bandDefs.push({ name, selectors: Object.freeze([...selectors]) });
271
+ }
272
+ /** Resolve a single selector to a layer id, throwing on unknown/ambiguous. */
273
+ _resolveSelector(bandName, selector) {
274
+ if (typeof selector === 'number') {
275
+ if (!this._layerNodeById.has(selector)) {
276
+ throw new Error(`TileMapView band "${bandName}": no layer with id ${selector} in map "${this._map.name}".`);
277
+ }
278
+ return selector;
279
+ }
280
+ const matches = this._map.layers.filter(layer => layer.name === selector);
281
+ if (matches.length === 0) {
282
+ throw new Error(`TileMapView band "${bandName}": no layer named "${selector}" in map "${this._map.name}".`);
283
+ }
284
+ if (matches.length > 1) {
285
+ throw new Error(`TileMapView band "${bandName}": layer name "${selector}" is ambiguous ` +
286
+ `(${matches.length} layers share it); reference it by id instead.`);
287
+ }
288
+ return matches[0].id;
289
+ }
290
+ /** Assign a freshly created node to the first band that selects its layer. */
291
+ _assignNewNode(node, layer) {
292
+ for (const def of this._bandDefs) {
293
+ if (this._definitionSelects(def, layer)) {
294
+ const band = this._bandByName.get(def.name);
295
+ band._adopt(node);
296
+ this._nodeBand.set(node, band);
297
+ return;
298
+ }
299
+ }
300
+ }
301
+ /** Whether a band definition selects the given layer (unambiguously by name). */
302
+ _definitionSelects(def, layer) {
303
+ for (const selector of def.selectors) {
304
+ if (typeof selector === 'number') {
305
+ if (selector === layer.id) {
306
+ return true;
307
+ }
308
+ }
309
+ else if (selector === layer.name) {
310
+ const sameName = this._map.layers.filter(other => other.name === selector).length;
311
+ if (sameName === 1) {
312
+ return true;
313
+ }
314
+ }
315
+ }
316
+ return false;
317
+ }
318
+ /** Detach + destroy a node, dropping it from band membership and registries. */
319
+ _removeNode(node) {
320
+ const band = this._nodeBand.get(node);
321
+ if (band) {
322
+ band._release(node);
323
+ this._nodeBand.delete(node);
324
+ }
325
+ else {
326
+ const directIndex = this._directLayerNodes.indexOf(node);
327
+ if (directIndex !== -1) {
328
+ this._directLayerNodes.splice(directIndex, 1);
329
+ }
330
+ }
331
+ node.parent?.removeChild(node);
332
+ this._layerNodeById.delete(node.layer.id);
333
+ const orderIndex = this._layerNodes.indexOf(node);
334
+ if (orderIndex !== -1) {
335
+ this._layerNodes.splice(orderIndex, 1);
336
+ }
337
+ node.destroy();
338
+ }
339
+ }
340
+
341
+ export { TileMapView };
342
+ //# sourceMappingURL=TileMapView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TileMapView.js","sources":["../../../src/TileMapView.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ import type { TextureRegion } from '@codexo/exojs';
2
+ import type { TileDefinition, TileProperties } from './types';
3
+ /**
4
+ * Options for constructing a {@link TileSet}.
5
+ * @advanced
6
+ */
7
+ export interface TileSetOptions {
8
+ /** Stable runtime name (unique within a {@link TileMap}). */
9
+ readonly name: string;
10
+ /** Texture atlas for this tileset. Textures are Loader-owned. */
11
+ readonly texture: TextureRegion;
12
+ /** Width of each tile in pixels. */
13
+ readonly tileWidth: number;
14
+ /** Height of each tile in pixels. */
15
+ readonly tileHeight: number;
16
+ /** Total number of tiles in this tileset. */
17
+ readonly tileCount: number;
18
+ /** Number of tile columns in the atlas grid. Computed from texture width / tileWidth if omitted. */
19
+ readonly columns?: number;
20
+ /** Pixel spacing between tiles in the atlas. Defaults to 0. */
21
+ readonly spacing?: number;
22
+ /** Pixel margin around the atlas. Defaults to 0. */
23
+ readonly margin?: number;
24
+ }
25
+ /**
26
+ * A resolved tileset: a uniform grid of tiles within a texture atlas.
27
+ *
28
+ * Does **not** own its texture — the Loader or application code retains
29
+ * texture ownership. Tileset dimensions are validated at construction and
30
+ * frozen thereafter.
31
+ *
32
+ * Multiple tilesets are supported per {@link TileMap}; each carries its own
33
+ * tile dimensions, spacing, and optional per-tile metadata.
34
+ * @advanced
35
+ */
36
+ export declare class TileSet {
37
+ /** Stable runtime name. */
38
+ readonly name: string;
39
+ /** Atlas texture region — Loader-owned, never destroyed by the tileset. */
40
+ readonly texture: TextureRegion;
41
+ /** Tile width in pixels. */
42
+ readonly tileWidth: number;
43
+ /** Tile height in pixels. */
44
+ readonly tileHeight: number;
45
+ /** Total number of tiles in the tileset. */
46
+ readonly tileCount: number;
47
+ /** Number of columns in the atlas grid. */
48
+ readonly columns: number;
49
+ /** Number of rows implied by tileCount and columns. */
50
+ readonly rows: number;
51
+ /** Pixel spacing between tiles in the atlas. */
52
+ readonly spacing: number;
53
+ /** Pixel margin around the atlas. */
54
+ readonly margin: number;
55
+ private readonly _definitions;
56
+ /**
57
+ * @throws When dimensions, counts, or spacing values are invalid.
58
+ */
59
+ constructor(options: TileSetOptions);
60
+ /**
61
+ * Set per-tile metadata for a local tile ID.
62
+ * Copies input to prevent caller-owned mutation leaking into the tileset.
63
+ * @internal
64
+ */
65
+ _setDefinition(localTileId: number, definition: Partial<TileDefinition>): void;
66
+ /**
67
+ * Build definitions from an array, replacing the internal definitions map.
68
+ * Each entry's properties are copied and frozen.
69
+ * @internal
70
+ */
71
+ _setDefinitions(definitions: readonly TileDefinition[]): void;
72
+ /**
73
+ * Retrieve per-tile metadata, or undefined if none defined.
74
+ * @advanced
75
+ */
76
+ getTileDefinition(localTileId: number): TileDefinition | undefined;
77
+ /**
78
+ * Compute the pixel-space source rectangle for a local tile ID
79
+ * within the atlas, accounting for columns, spacing, and margin.
80
+ * @advanced
81
+ */
82
+ getTileRect(localTileId: number): {
83
+ x: number;
84
+ y: number;
85
+ width: number;
86
+ height: number;
87
+ };
88
+ /**
89
+ * Iterate over all defined tiles (sparse).
90
+ * @advanced
91
+ */
92
+ definedTiles(): IterableIterator<TileDefinition>;
93
+ /**
94
+ * Read-only snapshot of all per-tile definitions.
95
+ * The returned record is a caller-owned copy.
96
+ * @advanced
97
+ */
98
+ get allDefinitions(): Readonly<Record<number, TileProperties | undefined>>;
99
+ }
@@ -0,0 +1,157 @@
1
+ import { validatePositiveInteger, validateNonNegativeInteger } from './types.js';
2
+
3
+ /**
4
+ * A resolved tileset: a uniform grid of tiles within a texture atlas.
5
+ *
6
+ * Does **not** own its texture — the Loader or application code retains
7
+ * texture ownership. Tileset dimensions are validated at construction and
8
+ * frozen thereafter.
9
+ *
10
+ * Multiple tilesets are supported per {@link TileMap}; each carries its own
11
+ * tile dimensions, spacing, and optional per-tile metadata.
12
+ * @advanced
13
+ */
14
+ class TileSet {
15
+ /** Stable runtime name. */
16
+ name;
17
+ /** Atlas texture region — Loader-owned, never destroyed by the tileset. */
18
+ texture;
19
+ /** Tile width in pixels. */
20
+ tileWidth;
21
+ /** Tile height in pixels. */
22
+ tileHeight;
23
+ /** Total number of tiles in the tileset. */
24
+ tileCount;
25
+ /** Number of columns in the atlas grid. */
26
+ columns;
27
+ /** Number of rows implied by tileCount and columns. */
28
+ rows;
29
+ /** Pixel spacing between tiles in the atlas. */
30
+ spacing;
31
+ /** Pixel margin around the atlas. */
32
+ margin;
33
+ _definitions;
34
+ /**
35
+ * @throws When dimensions, counts, or spacing values are invalid.
36
+ */
37
+ constructor(options) {
38
+ if (!options.name || typeof options.name !== 'string') {
39
+ throw new Error('TileSet name must be a non-empty string.');
40
+ }
41
+ if (!options.texture) {
42
+ throw new Error('TileSet requires a valid TextureRegion.');
43
+ }
44
+ validatePositiveInteger(options.tileWidth, 'tileWidth');
45
+ validatePositiveInteger(options.tileHeight, 'tileHeight');
46
+ validatePositiveInteger(options.tileCount, 'tileCount');
47
+ const spacing = options.spacing ?? 0;
48
+ const margin = options.margin ?? 0;
49
+ validateNonNegativeInteger(spacing, 'spacing');
50
+ validateNonNegativeInteger(margin, 'margin');
51
+ const atlasWidth = options.texture.width - margin * 2;
52
+ const atlasHeight = options.texture.height - margin * 2;
53
+ const columns = options.columns ?? Math.floor(atlasWidth / options.tileWidth);
54
+ validatePositiveInteger(columns, 'columns');
55
+ if (columns <= 0) {
56
+ throw new Error(`TileSet columns must be positive (got ${columns}).`);
57
+ }
58
+ if (options.tileWidth * columns + spacing * (columns - 1) > atlasWidth) {
59
+ throw new Error(`TileSet grid width exceeds atlas: ${options.tileWidth}*${columns}` +
60
+ ` + ${spacing}*${columns - 1} > ${atlasWidth}.`);
61
+ }
62
+ const rows = Math.ceil(options.tileCount / columns);
63
+ if (rows > 0 && options.tileHeight * rows + spacing * (rows - 1) > atlasHeight) {
64
+ throw new Error(`TileSet grid height exceeds atlas: ${options.tileHeight}*${rows}` +
65
+ ` + ${spacing}*${rows - 1} > ${atlasHeight}.`);
66
+ }
67
+ this.name = options.name;
68
+ this.texture = options.texture;
69
+ this.tileWidth = options.tileWidth;
70
+ this.tileHeight = options.tileHeight;
71
+ this.tileCount = options.tileCount;
72
+ this.columns = columns;
73
+ this.rows = rows;
74
+ this.spacing = spacing;
75
+ this.margin = margin;
76
+ this._definitions = new Map();
77
+ }
78
+ /**
79
+ * Set per-tile metadata for a local tile ID.
80
+ * Copies input to prevent caller-owned mutation leaking into the tileset.
81
+ * @internal
82
+ */
83
+ _setDefinition(localTileId, definition) {
84
+ if (localTileId < 0 || localTileId >= this.tileCount) {
85
+ throw new Error(`Tile definition localTileId ${localTileId} out of range [0, ${this.tileCount - 1}].`);
86
+ }
87
+ const props = definition.properties
88
+ ? Object.freeze({ ...definition.properties })
89
+ : undefined;
90
+ this._definitions.set(localTileId, {
91
+ localTileId,
92
+ properties: props,
93
+ });
94
+ }
95
+ /**
96
+ * Build definitions from an array, replacing the internal definitions map.
97
+ * Each entry's properties are copied and frozen.
98
+ * @internal
99
+ */
100
+ _setDefinitions(definitions) {
101
+ const map = this._definitions;
102
+ map.clear();
103
+ for (const def of definitions) {
104
+ const props = def.properties
105
+ ? Object.freeze({ ...def.properties })
106
+ : undefined;
107
+ map.set(def.localTileId, { localTileId: def.localTileId, properties: props });
108
+ }
109
+ }
110
+ /**
111
+ * Retrieve per-tile metadata, or undefined if none defined.
112
+ * @advanced
113
+ */
114
+ getTileDefinition(localTileId) {
115
+ return this._definitions.get(localTileId);
116
+ }
117
+ /**
118
+ * Compute the pixel-space source rectangle for a local tile ID
119
+ * within the atlas, accounting for columns, spacing, and margin.
120
+ * @advanced
121
+ */
122
+ getTileRect(localTileId) {
123
+ if (localTileId < 0 || localTileId >= this.tileCount) {
124
+ throw new Error(`getTileRect: localTileId ${localTileId} out of range [0, ${this.tileCount - 1}].`);
125
+ }
126
+ const col = localTileId % this.columns;
127
+ const row = Math.floor(localTileId / this.columns);
128
+ return {
129
+ x: this.margin + col * (this.tileWidth + this.spacing),
130
+ y: this.margin + row * (this.tileHeight + this.spacing),
131
+ width: this.tileWidth,
132
+ height: this.tileHeight,
133
+ };
134
+ }
135
+ /**
136
+ * Iterate over all defined tiles (sparse).
137
+ * @advanced
138
+ */
139
+ definedTiles() {
140
+ return this._definitions.values();
141
+ }
142
+ /**
143
+ * Read-only snapshot of all per-tile definitions.
144
+ * The returned record is a caller-owned copy.
145
+ * @advanced
146
+ */
147
+ get allDefinitions() {
148
+ const result = {};
149
+ for (const [id, def] of this._definitions) {
150
+ result[id] = def.properties;
151
+ }
152
+ return Object.freeze(result);
153
+ }
154
+ }
155
+
156
+ export { TileSet };
157
+ //# sourceMappingURL=TileSet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TileSet.js","sources":["../../../src/TileSet.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}