@codexo/exojs-ldtk 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 (67) hide show
  1. package/README.md +38 -20
  2. package/dist/esm/LdtkData.d.ts +59 -14
  3. package/dist/esm/LdtkData.d.ts.map +1 -0
  4. package/dist/esm/LdtkData.js +8 -16
  5. package/dist/esm/LdtkData.js.map +1 -1
  6. package/dist/esm/LdtkMap.d.ts +25 -6
  7. package/dist/esm/LdtkMap.d.ts.map +1 -0
  8. package/dist/esm/LdtkMap.js +88 -63
  9. package/dist/esm/LdtkMap.js.map +1 -1
  10. package/dist/esm/LdtkProject.d.ts +107 -0
  11. package/dist/esm/LdtkProject.d.ts.map +1 -0
  12. package/dist/esm/LdtkProject.js +136 -0
  13. package/dist/esm/LdtkProject.js.map +1 -0
  14. package/dist/esm/index.d.ts +1 -0
  15. package/dist/esm/index.d.ts.map +1 -0
  16. package/dist/esm/index.js +11 -7
  17. package/dist/esm/ldtkExtension.d.ts +9 -5
  18. package/dist/esm/ldtkExtension.d.ts.map +1 -0
  19. package/dist/esm/ldtkExtension.js +25 -22
  20. package/dist/esm/ldtkExtension.js.map +1 -1
  21. package/dist/esm/ldtkLevelEntries.d.ts +4 -3
  22. package/dist/esm/ldtkLevelEntries.d.ts.map +1 -0
  23. package/dist/esm/ldtkLevelEntries.js +30 -26
  24. package/dist/esm/ldtkLevelEntries.js.map +1 -1
  25. package/dist/esm/ldtkParallax.d.ts +22 -0
  26. package/dist/esm/ldtkParallax.d.ts.map +1 -0
  27. package/dist/esm/ldtkParallax.js +22 -0
  28. package/dist/esm/ldtkParallax.js.map +1 -0
  29. package/dist/esm/ldtkToMapWorld.d.ts +20 -0
  30. package/dist/esm/ldtkToMapWorld.d.ts.map +1 -0
  31. package/dist/esm/ldtkToMapWorld.js +76 -0
  32. package/dist/esm/ldtkToMapWorld.js.map +1 -0
  33. package/dist/esm/ldtkToTileMap.d.ts +48 -10
  34. package/dist/esm/ldtkToTileMap.d.ts.map +1 -0
  35. package/dist/esm/ldtkToTileMap.js +410 -387
  36. package/dist/esm/ldtkToTileMap.js.map +1 -1
  37. package/dist/esm/ldtkTypes.d.ts +47 -0
  38. package/dist/esm/ldtkTypes.d.ts.map +1 -0
  39. package/dist/esm/ldtkTypes.js +57 -0
  40. package/dist/esm/ldtkTypes.js.map +1 -0
  41. package/dist/esm/loadLdtkMap.d.ts +30 -5
  42. package/dist/esm/loadLdtkMap.d.ts.map +1 -0
  43. package/dist/esm/loadLdtkMap.js +139 -133
  44. package/dist/esm/loadLdtkMap.js.map +1 -1
  45. package/dist/esm/loadLdtkProject.d.ts +17 -0
  46. package/dist/esm/loadLdtkProject.d.ts.map +1 -0
  47. package/dist/esm/loadLdtkProject.js +31 -0
  48. package/dist/esm/loadLdtkProject.js.map +1 -0
  49. package/dist/esm/public.d.ts +24 -9
  50. package/dist/esm/public.d.ts.map +1 -0
  51. package/dist/esm/public.js +11 -0
  52. package/dist/esm/url.d.ts +16 -0
  53. package/dist/esm/url.d.ts.map +1 -0
  54. package/dist/esm/url.js +31 -0
  55. package/dist/esm/url.js.map +1 -0
  56. package/dist/esm/validate.d.ts +27 -0
  57. package/dist/esm/validate.d.ts.map +1 -0
  58. package/dist/esm/validate.js +327 -0
  59. package/dist/esm/validate.js.map +1 -0
  60. package/package.json +10 -18
  61. package/dist/esm/index.js.map +0 -1
  62. package/dist/esm/ldtkBinding.d.ts +0 -22
  63. package/dist/esm/ldtkBinding.js +0 -31
  64. package/dist/esm/ldtkBinding.js.map +0 -1
  65. package/dist/esm/register.d.ts +0 -1
  66. package/dist/esm/register.js +0 -17
  67. package/dist/esm/register.js.map +0 -1
