@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.
Files changed (151) hide show
  1. package/README.md +33 -26
  2. package/dist/esm/ChunkSource.d.ts +33 -0
  3. package/dist/esm/ChunkSource.d.ts.map +1 -0
  4. package/dist/esm/ChunkStreamer.d.ts +98 -0
  5. package/dist/esm/ChunkStreamer.d.ts.map +1 -0
  6. package/dist/esm/ChunkStreamer.js +201 -0
  7. package/dist/esm/ChunkStreamer.js.map +1 -0
  8. package/dist/esm/ImageLayer.d.ts +11 -3
  9. package/dist/esm/ImageLayer.d.ts.map +1 -0
  10. package/dist/esm/ImageLayer.js +71 -64
  11. package/dist/esm/ImageLayer.js.map +1 -1
  12. package/dist/esm/ImageLayerNode.d.ts +89 -0
  13. package/dist/esm/ImageLayerNode.d.ts.map +1 -0
  14. package/dist/esm/ImageLayerNode.js +205 -0
  15. package/dist/esm/ImageLayerNode.js.map +1 -0
  16. package/dist/esm/MapObject.d.ts +70 -0
  17. package/dist/esm/MapObject.d.ts.map +1 -0
  18. package/dist/esm/MapObject.js +34 -0
  19. package/dist/esm/MapObject.js.map +1 -0
  20. package/dist/esm/MapObjectSpawner.d.ts +133 -0
  21. package/dist/esm/MapObjectSpawner.d.ts.map +1 -0
  22. package/dist/esm/MapObjectSpawner.js +147 -0
  23. package/dist/esm/MapObjectSpawner.js.map +1 -0
  24. package/dist/esm/MapSpawnSession.d.ts +53 -0
  25. package/dist/esm/MapSpawnSession.d.ts.map +1 -0
  26. package/dist/esm/MapSpawnSession.js +88 -0
  27. package/dist/esm/MapSpawnSession.js.map +1 -0
  28. package/dist/esm/MapWorld.d.ts +134 -0
  29. package/dist/esm/MapWorld.d.ts.map +1 -0
  30. package/dist/esm/MapWorld.js +150 -0
  31. package/dist/esm/MapWorld.js.map +1 -0
  32. package/dist/esm/MapWorldRuntime.d.ts +182 -0
  33. package/dist/esm/MapWorldRuntime.d.ts.map +1 -0
  34. package/dist/esm/MapWorldRuntime.js +261 -0
  35. package/dist/esm/MapWorldRuntime.js.map +1 -0
  36. package/dist/esm/ObjectLayer.d.ts +93 -7
  37. package/dist/esm/ObjectLayer.d.ts.map +1 -0
  38. package/dist/esm/ObjectLayer.js +184 -167
  39. package/dist/esm/ObjectLayer.js.map +1 -1
  40. package/dist/esm/SampledChunkSource.d.ts +43 -0
  41. package/dist/esm/SampledChunkSource.d.ts.map +1 -0
  42. package/dist/esm/SampledChunkSource.js +48 -0
  43. package/dist/esm/SampledChunkSource.js.map +1 -0
  44. package/dist/esm/TileAnimator.d.ts +12 -2
  45. package/dist/esm/TileAnimator.d.ts.map +1 -0
  46. package/dist/esm/TileAnimator.js +154 -165
  47. package/dist/esm/TileAnimator.js.map +1 -1
  48. package/dist/esm/TileChunk.d.ts +30 -5
  49. package/dist/esm/TileChunk.d.ts.map +1 -0
  50. package/dist/esm/TileChunk.js +190 -188
  51. package/dist/esm/TileChunk.js.map +1 -1
  52. package/dist/esm/TileChunkNode.d.ts +18 -3
  53. package/dist/esm/TileChunkNode.d.ts.map +1 -0
  54. package/dist/esm/TileChunkNode.js +104 -85
  55. package/dist/esm/TileChunkNode.js.map +1 -1
  56. package/dist/esm/TileLayer.d.ts +104 -24
  57. package/dist/esm/TileLayer.d.ts.map +1 -0
  58. package/dist/esm/TileLayer.js +511 -469
  59. package/dist/esm/TileLayer.js.map +1 -1
  60. package/dist/esm/TileLayerNode.d.ts +52 -11
  61. package/dist/esm/TileLayerNode.d.ts.map +1 -0
  62. package/dist/esm/TileLayerNode.js +224 -166
  63. package/dist/esm/TileLayerNode.js.map +1 -1
  64. package/dist/esm/TileMap.d.ts +96 -31
  65. package/dist/esm/TileMap.d.ts.map +1 -0
  66. package/dist/esm/TileMap.js +401 -357
  67. package/dist/esm/TileMap.js.map +1 -1
  68. package/dist/esm/TileMapBand.d.ts +42 -29
  69. package/dist/esm/TileMapBand.d.ts.map +1 -0
  70. package/dist/esm/TileMapBand.js +151 -158
  71. package/dist/esm/TileMapBand.js.map +1 -1
  72. package/dist/esm/TileMapNode.d.ts +34 -18
  73. package/dist/esm/TileMapNode.d.ts.map +1 -0
  74. package/dist/esm/TileMapNode.js +122 -109
  75. package/dist/esm/TileMapNode.js.map +1 -1
  76. package/dist/esm/TileMapView.d.ts +108 -47
  77. package/dist/esm/TileMapView.d.ts.map +1 -0
  78. package/dist/esm/TileMapView.js +385 -338
  79. package/dist/esm/TileMapView.js.map +1 -1
  80. package/dist/esm/TileSet.d.ts +15 -6
  81. package/dist/esm/TileSet.d.ts.map +1 -0
  82. package/dist/esm/TileSet.js +161 -181
  83. package/dist/esm/TileSet.js.map +1 -1
  84. package/dist/esm/WangSet.d.ts +5 -4
  85. package/dist/esm/WangSet.d.ts.map +1 -0
  86. package/dist/esm/WangSet.js +70 -78
  87. package/dist/esm/WangSet.js.map +1 -1
  88. package/dist/esm/WorkerSampledChunkSource.d.ts +95 -0
  89. package/dist/esm/WorkerSampledChunkSource.d.ts.map +1 -0
  90. package/dist/esm/WorkerSampledChunkSource.js +117 -0
  91. package/dist/esm/WorkerSampledChunkSource.js.map +1 -0
  92. package/dist/esm/autoTile.d.ts +10 -5
  93. package/dist/esm/autoTile.d.ts.map +1 -0
  94. package/dist/esm/autoTile.js +164 -205
  95. package/dist/esm/autoTile.js.map +1 -1
  96. package/dist/esm/chunkGeometry.d.ts +8 -7
  97. package/dist/esm/chunkGeometry.d.ts.map +1 -0
  98. package/dist/esm/chunkGeometry.js +83 -94
  99. package/dist/esm/chunkGeometry.js.map +1 -1
  100. package/dist/esm/index.d.ts +1 -0
  101. package/dist/esm/index.d.ts.map +1 -0
  102. package/dist/esm/index.js +26 -15
  103. package/dist/esm/nodeBounds.d.ts +20 -0
  104. package/dist/esm/nodeBounds.d.ts.map +1 -0
  105. package/dist/esm/nodeBounds.js +40 -0
  106. package/dist/esm/nodeBounds.js.map +1 -0
  107. package/dist/esm/pixelSnap.d.ts +4 -3
  108. package/dist/esm/pixelSnap.d.ts.map +1 -0
  109. package/dist/esm/pixelSnap.js +18 -16
  110. package/dist/esm/pixelSnap.js.map +1 -1
  111. package/dist/esm/public.d.ts +23 -3
  112. package/dist/esm/public.d.ts.map +1 -0
  113. package/dist/esm/tileCollision.d.ts +190 -0
  114. package/dist/esm/tileCollision.d.ts.map +1 -0
  115. package/dist/esm/tileCollision.js +367 -0
  116. package/dist/esm/tileCollision.js.map +1 -0
  117. package/dist/esm/tileWord.d.ts +12 -0
  118. package/dist/esm/tileWord.d.ts.map +1 -0
  119. package/dist/esm/tileWord.js +16 -0
  120. package/dist/esm/tileWord.js.map +1 -0
  121. package/dist/esm/tilemapExtension.d.ts +4 -3
  122. package/dist/esm/tilemapExtension.d.ts.map +1 -0
  123. package/dist/esm/tilemapExtension.js +47 -47
  124. package/dist/esm/tilemapExtension.js.map +1 -1
  125. package/dist/esm/tilemapSerializers.d.ts +5 -4
  126. package/dist/esm/tilemapSerializers.d.ts.map +1 -0
  127. package/dist/esm/tilemapSerializers.js +48 -41
  128. package/dist/esm/tilemapSerializers.js.map +1 -1
  129. package/dist/esm/types.d.ts +34 -18
  130. package/dist/esm/types.d.ts.map +1 -0
  131. package/dist/esm/types.js +111 -120
  132. package/dist/esm/types.js.map +1 -1
  133. package/dist/esm/webgl2/WebGl2TileChunkRenderer.d.ts +50 -2
  134. package/dist/esm/webgl2/WebGl2TileChunkRenderer.d.ts.map +1 -0
  135. package/dist/esm/webgl2/WebGl2TileChunkRenderer.js +366 -332
  136. package/dist/esm/webgl2/WebGl2TileChunkRenderer.js.map +1 -1
  137. package/dist/esm/webgl2/shaders/tile-chunk.frag.js +6 -0
  138. package/dist/esm/webgl2/shaders/tile-chunk.frag.js.map +1 -0
  139. package/dist/esm/webgl2/shaders/tile-chunk.vert.js +6 -0
  140. package/dist/esm/webgl2/shaders/tile-chunk.vert.js.map +1 -0
  141. package/dist/esm/webgpu/WebGpuTileChunkRenderer.d.ts +70 -4
  142. package/dist/esm/webgpu/WebGpuTileChunkRenderer.d.ts.map +1 -0
  143. package/dist/esm/webgpu/WebGpuTileChunkRenderer.js +496 -383
  144. package/dist/esm/webgpu/WebGpuTileChunkRenderer.js.map +1 -1
  145. package/dist/esm/webgpu/shaders/tile-chunk.wgsl.js +6 -0
  146. package/dist/esm/webgpu/shaders/tile-chunk.wgsl.js.map +1 -0
  147. package/package.json +8 -15
  148. package/dist/esm/index.js.map +0 -1
  149. package/dist/esm/register.d.ts +0 -1
  150. package/dist/esm/register.js +0 -25
  151. package/dist/esm/register.js.map +0 -1
