@codexo/exojs-ldtk 0.14.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Codexo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,175 @@
1
+ /**
2
+ * TypeScript types for the LDtk JSON format (version 1.5.x).
3
+ *
4
+ * These interfaces model the root LDtk JSON document as produced by the LDtk
5
+ * level editor. Only the fields consumed by the ExoJS runtime adapter are
6
+ * declared here; unknown fields are not stripped at parse time.
7
+ *
8
+ * @see https://ldtk.io/json/
9
+ */
10
+ /** Flip-bit constants for {@link LdtkTileData.f}. */
11
+ export declare const ldtkFlipNone = 0;
12
+ export declare const ldtkFlipX = 1;
13
+ export declare const ldtkFlipY = 2;
14
+ export declare const ldtkFlipXy = 3;
15
+ /** A single tile placed in a Tiles or AutoLayer layer instance. */
16
+ export interface LdtkTileData {
17
+ /** Pixel position `[x, y]` of this tile within the layer. */
18
+ readonly px: readonly [number, number];
19
+ /** Source position `[x, y]` in the tileset image (top-left of the tile). */
20
+ readonly src: readonly [number, number];
21
+ /**
22
+ * Flip bits: `0` = none, `1` = flipX, `2` = flipY, `3` = flipX + flipY.
23
+ * Use {@link LDTK_FLIP_X} / {@link LDTK_FLIP_Y} constants for clarity.
24
+ */
25
+ readonly f: number;
26
+ /** Local tile index in the owning tileset. */
27
+ readonly t: number;
28
+ /** Per-tile opacity in `[0, 1]`. Defaults to `1` when absent. */
29
+ readonly a?: number;
30
+ }
31
+ /** A field value on an entity or level instance. */
32
+ export interface LdtkFieldInstance {
33
+ readonly __identifier: string;
34
+ readonly __type: string;
35
+ readonly __value: unknown;
36
+ }
37
+ /** An entity instance placed in an Entities layer. */
38
+ export interface LdtkEntityInstance {
39
+ /** Entity definition identifier (class name). */
40
+ readonly __identifier: string;
41
+ /** Alias of `__identifier`, mirrors the entity definition type. */
42
+ readonly __type: string;
43
+ /** Pixel position `[x, y]` of the entity origin. */
44
+ readonly px: readonly [number, number];
45
+ readonly width: number;
46
+ readonly height: number;
47
+ readonly fieldInstances: readonly LdtkFieldInstance[];
48
+ /** Globally unique instance id (UUID string). */
49
+ readonly iid: string;
50
+ /** UID of the entity definition this instance was created from. */
51
+ readonly defUid: number;
52
+ }
53
+ /** Discriminant string for a layer instance type. */
54
+ export type LdtkLayerType = 'Tiles' | 'IntGrid' | 'Entities' | 'AutoLayer';
55
+ /** A layer instance within a level. */
56
+ export interface LdtkLayerInstance {
57
+ /** Layer definition identifier. */
58
+ readonly __identifier: string;
59
+ /** Layer type discriminant. */
60
+ readonly __type: LdtkLayerType;
61
+ /** Layer width in grid cells. */
62
+ readonly __cWid: number;
63
+ /** Layer height in grid cells. */
64
+ readonly __cHei: number;
65
+ /** Grid / tile size in pixels. */
66
+ readonly __gridSize: number;
67
+ /** UID of the layer definition. */
68
+ readonly layerDefUid: number;
69
+ /** UID of the parent level. */
70
+ readonly levelId: number;
71
+ readonly visible: boolean;
72
+ /** Globally unique instance id (UUID string). */
73
+ readonly iid: string;
74
+ /**
75
+ * UID of the tileset used by this layer.
76
+ * Present for `Tiles`, `AutoLayer`, and `IntGrid` layers that use a tileset.
77
+ */
78
+ readonly __tilesetDefUid?: number;
79
+ /** Placed tiles for `Tiles` layer type. */
80
+ readonly gridTiles?: readonly LdtkTileData[];
81
+ /** Auto-computed tiles for `AutoLayer` (and `IntGrid` + auto-rules) layer types. */
82
+ readonly autoLayerTiles?: readonly LdtkTileData[];
83
+ /** Entity instances for `Entities` layer type. */
84
+ readonly entityInstances?: readonly LdtkEntityInstance[];
85
+ /**
86
+ * Flat CSV array of IntGrid values for `IntGrid` layer type.
87
+ * Index = `y * __cWid + x`. `0` = empty cell.
88
+ */
89
+ readonly intGridCsv?: readonly number[];
90
+ /** Horizontal pixel offset applied to the layer. */
91
+ readonly pxOffsetX?: number;
92
+ /** Vertical pixel offset applied to the layer. */
93
+ readonly pxOffsetY?: number;
94
+ /** Layer opacity in `[0, 1]`. */
95
+ readonly opacity?: number;
96
+ }
97
+ /** A level in the LDtk world. */
98
+ export interface LdtkLevel {
99
+ /** Human-readable level identifier (unique within the world). */
100
+ readonly identifier: string;
101
+ readonly uid: number;
102
+ /** Globally unique instance id (UUID string). */
103
+ readonly iid: string;
104
+ /** World-space X position of the level's top-left corner in pixels. */
105
+ readonly worldX: number;
106
+ /** World-space Y position of the level's top-left corner in pixels. */
107
+ readonly worldY: number;
108
+ /** Level width in pixels. */
109
+ readonly pxWid: number;
110
+ /** Level height in pixels. */
111
+ readonly pxHei: number;
112
+ readonly bgColor?: string;
113
+ /**
114
+ * Layer instances in this level (top-to-bottom render order).
115
+ * `null` when the level is stored in a separate `.ldtkl` file and has not
116
+ * been loaded yet.
117
+ */
118
+ readonly layerInstances: readonly LdtkLayerInstance[] | null;
119
+ readonly fieldInstances?: readonly LdtkFieldInstance[];
120
+ /** Relative path to an external `.ldtkl` file for multi-world setups. */
121
+ readonly externalRelPath?: string;
122
+ }
123
+ /** Tileset definition from `defs.tilesets`. */
124
+ export interface LdtkTilesetDef {
125
+ readonly uid: number;
126
+ /** Human-readable tileset identifier. */
127
+ readonly identifier: string;
128
+ /**
129
+ * Relative path to the tileset atlas image.
130
+ * `null` for internal / embedded tilesets with no image.
131
+ */
132
+ readonly relPath: string | null;
133
+ /** Tile grid size (both width and height) in pixels. */
134
+ readonly tileGridSize: number;
135
+ /** Tileset image width in pixels. */
136
+ readonly pxWid: number;
137
+ /** Tileset image height in pixels. */
138
+ readonly pxHei: number;
139
+ /** Pixel spacing between tiles in the atlas. */
140
+ readonly spacing?: number;
141
+ /** Pixel padding (margin) around the atlas edges. */
142
+ readonly padding?: number;
143
+ }
144
+ /** An IntGrid value definition (maps a raw int to a named, coloured entry). */
145
+ export interface LdtkIntGridValueDef {
146
+ readonly value: number;
147
+ readonly identifier: string | null;
148
+ readonly color: string;
149
+ }
150
+ /** Layer definition from `defs.layers`. */
151
+ export interface LdtkLayerDef {
152
+ readonly uid: number;
153
+ readonly identifier: string;
154
+ readonly type: LdtkLayerType;
155
+ /** UID of the default tileset for this layer. `null` or absent = none. */
156
+ readonly tilesetDefUid?: number | null;
157
+ readonly gridSize: number;
158
+ readonly intGridValues?: readonly LdtkIntGridValueDef[];
159
+ }
160
+ /** Top-level definitions block (`defs`). */
161
+ export interface LdtkDefs {
162
+ readonly tilesets: readonly LdtkTilesetDef[];
163
+ readonly layers: readonly LdtkLayerDef[];
164
+ }
165
+ /** Root LDtk JSON document (`*.ldtk`). */
166
+ export interface LdtkData {
167
+ /** LDtk JSON format version string (e.g. `"1.5.3"`). */
168
+ readonly jsonVersion: string;
169
+ readonly worldGridWidth?: number;
170
+ readonly worldGridHeight?: number;
171
+ readonly defaultGridSize?: number;
172
+ readonly bgColor?: string;
173
+ readonly defs: LdtkDefs;
174
+ readonly levels: readonly LdtkLevel[];
175
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * TypeScript types for the LDtk JSON format (version 1.5.x).
3
+ *
4
+ * These interfaces model the root LDtk JSON document as produced by the LDtk
5
+ * level editor. Only the fields consumed by the ExoJS runtime adapter are
6
+ * declared here; unknown fields are not stripped at parse time.
7
+ *
8
+ * @see https://ldtk.io/json/
9
+ */
10
+ /* eslint-disable @typescript-eslint/naming-convention -- LDtk uses __ prefix for runtime fields */
11
+ // ── Tile data ─────────────────────────────────────────────────────────────────
12
+ /** Flip-bit constants for {@link LdtkTileData.f}. */
13
+ const ldtkFlipNone = 0;
14
+ const ldtkFlipX = 1;
15
+ const ldtkFlipY = 2;
16
+ const ldtkFlipXy = 3;
17
+
18
+ export { ldtkFlipNone, ldtkFlipX, ldtkFlipXy, ldtkFlipY };
19
+ //# sourceMappingURL=LdtkData.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LdtkData.js","sources":["../../../src/LdtkData.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;;;;;;;;AAQG;AAEH;AAEA;AAEA;AACO,MAAM,YAAY,GAAG;AACrB,MAAM,SAAS,GAAG;AAClB,MAAM,SAAS,GAAG;AAClB,MAAM,UAAU,GAAG;;;;"}
@@ -0,0 +1,43 @@
1
+ import type { TileMap } from '@codexo/exojs-tilemap';
2
+ import type { LdtkData } from './LdtkData';
3
+ /**
4
+ * A parsed LDtk world document: holds the raw JSON data and the converted
5
+ * runtime {@link TileMap} for each level.
6
+ *
7
+ * `LdtkMap` is the parsed source model. Each LDtk level is independently
8
+ * convertible to a format-independent `TileMap`; access them via
9
+ * {@link levels} (by document order) or by name via {@link getLevelByName}.
10
+ *
11
+ * Construction is cheap — the runtime `TileMap[]` is supplied externally
12
+ * (built by {@link import('./ldtkToTileMap').ldtkToTileMap}). The map does
13
+ * **not** own tileset textures; those remain in the Loader cache.
14
+ */
15
+ export declare class LdtkMap {
16
+ /** Resolved URL this map was loaded from. */
17
+ readonly source: string;
18
+ /** The raw parsed LDtk document. */
19
+ readonly data: LdtkData;
20
+ /**
21
+ * Runtime TileMaps — one per LDtk level, in document order.
22
+ *
23
+ * The index here corresponds to `data.levels[i]`. Levels for which
24
+ * conversion was skipped (e.g. external `.ldtkl` files not yet loaded)
25
+ * are `undefined` at that position.
26
+ */
27
+ readonly levels: readonly TileMap[];
28
+ constructor(source: string, data: LdtkData, levels: readonly TileMap[]);
29
+ /**
30
+ * Find a level's runtime {@link TileMap} by the LDtk level `identifier`,
31
+ * or `undefined` when no level with that name exists.
32
+ *
33
+ * The lookup is O(n) in the number of levels.
34
+ */
35
+ getLevelByName(identifier: string): TileMap | undefined;
36
+ /**
37
+ * Destroy all owned runtime TileMaps.
38
+ *
39
+ * Is idempotent. Does NOT destroy tileset textures (Loader-owned) or any
40
+ * SceneNodes — the application is responsible for those.
41
+ */
42
+ destroy(): void;
43
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * A parsed LDtk world document: holds the raw JSON data and the converted
3
+ * runtime {@link TileMap} for each level.
4
+ *
5
+ * `LdtkMap` is the parsed source model. Each LDtk level is independently
6
+ * convertible to a format-independent `TileMap`; access them via
7
+ * {@link levels} (by document order) or by name via {@link getLevelByName}.
8
+ *
9
+ * Construction is cheap — the runtime `TileMap[]` is supplied externally
10
+ * (built by {@link import('./ldtkToTileMap').ldtkToTileMap}). The map does
11
+ * **not** own tileset textures; those remain in the Loader cache.
12
+ */
13
+ class LdtkMap {
14
+ /** Resolved URL this map was loaded from. */
15
+ source;
16
+ /** The raw parsed LDtk document. */
17
+ data;
18
+ /**
19
+ * Runtime TileMaps — one per LDtk level, in document order.
20
+ *
21
+ * The index here corresponds to `data.levels[i]`. Levels for which
22
+ * conversion was skipped (e.g. external `.ldtkl` files not yet loaded)
23
+ * are `undefined` at that position.
24
+ */
25
+ levels;
26
+ constructor(source, data, levels) {
27
+ this.source = source;
28
+ this.data = data;
29
+ this.levels = levels;
30
+ }
31
+ /**
32
+ * Find a level's runtime {@link TileMap} by the LDtk level `identifier`,
33
+ * or `undefined` when no level with that name exists.
34
+ *
35
+ * The lookup is O(n) in the number of levels.
36
+ */
37
+ getLevelByName(identifier) {
38
+ const index = this.data.levels.findIndex(level => level.identifier === identifier);
39
+ if (index === -1)
40
+ return undefined;
41
+ return this.levels[index];
42
+ }
43
+ /**
44
+ * Destroy all owned runtime TileMaps.
45
+ *
46
+ * Is idempotent. Does NOT destroy tileset textures (Loader-owned) or any
47
+ * SceneNodes — the application is responsible for those.
48
+ */
49
+ destroy() {
50
+ for (const level of this.levels) {
51
+ level.destroy();
52
+ }
53
+ }
54
+ }
55
+
56
+ export { LdtkMap };
57
+ //# sourceMappingURL=LdtkMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LdtkMap.js","sources":["../../../src/LdtkMap.ts"],"sourcesContent":[null],"names":[],"mappings":"AAIA;;;;;;;;;;;AAWG;MACU,OAAO,CAAA;;AAEF,IAAA,MAAM;;AAEN,IAAA,IAAI;AACpB;;;;;;AAMG;AACa,IAAA,MAAM;AAEtB,IAAA,WAAA,CAAmB,MAAc,EAAE,IAAc,EAAE,MAA0B,EAAA;AAC3E,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;AACpB,QAAA,IAAI,CAAC,IAAI,GAAG,IAAI;AAChB,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;IACtB;AAEA;;;;;AAKG;AACI,IAAA,cAAc,CAAC,UAAkB,EAAA;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,KAAK,UAAU,CAAC;QAClF,IAAI,KAAK,KAAK,EAAE;AAAE,YAAA,OAAO,SAAS;AAClC,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;IAC3B;AAEA;;;;;AAKG;IACI,OAAO,GAAA;AACZ,QAAA,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE;YAC/B,KAAK,CAAC,OAAO,EAAE;QACjB;IACF;AACD;;;;"}
@@ -0,0 +1 @@
1
+ export * from './public';
@@ -0,0 +1,7 @@
1
+ export { ldtkMapBinding } from './ldtkBinding.js';
2
+ export { ldtkExtension } from './ldtkExtension.js';
3
+ export { LdtkMap } from './LdtkMap.js';
4
+ export { ldtkToTileMap } from './ldtkToTileMap.js';
5
+ export { ldtkFlipNone, ldtkFlipX, ldtkFlipXy, ldtkFlipY } from './LdtkData.js';
6
+ export { ObjectKind, ObjectLayer, TILE_TRANSFORM_IDENTITY, TileLayer, TileMap, TileMapView, TileSet, tilemapExtension } from '@codexo/exojs-tilemap';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
@@ -0,0 +1,22 @@
1
+ import { LdtkMap } from './LdtkMap';
2
+ /**
3
+ * Declarative asset binding for {@link LdtkMap}.
4
+ *
5
+ * Claims the `ldtk` file extension so that:
6
+ * - `loader.load(LdtkMap, 'world.ldtk')` — returns the parsed
7
+ * {@link LdtkMap} with all levels pre-converted to runtime
8
+ * {@link import('@codexo/exojs-tilemap').TileMap}s.
9
+ * - `loader.load('world.ldtk')` — auto-routed to `LdtkMap` via
10
+ * the `ExtensionTypeMap` augmentation in `public.ts`.
11
+ *
12
+ * Each loaded level's TileMap is accessible via {@link LdtkMap.levels} or
13
+ * {@link LdtkMap.getLevelByName}.
14
+ */
15
+ export declare const ldtkMapBinding: {
16
+ type: typeof LdtkMap;
17
+ typeNames: string[];
18
+ extensions: string[];
19
+ create(): {
20
+ load(req: import("@codexo/exojs").AssetLoadRequest<undefined>, ctx: import("@codexo/exojs").AssetLoaderContext): Promise<LdtkMap>;
21
+ };
22
+ };
@@ -0,0 +1,31 @@
1
+ import { LdtkMap } from './LdtkMap.js';
2
+ import { loadLdtkMap } from './loadLdtkMap.js';
3
+
4
+ /**
5
+ * Declarative asset binding for {@link LdtkMap}.
6
+ *
7
+ * Claims the `ldtk` file extension so that:
8
+ * - `loader.load(LdtkMap, 'world.ldtk')` — returns the parsed
9
+ * {@link LdtkMap} with all levels pre-converted to runtime
10
+ * {@link import('@codexo/exojs-tilemap').TileMap}s.
11
+ * - `loader.load('world.ldtk')` — auto-routed to `LdtkMap` via
12
+ * the `ExtensionTypeMap` augmentation in `public.ts`.
13
+ *
14
+ * Each loaded level's TileMap is accessible via {@link LdtkMap.levels} or
15
+ * {@link LdtkMap.getLevelByName}.
16
+ */
17
+ const ldtkMapBinding = {
18
+ type: LdtkMap,
19
+ typeNames: ['ldtkMap'],
20
+ extensions: ['ldtk'],
21
+ create() {
22
+ return {
23
+ async load(req, ctx) {
24
+ return loadLdtkMap(req.source, ctx);
25
+ },
26
+ };
27
+ },
28
+ };
29
+
30
+ export { ldtkMapBinding };
31
+ //# sourceMappingURL=ldtkBinding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ldtkBinding.js","sources":["../../../src/ldtkBinding.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAKA;;;;;;;;;;;;AAYG;AACI,MAAM,cAAc,GAAG;AAC5B,IAAA,IAAI,EAAE,OAAO;IACb,SAAS,EAAE,CAAC,SAAS,CAAC;IACtB,UAAU,EAAE,CAAC,MAAM,CAAC;IACpB,MAAM,GAAA;QACJ,OAAO;AACL,YAAA,MAAM,IAAI,CAAC,GAAG,EAAE,GAAG,EAAA;gBACjB,OAAO,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;YACrC,CAAC;SAC8B;IACnC,CAAC;;;;;"}
@@ -0,0 +1,17 @@
1
+ import type { Extension } from '@codexo/exojs/extensions';
2
+ /**
3
+ * Default immutable LDtk extension descriptor.
4
+ *
5
+ * Registers one asset binding:
6
+ * - {@link ldtkMapBinding} — `loader.load(LdtkMap, 'world.ldtk')` → fetches
7
+ * the `.ldtk` JSON, loads all referenced tileset images, and returns a
8
+ * fully assembled {@link LdtkMap} with one runtime
9
+ * {@link import('@codexo/exojs-tilemap').TileMap} per level.
10
+ *
11
+ * Depends on {@link tilemapExtension} so that snapshot construction always
12
+ * materialises the generic tilemap runtime before the LDtk adapter.
13
+ *
14
+ * Use with `ApplicationOptions.extensions` or call
15
+ * `import '@codexo/exojs-ldtk/register'` for global auto-registration.
16
+ */
17
+ export declare const ldtkExtension: Extension;
@@ -0,0 +1,28 @@
1
+ import { tilemapExtension } from '@codexo/exojs-tilemap';
2
+ import { ldtkMapBinding } from './ldtkBinding.js';
3
+
4
+ /**
5
+ * Default immutable LDtk extension descriptor.
6
+ *
7
+ * Registers one asset binding:
8
+ * - {@link ldtkMapBinding} — `loader.load(LdtkMap, 'world.ldtk')` → fetches
9
+ * the `.ldtk` JSON, loads all referenced tileset images, and returns a
10
+ * fully assembled {@link LdtkMap} with one runtime
11
+ * {@link import('@codexo/exojs-tilemap').TileMap} per level.
12
+ *
13
+ * Depends on {@link tilemapExtension} so that snapshot construction always
14
+ * materialises the generic tilemap runtime before the LDtk adapter.
15
+ *
16
+ * Use with `ApplicationOptions.extensions` or call
17
+ * `import '@codexo/exojs-ldtk/register'` for global auto-registration.
18
+ */
19
+ const ldtkExtension = Object.freeze({
20
+ id: '@codexo/exojs-ldtk',
21
+ dependencies: [tilemapExtension],
22
+ // Localized erasure cast: typed binding meets the untyped Extension.assets
23
+ // contract here. Runtime behaviour is unaffected.
24
+ assets: [ldtkMapBinding],
25
+ });
26
+
27
+ export { ldtkExtension };
28
+ //# sourceMappingURL=ldtkExtension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ldtkExtension.js","sources":["../../../src/ldtkExtension.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAKA;;;;;;;;;;;;;;AAcG;AACI,MAAM,aAAa,GAAc,MAAM,CAAC,MAAM,CAAC;AACpD,IAAA,EAAE,EAAE,oBAAoB;IACxB,YAAY,EAAE,CAAC,gBAAgB,CAAC;;;IAGhC,MAAM,EAAE,CAAC,cAAc,CAA8B;AACtD,CAAA;;;;"}
@@ -0,0 +1,40 @@
1
+ import type { TileSet } from '@codexo/exojs-tilemap';
2
+ import { TILE_TRANSFORM_IDENTITY } from '@codexo/exojs-tilemap';
3
+ import type { LdtkData } from './LdtkData';
4
+ import { LdtkMap } from './LdtkMap';
5
+ /**
6
+ * Options for {@link ldtkToTileMap}.
7
+ */
8
+ export interface LdtkToTileMapOptions {
9
+ /**
10
+ * Source URL of the loaded `.ldtk` file, used as {@link LdtkMap.source}.
11
+ * Defaults to an empty string when omitted (e.g. programmatic / test usage).
12
+ */
13
+ readonly source?: string;
14
+ /**
15
+ * Pre-loaded runtime {@link TileSet}s keyed by LDtk tileset UID.
16
+ *
17
+ * When provided, tile layers are populated with tile data from
18
+ * `gridTiles` / `autoLayerTiles`. Without this map, tile layers are created
19
+ * with the correct dimensions but no tiles are placed — only entity and
20
+ * object layers carry data.
21
+ *
22
+ * Populate via {@link import('./loadLdtkMap').loadLdtkMap} for asset-loading
23
+ * flows, or pass a hand-crafted map for testing.
24
+ */
25
+ readonly tilesets?: ReadonlyMap<number, TileSet>;
26
+ }
27
+ /**
28
+ * Convert a raw {@link LdtkData} document into an {@link LdtkMap} containing
29
+ * one runtime {@link TileMap} per LDtk level.
30
+ *
31
+ * Tile layers (`Tiles` / `AutoLayer`) become renderable `TileLayer`s. IntGrid
32
+ * layers become dimension-correct `TileLayer`s — tile data is placed only when
33
+ * the layer carries `autoLayerTiles`. Entity layers become data-only
34
+ * `ObjectLayer`s with entity position, size, and scalar field properties.
35
+ *
36
+ * Pass `options.tilesets` to populate tile data; omit it for structure-only
37
+ * conversion (useful in unit tests that do not need textures).
38
+ */
39
+ export declare function ldtkToTileMap(data: LdtkData, options?: LdtkToTileMapOptions): LdtkMap;
40
+ export { TILE_TRANSFORM_IDENTITY };
@@ -0,0 +1,200 @@
1
+ import { ObjectLayer, TileMap, TileLayer } from '@codexo/exojs-tilemap';
2
+ export { TILE_TRANSFORM_IDENTITY } from '@codexo/exojs-tilemap';
3
+ import { ldtkFlipY, ldtkFlipX } from './LdtkData.js';
4
+ import { LdtkMap } from './LdtkMap.js';
5
+
6
+ /**
7
+ * Convert a raw {@link LdtkData} document into an {@link LdtkMap} containing
8
+ * one runtime {@link TileMap} per LDtk level.
9
+ *
10
+ * Tile layers (`Tiles` / `AutoLayer`) become renderable `TileLayer`s. IntGrid
11
+ * layers become dimension-correct `TileLayer`s — tile data is placed only when
12
+ * the layer carries `autoLayerTiles`. Entity layers become data-only
13
+ * `ObjectLayer`s with entity position, size, and scalar field properties.
14
+ *
15
+ * Pass `options.tilesets` to populate tile data; omit it for structure-only
16
+ * conversion (useful in unit tests that do not need textures).
17
+ */
18
+ function ldtkToTileMap(data, options) {
19
+ const source = options?.source ?? '';
20
+ const tilesets = options?.tilesets ?? new Map();
21
+ const levels = data.levels.map((level, levelIndex) => convertLevel(level, levelIndex, data, tilesets));
22
+ return new LdtkMap(source, data, levels);
23
+ }
24
+ // ── Level conversion ──────────────────────────────────────────────────────────
25
+ // eslint-disable-next-line complexity
26
+ function convertLevel(level, levelIndex, data, tilesets) {
27
+ // Derive map-level tile size from the first non-entity layer, or fall back.
28
+ const gridSize = pickLevelGridSize(level, data.defaultGridSize ?? 16);
29
+ const mapWidth = Math.max(1, Math.ceil(level.pxWid / gridSize));
30
+ const mapHeight = Math.max(1, Math.ceil(level.pxHei / gridSize));
31
+ const runtimeTilesets = [...tilesets.values()];
32
+ const runtimeLayers = [];
33
+ const runtimeObjectLayers = [];
34
+ // LDtk stores layers top-to-bottom (first = top-most); preserve that order.
35
+ const layerInstances = level.layerInstances ?? [];
36
+ let entityCounter = 0;
37
+ for (const layerInst of layerInstances) {
38
+ const layerGridSize = layerInst.__gridSize;
39
+ // Layer IDs must be unique within a TileMap (= one level).
40
+ // Use layerDefUid directly — it is unique per layer definition in the file.
41
+ const layerId = layerInst.layerDefUid;
42
+ switch (layerInst.__type) {
43
+ case 'Tiles':
44
+ case 'AutoLayer': {
45
+ const rLayer = makeTileLayer(layerInst, layerId, runtimeTilesets);
46
+ const tiles = layerInst.__type === 'Tiles'
47
+ ? (layerInst.gridTiles ?? [])
48
+ : (layerInst.autoLayerTiles ?? []);
49
+ const tsUid = layerInst.__tilesetDefUid;
50
+ if (tsUid !== undefined) {
51
+ const rts = tilesets.get(tsUid);
52
+ if (rts)
53
+ populateTileLayer(rLayer, tiles, rts, layerGridSize);
54
+ }
55
+ runtimeLayers.push(rLayer);
56
+ break;
57
+ }
58
+ case 'IntGrid': {
59
+ const rLayer = makeTileLayer(layerInst, layerId, runtimeTilesets);
60
+ // IntGrid layers may carry auto-tiles when "Auto-layer" rules are
61
+ // configured. Use those for rendering; raw intGridCsv is data-only.
62
+ const autoTiles = layerInst.autoLayerTiles ?? [];
63
+ const tsUid = layerInst.__tilesetDefUid;
64
+ if (autoTiles.length > 0 && tsUid !== undefined) {
65
+ const rts = tilesets.get(tsUid);
66
+ if (rts)
67
+ populateTileLayer(rLayer, autoTiles, rts, layerGridSize);
68
+ }
69
+ runtimeLayers.push(rLayer);
70
+ break;
71
+ }
72
+ case 'Entities': {
73
+ const objects = convertEntityLayer(layerInst, layerGridSize, levelIndex, entityCounter);
74
+ entityCounter += layerInst.entityInstances?.length ?? 0;
75
+ runtimeObjectLayers.push(new ObjectLayer({
76
+ id: layerId,
77
+ name: layerInst.__identifier,
78
+ visible: layerInst.visible,
79
+ opacity: layerInst.opacity ?? 1,
80
+ offsetX: layerInst.pxOffsetX ?? 0,
81
+ offsetY: layerInst.pxOffsetY ?? 0,
82
+ objects,
83
+ }));
84
+ break;
85
+ }
86
+ }
87
+ }
88
+ return new TileMap({
89
+ name: level.identifier,
90
+ width: mapWidth,
91
+ height: mapHeight,
92
+ tileWidth: gridSize,
93
+ tileHeight: gridSize,
94
+ tilesets: runtimeTilesets,
95
+ layers: runtimeLayers,
96
+ objectLayers: runtimeObjectLayers,
97
+ properties: {
98
+ ldtkUid: level.uid,
99
+ ldtkIid: level.iid,
100
+ worldX: level.worldX,
101
+ worldY: level.worldY,
102
+ },
103
+ });
104
+ }
105
+ // ── Helpers: TileLayer ────────────────────────────────────────────────────────
106
+ function makeTileLayer(layerInst, layerId, tilesets) {
107
+ return new TileLayer({
108
+ id: layerId,
109
+ name: layerInst.__identifier,
110
+ width: layerInst.__cWid,
111
+ height: layerInst.__cHei,
112
+ tilesets,
113
+ tileWidth: layerInst.__gridSize,
114
+ tileHeight: layerInst.__gridSize,
115
+ visible: layerInst.visible,
116
+ opacity: layerInst.opacity ?? 1,
117
+ offsetX: layerInst.pxOffsetX ?? 0,
118
+ offsetY: layerInst.pxOffsetY ?? 0,
119
+ });
120
+ }
121
+ function populateTileLayer(layer, tiles, tileset, gridSize) {
122
+ for (const tile of tiles) {
123
+ const tx = Math.floor(tile.px[0] / gridSize);
124
+ const ty = Math.floor(tile.px[1] / gridSize);
125
+ if (!layer.inBounds(tx, ty))
126
+ continue;
127
+ const localTileId = tile.t;
128
+ if (localTileId < 0 || localTileId >= tileset.tileCount)
129
+ continue;
130
+ const f = tile.f;
131
+ layer.setTileAt(tx, ty, {
132
+ tileset,
133
+ localTileId,
134
+ transform: {
135
+ flipX: (f & ldtkFlipX) !== 0,
136
+ flipY: (f & ldtkFlipY) !== 0,
137
+ diagonal: false,
138
+ },
139
+ });
140
+ }
141
+ }
142
+ // ── Helpers: ObjectLayer ──────────────────────────────────────────────────────
143
+ function convertEntityLayer(layerInst, _gridSize, levelIndex, baseCounter) {
144
+ const instances = layerInst.entityInstances ?? [];
145
+ const objects = [];
146
+ for (let i = 0; i < instances.length; i++) {
147
+ const entity = instances[i];
148
+ if (entity === undefined)
149
+ continue;
150
+ // Build a deterministic numeric id: (levelIndex * 1_000_000) + counter.
151
+ const id = levelIndex * 1_000_000 + baseCounter + i;
152
+ objects.push(convertEntity(entity, id));
153
+ }
154
+ return objects;
155
+ }
156
+ function convertEntity(entity, id) {
157
+ return {
158
+ kind: 'rectangle',
159
+ id,
160
+ name: entity.__identifier,
161
+ type: entity.__identifier,
162
+ x: entity.px[0],
163
+ y: entity.px[1],
164
+ width: entity.width,
165
+ height: entity.height,
166
+ rotation: 0,
167
+ visible: true,
168
+ properties: convertFieldInstances(entity.fieldInstances),
169
+ };
170
+ }
171
+ /**
172
+ * Project LDtk field instances to a flat {@link TileProperties} bag.
173
+ * Only scalar values (string, number, boolean) are forwarded; complex types
174
+ * (arrays, colours, enums-as-objects) are silently skipped.
175
+ */
176
+ function convertFieldInstances(fields) {
177
+ if (fields.length === 0)
178
+ return Object.freeze({});
179
+ const out = {};
180
+ for (const field of fields) {
181
+ const v = field.__value;
182
+ if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') {
183
+ out[field.__identifier] = v;
184
+ }
185
+ }
186
+ return Object.freeze(out);
187
+ }
188
+ // ── Helpers: grid size ────────────────────────────────────────────────────────
189
+ function pickLevelGridSize(level, fallback) {
190
+ const instances = level.layerInstances ?? [];
191
+ for (const layer of instances) {
192
+ if (layer.__type !== 'Entities' && layer.__gridSize > 0) {
193
+ return layer.__gridSize;
194
+ }
195
+ }
196
+ return fallback;
197
+ }
198
+
199
+ export { ldtkToTileMap };
200
+ //# sourceMappingURL=ldtkToTileMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ldtkToTileMap.js","sources":["../../../src/ldtkToTileMap.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAuCA;;;;;;;;;;;AAWG;AACG,SAAU,aAAa,CAAC,IAAc,EAAE,OAA8B,EAAA;AAC1E,IAAA,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,EAAE;IACpC,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,IAAI,GAAG,EAAmB;IAEhE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,KAC/C,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,CAChD;IAED,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;AAC1C;AAEA;AAEA;AACA,SAAS,YAAY,CACnB,KAAgB,EAChB,UAAkB,EAClB,IAAc,EACd,QAAsC,EAAA;;AAGtC,IAAA,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,IAAI,EAAE,CAAC;AACrE,IAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC;AAC/D,IAAA,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC;IAEhE,MAAM,eAAe,GAAc,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;IACzD,MAAM,aAAa,GAAgB,EAAE;IACrC,MAAM,mBAAmB,GAAkB,EAAE;;AAG7C,IAAA,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,IAAI,EAAE;IACjD,IAAI,aAAa,GAAG,CAAC;AAErB,IAAA,KAAK,MAAM,SAAS,IAAI,cAAc,EAAE;AACtC,QAAA,MAAM,aAAa,GAAG,SAAS,CAAC,UAAU;;;AAG1C,QAAA,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW;AAErC,QAAA,QAAQ,SAAS,CAAC,MAAM;AACtB,YAAA,KAAK,OAAO;YACZ,KAAK,WAAW,EAAE;gBAChB,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,EAAE,OAAO,EAAE,eAAe,CAAC;AACjE,gBAAA,MAAM,KAAK,GACT,SAAS,CAAC,MAAM,KAAK;AACnB,uBAAG,SAAS,CAAC,SAAS,IAAI,EAAE;uBACzB,SAAS,CAAC,cAAc,IAAI,EAAE,CAAC;AACtC,gBAAA,MAAM,KAAK,GAAG,SAAS,CAAC,eAAe;AACvC,gBAAA,IAAI,KAAK,KAAK,SAAS,EAAE;oBACvB,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;AAC/B,oBAAA,IAAI,GAAG;wBAAE,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,aAAa,CAAC;gBAC/D;AACA,gBAAA,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;gBAC1B;YACF;YAEA,KAAK,SAAS,EAAE;gBACd,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,EAAE,OAAO,EAAE,eAAe,CAAC;;;AAGjE,gBAAA,MAAM,SAAS,GAAG,SAAS,CAAC,cAAc,IAAI,EAAE;AAChD,gBAAA,MAAM,KAAK,GAAG,SAAS,CAAC,eAAe;gBACvC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,KAAK,SAAS,EAAE;oBAC/C,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;AAC/B,oBAAA,IAAI,GAAG;wBAAE,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,CAAC;gBACnE;AACA,gBAAA,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;gBAC1B;YACF;YAEA,KAAK,UAAU,EAAE;AACf,gBAAA,MAAM,OAAO,GAAG,kBAAkB,CAChC,SAAS,EACT,aAAa,EACb,UAAU,EACV,aAAa,CACd;gBACD,aAAa,IAAI,SAAS,CAAC,eAAe,EAAE,MAAM,IAAI,CAAC;AACvD,gBAAA,mBAAmB,CAAC,IAAI,CACtB,IAAI,WAAW,CAAC;AACd,oBAAA,EAAE,EAAE,OAAO;oBACX,IAAI,EAAE,SAAS,CAAC,YAAY;oBAC5B,OAAO,EAAE,SAAS,CAAC,OAAO;AAC1B,oBAAA,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,CAAC;AAC/B,oBAAA,OAAO,EAAE,SAAS,CAAC,SAAS,IAAI,CAAC;AACjC,oBAAA,OAAO,EAAE,SAAS,CAAC,SAAS,IAAI,CAAC;oBACjC,OAAO;AACR,iBAAA,CAAC,CACH;gBACD;YACF;;IAEJ;IAEA,OAAO,IAAI,OAAO,CAAC;QACjB,IAAI,EAAE,KAAK,CAAC,UAAU;AACtB,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,MAAM,EAAE,SAAS;AACjB,QAAA,SAAS,EAAE,QAAQ;AACnB,QAAA,UAAU,EAAE,QAAQ;AACpB,QAAA,QAAQ,EAAE,eAAe;AACzB,QAAA,MAAM,EAAE,aAAa;AACrB,QAAA,YAAY,EAAE,mBAAmB;AACjC,QAAA,UAAU,EAAE;YACV,OAAO,EAAE,KAAK,CAAC,GAAG;YAClB,OAAO,EAAE,KAAK,CAAC,GAAG;YAClB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;AACrB,SAAA;AACF,KAAA,CAAC;AACJ;AAEA;AAEA,SAAS,aAAa,CACpB,SAA4B,EAC5B,OAAe,EACf,QAA4B,EAAA;IAE5B,OAAO,IAAI,SAAS,CAAC;AACnB,QAAA,EAAE,EAAE,OAAO;QACX,IAAI,EAAE,SAAS,CAAC,YAAY;QAC5B,KAAK,EAAE,SAAS,CAAC,MAAM;QACvB,MAAM,EAAE,SAAS,CAAC,MAAM;QACxB,QAAQ;QACR,SAAS,EAAE,SAAS,CAAC,UAAU;QAC/B,UAAU,EAAE,SAAS,CAAC,UAAU;QAChC,OAAO,EAAE,SAAS,CAAC,OAAO;AAC1B,QAAA,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,CAAC;AAC/B,QAAA,OAAO,EAAE,SAAS,CAAC,SAAS,IAAI,CAAC;AACjC,QAAA,OAAO,EAAE,SAAS,CAAC,SAAS,IAAI,CAAC;AAClC,KAAA,CAAC;AACJ;AAEA,SAAS,iBAAiB,CACxB,KAAgB,EAChB,KAA8B,EAC9B,OAAgB,EAChB,QAAgB,EAAA;AAEhB,IAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;AACxB,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;AAC5C,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;QAC5C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;YAAE;AAE7B,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC;QAC1B,IAAI,WAAW,GAAG,CAAC,IAAI,WAAW,IAAI,OAAO,CAAC,SAAS;YAAE;AAEzD,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;AAChB,QAAA,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE;YACtB,OAAO;YACP,WAAW;AACX,YAAA,SAAS,EAAE;AACT,gBAAA,KAAK,EAAE,CAAC,CAAC,GAAG,SAAS,MAAM,CAAC;AAC5B,gBAAA,KAAK,EAAE,CAAC,CAAC,GAAG,SAAS,MAAM,CAAC;AAC5B,gBAAA,QAAQ,EAAE,KAAK;AAChB,aAAA;AACF,SAAA,CAAC;IACJ;AACF;AAEA;AAEA,SAAS,kBAAkB,CACzB,SAA4B,EAC5B,SAAiB,EACjB,UAAkB,EAClB,WAAmB,EAAA;AAEnB,IAAA,MAAM,SAAS,GAAG,SAAS,CAAC,eAAe,IAAI,EAAE;IACjD,MAAM,OAAO,GAAoB,EAAE;AAEnC,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACzC,QAAA,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;QAC3B,IAAI,MAAM,KAAK,SAAS;YAAE;;QAE1B,MAAM,EAAE,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzC;AAEA,IAAA,OAAO,OAAO;AAChB;AAEA,SAAS,aAAa,CAAC,MAA0B,EAAE,EAAU,EAAA;IAC3D,OAAO;AACL,QAAA,IAAI,EAAE,WAAW;QACjB,EAAE;QACF,IAAI,EAAE,MAAM,CAAC,YAAY;QACzB,IAAI,EAAE,MAAM,CAAC,YAAY;AACzB,QAAA,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AACf,QAAA,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QACf,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;AACrB,QAAA,QAAQ,EAAE,CAAC;AACX,QAAA,OAAO,EAAE,IAAI;AACb,QAAA,UAAU,EAAE,qBAAqB,CAAC,MAAM,CAAC,cAAc,CAAC;KACzD;AACH;AAEA;;;;AAIG;AACH,SAAS,qBAAqB,CAAC,MAAoC,EAAA;AACjE,IAAA,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IACjD,MAAM,GAAG,GAAsC,EAAE;AACjD,IAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;AAC1B,QAAA,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO;AACvB,QAAA,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,SAAS,EAAE;AAC5E,YAAA,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC;QAC7B;IACF;AACA,IAAA,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;AAC3B;AAEA;AAEA,SAAS,iBAAiB,CAAC,KAAgB,EAAE,QAAgB,EAAA;AAC3D,IAAA,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc,IAAI,EAAE;AAC5C,IAAA,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE;AAC7B,QAAA,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,EAAE;YACvD,OAAO,KAAK,CAAC,UAAU;QACzB;IACF;AACA,IAAA,OAAO,QAAQ;AACjB;;;;"}
@@ -0,0 +1,12 @@
1
+ import { type AssetLoaderContext } from '@codexo/exojs';
2
+ import type { LdtkMap } from './LdtkMap';
3
+ /**
4
+ * Fetch a `.ldtk` file, load all referenced tileset images, and return a
5
+ * fully assembled {@link LdtkMap} with one runtime {@link import('@codexo/exojs-tilemap').TileMap}
6
+ * per level.
7
+ *
8
+ * Tilesets without an atlas image (`relPath = null`) are silently skipped;
9
+ * their tiles will not appear in the rendered output.
10
+ * @internal
11
+ */
12
+ export declare function loadLdtkMap(source: string, context: AssetLoaderContext): Promise<LdtkMap>;
@@ -0,0 +1,81 @@
1
+ import { Texture, TextureRegion } from '@codexo/exojs';
2
+ import { TileSet } from '@codexo/exojs-tilemap';
3
+ import { ldtkToTileMap } from './ldtkToTileMap.js';
4
+
5
+ // ── URL resolution ────────────────────────────────────────────────────────────
6
+ /**
7
+ * Resolve a tileset-relative path against the base `.ldtk` URL.
8
+ * Mirrors the approach used by the Tiled adapter.
9
+ */
10
+ function resolveLdtkUrl(relPath, baseUrl) {
11
+ return new URL(relPath, baseUrl).href;
12
+ }
13
+ // ── Tileset loading ───────────────────────────────────────────────────────────
14
+ /**
15
+ * Load one LDtk tileset definition into a runtime {@link TileSet}.
16
+ * Returns `null` when the tileset has no atlas image (`relPath` is null or
17
+ * empty) — those entries are silently skipped and their tiles will not render.
18
+ */
19
+ async function loadLdtkTileset(def, ldtkSource, context) {
20
+ if (!def.relPath)
21
+ return null;
22
+ const imageUrl = resolveLdtkUrl(def.relPath, ldtkSource);
23
+ const texture = (await context.loader.load(Texture, imageUrl));
24
+ const tileSize = def.tileGridSize;
25
+ const spacing = def.spacing ?? 0;
26
+ const margin = def.padding ?? 0;
27
+ // Compute columns / tileCount from atlas dimensions.
28
+ const innerWidth = def.pxWid - margin * 2;
29
+ const innerHeight = def.pxHei - margin * 2;
30
+ const columns = Math.floor((innerWidth + spacing) / (tileSize + spacing));
31
+ const rows = Math.floor((innerHeight + spacing) / (tileSize + spacing));
32
+ if (columns <= 0 || rows <= 0)
33
+ return null;
34
+ const tileCount = columns * rows;
35
+ const region = new TextureRegion(texture, {
36
+ x: 0,
37
+ y: 0,
38
+ width: def.pxWid,
39
+ height: def.pxHei,
40
+ });
41
+ return new TileSet({
42
+ name: def.identifier,
43
+ texture: region,
44
+ tileWidth: tileSize,
45
+ tileHeight: tileSize,
46
+ tileCount,
47
+ columns,
48
+ spacing,
49
+ margin,
50
+ });
51
+ }
52
+ // ── Public loader ─────────────────────────────────────────────────────────────
53
+ /**
54
+ * Fetch a `.ldtk` file, load all referenced tileset images, and return a
55
+ * fully assembled {@link LdtkMap} with one runtime {@link import('@codexo/exojs-tilemap').TileMap}
56
+ * per level.
57
+ *
58
+ * Tilesets without an atlas image (`relPath = null`) are silently skipped;
59
+ * their tiles will not appear in the rendered output.
60
+ * @internal
61
+ */
62
+ async function loadLdtkMap(source, context) {
63
+ const raw = await context.fetchJson(source);
64
+ // Cast without deep validation — structural errors surface as runtime
65
+ // exceptions when we access fields during conversion.
66
+ const data = raw;
67
+ // Load all referenced tilesets concurrently.
68
+ const tilesetEntries = await Promise.all(data.defs.tilesets.map(async (def) => {
69
+ const ts = await loadLdtkTileset(def, source, context);
70
+ return [def.uid, ts];
71
+ }));
72
+ const tilesets = new Map();
73
+ for (const [uid, ts] of tilesetEntries) {
74
+ if (ts !== null)
75
+ tilesets.set(uid, ts);
76
+ }
77
+ return ldtkToTileMap(data, { source, tilesets });
78
+ }
79
+
80
+ export { loadLdtkMap };
81
+ //# sourceMappingURL=loadLdtkMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadLdtkMap.js","sources":["../../../src/loadLdtkMap.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAOA;AAEA;;;AAGG;AACH,SAAS,cAAc,CAAC,OAAe,EAAE,OAAe,EAAA;IACtD,OAAO,IAAI,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI;AACvC;AAEA;AAEA;;;;AAIG;AACH,eAAe,eAAe,CAC5B,GAAmB,EACnB,UAAkB,EAClB,OAA2B,EAAA;IAE3B,IAAI,CAAC,GAAG,CAAC,OAAO;AAAE,QAAA,OAAO,IAAI;IAE7B,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC;AACxD,IAAA,MAAM,OAAO,IAAI,MAAM,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAY;AAEzE,IAAA,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY;AACjC,IAAA,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC;AAChC,IAAA,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC;;IAG/B,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC;IACzC,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC;AAC1C,IAAA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,CAAC;AACzE,IAAA,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,CAAC;AAEvE,IAAA,IAAI,OAAO,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;AAAE,QAAA,OAAO,IAAI;AAE1C,IAAA,MAAM,SAAS,GAAG,OAAO,GAAG,IAAI;AAChC,IAAA,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,OAAO,EAAE;AACxC,QAAA,CAAC,EAAE,CAAC;AACJ,QAAA,CAAC,EAAE,CAAC;QACJ,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,MAAM,EAAE,GAAG,CAAC,KAAK;AAClB,KAAA,CAAC;IAEF,OAAO,IAAI,OAAO,CAAC;QACjB,IAAI,EAAE,GAAG,CAAC,UAAU;AACpB,QAAA,OAAO,EAAE,MAAM;AACf,QAAA,SAAS,EAAE,QAAQ;AACnB,QAAA,UAAU,EAAE,QAAQ;QACpB,SAAS;QACT,OAAO;QACP,OAAO;QACP,MAAM;AACP,KAAA,CAAC;AACJ;AAEA;AAEA;;;;;;;;AAQG;AACI,eAAe,WAAW,CAC/B,MAAc,EACd,OAA2B,EAAA;IAE3B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC;;;IAG3C,MAAM,IAAI,GAAG,GAAe;;AAG5B,IAAA,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,GAAG,CACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,GAAG,KAAI;QACnC,MAAM,EAAE,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC;AACtD,QAAA,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAU;IAC/B,CAAC,CAAC,CACH;AAED,IAAA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAmB;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,cAAc,EAAE;QACtC,IAAI,EAAE,KAAK,IAAI;AAAE,YAAA,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC;IACxC;IAEA,OAAO,aAAa,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAClD;;;;"}
@@ -0,0 +1,24 @@
1
+ export { ldtkMapBinding } from './ldtkBinding';
2
+ export { ldtkExtension } from './ldtkExtension';
3
+ export { LdtkMap } from './LdtkMap';
4
+ export type { LdtkToTileMapOptions } from './ldtkToTileMap';
5
+ export { ldtkToTileMap } from './ldtkToTileMap';
6
+ export type { LdtkData, LdtkDefs, LdtkEntityInstance, LdtkFieldInstance, LdtkIntGridValueDef, LdtkLayerDef, LdtkLayerInstance, LdtkLayerType, LdtkLevel, LdtkTileData, LdtkTilesetDef, } from './LdtkData';
7
+ export { ldtkFlipNone, ldtkFlipX, ldtkFlipXy, ldtkFlipY } from './LdtkData';
8
+ export type { ChunkCoord, EllipseObject, ObjectLayerOptions, ObjectPoint, ObjectQuery, ObjectSchema, PackedTile, PointObject, PolygonObject, PolylineObject, ReadonlyTileChunk, RectangleObject, ResolvedTile, TileDefinition, TileLayerOptions, TileMapObject, TileMapObjectKind, TileMapOptions, TileMapViewOptions, TileObject, TileProperties, TilePropertyValue, TileSetOptions, TileTransform, } from '@codexo/exojs-tilemap';
9
+ export { ObjectKind, ObjectLayer, TILE_TRANSFORM_IDENTITY, TileLayer, TileMap, tilemapExtension, TileMapView, TileSet, } from '@codexo/exojs-tilemap';
10
+ import type { LdtkMap } from './LdtkMap';
11
+ declare module '@codexo/exojs' {
12
+ interface ExtensionTypeMap {
13
+ /** `.ldtk` path-only loads resolve to {@link LdtkMap}. */
14
+ ldtk: LdtkMap;
15
+ }
16
+ interface AssetDefinitions {
17
+ ldtkMap: {
18
+ resource: LdtkMap;
19
+ config: {
20
+ source: string;
21
+ };
22
+ };
23
+ }
24
+ }
@@ -0,0 +1 @@
1
+ export * from './public';
@@ -0,0 +1,17 @@
1
+ import { ExtensionRegistry } from '@codexo/exojs/extensions';
2
+ import { ldtkExtension } from './ldtkExtension.js';
3
+ export { ldtkMapBinding } from './ldtkBinding.js';
4
+ export { LdtkMap } from './LdtkMap.js';
5
+ export { ldtkToTileMap } from './ldtkToTileMap.js';
6
+ export { ldtkFlipNone, ldtkFlipX, ldtkFlipXy, ldtkFlipY } from './LdtkData.js';
7
+ export { ObjectKind, ObjectLayer, TILE_TRANSFORM_IDENTITY, TileLayer, TileMap, TileMapView, TileSet, tilemapExtension } from '@codexo/exojs-tilemap';
8
+
9
+ // @codexo/exojs-ldtk/register — explicit registration entry.
10
+ // Importing this entry registers the default ldtkExtension descriptor
11
+ // in the global ExtensionRegistry. Subsequently constructed Applications
12
+ // that use global defaults will receive the LDtk extension.
13
+ // This is the only side-effectful entry in this package.
14
+ ExtensionRegistry.register(ldtkExtension);
15
+
16
+ export { ldtkExtension };
17
+ //# 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,aAAa,CAAC;;;;"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@codexo/exojs-ldtk",
3
+ "version": "0.14.0",
4
+ "description": "LDtk level format asset extension for ExoJS.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/Exoridus/ExoJS.git",
8
+ "directory": "packages/exojs-ldtk"
9
+ },
10
+ "type": "module",
11
+ "sideEffects": [
12
+ "./dist/esm/register.js"
13
+ ],
14
+ "main": "./dist/esm/index.js",
15
+ "module": "./dist/esm/index.js",
16
+ "types": "./dist/esm/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/esm/index.d.ts",
20
+ "import": "./dist/esm/index.js",
21
+ "default": "./dist/esm/index.js"
22
+ },
23
+ "./register": {
24
+ "types": "./dist/esm/register.d.ts",
25
+ "import": "./dist/esm/register.js",
26
+ "default": "./dist/esm/register.js"
27
+ },
28
+ "./package.json": "./package.json"
29
+ },
30
+ "files": [
31
+ "dist/esm/",
32
+ "README.md",
33
+ "LICENSE"
34
+ ],
35
+ "peerDependencies": {
36
+ "@codexo/exojs": "0.14.x"
37
+ },
38
+ "dependencies": {
39
+ "@codexo/exojs-tilemap": "0.14.0"
40
+ },
41
+ "devDependencies": {
42
+ "@codexo/exojs": "0.14.0",
43
+ "@codexo/exojs-config": "0.0.0"
44
+ },
45
+ "license": "MIT",
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "scripts": {
50
+ "build": "tsx ../../node_modules/rollup/dist/bin/rollup -c --environment EXOJS_ENV:production",
51
+ "build:dev": "tsx ../../node_modules/rollup/dist/bin/rollup -c --environment EXOJS_ENV:development",
52
+ "typecheck": "tsc --noEmit",
53
+ "lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
54
+ "test": "vitest run --root ../.. --project=exojs-ldtk"
55
+ }
56
+ }