@@ -0,0 +1,76 @@
1
+ import { getLdtkLevelEntries } from "./ldtkLevelEntries.js";
2
+ import { buildLdtkLevelProperties } from "./ldtkToTileMap.js";
3
+ import { MapLevelSide, MapWorld } from "@codexo/exojs-tilemap";
4
+
5
+ //#region src/ldtkToMapWorld.ts
6
+ /**
7
+ * LDtk direction codes, as emitted in `__neighbours[].dir`. The cardinal four
8
+ * have always existed; the depth relations arrived with LDtk 1.x.
9
+ */
10
+ const SIDE_BY_DIR = Object.freeze({
11
+ n: MapLevelSide.North,
12
+ s: MapLevelSide.South,
13
+ e: MapLevelSide.East,
14
+ w: MapLevelSide.West,
15
+ o: MapLevelSide.Overlap,
16
+ "<": MapLevelSide.Below,
17
+ ">": MapLevelSide.Above
18
+ });
19
+ const convertNeighbours = (level) => {
20
+ const raw = level.__neighbours;
21
+ if (raw === void 0 || raw === null || raw.length === 0) return [];
22
+ return raw.map((neighbour) => ({
23
+ id: neighbour.levelIid,
24
+ side: SIDE_BY_DIR[neighbour.dir] ?? MapLevelSide.Unknown
25
+ }));
26
+ };
27
+ const convertLevel = (level, worldIid, index) => ({
28
+ id: level.iid,
29
+ name: level.identifier,
30
+ index,
31
+ bounds: {
32
+ x: level.worldX,
33
+ y: level.worldY,
34
+ width: level.pxWid,
35
+ height: level.pxHei
36
+ },
37
+ external: Boolean(level.externalRelPath),
38
+ neighbours: convertNeighbours(level),
39
+ properties: buildLdtkLevelProperties(level, worldIid)
40
+ });
41
+ /**
42
+ * Build the format-neutral world model for an LDtk document: one
43
+ * {@link MapWorld} per LDtk world, in document order.
44
+ *
45
+ * A single-world project - the overwhelmingly common shape - yields exactly one
46
+ * unnamed world. A multi-world project yields one per entry of `worlds[]`, each
47
+ * named by its identifier, and they stay separate on purpose: LDtk worlds have independent coordinate spaces, so merging them
48
+ * would make {@link MapWorld.bounds} and {@link MapWorld.getLevelsInBounds}
49
+ * report overlaps that do not exist.
50
+ *
51
+ * {@link MapLevel.index} counts across the whole document, matching the
52
+ * flattened order {@link import('./LdtkMap').LdtkMap.levels} uses.
53
+ *
54
+ * Level metadata only: no layer payload is read, so this is safe to call on a
55
+ * document whose external levels have not been fetched.
56
+ */
57
+ const ldtkToMapWorld = (data) => {
58
+ const entries = getLdtkLevelEntries(data);
59
+ if (data.worlds && data.worlds.length > 0) {
60
+ const worlds = [];
61
+ let index = 0;
62
+ for (const world of data.worlds) {
63
+ const levels = world.levels.map((level) => convertLevel(level, world.iid, index++));
64
+ worlds.push(new MapWorld({
65
+ name: world.identifier,
66
+ levels
67
+ }));
68
+ }
69
+ return Object.freeze(worlds);
70
+ }
71
+ return Object.freeze([new MapWorld({ levels: entries.map((entry, index) => convertLevel(entry.level, entry.worldIid, index)) })]);
72
+ };
73
+
74
+ //#endregion
75
+ export { ldtkToMapWorld };
76
+ //# sourceMappingURL=ldtkToMapWorld.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ldtkToMapWorld.js","names":[],"sources":["../../src/ldtkToMapWorld.ts"],"sourcesContent":["import type { MapLevel, MapLevelNeighbour } from '@codexo/exojs-tilemap';\nimport { MapLevelSide, MapWorld } from '@codexo/exojs-tilemap';\n\nimport type { LdtkData, LdtkLevel } from './LdtkData';\nimport { getLdtkLevelEntries } from './ldtkLevelEntries';\nimport { buildLdtkLevelProperties } from './ldtkToTileMap';\n\n/**\n * LDtk direction codes, as emitted in `__neighbours[].dir`. The cardinal four\n * have always existed; the depth relations arrived with LDtk 1.x.\n */\nconst SIDE_BY_DIR: Readonly<Record<string, MapLevelSide>> = Object.freeze({\n n: MapLevelSide.North,\n s: MapLevelSide.South,\n e: MapLevelSide.East,\n w: MapLevelSide.West,\n o: MapLevelSide.Overlap,\n '<': MapLevelSide.Below,\n '>': MapLevelSide.Above,\n});\n\nconst convertNeighbours = (level: LdtkLevel): readonly MapLevelNeighbour[] => {\n const raw = level.__neighbours;\n if (raw === undefined || raw === null || raw.length === 0) return [];\n\n return raw.map(neighbour => ({\n id: neighbour.levelIid,\n // An unrecognised code still means the levels are adjacent, so the edge is\n // kept and only its side degrades - dropping it would lose real data if a\n // future LDtk adds a direction.\n side: SIDE_BY_DIR[neighbour.dir] ?? MapLevelSide.Unknown,\n }));\n};\n\nconst convertLevel = (level: LdtkLevel, worldIid: string | undefined, index: number): MapLevel => ({\n id: level.iid,\n name: level.identifier,\n index,\n bounds: { x: level.worldX, y: level.worldY, width: level.pxWid, height: level.pxHei },\n external: Boolean(level.externalRelPath),\n neighbours: convertNeighbours(level),\n properties: buildLdtkLevelProperties(level, worldIid),\n});\n\n/**\n * Build the format-neutral world model for an LDtk document: one\n * {@link MapWorld} per LDtk world, in document order.\n *\n * A single-world project - the overwhelmingly common shape - yields exactly one\n * unnamed world. A multi-world project yields one per entry of `worlds[]`, each\n * named by its identifier, and they stay separate on purpose: LDtk worlds have independent coordinate spaces, so merging them\n * would make {@link MapWorld.bounds} and {@link MapWorld.getLevelsInBounds}\n * report overlaps that do not exist.\n *\n * {@link MapLevel.index} counts across the whole document, matching the\n * flattened order {@link import('./LdtkMap').LdtkMap.levels} uses.\n *\n * Level metadata only: no layer payload is read, so this is safe to call on a\n * document whose external levels have not been fetched.\n */\nexport const ldtkToMapWorld = (data: LdtkData): readonly MapWorld[] => {\n const entries = getLdtkLevelEntries(data);\n\n if (data.worlds && data.worlds.length > 0) {\n const worlds: MapWorld[] = [];\n let index = 0;\n\n for (const world of data.worlds) {\n const levels = world.levels.map(level => convertLevel(level, world.iid, index++));\n worlds.push(new MapWorld({ name: world.identifier, levels }));\n }\n\n return Object.freeze(worlds);\n }\n\n return Object.freeze([new MapWorld({ levels: entries.map((entry, index) => convertLevel(entry.level, entry.worldIid, index)) })]);\n};\n"],"mappings":";;;;;;;;;AAWA,MAAM,cAAsD,OAAO,OAAO;CACxE,GAAG,aAAa;CAChB,GAAG,aAAa;CAChB,GAAG,aAAa;CAChB,GAAG,aAAa;CAChB,GAAG,aAAa;CAChB,KAAK,aAAa;CAClB,KAAK,aAAa;AACpB,CAAC;AAED,MAAM,qBAAqB,UAAmD;CAC5E,MAAM,MAAM,MAAM;CAClB,IAAI,QAAQ,UAAa,QAAQ,QAAQ,IAAI,WAAW,GAAG,OAAO,CAAC;CAEnE,OAAO,IAAI,KAAI,eAAc;EAC3B,IAAI,UAAU;EAId,MAAM,YAAY,UAAU,QAAQ,aAAa;CACnD,EAAE;AACJ;AAEA,MAAM,gBAAgB,OAAkB,UAA8B,WAA6B;CACjG,IAAI,MAAM;CACV,MAAM,MAAM;CACZ;CACA,QAAQ;EAAE,GAAG,MAAM;EAAQ,GAAG,MAAM;EAAQ,OAAO,MAAM;EAAO,QAAQ,MAAM;CAAM;CACpF,UAAU,QAAQ,MAAM,eAAe;CACvC,YAAY,kBAAkB,KAAK;CACnC,YAAY,yBAAyB,OAAO,QAAQ;AACtD;;;;;;;;;;;;;;;;;AAkBA,MAAa,kBAAkB,SAAwC;CACrE,MAAM,UAAU,oBAAoB,IAAI;CAExC,IAAI,KAAK,UAAU,KAAK,OAAO,SAAS,GAAG;EACzC,MAAM,SAAqB,CAAC;EAC5B,IAAI,QAAQ;EAEZ,KAAK,MAAM,SAAS,KAAK,QAAQ;GAC/B,MAAM,SAAS,MAAM,OAAO,KAAI,UAAS,aAAa,OAAO,MAAM,KAAK,OAAO,CAAC;GAChF,OAAO,KAAK,IAAI,SAAS;IAAE,MAAM,MAAM;IAAY;GAAO,CAAC,CAAC;EAC9D;EAEA,OAAO,OAAO,OAAO,MAAM;CAC7B;CAEA,OAAO,OAAO,OAAO,CAAC,IAAI,SAAS,EAAE,QAAQ,QAAQ,KAAK,OAAO,UAAU,aAAa,MAAM,OAAO,MAAM,UAAU,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AAClI"}
@@ -1,6 +1,6 @@
1
- import type { TileSet } from '@codexo/exojs-tilemap';
2
- import { TILE_TRANSFORM_IDENTITY, TileLayer } from '@codexo/exojs-tilemap';
3
- import type { LdtkData, LdtkIntGridValueDef } from './LdtkData';
1
+ import type { TileCellSource, TileProperties, TileSet } from '@codexo/exojs-tilemap';
2
+ import { TILE_TRANSFORM_IDENTITY, TileLayer, TileMap } from '@codexo/exojs-tilemap';
3
+ import type { LdtkData, LdtkIntGridValueDef, LdtkLevel } from './LdtkData';
4
4
  import { LdtkMap } from './LdtkMap';