package/dist/esm/types.js CHANGED
@@ -1,138 +1,129 @@
1
- // ── Properties ────────────────────────────────────────────────────────────
1
+ //#region src/types.ts
2
2
  /**
3
- * Discriminant for the three structured, non-scalar {@link TilePropertyValue}
4
- * variants: {@link TilePropertyPoint}, {@link TilePropertyObjectRef}, and
5
- * {@link TilePropertyTileRef}.
6
- *
7
- * Modelled as a frozen string map (not a TS `enum`) so the values stay
8
- * wire-stable, survive `verbatimModuleSyntax` (no emitted runtime helper),
9
- * and follow the package convention for enum-like constants (see
10
- * {@link import('./ObjectLayer').ObjectKind}).
11
- * @stable
12
- */
3
+ * Discriminant for the three structured, non-scalar {@link TilePropertyValue}
4
+ * variants: {@link TilePropertyPoint}, {@link TilePropertyObjectRef}, and
5
+ * {@link TilePropertyTileRef}.
6
+ *
7
+ * Modelled as a frozen string map (not a TS `enum`) so the values stay
8
+ * wire-stable, survive `verbatimModuleSyntax` (no emitted runtime helper),
9
+ * and follow the package convention for enum-like constants (see
10
+ * {@link import('./ObjectLayer').ObjectKind}).
11
+ * @stable
12
+ */
13
13
  const TilePropertyKind = {
14
- Point: 'point',
15
- ObjectRef: 'objectRef',
16
- TileRef: 'tileRef',
14
+ Point: "point",
15
+ ObjectRef: "objectRef",
16
+ TileRef: "tileRef"
17
17
  };
18
18
  /** The identity transform: no flip, no diagonal. */
19
19
  const TILE_TRANSFORM_IDENTITY = Object.freeze({
20
- flipX: false,
21
- flipY: false,
22
- diagonal: false,
20
+ flipX: false,
21
+ flipY: false,
22
+ diagonal: false
23
23
  });
24
24
  /** Bit width allocated to the local tile ID within a packed tile word. */
25
25
  const PACKED_LOCAL_BITS = 20;
