@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.
- package/LICENSE +21 -0
- package/README.md +187 -0
- package/dist/esm/TileChunk.d.ts +136 -0
- package/dist/esm/TileChunk.js +192 -0
- package/dist/esm/TileChunk.js.map +1 -0
- package/dist/esm/TileChunkNode.d.ts +59 -0
- package/dist/esm/TileChunkNode.js +89 -0
- package/dist/esm/TileChunkNode.js.map +1 -0
- package/dist/esm/TileLayer.d.ts +229 -0
- package/dist/esm/TileLayer.js +450 -0
- package/dist/esm/TileLayer.js.map +1 -0
- package/dist/esm/TileLayerNode.d.ts +81 -0
- package/dist/esm/TileLayerNode.js +142 -0
- package/dist/esm/TileLayerNode.js.map +1 -0
- package/dist/esm/TileMap.d.ts +178 -0
- package/dist/esm/TileMap.js +262 -0
- package/dist/esm/TileMap.js.map +1 -0
- package/dist/esm/TileMapBand.d.ts +97 -0
- package/dist/esm/TileMapBand.js +161 -0
- package/dist/esm/TileMapBand.js.map +1 -0
- package/dist/esm/TileMapNode.d.ts +71 -0
- package/dist/esm/TileMapNode.js +113 -0
- package/dist/esm/TileMapNode.js.map +1 -0
- package/dist/esm/TileMapView.d.ts +182 -0
- package/dist/esm/TileMapView.js +342 -0
- package/dist/esm/TileMapView.js.map +1 -0
- package/dist/esm/TileSet.d.ts +99 -0
- package/dist/esm/TileSet.js +157 -0
- package/dist/esm/TileSet.js.map +1 -0
- package/dist/esm/chunkGeometry.d.ts +71 -0
- package/dist/esm/chunkGeometry.js +98 -0
- package/dist/esm/chunkGeometry.js.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/pixelSnap.d.ts +12 -0
- package/dist/esm/pixelSnap.js +19 -0
- package/dist/esm/pixelSnap.js.map +1 -0
- package/dist/esm/public.d.ts +18 -0
- package/dist/esm/register.d.ts +1 -0
- package/dist/esm/register.js +20 -0
- package/dist/esm/register.js.map +1 -0
- package/dist/esm/tilemapExtension.d.ts +18 -0
- package/dist/esm/tilemapExtension.js +52 -0
- package/dist/esm/tilemapExtension.js.map +1 -0
- package/dist/esm/types.d.ts +139 -0
- package/dist/esm/types.js +121 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/webgl2/WebGl2TileChunkRenderer.d.ts +39 -0
- package/dist/esm/webgl2/WebGl2TileChunkRenderer.js +339 -0
- package/dist/esm/webgl2/WebGl2TileChunkRenderer.js.map +1 -0
- package/dist/esm/webgpu/WebGpuTileChunkRenderer.d.ts +42 -0
- package/dist/esm/webgpu/WebGpuTileChunkRenderer.js +390 -0
- package/dist/esm/webgpu/WebGpuTileChunkRenderer.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Texture } from '@codexo/exojs';
|
|
2
|
+
import type { ReadonlyTileChunk } from './TileChunk';
|
|
3
|
+
import type { TileSet } from './TileSet';
|
|
4
|
+
import type { TileTransform } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* One textured tile quad in chunk-local pixel space.
|
|
7
|
+
*
|
|
8
|
+
* `u0/v0/u1/v1` are the raw (min/max) source UV bounds of the tile within its
|
|
9
|
+
* tileset texture — flip/orientation is **not** baked here; it travels in
|
|
10
|
+
* {@link TileQuad.orient} and is applied by the per-backend renderer (flipX/Y
|
|
11
|
+
* via UV-corner swap, diagonal via an axis swap in the shader). Keeping the
|
|
12
|
+
* geometry orientation-neutral lets both backends share one CPU builder.
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export interface TileQuad {
|
|
16
|
+
/** Local destination rect, left/top (chunk-local pixels). */
|
|
17
|
+
readonly x0: number;
|
|
18
|
+
readonly y0: number;
|
|
19
|
+
/** Local destination rect, right/bottom (chunk-local pixels). */
|
|
20
|
+
readonly x1: number;
|
|
21
|
+
readonly y1: number;
|
|
22
|
+
/** Normalised source UV bounds (always min ≤ max). */
|
|
23
|
+
readonly u0: number;
|
|
24
|
+
readonly v0: number;
|
|
25
|
+
readonly u1: number;
|
|
26
|
+
readonly v1: number;
|
|
27
|
+
/** Orientation code: bit0 = flipX, bit1 = flipY, bit2 = diagonal. */
|
|
28
|
+
readonly orient: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Geometry for one tileset "page" within a chunk: every tile in the chunk that
|
|
32
|
+
* draws from a single tileset texture, grouped so the renderer can batch by
|
|
33
|
+
* `(shader, texture)`.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
export interface ChunkPage {
|
|
37
|
+
/** The tileset all quads in this page draw from. */
|
|
38
|
+
readonly tileset: TileSet;
|
|
39
|
+
/** The underlying GPU texture (the tileset's atlas), bound once per page. */
|
|
40
|
+
readonly texture: Texture;
|
|
41
|
+
/** The tile quads for this page, in deterministic row-major order. */
|
|
42
|
+
readonly quads: readonly TileQuad[];
|
|
43
|
+
}
|
|
44
|
+
/** Pack a {@link TileTransform} into a 3-bit orientation code. @internal */
|
|
45
|
+
export declare function orientCode(transform: TileTransform): number;
|
|
46
|
+
/** Read the cumulative chunk-geometry rebuild count. @internal */
|
|
47
|
+
export declare function getTileGeometryRebuildCount(): number;
|
|
48
|
+
/** Reset the chunk-geometry rebuild counter (call before a measured frame). @internal */
|
|
49
|
+
export declare function resetTileGeometryRebuildCount(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Build per-tileset page geometry for a single chunk.
|
|
52
|
+
*
|
|
53
|
+
* Iterates the chunk's packed cells in deterministic row-major order, skipping
|
|
54
|
+
* empties, out-of-range tilesets, and out-of-range local tile ids (all treated
|
|
55
|
+
* as empty — this is the renderer's half of the G-GID contract). Each surviving
|
|
56
|
+
* cell is resolved to its source UV rect (from `tileset.getTileRect` + the
|
|
57
|
+
* tileset `TextureRegion`) and a chunk-local destination rect (bottom-left
|
|
58
|
+
* aligned per Tiled orthogonal semantics, so tilesets whose tiles are taller
|
|
59
|
+
* than the map grid extend upward).
|
|
60
|
+
*
|
|
61
|
+
* Allocation happens here only — the result is cached on the owning
|
|
62
|
+
* {@link import('./TileChunkNode').TileChunkNode} keyed by `chunk.revision`, so
|
|
63
|
+
* unchanged chunks never rebuild and the per-frame path stays allocation-free.
|
|
64
|
+
*
|
|
65
|
+
* @param chunk The readonly chunk view to build from.
|
|
66
|
+
* @param tilesets The layer's tileset array (packed `tilesetIndex` selects one).
|
|
67
|
+
* @param tileWidth Map/layer tile cell width in pixels.
|
|
68
|
+
* @param tileHeight Map/layer tile cell height in pixels.
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
export declare function buildChunkPages(chunk: ReadonlyTileChunk, tilesets: readonly TileSet[], tileWidth: number, tileHeight: number): ChunkPage[];
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { unpackTile } from './types.js';
|
|
2
|
+
|
|
3
|
+
/** Pack a {@link TileTransform} into a 3-bit orientation code. @internal */
|
|
4
|
+
function orientCode(transform) {
|
|
5
|
+
return (transform.flipX ? 1 : 0) | (transform.flipY ? 2 : 0) | (transform.diagonal ? 4 : 0);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Build per-tileset page geometry for a single chunk.
|
|
9
|
+
*
|
|
10
|
+
* Iterates the chunk's packed cells in deterministic row-major order, skipping
|
|
11
|
+
* empties, out-of-range tilesets, and out-of-range local tile ids (all treated
|
|
12
|
+
* as empty — this is the renderer's half of the G-GID contract). Each surviving
|
|
13
|
+
* cell is resolved to its source UV rect (from `tileset.getTileRect` + the
|
|
14
|
+
* tileset `TextureRegion`) and a chunk-local destination rect (bottom-left
|
|
15
|
+
* aligned per Tiled orthogonal semantics, so tilesets whose tiles are taller
|
|
16
|
+
* than the map grid extend upward).
|
|
17
|
+
*
|
|
18
|
+
* Allocation happens here only — the result is cached on the owning
|
|
19
|
+
* {@link import('./TileChunkNode').TileChunkNode} keyed by `chunk.revision`, so
|
|
20
|
+
* unchanged chunks never rebuild and the per-frame path stays allocation-free.
|
|
21
|
+
*
|
|
22
|
+
* @param chunk The readonly chunk view to build from.
|
|
23
|
+
* @param tilesets The layer's tileset array (packed `tilesetIndex` selects one).
|
|
24
|
+
* @param tileWidth Map/layer tile cell width in pixels.
|
|
25
|
+
* @param tileHeight Map/layer tile cell height in pixels.
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
function buildChunkPages(chunk, tilesets, tileWidth, tileHeight) {
|
|
29
|
+
if (chunk.empty) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
const buckets = new Map();
|
|
33
|
+
const width = chunk.width;
|
|
34
|
+
const height = chunk.height;
|
|
35
|
+
for (let ly = 0; ly < height; ly++) {
|
|
36
|
+
for (let lx = 0; lx < width; lx++) {
|
|
37
|
+
const packed = chunk.getRawAt(lx, ly);
|
|
38
|
+
if (packed === 0) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const decoded = unpackTile(packed);
|
|
42
|
+
if (decoded === null) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const tileset = tilesets[decoded.tilesetIndex];
|
|
46
|
+
// Out-of-range tileset or local id → treat as empty (G-GID). getTileRect
|
|
47
|
+
// throws on an out-of-range id, so the bounds check must precede it.
|
|
48
|
+
if (tileset === undefined || decoded.localTileId >= tileset.tileCount) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const region = tileset.texture;
|
|
52
|
+
const texture = region.texture;
|
|
53
|
+
const textureWidth = texture.width;
|
|
54
|
+
const textureHeight = texture.height;
|
|
55
|
+
if (textureWidth <= 0 || textureHeight <= 0) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const rect = tileset.getTileRect(decoded.localTileId);
|
|
59
|
+
// Absolute source pixel rect = tileset-region offset + in-atlas tile rect.
|
|
60
|
+
const sx = region.x + rect.x;
|
|
61
|
+
const sy = region.y + rect.y;
|
|
62
|
+
// Exact tile UVs, no half-texel inset. This assumes NEAREST filtering on
|
|
63
|
+
// the tileset atlas (the typical pixel-art case). Under LINEAR/mipmap
|
|
64
|
+
// filtering an atlas WITHOUT extrusion padding can bleed neighbouring
|
|
65
|
+
// tiles at the edges; author tilesets with extruded margins for linear
|
|
66
|
+
// sampling. (Extrusion-aware tilemap UV insetting — already done on the
|
|
67
|
+
// NineSlice/RepeatingSprite geometry paths — is a v0.14 follow-up.)
|
|
68
|
+
const u0 = sx / textureWidth;
|
|
69
|
+
const v0 = sy / textureHeight;
|
|
70
|
+
const u1 = (sx + rect.width) / textureWidth;
|
|
71
|
+
const v1 = (sy + rect.height) / textureHeight;
|
|
72
|
+
// Bottom-left aligned destination (Tiled orthogonal). Uniform tiles
|
|
73
|
+
// (rect.height === tileHeight) collapse to a plain cell rect.
|
|
74
|
+
const x0 = lx * tileWidth;
|
|
75
|
+
const y0 = ly * tileHeight + tileHeight - rect.height;
|
|
76
|
+
const x1 = x0 + rect.width;
|
|
77
|
+
const y1 = y0 + rect.height;
|
|
78
|
+
let bucket = buckets.get(tileset);
|
|
79
|
+
if (bucket === undefined) {
|
|
80
|
+
bucket = [];
|
|
81
|
+
buckets.set(tileset, bucket);
|
|
82
|
+
}
|
|
83
|
+
bucket.push({ x0, y0, x1, y1, u0, v0, u1, v1, orient: orientCode(decoded.transform) });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Emit pages in tileset-array order for deterministic, reproducible builds.
|
|
87
|
+
const pages = [];
|
|
88
|
+
for (const tileset of tilesets) {
|
|
89
|
+
const quads = buckets.get(tileset);
|
|
90
|
+
if (quads !== undefined && quads.length > 0) {
|
|
91
|
+
pages.push({ tileset, texture: tileset.texture.texture, quads });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return pages;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { buildChunkPages, orientCode };
|
|
98
|
+
//# sourceMappingURL=chunkGeometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunkGeometry.js","sources":["../../../src/chunkGeometry.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './public';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { tilemapExtension } from './tilemapExtension.js';
|
|
2
|
+
export { TileLayer } from './TileLayer.js';
|
|
3
|
+
export { TileMap } from './TileMap.js';
|
|
4
|
+
export { TileSet } from './TileSet.js';
|
|
5
|
+
export { TileLayerNode } from './TileLayerNode.js';
|
|
6
|
+
export { TileMapNode } from './TileMapNode.js';
|
|
7
|
+
export { TileMapBand } from './TileMapBand.js';
|
|
8
|
+
export { TileMapView } from './TileMapView.js';
|
|
9
|
+
export { TILE_TRANSFORM_IDENTITY, tileToChunkCoord, tileToLocalInChunk } from './types.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PixelSnapMode } from '@codexo/exojs/rendering';
|
|
2
|
+
/**
|
|
3
|
+
* Throw a deterministic error when `mode` is not a valid {@link PixelSnapMode}.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the core `Drawable` setter's guard so the tilemap node passthroughs
|
|
6
|
+
* (`TileMapView` / `TileMapNode` / `TileLayerNode`) reject JavaScript-invalid
|
|
7
|
+
* values atomically — even for an empty layer that has no chunk drawable to
|
|
8
|
+
* delegate the validation to. Kept local because the core guard is not part of
|
|
9
|
+
* the public API surface.
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
export declare function assertPixelSnapMode(mode: PixelSnapMode): void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const validPixelSnapModes = new Set(['none', 'position', 'geometry']);
|
|
2
|
+
/**
|
|
3
|
+
* Throw a deterministic error when `mode` is not a valid {@link PixelSnapMode}.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the core `Drawable` setter's guard so the tilemap node passthroughs
|
|
6
|
+
* (`TileMapView` / `TileMapNode` / `TileLayerNode`) reject JavaScript-invalid
|
|
7
|
+
* values atomically — even for an empty layer that has no chunk drawable to
|
|
8
|
+
* delegate the validation to. Kept local because the core guard is not part of
|
|
9
|
+
* the public API surface.
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
function assertPixelSnapMode(mode) {
|
|
13
|
+
if (typeof mode !== 'string' || !validPixelSnapModes.has(mode)) {
|
|
14
|
+
throw new Error(`pixelSnapMode must be 'none', 'position', or 'geometry' (got ${String(mode)}).`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { assertPixelSnapMode };
|
|
19
|
+
//# sourceMappingURL=pixelSnap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pixelSnap.js","sources":["../../../src/pixelSnap.ts"],"sourcesContent":[null],"names":[],"mappings":"AAEA,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAS,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;AAElG;;;;;;;;;AASG;AACG,SAAU,mBAAmB,CAAC,IAAmB,EAAA;AACrD,IAAA,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QAC9D,MAAM,IAAI,KAAK,CAAC,CAAA,6DAAA,EAAgE,MAAM,CAAC,IAAI,CAAC,CAAA,EAAA,CAAI,CAAC;IACnG;AACF;;;;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { tilemapExtension } from './tilemapExtension';
|
|
2
|
+
export type { Extension } from '@codexo/exojs/extensions';
|
|
3
|
+
export type { ReadonlyTileChunk } from './TileChunk';
|
|
4
|
+
export type { TileLayerOptions } from './TileLayer';
|
|
5
|
+
export { TileLayer } from './TileLayer';
|
|
6
|
+
export type { TileMapOptions } from './TileMap';
|
|
7
|
+
export { TileMap } from './TileMap';
|
|
8
|
+
export type { TileSetOptions } from './TileSet';
|
|
9
|
+
export { TileSet } from './TileSet';
|
|
10
|
+
export type { TileLayerNodeOptions } from './TileLayerNode';
|
|
11
|
+
export { TileLayerNode } from './TileLayerNode';
|
|
12
|
+
export type { TileMapNodeOptions } from './TileMapNode';
|
|
13
|
+
export { TileMapNode } from './TileMapNode';
|
|
14
|
+
export { TileMapBand } from './TileMapBand';
|
|
15
|
+
export type { TileLayerSelector, TileMapBandDefinition, TileMapViewOptions, } from './TileMapView';
|
|
16
|
+
export { TileMapView } from './TileMapView';
|
|
17
|
+
export type { ChunkCoord, PackedTile, ResolvedTile, TileDefinition, TileProperties, TilePropertyValue, TileTransform, } from './types';
|
|
18
|
+
export { TILE_TRANSFORM_IDENTITY, tileToChunkCoord, tileToLocalInChunk, } from './types';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './public';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ExtensionRegistry } from '@codexo/exojs/extensions';
|
|
2
|
+
import { tilemapExtension } from './tilemapExtension.js';
|
|
3
|
+
export { TileLayer } from './TileLayer.js';
|
|
4
|
+
export { TileMap } from './TileMap.js';
|
|
5
|
+
export { TileSet } from './TileSet.js';
|
|
6
|
+
export { TileLayerNode } from './TileLayerNode.js';
|
|
7
|
+
export { TileMapNode } from './TileMapNode.js';
|
|
8
|
+
export { TileMapBand } from './TileMapBand.js';
|
|
9
|
+
export { TileMapView } from './TileMapView.js';
|
|
10
|
+
export { TILE_TRANSFORM_IDENTITY, tileToChunkCoord, tileToLocalInChunk } from './types.js';
|
|
11
|
+
|
|
12
|
+
// @codexo/exojs-tilemap/register — explicit registration entry.
|
|
13
|
+
// Importing this entry registers the default tilemapExtension descriptor
|
|
14
|
+
// in the global ExtensionRegistry. Subsequently constructed Applications
|
|
15
|
+
// that use global defaults will receive the tilemap extension.
|
|
16
|
+
// This is the only side-effectful entry in this package.
|
|
17
|
+
ExtensionRegistry.register(tilemapExtension);
|
|
18
|
+
|
|
19
|
+
export { tilemapExtension };
|
|
20
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sources":["../../../src/register.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AAMA,iBAAiB,CAAC,QAAQ,CAAC,gBAAgB,CAAC;;;;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Extension } from '@codexo/exojs/extensions';
|
|
2
|
+
/**
|
|
3
|
+
* Default immutable tilemap extension descriptor.
|
|
4
|
+
*
|
|
5
|
+
* Registers the WebGL2/WebGPU tile chunk renderers (`renderers`); it carries no
|
|
6
|
+
* asset bindings — there is no generic on-disk tilemap format in this slice, so
|
|
7
|
+
* format adapters (e.g. `@codexo/exojs-tiled`) own loading and depend on this
|
|
8
|
+
* descriptor to pull in rendering.
|
|
9
|
+
*
|
|
10
|
+
* Install + register directly for procedural / hand-built maps
|
|
11
|
+
* (`extensions: [tilemapExtension]` plus a `TileMap` built via the runtime), or
|
|
12
|
+
* receive it transitively through a format adapter's `dependencies`.
|
|
13
|
+
*
|
|
14
|
+
* Use with `ApplicationOptions.extensions` or call
|
|
15
|
+
* `import '@codexo/exojs-tilemap/register'` for global auto-registration.
|
|
16
|
+
* @advanced
|
|
17
|
+
*/
|
|
18
|
+
export declare const tilemapExtension: Extension;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { RenderBackendType } from '@codexo/exojs/rendering';
|
|
2
|
+
import { TileChunkNode } from './TileChunkNode.js';
|
|
3
|
+
import { WebGl2TileChunkRenderer } from './webgl2/WebGl2TileChunkRenderer.js';
|
|
4
|
+
import { WebGpuTileChunkRenderer } from './webgpu/WebGpuTileChunkRenderer.js';
|
|
5
|
+
|
|
6
|
+
/** Per-tile instance batch size for the WebGL2 tile chunk renderer. */
|
|
7
|
+
const tileRendererBatchSize = 4096;
|
|
8
|
+
/**
|
|
9
|
+
* Build the renderer binding that wires the per-backend
|
|
10
|
+
* {@link import('./TileChunkNode').TileChunkNode} renderers. The binding targets
|
|
11
|
+
* the internal chunk drawable; applications never construct it directly — they
|
|
12
|
+
* build {@link import('./TileMapNode').TileMapNode} /
|
|
13
|
+
* {@link import('./TileLayerNode').TileLayerNode}, whose chunk children resolve
|
|
14
|
+
* to this renderer through the registry prototype walk.
|
|
15
|
+
*/
|
|
16
|
+
function buildTileChunkRendererBinding(batchSize) {
|
|
17
|
+
return {
|
|
18
|
+
targets: [TileChunkNode],
|
|
19
|
+
create(backend) {
|
|
20
|
+
if (backend.backendType === RenderBackendType.WebGl2) {
|
|
21
|
+
return new WebGl2TileChunkRenderer(batchSize);
|
|
22
|
+
}
|
|
23
|
+
if (backend.backendType === RenderBackendType.WebGpu) {
|
|
24
|
+
return new WebGpuTileChunkRenderer();
|
|
25
|
+
}
|
|
26
|
+
throw new Error(`Unsupported render backend: ${String(backend.backendType)}`);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Default immutable tilemap extension descriptor.
|
|
32
|
+
*
|
|
33
|
+
* Registers the WebGL2/WebGPU tile chunk renderers (`renderers`); it carries no
|
|
34
|
+
* asset bindings — there is no generic on-disk tilemap format in this slice, so
|
|
35
|
+
* format adapters (e.g. `@codexo/exojs-tiled`) own loading and depend on this
|
|
36
|
+
* descriptor to pull in rendering.
|
|
37
|
+
*
|
|
38
|
+
* Install + register directly for procedural / hand-built maps
|
|
39
|
+
* (`extensions: [tilemapExtension]` plus a `TileMap` built via the runtime), or
|
|
40
|
+
* receive it transitively through a format adapter's `dependencies`.
|
|
41
|
+
*
|
|
42
|
+
* Use with `ApplicationOptions.extensions` or call
|
|
43
|
+
* `import '@codexo/exojs-tilemap/register'` for global auto-registration.
|
|
44
|
+
* @advanced
|
|
45
|
+
*/
|
|
46
|
+
const tilemapExtension = Object.freeze({
|
|
47
|
+
id: '@codexo/exojs-tilemap',
|
|
48
|
+
renderers: [buildTileChunkRendererBinding(tileRendererBatchSize)],
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
export { tilemapExtension };
|
|
52
|
+
//# sourceMappingURL=tilemapExtension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tilemapExtension.js","sources":["../../../src/tilemapExtension.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAQA;AACA,MAAM,qBAAqB,GAAG,IAAI;AAElC;;;;;;;AAOG;AACH,SAAS,6BAA6B,CAAC,SAAiB,EAAA;IACtD,OAAO;QACL,OAAO,EAAE,CAAC,aAAa,CAAC;AACxB,QAAA,MAAM,CAAC,OAAsB,EAAA;YAC3B,IAAI,OAAO,CAAC,WAAW,KAAK,iBAAiB,CAAC,MAAM,EAAE;AACpD,gBAAA,OAAO,IAAI,uBAAuB,CAAC,SAAS,CAAC;YAC/C;YAEA,IAAI,OAAO,CAAC,WAAW,KAAK,iBAAiB,CAAC,MAAM,EAAE;gBACpD,OAAO,IAAI,uBAAuB,EAAE;YACtC;AAEA,YAAA,MAAM,IAAI,KAAK,CAAC,CAAA,4BAAA,EAA+B,MAAM,CAAC,OAAO,CAAC,WAA2B,CAAC,CAAA,CAAE,CAAC;QAC/F,CAAC;KACF;AACH;AAEA;;;;;;;;;;;;;;;AAeG;AACI,MAAM,gBAAgB,GAAc,MAAM,CAAC,MAAM,CAAC;AACvD,IAAA,EAAE,EAAE,uBAAuB;AAC3B,IAAA,SAAS,EAAE,CAAC,6BAA6B,CAAC,qBAAqB,CAAC,CAAC;AAClE,CAAA;;;;"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { TileSet } from './TileSet';
|
|
2
|
+
/**
|
|
3
|
+
* Union of legal tile-property value types in the generic runtime.
|
|
4
|
+
* Format-neutral; adapters map their native property systems into this set.
|
|
5
|
+
* @advanced
|
|
6
|
+
*/
|
|
7
|
+
export type TilePropertyValue = null | boolean | number | string;
|
|
8
|
+
/**
|
|
9
|
+
* An immutable, flat key-value bag of generic tile properties.
|
|
10
|
+
* Adapters copy and freeze source properties; the runtime never retains
|
|
11
|
+
* a caller-owned mutable object.
|
|
12
|
+
* @advanced
|
|
13
|
+
*/
|
|
14
|
+
export type TileProperties = Readonly<Record<string, TilePropertyValue>>;
|
|
15
|
+
/**
|
|
16
|
+
* Describes the orientation of a placed tile independent of source-format
|
|
17
|
+
* flip-bit encodings. The eight legal combinations map to the eight distinct
|
|
18
|
+
* 90°-rotation-and-flip states of a rectangular texture quad.
|
|
19
|
+
*
|
|
20
|
+
* Applying the transform at geometry-build time (reordering UV corners)
|
|
21
|
+
* avoids per-tile runtime cost and per-frame matrix allocation.
|
|
22
|
+
* @stable
|
|
23
|
+
*/
|
|
24
|
+
export interface TileTransform {
|
|
25
|
+
/** Horizontal flip (mirror left-right). */
|
|
26
|
+
readonly flipX: boolean;
|
|
27
|
+
/** Vertical flip (mirror top-bottom). */
|
|
28
|
+
readonly flipY: boolean;
|
|
29
|
+
/** Anti-diagonal flip (transpose of the UV axes). Combined with flips produces 90° rotations. */
|
|
30
|
+
readonly diagonal: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** The identity transform: no flip, no diagonal. */
|
|
33
|
+
export declare const TILE_TRANSFORM_IDENTITY: Readonly<TileTransform>;
|
|
34
|
+
/**
|
|
35
|
+
* Short string label for a {@link TileTransform} (debug / serialisation).
|
|
36
|
+
* Returns one of the eight deterministic names, e.g. `"flipX"` or `"diag+flipX+flipY"`.
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export declare function tileTransformLabel(t: TileTransform): string;
|
|
40
|
+
/**
|
|
41
|
+
* Opaque packed tile data stored in a {@link TileChunk}'s compact array.
|
|
42
|
+
* 0 means "empty cell". Any non-zero value encodes localTileId, tilesetIndex,
|
|
43
|
+
* and flip bits according to the bit-layout constants below.
|
|
44
|
+
*
|
|
45
|
+
* A `PackedTile` is **not** a source-format GID — it is a fully resolved
|
|
46
|
+
* internal compact representation. Use {@link packTile} / {@link unpackTile}
|
|
47
|
+
* (package-internal) to convert between packed form and a {@link ResolvedTile}
|
|
48
|
+
* if writing adapters.
|
|
49
|
+
*
|
|
50
|
+
* In public APIs, prefer {@link ResolvedTile} or null for queries.
|
|
51
|
+
* `PackedTile` is exposed as `@advanced` so `ReadonlyTileChunk.getRawAt()`
|
|
52
|
+
* has a self-documenting return type.
|
|
53
|
+
* @advanced
|
|
54
|
+
*/
|
|
55
|
+
export type PackedTile = number;
|
|
56
|
+
/** Bit width allocated to the local tile ID within a packed tile word. */
|
|
57
|
+
export declare const PACKED_LOCAL_BITS = 20;
|
|
58
|
+
/** Bit width allocated to the tileset index within a packed tile word. */
|
|
59
|
+
export declare const PACKED_TILESET_BITS = 9;
|
|
60
|
+
/** Bit width allocated to the transform/flip bits. */
|
|
61
|
+
export declare const PACKED_TRANSFORM_BITS = 3;
|
|
62
|
+
export declare const PACKED_LOCAL_MASK: number;
|
|
63
|
+
export declare const PACKED_TILESET_MASK: number;
|
|
64
|
+
export declare const PACKED_TRANSFORM_MASK: number;
|
|
65
|
+
export declare const PACKED_TILESET_SHIFT = 20;
|
|
66
|
+
export declare const PACKED_TRANSFORM_SHIFT: number;
|
|
67
|
+
/** Maximum tileset index representable in a packed tile. */
|
|
68
|
+
export declare const MAX_TILESET_INDEX: number;
|
|
69
|
+
/** Maximum local tile ID representable in a packed tile (1-based storage). */
|
|
70
|
+
export declare const MAX_LOCAL_TILE_ID: number;
|
|
71
|
+
/**
|
|
72
|
+
* Encode a tileset-local tile reference and transform into a packed word.
|
|
73
|
+
* The localTileId is stored as (localTileId + 1) so that a packed value of 0
|
|
74
|
+
* cleanly represents an empty cell, while tile 0 from tileset 0 with identity
|
|
75
|
+
* transform is stored as 1 (non-zero).
|
|
76
|
+
* Returns 0 for an empty cell.
|
|
77
|
+
* @internal
|
|
78
|
+
*/
|
|
79
|
+
export declare function packTile(tilesetIndex: number, localTileId: number, transform: TileTransform): PackedTile;
|
|
80
|
+
/**
|
|
81
|
+
* Decode a packed word into its components.
|
|
82
|
+
* Returns null for an empty cell (packed === 0).
|
|
83
|
+
* @internal
|
|
84
|
+
*/
|
|
85
|
+
export declare function unpackTile(packed: PackedTile): {
|
|
86
|
+
tilesetIndex: number;
|
|
87
|
+
localTileId: number;
|
|
88
|
+
transform: TileTransform;
|
|
89
|
+
} | null;
|
|
90
|
+
/**
|
|
91
|
+
* A fully resolved, format-independent tile reference returned by queries.
|
|
92
|
+
* Materialised on-demand from the packed storage; never stored as a per-cell
|
|
93
|
+
* heap object.
|
|
94
|
+
* @advanced
|
|
95
|
+
*/
|
|
96
|
+
export interface ResolvedTile {
|
|
97
|
+
/** The owning tileset (already resolved from source-format GID). */
|
|
98
|
+
readonly tileset: TileSet;
|
|
99
|
+
/** 0-based tile index within the tileset. */
|
|
100
|
+
readonly localTileId: number;
|
|
101
|
+
/** Orientation transform for this placed tile. */
|
|
102
|
+
readonly transform: TileTransform;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Optional per-tile metadata in a {@link TileSet}. Sparse — only defined
|
|
106
|
+
* tiles carry a definition. May carry animation data in future slices.
|
|
107
|
+
* @advanced
|
|
108
|
+
*/
|
|
109
|
+
export interface TileDefinition {
|
|
110
|
+
/** The local tile ID this definition belongs to. */
|
|
111
|
+
readonly localTileId: number;
|
|
112
|
+
/** Tile properties (copied and frozen by the tileset). */
|
|
113
|
+
readonly properties?: TileProperties;
|
|
114
|
+
}
|
|
115
|
+
/** A signed chunk coordinate pair. */
|
|
116
|
+
export interface ChunkCoord {
|
|
117
|
+
readonly cx: number;
|
|
118
|
+
readonly cy: number;
|
|
119
|
+
}
|
|
120
|
+
/** Convert tile coordinates to chunk coordinates given a chunk size. */
|
|
121
|
+
export declare function tileToChunkCoord(tx: number, ty: number, chunkW: number, chunkH: number): ChunkCoord;
|
|
122
|
+
/** Convert tile coordinates to local-in-chunk coordinates. */
|
|
123
|
+
export declare function tileToLocalInChunk(tx: number, ty: number, chunkW: number, chunkH: number): {
|
|
124
|
+
lx: number;
|
|
125
|
+
ly: number;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Validate that a value is a finite, safe, positive integer.
|
|
129
|
+
* Used for dimensions, tile counts, chunk sizes.
|
|
130
|
+
*/
|
|
131
|
+
export declare function validatePositiveInteger(value: number, label: string): void;
|
|
132
|
+
/**
|
|
133
|
+
* Validate a non-negative finite integer.
|
|
134
|
+
*/
|
|
135
|
+
export declare function validateNonNegativeInteger(value: number, label: string): void;
|
|
136
|
+
/**
|
|
137
|
+
* Validate that a value is a finite integer (may be negative).
|
|
138
|
+
*/
|
|
139
|
+
export declare function validateInteger(value: number, label: string): void;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/** The identity transform: no flip, no diagonal. */
|
|
2
|
+
const TILE_TRANSFORM_IDENTITY = Object.freeze({
|
|
3
|
+
flipX: false,
|
|
4
|
+
flipY: false,
|
|
5
|
+
diagonal: false,
|
|
6
|
+
});
|
|
7
|
+
/** Bit width allocated to the local tile ID within a packed tile word. */
|
|
8
|
+
const PACKED_LOCAL_BITS = 20;
|
|
9
|
+
/** Bit width allocated to the tileset index within a packed tile word. */
|
|
10
|
+
const PACKED_TILESET_BITS = 9;
|
|
11
|
+
/** Bit width allocated to the transform/flip bits. */
|
|
12
|
+
const PACKED_TRANSFORM_BITS = 3;
|
|
13
|
+
const PACKED_LOCAL_MASK = (1 << PACKED_LOCAL_BITS) - 1;
|
|
14
|
+
const PACKED_TILESET_MASK = ((1 << PACKED_TILESET_BITS) - 1) << PACKED_LOCAL_BITS;
|
|
15
|
+
const PACKED_TRANSFORM_MASK = ((1 << PACKED_TRANSFORM_BITS) - 1) << (PACKED_LOCAL_BITS + PACKED_TILESET_BITS);
|
|
16
|
+
const PACKED_TILESET_SHIFT = PACKED_LOCAL_BITS;
|
|
17
|
+
const PACKED_TRANSFORM_SHIFT = PACKED_LOCAL_BITS + PACKED_TILESET_BITS;
|
|
18
|
+
/** Maximum tileset index representable in a packed tile. */
|
|
19
|
+
const MAX_TILESET_INDEX = (1 << PACKED_TILESET_BITS) - 1;
|
|
20
|
+
/** Maximum local tile ID representable in a packed tile (1-based storage). */
|
|
21
|
+
const MAX_LOCAL_TILE_ID = (1 << PACKED_LOCAL_BITS) - 2;
|
|
22
|
+
// Transform bit-field values (bit 0 = flipX, bit 1 = flipY, bit 2 = diagonal).
|
|
23
|
+
const TRANSFORM_FLIP_X = 1 << 0;
|
|
24
|
+
const TRANSFORM_FLIP_Y = 1 << 1;
|
|
25
|
+
const TRANSFORM_DIAGONAL = 1 << 2;
|
|
26
|
+
/**
|
|
27
|
+
* Encode a tileset-local tile reference and transform into a packed word.
|
|
28
|
+
* The localTileId is stored as (localTileId + 1) so that a packed value of 0
|
|
29
|
+
* cleanly represents an empty cell, while tile 0 from tileset 0 with identity
|
|
30
|
+
* transform is stored as 1 (non-zero).
|
|
31
|
+
* Returns 0 for an empty cell.
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
function packTile(tilesetIndex, localTileId, transform) {
|
|
35
|
+
if (tilesetIndex < 0 || tilesetIndex > MAX_TILESET_INDEX) {
|
|
36
|
+
throw new Error(`Tileset index ${tilesetIndex} exceeds maximum ${MAX_TILESET_INDEX}.`);
|
|
37
|
+
}
|
|
38
|
+
if (localTileId < 0 || localTileId > MAX_LOCAL_TILE_ID) {
|
|
39
|
+
throw new Error(`Local tile ID ${localTileId} exceeds maximum ${MAX_LOCAL_TILE_ID}.`);
|
|
40
|
+
}
|
|
41
|
+
let bits = 0;
|
|
42
|
+
if (transform.flipX)
|
|
43
|
+
bits |= TRANSFORM_FLIP_X;
|
|
44
|
+
if (transform.flipY)
|
|
45
|
+
bits |= TRANSFORM_FLIP_Y;
|
|
46
|
+
if (transform.diagonal)
|
|
47
|
+
bits |= TRANSFORM_DIAGONAL;
|
|
48
|
+
// +1 so 0 means "empty" not "tile 0 without transform"
|
|
49
|
+
const storedId = localTileId + 1;
|
|
50
|
+
return (storedId & PACKED_LOCAL_MASK)
|
|
51
|
+
| ((tilesetIndex << PACKED_TILESET_SHIFT) & PACKED_TILESET_MASK)
|
|
52
|
+
| ((bits << PACKED_TRANSFORM_SHIFT) & PACKED_TRANSFORM_MASK);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Decode a packed word into its components.
|
|
56
|
+
* Returns null for an empty cell (packed === 0).
|
|
57
|
+
* @internal
|
|
58
|
+
*/
|
|
59
|
+
function unpackTile(packed) {
|
|
60
|
+
if (packed === 0)
|
|
61
|
+
return null;
|
|
62
|
+
const storedId = packed & PACKED_LOCAL_MASK;
|
|
63
|
+
// Undo the +1 offset applied during packTile.
|
|
64
|
+
const localTileId = storedId - 1;
|
|
65
|
+
const tilesetIndex = (packed & PACKED_TILESET_MASK) >>> PACKED_TILESET_SHIFT;
|
|
66
|
+
const rawTransform = (packed & PACKED_TRANSFORM_MASK) >>> PACKED_TRANSFORM_SHIFT;
|
|
67
|
+
return {
|
|
68
|
+
tilesetIndex,
|
|
69
|
+
localTileId,
|
|
70
|
+
transform: {
|
|
71
|
+
flipX: !!(rawTransform & TRANSFORM_FLIP_X),
|
|
72
|
+
flipY: !!(rawTransform & TRANSFORM_FLIP_Y),
|
|
73
|
+
diagonal: !!(rawTransform & TRANSFORM_DIAGONAL),
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** Convert tile coordinates to chunk coordinates given a chunk size. */
|
|
78
|
+
function tileToChunkCoord(tx, ty, chunkW, chunkH) {
|
|
79
|
+
return {
|
|
80
|
+
cx: Math.floor(tx / chunkW),
|
|
81
|
+
cy: Math.floor(ty / chunkH),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/** Convert tile coordinates to local-in-chunk coordinates. */
|
|
85
|
+
function tileToLocalInChunk(tx, ty, chunkW, chunkH) {
|
|
86
|
+
return {
|
|
87
|
+
lx: ((tx % chunkW) + chunkW) % chunkW,
|
|
88
|
+
ly: ((ty % chunkH) + chunkH) % chunkH,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Validate that a value is a finite, safe, positive integer.
|
|
93
|
+
* Used for dimensions, tile counts, chunk sizes.
|
|
94
|
+
*/
|
|
95
|
+
function validatePositiveInteger(value, label) {
|
|
96
|
+
if (!Number.isFinite(value) || !Number.isInteger(value) || value <= 0) {
|
|
97
|
+
throw new Error(`${label} must be a positive integer (got ${value}).`);
|
|
98
|
+
}
|
|
99
|
+
if (value > Number.MAX_SAFE_INTEGER) {
|
|
100
|
+
throw new Error(`${label} exceeds safe integer range (got ${value}).`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Validate a non-negative finite integer.
|
|
105
|
+
*/
|
|
106
|
+
function validateNonNegativeInteger(value, label) {
|
|
107
|
+
if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {
|
|
108
|
+
throw new Error(`${label} must be a non-negative integer (got ${value}).`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Validate that a value is a finite integer (may be negative).
|
|
113
|
+
*/
|
|
114
|
+
function validateInteger(value, label) {
|
|
115
|
+
if (!Number.isFinite(value) || !Number.isInteger(value)) {
|
|
116
|
+
throw new Error(`${label} must be a finite integer (got ${value}).`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
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, packTile, tileToChunkCoord, tileToLocalInChunk, unpackTile, validateInteger, validateNonNegativeInteger, validatePositiveInteger };
|
|
121
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sources":["../../../src/types.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|