5
5
  /**
6
6
  * Options for {@link ldtkToTileMap}.
@@ -16,7 +16,7 @@ export interface LdtkToTileMapOptions {
16
16
  *
17
17
  * When provided, tile layers are populated with tile data from
18
18
  * `gridTiles` / `autoLayerTiles`. Without this map, tile layers are created
19
- * with the correct dimensions but no tiles are placed only entity and
19
+ * with the correct dimensions but no tiles are placed - only entity and
20
20
  * object layers carry data.
21
21
  *
22
22
  * Populate via {@link import('./loadLdtkMap').loadLdtkMap} for asset-loading
@@ -29,7 +29,7 @@ export interface LdtkToTileMapOptions {
29
29
  * one runtime {@link TileMap} per LDtk level.
30
30
  *
31
31
  * Tile layers (`Tiles` / `AutoLayer`) become renderable `TileLayer`s. IntGrid
32
- * layers become dimension-correct `TileLayer`s tile data is placed only when
32
+ * layers become dimension-correct `TileLayer`s - tile data is placed only when
33
33
  * the layer carries `autoLayerTiles`. Entity layers become data-only
34
34
  * `ObjectLayer`s with entity position, size, and scalar field properties.
35
35
  *
@@ -37,11 +37,28 @@ export interface LdtkToTileMapOptions {
37
37
  * conversion (useful in unit tests that do not need textures).
38
38
  *
39
39
  * Transparently handles both LDtk root shapes via {@link getLdtkLevelEntries}:
40
- * single-world (`data.levels`) and multi-world (`data.worlds[].levels`) in
40
+ * single-world (`data.levels`) and multi-world (`data.worlds[].levels`) - in
41
41
  * the latter case every converted level's `TileMap.properties` is additionally
42
42
  * tagged with its owning world's iid under the reserved `ldtkWorldIid` key.
43
43
  */