26
- /** Bit width allocated to the tileset index within a packed tile word. */
27
- const PACKED_TILESET_BITS = 9;
28
- /** Bit width allocated to the transform/flip bits. */
29
- const PACKED_TRANSFORM_BITS = 3;
30
- const PACKED_LOCAL_MASK = (1 << PACKED_LOCAL_BITS) - 1;
31
- const PACKED_TILESET_MASK = ((1 << PACKED_TILESET_BITS) - 1) << PACKED_LOCAL_BITS;
32
- const PACKED_TRANSFORM_MASK = ((1 << PACKED_TRANSFORM_BITS) - 1) << (PACKED_LOCAL_BITS + PACKED_TILESET_BITS);
33
- const PACKED_TILESET_SHIFT = PACKED_LOCAL_BITS;
34
- const PACKED_TRANSFORM_SHIFT = PACKED_LOCAL_BITS + PACKED_TILESET_BITS;
26
+ const PACKED_LOCAL_MASK = (1 << 20) - 1;
27
+ const PACKED_TILESET_MASK = 511 << 20;
28
+ const PACKED_TRANSFORM_MASK = 7 << 29;
29
+ const PACKED_TILESET_SHIFT = 20;
30
+ const PACKED_TRANSFORM_SHIFT = 29;
35
31
  /** Maximum tileset index representable in a packed tile. */
36
- const MAX_TILESET_INDEX = (1 << PACKED_TILESET_BITS) - 1;
32
+ const MAX_TILESET_INDEX = 511;
37
33
  /** Maximum local tile ID representable in a packed tile (1-based storage). */
38
- const MAX_LOCAL_TILE_ID = (1 << PACKED_LOCAL_BITS) - 2;
39
- // Transform bit-field values (bit 0 = flipX, bit 1 = flipY, bit 2 = diagonal).
40
- const TRANSFORM_FLIP_X = 1 << 0;
41
- const TRANSFORM_FLIP_Y = 1 << 1;
42
- const TRANSFORM_DIAGONAL = 1 << 2;
34
+ const MAX_LOCAL_TILE_ID = (1 << 20) - 2;
35
+ const TRANSFORM_FLIP_X = 1;
36
+ const TRANSFORM_FLIP_Y = 2;
37
+ const TRANSFORM_DIAGONAL = 4;
43
38
  /**
44
- * Encode a tileset-local tile reference and transform into a packed word.
45
- * The localTileId is stored as (localTileId + 1) so that a packed value of 0
46
- * cleanly represents an empty cell, while tile 0 from tileset 0 with identity
47
- * transform is stored as 1 (non-zero).
48
- * Returns 0 for an empty cell.
49
- * @internal
50
- */
51
- function packTile(tilesetIndex, localTileId, transform) {
52
- if (tilesetIndex < 0 || tilesetIndex > MAX_TILESET_INDEX) {
53
- throw new Error(`Tileset index ${tilesetIndex} exceeds maximum ${MAX_TILESET_INDEX}.`);
54
- }
55
- if (localTileId < 0 || localTileId > MAX_LOCAL_TILE_ID) {
56
- throw new Error(`Local tile ID ${localTileId} exceeds maximum ${MAX_LOCAL_TILE_ID}.`);
57
- }
58
- let bits = 0;
59
- if (transform.flipX)
60
- bits |= TRANSFORM_FLIP_X;
61
- if (transform.flipY)
62
- bits |= TRANSFORM_FLIP_Y;
63
- if (transform.diagonal)
64
- bits |= TRANSFORM_DIAGONAL;
65
- // +1 so 0 means "empty" not "tile 0 without transform"
66
- const storedId = localTileId + 1;
67
- return (storedId & PACKED_LOCAL_MASK)
68
- | ((tilesetIndex << PACKED_TILESET_SHIFT) & PACKED_TILESET_MASK)
69
- | ((bits << PACKED_TRANSFORM_SHIFT) & PACKED_TRANSFORM_MASK);
70
- }
39
+ * Encode a tileset-local tile reference and transform into a packed word.
40
+ * The localTileId is stored as (localTileId + 1) so that a packed value of 0
41
+ * cleanly represents an empty cell, while tile 0 from tileset 0 with identity
42
+ * transform is stored as 1 (non-zero).
43
+ * Returns 0 for an empty cell.
44
+ *
45
+ * Public so chunk-provider authors (e.g. a format adapter or procedural
46
+ * generator) can build a {@link ChunkPayload}'s `tiles` array without
47
+ * duplicating this encoding.
48
+ * @advanced
49
+ */
50
+ const packTile = (tilesetIndex, localTileId, transform) => {
51
+ if (tilesetIndex < 0 || tilesetIndex > 511) throw new Error(`Tileset index ${tilesetIndex} exceeds maximum ${511}.`);
52
+ if (localTileId < 0 || localTileId > 1048574) throw new Error(`Local tile ID ${localTileId} exceeds maximum ${MAX_LOCAL_TILE_ID}.`);
53
+ let bits = 0;
54
+ if (transform.flipX) bits |= TRANSFORM_FLIP_X;
55
+ if (transform.flipY) bits |= TRANSFORM_FLIP_Y;
56
+ if (transform.diagonal) bits |= TRANSFORM_DIAGONAL;
57
+ return localTileId + 1 & PACKED_LOCAL_MASK | tilesetIndex << 20 & PACKED_TILESET_MASK | bits << 29 & PACKED_TRANSFORM_MASK;
58
+ };
71
59
  /**
72
- * Decode a packed word into its components.
73
- * Returns null for an empty cell (packed === 0).
74
- * @internal
75
- */
76
- function unpackTile(packed) {
77
- if (packed === 0)
78
- return null;
79
- const storedId = packed & PACKED_LOCAL_MASK;
80
- // Undo the +1 offset applied during packTile.
81
- const localTileId = storedId - 1;
82
- const tilesetIndex = (packed & PACKED_TILESET_MASK) >>> PACKED_TILESET_SHIFT;
83
- const rawTransform = (packed & PACKED_TRANSFORM_MASK) >>> PACKED_TRANSFORM_SHIFT;
84
- return {
85
- tilesetIndex,
86
- localTileId,
87
- transform: {
88
- flipX: !!(rawTransform & TRANSFORM_FLIP_X),
89
- flipY: !!(rawTransform & TRANSFORM_FLIP_Y),
90
- diagonal: !!(rawTransform & TRANSFORM_DIAGONAL),
91
- },
92
- };
93
- }
60
+ * Decode a packed word into its components.
61
+ * Returns null for an empty cell (packed === 0).
62
+ * @advanced
63
+ */
64
+ const unpackTile = (packed) => {
65
+ if (packed === 0) return null;
66
+ const localTileId = (packed & PACKED_LOCAL_MASK) - 1;
67
+ const tilesetIndex = (packed & PACKED_TILESET_MASK) >>> 20;
68
+ const rawTransform = (packed & PACKED_TRANSFORM_MASK) >>> 29;
69
+ return {
70
+ tilesetIndex,
71
+ localTileId,
72
+ transform: {
73
+ flipX: !!(rawTransform & TRANSFORM_FLIP_X),
74
+ flipY: !!(rawTransform & TRANSFORM_FLIP_Y),
75
+ diagonal: !!(rawTransform & TRANSFORM_DIAGONAL)
76
+ }
77
+ };
78
+ };
94
79
  /** Convert tile coordinates to chunk coordinates given a chunk size. */