44
- export declare function ldtkToTileMap(data: LdtkData, options?: LdtkToTileMapOptions): LdtkMap;
44
+ export declare const ldtkToTileMap: (data: LdtkData, options?: LdtkToTileMapOptions) => LdtkMap;
45
+ /**
46
+ * Convert one already-resolved LDtk level into its runtime {@link TileMap}.
47
+ *
48
+ * `level.layerInstances` must be present: an externalized level has to have its
49
+ * `.ldtkl` payload merged in first, or the result is an empty map.
50
+ * @internal
51
+ */
52
+ export declare const ldtkLevelToTileMap: (level: LdtkLevel, worldIid: string | undefined, levelIndex: number, data: LdtkData, tilesets: ReadonlyMap<number, TileSet>) => TileMap;
53
+ /**
54
+ * The property bag a level contributes to its runtime representation - user
55
+ * fields first, then the reserved LDtk keys, so a same-named user field can
56
+ * never clobber them. `ldtkWorldIid` is added only for multi-world documents;
57
+ * a single-world document's properties stay exactly as they were before
58
+ * multi-world support existed.
59
+ * @internal
60
+ */
61
+ export declare const buildLdtkLevelProperties: (level: LdtkLevel, worldIid: string | undefined) => TileProperties;
45
62
  /**
46
63
  * Reserved {@link TileLayer.properties} key holding the JSON-encoded raw
47
64
  * IntGrid CSV array (`readonly number[]`) for a `TileLayer` converted from an
@@ -52,7 +69,7 @@ export declare const ldtkIntGridCsvProperty = "ldtkIntGridCsv";
52
69
  /**
53
70
  * Reserved {@link TileLayer.properties} key holding the JSON-encoded
54
71
  * {@link LdtkIntGridValueDef} array for a `TileLayer` converted from an LDtk
55
- * `IntGrid` layer instance the raw-int → named/coloured mapping declared on
72
+ * `IntGrid` layer instance - the raw-int → named/coloured mapping declared on
56
73
  * the owning layer definition (`data.defs.layers[].intGridValues`).
57
74
  * Prefer {@link getLdtkIntGridValueAt} over reading this directly.
58
75
  */
@@ -67,8 +84,29 @@ export declare const ldtkIntGridValuesProperty = "ldtkIntGridValues";
67
84
  * via {@link ldtkIntGridCsvProperty} / {@link ldtkIntGridValuesProperty}).
68
85
  *
69
86
  * The underlying JSON-encoded CSV/value-defs properties are parsed once per
70
- * layer and cached (see {@link getParsedIntGridData}) safe to call from a
87
+ * layer and cached (see {@link getParsedIntGridData}) - safe to call from a
71
88
  * hot path (e.g. per-cell or per-frame collision/classification checks).
72
89
  */
73
- export declare function getLdtkIntGridValueAt(layer: TileLayer, x: number, y: number): LdtkIntGridValueDef | undefined;
90
+ export declare const getLdtkIntGridValueAt: (layer: TileLayer, x: number, y: number) => LdtkIntGridValueDef | undefined;
91
+ /**
92
+ * Per-cell collision classification for a `TileLayer` converted from an LDtk
93
+ * `IntGrid` layer instance, or `undefined` when the layer carries no IntGrid
94
+ * data (not converted from an IntGrid layer instance, or unbounded).
95
+ *
96
+ * The classification is the value's LDtk-authored identifier, falling back to
97
+ * the raw integer as a string when the value definition declares none. Cells
98
+ * whose raw value is `0` (empty) classify as `null`. Distinct IntGrid values
99
+ * stay distinct strings: what they mean - solid, water, hazard - is the
100
+ * caller's to decide, and an unrecognised value is data, not an error.
101
+ *
102
+ * The result reads the layer's frozen IntGrid data, so it is stable for the
103
+ * lifetime of the layer and safe to hand to a consumer that samples it while
104
+ * building geometry.
105
+ *
106
+ * ```ts
107
+ * const geometry = buildTileCollisionGeometry(layer, { cells: createLdtkIntGridCellSource(layer) });
108
+ * ```
109
+ */
110
+ export declare const createLdtkIntGridCellSource: (layer: TileLayer) => TileCellSource | undefined;
74
111
  export { TILE_TRANSFORM_IDENTITY };
112
+ //# sourceMappingURL=ldtkToTileMap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ldtkToTileMap.d.ts","sourceRoot":"","sources":["../../src/ldtkToTileMap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAiB,cAAc,EAAqB,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACvH,OAAO,EAAe,uBAAuB,EAAE,SAAS,EAAE,OAAO,EAAoB,MAAM,uBAAuB,CAAC;AAEnH,OAAO,KAAK,EAAE,QAAQ,EAAyC,mBAAmB,EAAqB,SAAS,EAAgB,MAAM,YAAY,CAAC;AAGnJ,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,QAAQ,EAAE,UAAU,oBAAoB,KAAG,OAO9E,CAAC;AAIF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,SAAS,EAChB,UAAU,MAAM,GAAG,SAAS,EAC5B,YAAY,MAAM,EAClB,MAAM,QAAQ,EACd,UAAU,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,KACrC,OAAoE,CAAC;AAoDxE;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,GAAI,OAAO,SAAS,EAAE,UAAU,MAAM,GAAG,SAAS,KAAG,cAOxF,CAAC;AAuHH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,mBAAmB,CAAC;AAEvD;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAiE7D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,GAAI,OAAO,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,mBAAmB,GAAG,SAepG,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,2BAA2B,GAAI,OAAO,SAAS,KAAG,cAAc,GAAG,SAuB/E,CAAC;AA8KF,OAAO,EAAE,uBAAuB,EAAE,CAAC"}