95
- function tileToChunkCoord(tx, ty, chunkW, chunkH) {
96
- return {
97
- cx: Math.floor(tx / chunkW),
98
- cy: Math.floor(ty / chunkH),
99
- };
100
- }
80
+ const tileToChunkCoord = (tx, ty, chunkW, chunkH) => ({
81
+ cx: Math.floor(tx / chunkW),
82
+ cy: Math.floor(ty / chunkH)
83
+ });
101
84
  /** Convert tile coordinates to local-in-chunk coordinates. */
102
- function tileToLocalInChunk(tx, ty, chunkW, chunkH) {
103
- return {
104
- lx: ((tx % chunkW) + chunkW) % chunkW,
105
- ly: ((ty % chunkH) + chunkH) % chunkH,
106
- };
107
- }
85
+ const tileToLocalInChunk = (tx, ty, chunkW, chunkH) => ({
86
+ lx: (tx % chunkW + chunkW) % chunkW,
87
+ ly: (ty % chunkH + chunkH) % chunkH
88
+ });
108
89
  /**
109
- * Validate that a value is a finite, safe, positive integer.
110
- * Used for dimensions, tile counts, chunk sizes.
111
- */
112
- function validatePositiveInteger(value, label) {
113
- if (!Number.isFinite(value) || !Number.isInteger(value) || value <= 0) {
114
- throw new Error(`${label} must be a positive integer (got ${value}).`);
115
- }
116
- if (value > Number.MAX_SAFE_INTEGER) {
117
- throw new Error(`${label} exceeds safe integer range (got ${value}).`);
118
- }
119
- }
90
+ * Validate that a value is a finite, safe, positive integer.
91
+ * Used for dimensions, tile counts, chunk sizes.
92
+ */
93
+ const validatePositiveInteger = (value, label) => {
94
+ if (!Number.isFinite(value) || !Number.isInteger(value) || value <= 0) throw new Error(`${label} must be a positive integer (got ${value}).`);
95
+ if (value > Number.MAX_SAFE_INTEGER) throw new Error(`${label} exceeds safe integer range (got ${value}).`);
96
+ };
120
97
  /**
121
- * Validate a non-negative finite integer.
122
- */
123
- function validateNonNegativeInteger(value, label) {
124
- if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {
125
- throw new Error(`${label} must be a non-negative integer (got ${value}).`);
126
- }
127
- }
98
+ * Validate a non-negative finite integer.
99
+ */
100
+ const validateNonNegativeInteger = (value, label) => {
101
+ if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) throw new Error(`${label} must be a non-negative integer (got ${value}).`);
102
+ };
103
+ /**
104
+ * Validate that a value is a finite integer (may be negative).
105
+ */
106
+ const validateInteger = (value, label) => {
107
+ if (!Number.isFinite(value) || !Number.isInteger(value)) throw new Error(`${label} must be a finite integer (got ${value}).`);
108
+ };
128
109
  /**
129
- * Validate that a value is a finite integer (may be negative).
130
- */
131
- function validateInteger(value, label) {
132
- if (!Number.isFinite(value) || !Number.isInteger(value)) {
133
- throw new Error(`${label} must be a finite integer (got ${value}).`);
134
- }
135
- }
110
+ * Validate a `width`/`height` pair that must be provided together (bounded)
111
+ * or omitted together (unbounded) - shared by {@link import('./TileLayer').TileLayer}
112
+ * and {@link import('./TileMap').TileMap}. When both are provided, each is
113
+ * validated as a positive integer via {@link validatePositiveInteger}.
114
+ *
115
+ * @param entityName Used in the paired-presence error message (e.g. `"TileLayer"`).
116
+ * @param fieldPrefix Used as the field-name prefix passed to {@link validatePositiveInteger} (e.g. `"layer"` for `"layer.width"`).
117
+ * @throws If exactly one of `width`/`height` is provided, or either is not a positive integer.
118
+ */
119
+ const validatePairedDimensions = (width, height, entityName, fieldPrefix) => {
120
+ if (width !== void 0 || height !== void 0) {
121
+ if (width === void 0 || height === void 0) throw new Error(`${entityName} width and height must both be provided (bounded) or both omitted (unbounded).`);
122
+ validatePositiveInteger(width, `${fieldPrefix}.width`);
123
+ validatePositiveInteger(height, `${fieldPrefix}.height`);
124
+ }
125
+ };
136
126
 
137
- export { MAX_LOCAL_TILE_ID, MAX_TILESET_INDEX, PACKED_LOCAL_BITS, PACKED_LOCAL_MASK, PACKED_TILESET_BITS, PACKED_TILESET_MASK, PACKED_TILESET_SHIFT, PACKED_TRANSFORM_BITS, PACKED_TRANSFORM_MASK, PACKED_TRANSFORM_SHIFT, TILE_TRANSFORM_IDENTITY, TilePropertyKind, packTile, tileToChunkCoord, tileToLocalInChunk, unpackTile, validateInteger, validateNonNegativeInteger, validatePositiveInteger };
138
- //# sourceMappingURL=types.js.map
127
+ //#endregion
128
+ export { MAX_LOCAL_TILE_ID, PACKED_LOCAL_MASK, PACKED_TILESET_MASK, PACKED_TRANSFORM_MASK, TILE_TRANSFORM_IDENTITY, TilePropertyKind, packTile, tileToChunkCoord, tileToLocalInChunk, unpackTile, validateInteger, validateNonNegativeInteger, validatePairedDimensions, validatePositiveInteger };
129
+ //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sources":["../../../src/types.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../src/types.ts"],"sourcesContent":["import type { TileMapObject } from './ObjectLayer';\nimport type { TileSet } from './TileSet';\n\n// ── Properties ────────────────────────────────────────────────────────────\n\n/**\n * Discriminant for the three structured, non-scalar {@link TilePropertyValue}\n * variants: {@link TilePropertyPoint}, {@link TilePropertyObjectRef}, and\n * {@link TilePropertyTileRef}.\n *\n * Modelled as a frozen string map (not a TS `enum`) so the values stay\n * wire-stable, survive `verbatimModuleSyntax` (no emitted runtime helper),\n * and follow the package convention for enum-like constants (see\n * {@link import('./ObjectLayer').ObjectKind}).\n * @stable\n */\nexport const TilePropertyKind = {\n Point: 'point',\n ObjectRef: 'objectRef',\n TileRef: 'tileRef',\n} as const;\n\n/** Structured-value discriminant for {@link TilePropertyValue}. */\nexport type TilePropertyKind = (typeof TilePropertyKind)[keyof typeof TilePropertyKind];\n\n/** A 2D point-valued tile property (e.g. an LDtk `Point` field). */\nexport interface TilePropertyPoint {\n readonly kind: typeof TilePropertyKind.Point;\n readonly cx: number;\n readonly cy: number;\n}\n\n/**\n * A reference to another object/entity. `id` is the referenced object's\n * identity - Tiled's numeric object id, or LDtk's `entityIid`. The extra\n * fields are LDtk-only navigation context (`undefined` for Tiled-sourced\n * refs) that lets a consumer resolve the reference without searching the\n * whole level tree.\n */\nexport interface TilePropertyObjectRef {\n readonly kind: typeof TilePropertyKind.ObjectRef;\n readonly id: string | number;\n readonly layerIid?: string;\n readonly levelIid?: string;\n readonly worldIid?: string;\n}\n\n/** A reference into a tileset region (e.g. an LDtk `Tile`-typed field). */\nexport interface TilePropertyTileRef {\n readonly kind: typeof TilePropertyKind.TileRef;\n readonly tilesetUid: number;\n readonly x: number;\n readonly y: number;\n readonly w: number;\n readonly h: number;\n}\n\n/**\n * Union of legal tile-property value types in the generic runtime.\n * Format-neutral; adapters map their native property systems into this set -\n * including the structured {@link TilePropertyPoint}, {@link TilePropertyObjectRef},\n * and {@link TilePropertyTileRef} variants, arrays of any of the above, and\n * nested property bags (e.g. Tiled `class`-typed properties).\n * @advanced\n */\nexport type TilePropertyValue =\n null | boolean | number | string | TilePropertyPoint | TilePropertyObjectRef | TilePropertyTileRef | readonly TilePropertyValue[] | TileProperties;\n\n/**\n * An immutable, flat key-value bag of generic tile properties.\n * Adapters copy and freeze source properties; the runtime never retains\n * a caller-owned mutable object.\n *\n * Declared as an interface (not a `Record<...>` type alias) so it can\n * mutually recurse with {@link TilePropertyValue} - a nested-bag member of\n * that union - without TypeScript's \"circularly references itself\" alias\n * restriction; structurally it behaves exactly like\n * `Readonly<Record<string, TilePropertyValue>>`.\n * @advanced\n */\nexport interface TileProperties {\n readonly [key: string]: TilePropertyValue;\n}\n\n// ── Tile orientation / transform ──────────────────────────────────────────\n\n/**\n * Describes the orientation of a placed tile independent of source-format\n * flip-bit encodings. The eight legal combinations map to the eight distinct\n * 90°-rotation-and-flip states of a rectangular texture quad.\n *\n * Applying the transform at geometry-build time (reordering UV corners)\n * avoids per-tile runtime cost and per-frame matrix allocation.\n * @stable\n */\nexport interface TileTransform {\n /** Horizontal flip (mirror left-right). */\n readonly flipX: boolean;\n /** Vertical flip (mirror top-bottom). */\n readonly flipY: boolean;\n /** Anti-diagonal flip (transpose of the UV axes). Combined with flips produces 90° rotations. */\n readonly diagonal: boolean;\n}\n\n/** The identity transform: no flip, no diagonal. */\nexport const TILE_TRANSFORM_IDENTITY: Readonly<TileTransform> = Object.freeze({\n flipX: false,\n flipY: false,\n diagonal: false,\n});\n\n/**\n * Short string label for a {@link TileTransform} (debug / serialisation).\n * Returns one of the eight deterministic names, e.g. `\"flipX\"` or `\"diag+flipX+flipY\"`.\n * @internal\n */\nexport const tileTransformLabel = (t: TileTransform): string => {\n const parts: string[] = [];\n if (t.diagonal) parts.push('diag');\n if (t.flipX) parts.push('flipX');\n if (t.flipY) parts.push('flipY');\n return parts.length === 0 ? 'identity' : parts.join('+');\n};\n\n// ── Tile identity ─────────────────────────────────────────────────────────\n\n/**\n * Opaque packed tile data stored in a {@link TileChunk}'s compact array.\n * 0 means \"empty cell\". Any non-zero value encodes localTileId, tilesetIndex,\n * and flip bits according to the bit-layout constants below.\n *\n * A `PackedTile` is **not** a source-format GID - it is a fully resolved\n * internal compact representation. Use {@link packTile} / {@link unpackTile}\n * to convert between packed form and a {@link ResolvedTile} if writing\n * adapters.\n *\n * In public APIs, prefer {@link ResolvedTile} or null for queries.\n * `PackedTile` is exposed as `@advanced` so `ReadonlyTileChunk.getRawAt()`\n * has a self-documenting return type.\n * @advanced\n */\nexport type PackedTile = number;\n\n/** Bit width allocated to the local tile ID within a packed tile word. */\nexport const PACKED_LOCAL_BITS = 20;\n/** Bit width allocated to the tileset index within a packed tile word. */\nexport const PACKED_TILESET_BITS = 9;\n/** Bit width allocated to the transform/flip bits. */\nexport const PACKED_TRANSFORM_BITS = 3;\n\nexport const PACKED_LOCAL_MASK = (1 << PACKED_LOCAL_BITS) - 1;\nexport const PACKED_TILESET_MASK = ((1 << PACKED_TILESET_BITS) - 1) << PACKED_LOCAL_BITS;\nexport const PACKED_TRANSFORM_MASK = ((1 << PACKED_TRANSFORM_BITS) - 1) << (PACKED_LOCAL_BITS + PACKED_TILESET_BITS);\n\nexport const PACKED_TILESET_SHIFT = PACKED_LOCAL_BITS;\nexport const PACKED_TRANSFORM_SHIFT = PACKED_LOCAL_BITS + PACKED_TILESET_BITS;\n\n/** Maximum tileset index representable in a packed tile. */\nexport const MAX_TILESET_INDEX = (1 << PACKED_TILESET_BITS) - 1;\n/** Maximum local tile ID representable in a packed tile (1-based storage). */\nexport const MAX_LOCAL_TILE_ID = (1 << PACKED_LOCAL_BITS) - 2;\n\n// Transform bit-field values (bit 0 = flipX, bit 1 = flipY, bit 2 = diagonal).\nconst TRANSFORM_FLIP_X = 1 << 0;\nconst TRANSFORM_FLIP_Y = 1 << 1;\nconst TRANSFORM_DIAGONAL = 1 << 2;\n\n/**\n * Encode a tileset-local tile reference and transform into a packed word.\n * The localTileId is stored as (localTileId + 1) so that a packed value of 0\n * cleanly represents an empty cell, while tile 0 from tileset 0 with identity\n * transform is stored as 1 (non-zero).\n * Returns 0 for an empty cell.\n *\n * Public so chunk-provider authors (e.g. a format adapter or procedural\n * generator) can build a {@link ChunkPayload}'s `tiles` array without\n * duplicating this encoding.\n * @advanced\n */\nexport const packTile = (tilesetIndex: number, localTileId: number, transform: TileTransform): PackedTile => {\n if (tilesetIndex < 0 || tilesetIndex > MAX_TILESET_INDEX) {\n throw new Error(`Tileset index ${tilesetIndex} exceeds maximum ${MAX_TILESET_INDEX}.`);\n }\n if (localTileId < 0 || localTileId > MAX_LOCAL_TILE_ID) {\n throw new Error(`Local tile ID ${localTileId} exceeds maximum ${MAX_LOCAL_TILE_ID}.`);\n }\n let bits = 0;\n if (transform.flipX) bits |= TRANSFORM_FLIP_X;\n if (transform.flipY) bits |= TRANSFORM_FLIP_Y;\n if (transform.diagonal) bits |= TRANSFORM_DIAGONAL;\n // +1 so 0 means \"empty\" not \"tile 0 without transform\"\n const storedId = localTileId + 1;\n return (\n (storedId & PACKED_LOCAL_MASK) | ((tilesetIndex << PACKED_TILESET_SHIFT) & PACKED_TILESET_MASK) | ((bits << PACKED_TRANSFORM_SHIFT) & PACKED_TRANSFORM_MASK)\n );\n};\n\n/**\n * Decode a packed word into its components.\n * Returns null for an empty cell (packed === 0).\n * @advanced\n */\nexport const unpackTile = (\n packed: PackedTile,\n): {\n tilesetIndex: number;\n localTileId: number;\n transform: TileTransform;\n} | null => {\n if (packed === 0) return null;\n const storedId = packed & PACKED_LOCAL_MASK;\n // Undo the +1 offset applied during packTile.\n const localTileId = storedId - 1;\n const tilesetIndex = (packed & PACKED_TILESET_MASK) >>> PACKED_TILESET_SHIFT;\n const rawTransform = (packed & PACKED_TRANSFORM_MASK) >>> PACKED_TRANSFORM_SHIFT;\n return {\n tilesetIndex,\n localTileId,\n transform: {\n flipX: !!(rawTransform & TRANSFORM_FLIP_X),\n flipY: !!(rawTransform & TRANSFORM_FLIP_Y),\n diagonal: !!(rawTransform & TRANSFORM_DIAGONAL),\n },\n };\n};\n\n// ── Resolved tile reference (public query result) ─────────────────────────\n\n/**\n * A fully resolved, format-independent tile reference returned by queries.\n * Materialised on-demand from the packed storage; never stored as a per-cell\n * heap object.\n * @advanced\n */\nexport interface ResolvedTile {\n /** The owning tileset (already resolved from source-format GID). */\n readonly tileset: TileSet;\n /** 0-based tile index within the tileset. */\n readonly localTileId: number;\n /** Orientation transform for this placed tile. */\n readonly transform: TileTransform;\n}\n\n// ── Tile animation ────────────────────────────────────────────────────────\n\n/**\n * One frame of a tile animation: which local tile to show, and for how long.\n * Mirrors Tiled's per-tile animation frame model.\n * @advanced\n */\nexport interface TileAnimationFrame {\n /** Local tile ID shown during this frame (within the tile's own tileset). */\n readonly localTileId: number;\n /** Frame duration in milliseconds. */\n readonly duration: number;\n}\n\n// ── TileDefinition ────────────────────────────────────────────────────────\n\n/**\n * Optional per-tile metadata in a {@link TileSet}. Sparse - only defined\n * tiles carry a definition.\n * @advanced\n */\nexport interface TileDefinition {\n /** The local tile ID this definition belongs to. */\n readonly localTileId: number;\n /** Tile properties (copied and frozen by the tileset). */\n readonly properties?: TileProperties;\n /**\n * Animation frame sequence for this tile, if animated. The frames are\n * driven at runtime by a {@link import('./TileAnimator').TileAnimator};\n * frame[0] is the tile's resting/base frame.\n */\n readonly animation?: readonly TileAnimationFrame[];\n /**\n * Per-tile collision shapes sourced from the Tiled `objectgroup` on the tile.\n * Shapes are in tile-local pixel space (origin = top-left of the tile cell).\n * Only present when the source map defines collision geometry for this tile.\n */\n readonly collision?: readonly TileMapObject[];\n}\n\n// ── Chunk coordinate helpers ──────────────────────────────────────────────\n\n/** A signed chunk coordinate pair. */\nexport interface ChunkCoord {\n readonly cx: number;\n readonly cy: number;\n}\n\n/** Convert tile coordinates to chunk coordinates given a chunk size. */\nexport const tileToChunkCoord = (tx: number, ty: number, chunkW: number, chunkH: number): ChunkCoord => ({\n cx: Math.floor(tx / chunkW),\n cy: Math.floor(ty / chunkH),\n});\n\n/** Convert tile coordinates to local-in-chunk coordinates. */\nexport const tileToLocalInChunk = (tx: number, ty: number, chunkW: number, chunkH: number): { lx: number; ly: number } => ({\n lx: ((tx % chunkW) + chunkW) % chunkW,\n ly: ((ty % chunkH) + chunkH) % chunkH,\n});\n\n/**\n * Validate that a value is a finite, safe, positive integer.\n * Used for dimensions, tile counts, chunk sizes.\n */\nexport const validatePositiveInteger = (value: number, label: string): void => {\n if (!Number.isFinite(value) || !Number.isInteger(value) || value <= 0) {\n throw new Error(`${label} must be a positive integer (got ${value}).`);\n }\n if (value > Number.MAX_SAFE_INTEGER) {\n throw new Error(`${label} exceeds safe integer range (got ${value}).`);\n }\n};\n\n/**\n * Validate a non-negative finite integer.\n */\nexport const validateNonNegativeInteger = (value: number, label: string): void => {\n if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {\n throw new Error(`${label} must be a non-negative integer (got ${value}).`);\n }\n};\n\n/**\n * Validate that a value is a finite integer (may be negative).\n */\nexport const validateInteger = (value: number, label: string): void => {\n if (!Number.isFinite(value) || !Number.isInteger(value)) {\n throw new Error(`${label} must be a finite integer (got ${value}).`);\n }\n};\n\n/**\n * Validate a `width`/`height` pair that must be provided together (bounded)\n * or omitted together (unbounded) - shared by {@link import('./TileLayer').TileLayer}\n * and {@link import('./TileMap').TileMap}. When both are provided, each is\n * validated as a positive integer via {@link validatePositiveInteger}.\n *\n * @param entityName Used in the paired-presence error message (e.g. `\"TileLayer\"`).\n * @param fieldPrefix Used as the field-name prefix passed to {@link validatePositiveInteger} (e.g. `\"layer\"` for `\"layer.width\"`).\n * @throws If exactly one of `width`/`height` is provided, or either is not a positive integer.\n */\nexport const validatePairedDimensions = (width: number | undefined, height: number | undefined, entityName: string, fieldPrefix: string): void => {\n if (width !== undefined || height !== undefined) {\n if (width === undefined || height === undefined) {\n throw new Error(`${entityName} width and height must both be provided (bounded) or both omitted (unbounded).`);\n }\n validatePositiveInteger(width, `${fieldPrefix}.width`);\n validatePositiveInteger(height, `${fieldPrefix}.height`);\n }\n};\n"],"mappings":";;;;;;;;;;;;AAgBA,MAAa,mBAAmB;CAC9B,OAAO;CACP,WAAW;CACX,SAAS;AACX;;AAqFA,MAAa,0BAAmD,OAAO,OAAO;CAC5E,OAAO;CACP,OAAO;CACP,UAAU;AACZ,CAAC;;AAmCD,MAAa,oBAAoB;AAMjC,MAAa,qBAAqB,WAA0B;AAC5D,MAAa,sBAAuB;AACpC,MAAa,wBAAyB,KAAsC;AAE5E,MAAa;AACb,MAAa,yBAAyB;;AAGtC,MAAa,oBAAoB;;AAEjC,MAAa,qBAAqB,WAA0B;AAG5D,MAAM,mBAAmB;AACzB,MAAM,mBAAmB;AACzB,MAAM,qBAAqB;;;;;;;;;;;;;AAc3B,MAAa,YAAY,cAAsB,aAAqB,cAAyC;CAC3G,IAAI,eAAe,KAAK,oBACtB,MAAM,IAAI,MAAM,iBAAiB,aAAa,uBAAqC,EAAE;CAEvF,IAAI,cAAc,KAAK,uBACrB,MAAM,IAAI,MAAM,iBAAiB,YAAY,mBAAmB,kBAAkB,EAAE;CAEtF,IAAI,OAAO;CACX,IAAI,UAAU,OAAO,QAAQ;CAC7B,IAAI,UAAU,OAAO,QAAQ;CAC7B,IAAI,UAAU,UAAU,QAAQ;CAGhC,OADiB,cAAc,IAEjB,oBAAuB,qBAAwC,sBAAyB,aAAkC;AAE1I;;;;;;AAOA,MAAa,cACX,WAKU;CACV,IAAI,WAAW,GAAG,OAAO;CAGzB,MAAM,eAFW,SAAS,qBAEK;CAC/B,MAAM,gBAAgB,SAAS;CAC/B,MAAM,gBAAgB,SAAS;CAC/B,OAAO;EACL;EACA;EACA,WAAW;GACT,OAAO,CAAC,EAAE,eAAe;GACzB,OAAO,CAAC,EAAE,eAAe;GACzB,UAAU,CAAC,EAAE,eAAe;EAC9B;CACF;AACF;;AAoEA,MAAa,oBAAoB,IAAY,IAAY,QAAgB,YAAgC;CACvG,IAAI,KAAK,MAAM,KAAK,MAAM;CAC1B,IAAI,KAAK,MAAM,KAAK,MAAM;AAC5B;;AAGA,MAAa,sBAAsB,IAAY,IAAY,QAAgB,YAAgD;CACzH,KAAM,KAAK,SAAU,UAAU;CAC/B,KAAM,KAAK,SAAU,UAAU;AACjC;;;;;AAMA,MAAa,2BAA2B,OAAe,UAAwB;CAC7E,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,OAAO,UAAU,KAAK,KAAK,SAAS,GAClE,MAAM,IAAI,MAAM,GAAG,MAAM,mCAAmC,MAAM,GAAG;CAEvE,IAAI,QAAQ,OAAO,kBACjB,MAAM,IAAI,MAAM,GAAG,MAAM,mCAAmC,MAAM,GAAG;AAEzE;;;;AAKA,MAAa,8BAA8B,OAAe,UAAwB;CAChF,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,GACjE,MAAM,IAAI,MAAM,GAAG,MAAM,uCAAuC,MAAM,GAAG;AAE7E;;;;AAKA,MAAa,mBAAmB,OAAe,UAAwB;CACrE,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,OAAO,UAAU,KAAK,GACpD,MAAM,IAAI,MAAM,GAAG,MAAM,iCAAiC,MAAM,GAAG;AAEvE;;;;;;;;;;;AAYA,MAAa,4BAA4B,OAA2B,QAA4B,YAAoB,gBAA8B;CAChJ,IAAI,UAAU,UAAa,WAAW,QAAW;EAC/C,IAAI,UAAU,UAAa,WAAW,QACpC,MAAM,IAAI,MAAM,GAAG,WAAW,+EAA+E;EAE/G,wBAAwB,OAAO,GAAG,YAAY,OAAO;EACrD,wBAAwB,QAAQ,GAAG,YAAY,QAAQ;CACzD;AACF"}
@@ -1,4 +1,4 @@
1
- import type { WebGl2Backend } from '@codexo/exojs/renderer-sdk';
1
+ import type { WebGl2Backend, WebGl2RetainedBatchPayload, WebGl2RetainedBatchReplayer, WebGl2RetainedNodeIndexRange } from '@codexo/exojs/renderer-sdk';
2
2
  import { AbstractWebGl2Renderer } from '@codexo/exojs/renderer-sdk';
3
3
  import type { TileChunkNode } from '../TileChunkNode';
4
4
  /**
@@ -9,19 +9,35 @@ import type { TileChunkNode } from '../TileChunkNode';
9
9
  * orientation-neutral and never re-uploaded for a camera pan.
10
10
  * @internal
11
11
  */
12
- export declare class WebGl2TileChunkRenderer extends AbstractWebGl2Renderer<TileChunkNode> {
12
+ export declare class WebGl2TileChunkRenderer extends AbstractWebGl2Renderer<TileChunkNode> implements WebGl2RetainedBatchReplayer {
13
+ /**
14
+ * Retained-batch capability opt-in: a tile chunk's per-flush
15
+ * instanced batches (fixed 32-byte layout, tile word at word 7) can be
16
+ * recorded into a group's instruction set and replayed from group-owned
17
+ * resources. Pixel-snapped draws are excluded by the collect-time
18
+ * recordability predicate (and belt-and-braces poisoning in {@link render});
19
+ * tile chunks have no custom-material path to exclude.
20
+ * @internal
21
+ */
22
+ readonly _supportsRetainedBatches = true;
13
23
  private readonly _shader;
14
24
  private readonly _batchSize;
15
25
  private readonly _instanceData;
16
26
  private readonly _instanceFloat32;
17
27
  private readonly _instanceUint32;
18
28
  private readonly _transformUnitScratch;
29
+ private readonly _baseTextureUnitScratch;
30
+ private readonly _recordTextures;
19
31
  private _quadIndex;
20
32
  private _maxNodeIndex;
33
+ private _batchNodeCount;
34
+ private _nodeBooked;
21
35
  private _currentBlendMode;
22
36
  private _currentTexture;
23
37
  private _currentView;
24
38
  private _currentViewId;
39
+ private _hasWrittenGroup;
40
+ private readonly _writtenGroupData;
25
41
  private _instanceBuffer;
26
42
  private _vao;
27
43
  private _connection;
@@ -30,6 +46,37 @@ export declare class WebGl2TileChunkRenderer extends AbstractWebGl2Renderer<Tile
30
46
  private _renderPage;
31
47
  private _writeRun;
32
48
  flush(): void;
49
+ /**
50
+ * Stage `u_projection` (live view) and `u_group` (live composed group
51
+ * matrix) on the shader, guarded by cached view/group stamps. Shared by the
52
+ * live flush path and retained-batch replay - replay resolves exactly the
53
+ * same live state a slow-path flush would.
54
+ */
55
+ private _stageViewUniforms;
56
+ /** @internal See {@link WebGl2RetainedBatchReplayer._scanRetainedNodeIndexRange}. */
57
+ _scanRetainedNodeIndexRange(payload: WebGl2RetainedBatchPayload, range: WebGl2RetainedNodeIndexRange): void;
58
+ /** @internal See {@link WebGl2RetainedBatchReplayer._rebaseRetainedNodeIndices} (group-local indices). */
59
+ _rebaseRetainedNodeIndices(payload: WebGl2RetainedBatchPayload, base: number): void;
60
+ /**
61
+ * Point the batch VAO's per-instance attributes at the bundle's persistent
62
+ * instance buffer, based at the batch's byte offset (WebGL2 has no
63
+ * baseInstance, hence one small VAO per recorded batch). Same attribute
64
+ * set/locations as the live VAO in {@link onConnect}.
65
+ * @internal
66
+ */
67
+ _configureRetainedVao(payload: WebGl2RetainedBatchPayload): void;
68
+ /**
69
+ * Replay one recorded batch: all STATE is resolved live - blend mode via
70
+ * the backend's dedup, `u_projection`/`u_group` from the live view + live
71
+ * composed group matrix (the camera-pan / group-move win), the single
72
+ * tileset texture bound to unit 0 by recorded slot order - and only the
73
+ * DATA is cached: the instance bytes in the bundle buffer (bound through
74
+ * the per-batch VAO) and the group-owned transform texture on the shared
75
+ * transform unit. The backend hook flushed any pending live batch before
76
+ * dispatching here and bumps the stats from the instruction descriptor.
77
+ * @internal
78
+ */
79
+ _replayRetainedBatch(payload: WebGl2RetainedBatchPayload): void;
33
80
  protected onConnect(backend: WebGl2Backend): void;
34
81
  protected onDisconnect(): void;
35
82
  destroy(): void;
@@ -37,3 +84,4 @@ export declare class WebGl2TileChunkRenderer extends AbstractWebGl2Renderer<Tile
37
84
  private _createBufferRuntime;
38
85
  private _createVaoRuntime;
39
86
  }
87
+ //# sourceMappingURL=WebGl2TileChunkRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebGl2TileChunkRenderer.d.ts","sourceRoot":"","sources":["../../../src/webgl2/WebGl2TileChunkRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,aAAa,EAEb,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAE7B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,sBAAsB,EAavB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAqBtD;;;;;;;GAOG;AACH,qBAAa,uBAAwB,SAAQ,sBAAsB,CAAC,aAAa,CAAE,YAAW,2BAA2B;IACvH;;;;;;;;OAQG;IACH,SAAgB,wBAAwB,QAAQ;IAEhD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAc;IAC5C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAe;IAChD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAc;IAE9C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAsD;IAG5F,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAmC;IAG3E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiD;IAEjF,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,aAAa,CAAK;IAM1B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAA2B;IACpD,OAAO,CAAC,eAAe,CAAwB;IAC/C,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,cAAc,CAAM;IAC5B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAuB;IAEzD,OAAO,CAAC,eAAe,CAAmC;IAC1D,OAAO,CAAC,IAAI,CAAwC;IACpD,OAAO,CAAC,WAAW,CAAuC;gBAEvC,SAAS,EAAE,MAAM;IAU7B,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAsBxC,OAAO,CAAC,WAAW;IA8CnB,OAAO,CAAC,SAAS;IA0DV,KAAK,IAAI,IAAI;IAqDpB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IA4B1B,qFAAqF;IAC9E,2BAA2B,CAAC,OAAO,EAAE,0BAA0B,EAAE,KAAK,EAAE,4BAA4B,GAAG,IAAI;IAqBlH,0GAA0G;IACnG,0BAA0B,CAAC,OAAO,EAAE,0BAA0B,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAgB1F;;;;;;OAMG;IACI,qBAAqB,CAAC,OAAO,EAAE,0BAA0B,GAAG,IAAI;IAkBvE;;;;;;;;;;OAUG;IACI,oBAAoB,CAAC,OAAO,EAAE,0BAA0B,GAAG,IAAI;IAgDtE,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAkBjD,SAAS,CAAC,YAAY,IAAI,IAAI;IAkBvB,OAAO,IAAI,IAAI;IAKtB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,oBAAoB;IAiC5B,OAAO,CAAC,iBAAiB;CA8C1B"}