@codexo/exojs-ldtk 0.15.2 → 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.
- package/README.md +38 -20
- package/dist/esm/LdtkData.d.ts +59 -14
- package/dist/esm/LdtkData.d.ts.map +1 -0
- package/dist/esm/LdtkData.js +8 -16
- package/dist/esm/LdtkData.js.map +1 -1
- package/dist/esm/LdtkMap.d.ts +25 -6
- package/dist/esm/LdtkMap.d.ts.map +1 -0
- package/dist/esm/LdtkMap.js +88 -63
- package/dist/esm/LdtkMap.js.map +1 -1
- package/dist/esm/LdtkProject.d.ts +107 -0
- package/dist/esm/LdtkProject.d.ts.map +1 -0
- package/dist/esm/LdtkProject.js +136 -0
- package/dist/esm/LdtkProject.js.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +11 -7
- package/dist/esm/ldtkExtension.d.ts +9 -5
- package/dist/esm/ldtkExtension.d.ts.map +1 -0
- package/dist/esm/ldtkExtension.js +25 -22
- package/dist/esm/ldtkExtension.js.map +1 -1
- package/dist/esm/ldtkLevelEntries.d.ts +4 -3
- package/dist/esm/ldtkLevelEntries.d.ts.map +1 -0
- package/dist/esm/ldtkLevelEntries.js +30 -26
- package/dist/esm/ldtkLevelEntries.js.map +1 -1
- package/dist/esm/ldtkParallax.d.ts +22 -0
- package/dist/esm/ldtkParallax.d.ts.map +1 -0
- package/dist/esm/ldtkParallax.js +22 -0
- package/dist/esm/ldtkParallax.js.map +1 -0
- package/dist/esm/ldtkToMapWorld.d.ts +20 -0
- package/dist/esm/ldtkToMapWorld.d.ts.map +1 -0
- package/dist/esm/ldtkToMapWorld.js +76 -0
- package/dist/esm/ldtkToMapWorld.js.map +1 -0
- package/dist/esm/ldtkToTileMap.d.ts +48 -10
- package/dist/esm/ldtkToTileMap.d.ts.map +1 -0
- package/dist/esm/ldtkToTileMap.js +410 -387
- package/dist/esm/ldtkToTileMap.js.map +1 -1
- package/dist/esm/ldtkTypes.d.ts +47 -0
- package/dist/esm/ldtkTypes.d.ts.map +1 -0
- package/dist/esm/ldtkTypes.js +57 -0
- package/dist/esm/ldtkTypes.js.map +1 -0
- package/dist/esm/loadLdtkMap.d.ts +30 -5
- package/dist/esm/loadLdtkMap.d.ts.map +1 -0
- package/dist/esm/loadLdtkMap.js +139 -133
- package/dist/esm/loadLdtkMap.js.map +1 -1
- package/dist/esm/loadLdtkProject.d.ts +17 -0
- package/dist/esm/loadLdtkProject.d.ts.map +1 -0
- package/dist/esm/loadLdtkProject.js +31 -0
- package/dist/esm/loadLdtkProject.js.map +1 -0
- package/dist/esm/public.d.ts +24 -9
- package/dist/esm/public.d.ts.map +1 -0
- package/dist/esm/public.js +11 -0
- package/dist/esm/url.d.ts +16 -0
- package/dist/esm/url.d.ts.map +1 -0
- package/dist/esm/url.js +31 -0
- package/dist/esm/url.js.map +1 -0
- package/dist/esm/validate.d.ts +27 -0
- package/dist/esm/validate.d.ts.map +1 -0
- package/dist/esm/validate.js +327 -0
- package/dist/esm/validate.js.map +1 -0
- package/package.json +9 -17
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/ldtkBinding.d.ts +0 -22
- package/dist/esm/ldtkBinding.js +0 -31
- package/dist/esm/ldtkBinding.js.map +0 -1
- package/dist/esm/register.d.ts +0 -1
- package/dist/esm/register.js +0 -17
- package/dist/esm/register.js.map +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { LoaderScope } from '@codexo/exojs';
|
|
2
|
+
import type { MapWorld, TileSet } from '@codexo/exojs-tilemap';
|
|
3
|
+
import { MapWorldRuntime } from '@codexo/exojs-tilemap';
|
|
4
|
+
import type { LdtkData } from './LdtkData';
|
|
5
|
+
/** Options for {@link LdtkProject.createRuntime}. */
|
|
6
|
+
export interface LdtkRuntimeOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Parent scope for everything the runtime loads. The runtime creates its own
|
|
9
|
+
* child scope under it and never destroys this one.
|
|
10
|
+
*/
|
|
11
|
+
readonly scope: LoaderScope;
|
|
12
|
+
/**
|
|
13
|
+
* Which world of a multi-world project to stream, by identifier. Defaults to
|
|
14
|
+
* the first world in document order, which is the only one a single-world
|
|
15
|
+
* project has.
|
|
16
|
+
*/
|
|
17
|
+
readonly world?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A loaded LDtk project, prepared for streaming: world layout and tileset
|
|
21
|
+
* atlases are resident, level payloads are not.
|
|
22
|
+
*
|
|
23
|
+
* This is the entry point for a game that loads levels as it needs them. Read
|
|
24
|
+
* {@link worlds} to decide what to load, then drive a
|
|
25
|
+
* {@link MapWorldRuntime} from {@link createRuntime} to load and unload
|
|
26
|
+
* individual levels, each with its own asset scope.
|
|
27
|
+
*
|
|
28
|
+
* What is eager, and why:
|
|
29
|
+
*
|
|
30
|
+
* - the `.ldtk` document itself, because the world layout is what the game
|
|
31
|
+
* navigates by;
|
|
32
|
+
* - every tileset atlas. This is a prefetch policy, not a technical
|
|
33
|
+
* requirement, and it is bounded: LDtk declares tilesets once per project
|
|
34
|
+
* (`defs.tilesets`), never per level, so the count does not grow with the
|
|
35
|
+
* number of levels. Paying for them once keeps a level load off the network
|
|
36
|
+
* entirely for a non-externalized project, and off the *image* network for an
|
|
37
|
+
* externalized one.
|
|
38
|
+
*
|
|
39
|
+
* The atlases are claimed by this asset's own scope, so their residency is tied
|
|
40
|
+
* to how long the `ldtkProject` asset is held - not to a
|
|
41
|
+
* {@link MapWorldRuntime}. Releasing the asset releases them; destroying a
|
|
42
|
+
* runtime does not.
|
|
43
|
+
*
|
|
44
|
+
* What is lazy:
|
|
45
|
+
*
|
|
46
|
+
* - external `.ldtkl` level payloads - fetched when the level loads, claimed
|
|
47
|
+
* by that level's scope, released when it unloads;
|
|
48
|
+
* - the conversion of a level into a runtime `TileMap`;
|
|
49
|
+
* - anything the level's {@link import('@codexo/exojs-tilemap').MapObjectSpawner} creates.
|
|
50
|
+
*
|
|
51
|
+
* Load the whole project at once with the `ldtkMap` asset type instead
|
|
52
|
+
* ({@link import('./LdtkMap').LdtkMap}) when a game is small enough not to
|
|
53
|
+
* need any of this.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* const project = await scene.loader.load(Asset.type('ldtkProject', 'world.ldtk'));
|
|
58
|
+
* const runtime = project.createRuntime({ scope: scene.loader });
|
|
59
|
+
*
|
|
60
|
+
* const forest = await runtime.loadLevel(project.world.getLevelByName('Forest')!.id, {
|
|
61
|
+
* spawner,
|
|
62
|
+
* context: { services, save },
|
|
63
|
+
* });
|
|
64
|
+
*
|
|
65
|
+
* scene.addChild(forest.map.createView().root);
|
|
66
|
+
* runtime.unloadLevel(forest.id);
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare class LdtkProject {
|
|
70
|
+
/** Resolved URL this project was loaded from. */
|
|
71
|
+
readonly source: string;
|
|
72
|
+
/** The raw parsed LDtk document. Externalized levels still carry `layerInstances: null`. */
|
|
73
|
+
readonly data: LdtkData;
|
|
74
|
+
/** Runtime tilesets keyed by LDtk tileset uid, shared by every level of the project. */
|
|
75
|
+
readonly tilesets: ReadonlyMap<number, TileSet>;
|
|
76
|
+
/** World layout, one entry per LDtk world. See {@link import('./ldtkToMapWorld').ldtkToMapWorld}. */
|
|
77
|
+
readonly worlds: readonly MapWorld[];
|
|
78
|
+
private readonly _entries;
|
|
79
|
+
/** Projects are produced by the `ldtkProject` asset binding. @internal */
|
|
80
|
+
constructor(source: string, data: LdtkData, tilesets: ReadonlyMap<number, TileSet>);
|
|
81
|
+
/**
|
|
82
|
+
* The project's only world. For a multi-world project this is the first in
|
|
83
|
+
* document order; read {@link worlds} to reach the others.
|
|
84
|
+
*/
|
|
85
|
+
get world(): MapWorld;
|
|
86
|
+
/** The world with this identifier, or `undefined`. */
|
|
87
|
+
getWorld(name: string): MapWorld | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Create the live runtime that loads and unloads this project's levels.
|
|
90
|
+
*
|
|
91
|
+
* The runtime is a separate lifetime from the project: destroying it unloads
|
|
92
|
+
* every level it holds and leaves the project - document, world layout and
|
|
93
|
+
* tilesets - intact, ready for a new runtime.
|
|
94
|
+
*
|
|
95
|
+
* @throws {Error} when `options.world` names no world of this project.
|
|
96
|
+
*/
|
|
97
|
+
createRuntime(options: LdtkRuntimeOptions): MapWorldRuntime;
|
|
98
|
+
private _loadLevel;
|
|
99
|
+
/**
|
|
100
|
+
* Fetch an externalized level's `.ldtkl` payload and merge it into the level
|
|
101
|
+
* record. The fetch is claimed by the level's own scope, so it is released
|
|
102
|
+
* when the level unloads and re-fetched (or served from the loader's cache)
|
|
103
|
+
* on a later load.
|
|
104
|
+
*/
|
|
105
|
+
private _resolveLevel;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=LdtkProject.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LdtkProject.d.ts","sourceRoot":"","sources":["../../src/LdtkProject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAuB,QAAQ,EAAW,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAC7F,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,QAAQ,EAAa,MAAM,YAAY,CAAC;AAQtD,qDAAqD;AACrD,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,qBAAa,WAAW;IACtB,iDAAiD;IACjD,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,4FAA4F;IAC5F,SAAgB,IAAI,EAAE,QAAQ,CAAC;IAC/B,wFAAwF;IACxF,SAAgB,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvD,qGAAqG;IACrG,SAAgB,MAAM,EAAE,SAAS,QAAQ,EAAE,CAAC;IAE5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;IAErD,0EAA0E;gBACvD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC;IAQzF;;;OAGG;IACH,IAAW,KAAK,IAAI,QAAQ,CAQ3B;IAED,sDAAsD;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAInD;;;;;;;;OAQG;IACI,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,eAAe;YAcpD,UAAU;IAYxB;;;;;OAKG;YACW,aAAa;CAiB5B"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { getLdtkLevelEntries } from "./ldtkLevelEntries.js";
|
|
2
|
+
import { ldtkLevelToTileMap } from "./ldtkToTileMap.js";
|
|
3
|
+
import { ldtkToMapWorld } from "./ldtkToMapWorld.js";
|
|
4
|
+
import { resolveLdtkUrl } from "./url.js";
|
|
5
|
+
import { validateLdtkLevelData } from "./validate.js";
|
|
6
|
+
import { MapWorldRuntime } from "@codexo/exojs-tilemap";
|
|
7
|
+
import { Asset } from "@codexo/exojs";
|
|
8
|
+
|
|
9
|
+
//#region src/LdtkProject.ts
|
|
10
|
+
/**
|
|
11
|
+
* A loaded LDtk project, prepared for streaming: world layout and tileset
|
|
12
|
+
* atlases are resident, level payloads are not.
|
|
13
|
+
*
|
|
14
|
+
* This is the entry point for a game that loads levels as it needs them. Read
|
|
15
|
+
* {@link worlds} to decide what to load, then drive a
|
|
16
|
+
* {@link MapWorldRuntime} from {@link createRuntime} to load and unload
|
|
17
|
+
* individual levels, each with its own asset scope.
|
|
18
|
+
*
|
|
19
|
+
* What is eager, and why:
|
|
20
|
+
*
|
|
21
|
+
* - the `.ldtk` document itself, because the world layout is what the game
|
|
22
|
+
* navigates by;
|
|
23
|
+
* - every tileset atlas. This is a prefetch policy, not a technical
|
|
24
|
+
* requirement, and it is bounded: LDtk declares tilesets once per project
|
|
25
|
+
* (`defs.tilesets`), never per level, so the count does not grow with the
|
|
26
|
+
* number of levels. Paying for them once keeps a level load off the network
|
|
27
|
+
* entirely for a non-externalized project, and off the *image* network for an
|
|
28
|
+
* externalized one.
|
|
29
|
+
*
|
|
30
|
+
* The atlases are claimed by this asset's own scope, so their residency is tied
|
|
31
|
+
* to how long the `ldtkProject` asset is held - not to a
|
|
32
|
+
* {@link MapWorldRuntime}. Releasing the asset releases them; destroying a
|
|
33
|
+
* runtime does not.
|
|
34
|
+
*
|
|
35
|
+
* What is lazy:
|
|
36
|
+
*
|
|
37
|
+
* - external `.ldtkl` level payloads - fetched when the level loads, claimed
|
|
38
|
+
* by that level's scope, released when it unloads;
|
|
39
|
+
* - the conversion of a level into a runtime `TileMap`;
|
|
40
|
+
* - anything the level's {@link import('@codexo/exojs-tilemap').MapObjectSpawner} creates.
|
|
41
|
+
*
|
|
42
|
+
* Load the whole project at once with the `ldtkMap` asset type instead
|
|
43
|
+
* ({@link import('./LdtkMap').LdtkMap}) when a game is small enough not to
|
|
44
|
+
* need any of this.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const project = await scene.loader.load(Asset.type('ldtkProject', 'world.ldtk'));
|
|
49
|
+
* const runtime = project.createRuntime({ scope: scene.loader });
|
|
50
|
+
*
|
|
51
|
+
* const forest = await runtime.loadLevel(project.world.getLevelByName('Forest')!.id, {
|
|
52
|
+
* spawner,
|
|
53
|
+
* context: { services, save },
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* scene.addChild(forest.map.createView().root);
|
|
57
|
+
* runtime.unloadLevel(forest.id);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
var LdtkProject = class {
|
|
61
|
+
/** Resolved URL this project was loaded from. */
|
|
62
|
+
source;
|
|
63
|
+
/** The raw parsed LDtk document. Externalized levels still carry `layerInstances: null`. */
|
|
64
|
+
data;
|
|
65
|
+
/** Runtime tilesets keyed by LDtk tileset uid, shared by every level of the project. */
|
|
66
|
+
tilesets;
|
|
67
|
+
/** World layout, one entry per LDtk world. See {@link import('./ldtkToMapWorld').ldtkToMapWorld}. */
|
|
68
|
+
worlds;
|
|
69
|
+
_entries;
|
|
70
|
+
/** Projects are produced by the `ldtkProject` asset binding. @internal */
|
|
71
|
+
constructor(source, data, tilesets) {
|
|
72
|
+
this.source = source;
|
|
73
|
+
this.data = data;
|
|
74
|
+
this.tilesets = tilesets;
|
|
75
|
+
this.worlds = ldtkToMapWorld(data);
|
|
76
|
+
this._entries = getLdtkLevelEntries(data);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The project's only world. For a multi-world project this is the first in
|
|
80
|
+
* document order; read {@link worlds} to reach the others.
|
|
81
|
+
*/
|
|
82
|
+
get world() {
|
|
83
|
+
const [first] = this.worlds;
|
|
84
|
+
if (first === void 0) throw new Error(`LdtkProject: "${this.source}" declares no world.`);
|
|
85
|
+
return first;
|
|
86
|
+
}
|
|
87
|
+
/** The world with this identifier, or `undefined`. */
|
|
88
|
+
getWorld(name) {
|
|
89
|
+
return this.worlds.find((world) => world.name === name);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Create the live runtime that loads and unloads this project's levels.
|
|
93
|
+
*
|
|
94
|
+
* The runtime is a separate lifetime from the project: destroying it unloads
|
|
95
|
+
* every level it holds and leaves the project - document, world layout and
|
|
96
|
+
* tilesets - intact, ready for a new runtime.
|
|
97
|
+
*
|
|
98
|
+
* @throws {Error} when `options.world` names no world of this project.
|
|
99
|
+
*/
|
|
100
|
+
createRuntime(options) {
|
|
101
|
+
const world = options.world === void 0 ? this.world : this.getWorld(options.world);
|
|
102
|
+
if (world === void 0) throw new Error(`LdtkProject: "${this.source}" has no world named "${options.world ?? ""}".`);
|
|
103
|
+
return new MapWorldRuntime({
|
|
104
|
+
world,
|
|
105
|
+
scope: options.scope,
|
|
106
|
+
load: (context) => this._loadLevel(context)
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async _loadLevel(context) {
|
|
110
|
+
const entry = this._entries[context.level.index];
|
|
111
|
+
if (entry === void 0) throw new Error(`LdtkProject: level "${context.level.id}" has index ${context.level.index}, which is outside "${this.source}".`);
|
|
112
|
+
const level = await this._resolveLevel(entry.level, context.scope);
|
|
113
|
+
return ldtkLevelToTileMap(level, entry.worldIid, context.level.index, this.data, this.tilesets);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Fetch an externalized level's `.ldtkl` payload and merge it into the level
|
|
117
|
+
* record. The fetch is claimed by the level's own scope, so it is released
|
|
118
|
+
* when the level unloads and re-fetched (or served from the loader's cache)
|
|
119
|
+
* on a later load.
|
|
120
|
+
*/
|
|
121
|
+
async _resolveLevel(level, scope) {
|
|
122
|
+
if (level.layerInstances !== null || level.externalRelPath === void 0 || level.externalRelPath === null || level.externalRelPath === "") return level;
|
|
123
|
+
const url = resolveLdtkUrl(level.externalRelPath, this.source);
|
|
124
|
+
const external = validateLdtkLevelData(await scope.load(Asset.type("json", url)), url);
|
|
125
|
+
const fieldInstances = external.fieldInstances ?? level.fieldInstances;
|
|
126
|
+
return {
|
|
127
|
+
...level,
|
|
128
|
+
layerInstances: external.layerInstances,
|
|
129
|
+
...fieldInstances !== void 0 && { fieldInstances }
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
//#endregion
|
|
135
|
+
export { LdtkProject };
|
|
136
|
+
//# sourceMappingURL=LdtkProject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LdtkProject.js","names":[],"sources":["../../src/LdtkProject.ts"],"sourcesContent":["import type { LoaderScope } from '@codexo/exojs';\nimport { Asset } from '@codexo/exojs';\nimport type { MapLevelLoadContext, MapWorld, TileMap, TileSet } from '@codexo/exojs-tilemap';\nimport { MapWorldRuntime } from '@codexo/exojs-tilemap';\n\nimport type { LdtkData, LdtkLevel } from './LdtkData';\nimport type { LdtkLevelEntry } from './ldtkLevelEntries';\nimport { getLdtkLevelEntries } from './ldtkLevelEntries';\nimport { ldtkToMapWorld } from './ldtkToMapWorld';\nimport { ldtkLevelToTileMap } from './ldtkToTileMap';\nimport { resolveLdtkUrl } from './url';\nimport { validateLdtkLevelData } from './validate';\n\n/** Options for {@link LdtkProject.createRuntime}. */\nexport interface LdtkRuntimeOptions {\n /**\n * Parent scope for everything the runtime loads. The runtime creates its own\n * child scope under it and never destroys this one.\n */\n readonly scope: LoaderScope;\n /**\n * Which world of a multi-world project to stream, by identifier. Defaults to\n * the first world in document order, which is the only one a single-world\n * project has.\n */\n readonly world?: string;\n}\n\n/**\n * A loaded LDtk project, prepared for streaming: world layout and tileset\n * atlases are resident, level payloads are not.\n *\n * This is the entry point for a game that loads levels as it needs them. Read\n * {@link worlds} to decide what to load, then drive a\n * {@link MapWorldRuntime} from {@link createRuntime} to load and unload\n * individual levels, each with its own asset scope.\n *\n * What is eager, and why:\n *\n * - the `.ldtk` document itself, because the world layout is what the game\n * navigates by;\n * - every tileset atlas. This is a prefetch policy, not a technical\n * requirement, and it is bounded: LDtk declares tilesets once per project\n * (`defs.tilesets`), never per level, so the count does not grow with the\n * number of levels. Paying for them once keeps a level load off the network\n * entirely for a non-externalized project, and off the *image* network for an\n * externalized one.\n *\n * The atlases are claimed by this asset's own scope, so their residency is tied\n * to how long the `ldtkProject` asset is held - not to a\n * {@link MapWorldRuntime}. Releasing the asset releases them; destroying a\n * runtime does not.\n *\n * What is lazy:\n *\n * - external `.ldtkl` level payloads - fetched when the level loads, claimed\n * by that level's scope, released when it unloads;\n * - the conversion of a level into a runtime `TileMap`;\n * - anything the level's {@link import('@codexo/exojs-tilemap').MapObjectSpawner} creates.\n *\n * Load the whole project at once with the `ldtkMap` asset type instead\n * ({@link import('./LdtkMap').LdtkMap}) when a game is small enough not to\n * need any of this.\n *\n * @example\n * ```ts\n * const project = await scene.loader.load(Asset.type('ldtkProject', 'world.ldtk'));\n * const runtime = project.createRuntime({ scope: scene.loader });\n *\n * const forest = await runtime.loadLevel(project.world.getLevelByName('Forest')!.id, {\n * spawner,\n * context: { services, save },\n * });\n *\n * scene.addChild(forest.map.createView().root);\n * runtime.unloadLevel(forest.id);\n * ```\n */\nexport class LdtkProject {\n /** Resolved URL this project was loaded from. */\n public readonly source: string;\n /** The raw parsed LDtk document. Externalized levels still carry `layerInstances: null`. */\n public readonly data: LdtkData;\n /** Runtime tilesets keyed by LDtk tileset uid, shared by every level of the project. */\n public readonly tilesets: ReadonlyMap<number, TileSet>;\n /** World layout, one entry per LDtk world. See {@link import('./ldtkToMapWorld').ldtkToMapWorld}. */\n public readonly worlds: readonly MapWorld[];\n\n private readonly _entries: readonly LdtkLevelEntry[];\n\n /** Projects are produced by the `ldtkProject` asset binding. @internal */\n public constructor(source: string, data: LdtkData, tilesets: ReadonlyMap<number, TileSet>) {\n this.source = source;\n this.data = data;\n this.tilesets = tilesets;\n this.worlds = ldtkToMapWorld(data);\n this._entries = getLdtkLevelEntries(data);\n }\n\n /**\n * The project's only world. For a multi-world project this is the first in\n * document order; read {@link worlds} to reach the others.\n */\n public get world(): MapWorld {\n const [first] = this.worlds;\n\n if (first === undefined) {\n throw new Error(`LdtkProject: \"${this.source}\" declares no world.`);\n }\n\n return first;\n }\n\n /** The world with this identifier, or `undefined`. */\n public getWorld(name: string): MapWorld | undefined {\n return this.worlds.find(world => world.name === name);\n }\n\n /**\n * Create the live runtime that loads and unloads this project's levels.\n *\n * The runtime is a separate lifetime from the project: destroying it unloads\n * every level it holds and leaves the project - document, world layout and\n * tilesets - intact, ready for a new runtime.\n *\n * @throws {Error} when `options.world` names no world of this project.\n */\n public createRuntime(options: LdtkRuntimeOptions): MapWorldRuntime {\n const world = options.world === undefined ? this.world : this.getWorld(options.world);\n\n if (world === undefined) {\n throw new Error(`LdtkProject: \"${this.source}\" has no world named \"${options.world ?? ''}\".`);\n }\n\n return new MapWorldRuntime({\n world,\n scope: options.scope,\n load: context => this._loadLevel(context),\n });\n }\n\n private async _loadLevel(context: MapLevelLoadContext): Promise<TileMap> {\n const entry = this._entries[context.level.index];\n\n if (entry === undefined) {\n throw new Error(`LdtkProject: level \"${context.level.id}\" has index ${context.level.index}, which is outside \"${this.source}\".`);\n }\n\n const level = await this._resolveLevel(entry.level, context.scope);\n\n return ldtkLevelToTileMap(level, entry.worldIid, context.level.index, this.data, this.tilesets);\n }\n\n /**\n * Fetch an externalized level's `.ldtkl` payload and merge it into the level\n * record. The fetch is claimed by the level's own scope, so it is released\n * when the level unloads and re-fetched (or served from the loader's cache)\n * on a later load.\n */\n private async _resolveLevel(level: LdtkLevel, scope: LoaderScope): Promise<LdtkLevel> {\n if (level.layerInstances !== null || level.externalRelPath === undefined || level.externalRelPath === null || level.externalRelPath === '') {\n return level;\n }\n\n const url = resolveLdtkUrl(level.externalRelPath, this.source);\n // Validated as strictly as an inlined level, with the `.ldtkl` file as the\n // error source - a malformed external payload must fail as loudly.\n const external = validateLdtkLevelData(await scope.load(Asset.type('json', url)), url);\n const fieldInstances = external.fieldInstances ?? level.fieldInstances;\n\n return {\n ...level,\n layerInstances: external.layerInstances,\n ...(fieldInstances !== undefined && { fieldInstances }),\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8EA,IAAa,cAAb,MAAyB;;CAEvB,AAAgB;;CAEhB,AAAgB;;CAEhB,AAAgB;;CAEhB,AAAgB;CAEhB,AAAiB;;CAGjB,AAAO,YAAY,QAAgB,MAAgB,UAAwC;EACzF,KAAK,SAAS;EACd,KAAK,OAAO;EACZ,KAAK,WAAW;EAChB,KAAK,SAAS,eAAe,IAAI;EACjC,KAAK,WAAW,oBAAoB,IAAI;CAC1C;;;;;CAMA,IAAW,QAAkB;EAC3B,MAAM,CAAC,SAAS,KAAK;EAErB,IAAI,UAAU,QACZ,MAAM,IAAI,MAAM,iBAAiB,KAAK,OAAO,qBAAqB;EAGpE,OAAO;CACT;;CAGA,AAAO,SAAS,MAAoC;EAClD,OAAO,KAAK,OAAO,MAAK,UAAS,MAAM,SAAS,IAAI;CACtD;;;;;;;;;;CAWA,AAAO,cAAc,SAA8C;EACjE,MAAM,QAAQ,QAAQ,UAAU,SAAY,KAAK,QAAQ,KAAK,SAAS,QAAQ,KAAK;EAEpF,IAAI,UAAU,QACZ,MAAM,IAAI,MAAM,iBAAiB,KAAK,OAAO,wBAAwB,QAAQ,SAAS,GAAG,GAAG;EAG9F,OAAO,IAAI,gBAAgB;GACzB;GACA,OAAO,QAAQ;GACf,OAAM,YAAW,KAAK,WAAW,OAAO;EAC1C,CAAC;CACH;CAEA,MAAc,WAAW,SAAgD;EACvE,MAAM,QAAQ,KAAK,SAAS,QAAQ,MAAM;EAE1C,IAAI,UAAU,QACZ,MAAM,IAAI,MAAM,uBAAuB,QAAQ,MAAM,GAAG,cAAc,QAAQ,MAAM,MAAM,sBAAsB,KAAK,OAAO,GAAG;EAGjI,MAAM,QAAQ,MAAM,KAAK,cAAc,MAAM,OAAO,QAAQ,KAAK;EAEjE,OAAO,mBAAmB,OAAO,MAAM,UAAU,QAAQ,MAAM,OAAO,KAAK,MAAM,KAAK,QAAQ;CAChG;;;;;;;CAQA,MAAc,cAAc,OAAkB,OAAwC;EACpF,IAAI,MAAM,mBAAmB,QAAQ,MAAM,oBAAoB,UAAa,MAAM,oBAAoB,QAAQ,MAAM,oBAAoB,IACtI,OAAO;EAGT,MAAM,MAAM,eAAe,MAAM,iBAAiB,KAAK,MAAM;EAG7D,MAAM,WAAW,sBAAsB,MAAM,MAAM,KAAK,MAAM,KAAK,QAAQ,GAAG,CAAC,GAAG,GAAG;EACrF,MAAM,iBAAiB,SAAS,kBAAkB,MAAM;EAExD,OAAO;GACL,GAAG;GACH,gBAAgB,SAAS;GACzB,GAAI,mBAAmB,UAAa,EAAE,eAAe;EACvD;CACF;AACF"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,UAAU,CAAC"}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { LDTK_FLIP_NONE, LDTK_FLIP_X, LDTK_FLIP_XY, LDTK_FLIP_Y } from "./LdtkData.js";
|
|
2
|
+
import { createLdtkIntGridCellSource, getLdtkIntGridValueAt, ldtkIntGridCsvProperty, ldtkIntGridValuesProperty, ldtkToTileMap } from "./ldtkToTileMap.js";
|
|
3
|
+
import { ldtkToMapWorld } from "./ldtkToMapWorld.js";
|
|
4
|
+
import { LdtkMap } from "./LdtkMap.js";
|
|
5
|
+
import { LdtkFormatError } from "./validate.js";
|
|
6
|
+
import { LdtkProject } from "./LdtkProject.js";
|
|
7
|
+
import { LdtkMapAssetType, LdtkProjectAssetType, ldtkMapType, ldtkProjectType } from "./ldtkTypes.js";
|
|
8
|
+
import { ldtkExtension } from "./ldtkExtension.js";
|
|
9
|
+
import { MapLevelRuntime, MapLevelSide, MapObjectSpawner, MapSpawnError, MapSpawnSession, MapWorld, MapWorldRuntime, ObjectKind, ObjectLayer, TILE_TRANSFORM_IDENTITY, TileLayer, TileMap, TileMapView, TilePropertyKind, TileSet, mapObjectDescriptor, mapObjectDescriptors, tilemapExtension } from "./public.js";
|
|
10
|
+
|
|
11
|
+
export { LDTK_FLIP_NONE, LDTK_FLIP_X, LDTK_FLIP_XY, LDTK_FLIP_Y, LdtkFormatError, LdtkMap, LdtkMapAssetType, LdtkProject, LdtkProjectAssetType, MapLevelRuntime, MapLevelSide, MapObjectSpawner, MapSpawnError, MapSpawnSession, MapWorld, MapWorldRuntime, ObjectKind, ObjectLayer, TILE_TRANSFORM_IDENTITY, TileLayer, TileMap, TileMapView, TilePropertyKind, TileSet, createLdtkIntGridCellSource, getLdtkIntGridValueAt, ldtkExtension, ldtkIntGridCsvProperty, ldtkIntGridValuesProperty, ldtkMapType, ldtkProjectType, ldtkToMapWorld, ldtkToTileMap, mapObjectDescriptor, mapObjectDescriptors, tilemapExtension };
|
|
@@ -2,16 +2,20 @@ import type { Extension } from '@codexo/exojs/extensions';
|
|
|
2
2
|
/**
|
|
3
3
|
* Default immutable LDtk extension descriptor.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* - {@link
|
|
7
|
-
* the `.ldtk`
|
|
5
|
+
* Installs two asset types:
|
|
6
|
+
* - {@link ldtkMapType} - `loader.load(ldtkMapType.asset('world.ldtk'))` reads
|
|
7
|
+
* the `.ldtk` document, loads all referenced tileset images, and returns a
|
|
8
8
|
* fully assembled {@link LdtkMap} with one runtime
|
|
9
9
|
* {@link import('@codexo/exojs-tilemap').TileMap} per level.
|
|
10
|
+
* - {@link ldtkProjectType} - `loader.load(ldtkProjectType.asset('world.ldtk'))`
|
|
11
|
+
* returns the world layout and tileset atlases only, for games that load
|
|
12
|
+
* levels on demand.
|
|
10
13
|
*
|
|
11
14
|
* Depends on {@link tilemapExtension} so that snapshot construction always
|
|
12
15
|
* materialises the generic tilemap runtime before the LDtk adapter.
|
|
13
16
|
*
|
|
14
|
-
*
|
|
15
|
-
* `
|
|
17
|
+
* Pass it to the application that should have it via
|
|
18
|
+
* `ApplicationOptions.extensions`.
|
|
16
19
|
*/
|
|
17
20
|
export declare const ldtkExtension: Extension;
|
|
21
|
+
//# sourceMappingURL=ldtkExtension.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ldtkExtension.d.ts","sourceRoot":"","sources":["../../src/ldtkExtension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAK1D;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,aAAa,EAAE,SAI1B,CAAC"}
|
|
@@ -1,28 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ldtkMapType, ldtkProjectType } from "./ldtkTypes.js";
|
|
2
|
+
import { tilemapExtension } from "@codexo/exojs-tilemap";
|
|
3
3
|
|
|
4
|
+
//#region src/ldtkExtension.ts
|
|
4
5
|
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
6
|
+
* Default immutable LDtk extension descriptor.
|
|
7
|
+
*
|
|
8
|
+
* Installs two asset types:
|
|
9
|
+
* - {@link ldtkMapType} - `loader.load(ldtkMapType.asset('world.ldtk'))` reads
|
|
10
|
+
* the `.ldtk` document, loads all referenced tileset images, and returns a
|
|
11
|
+
* fully assembled {@link LdtkMap} with one runtime
|
|
12
|
+
* {@link import('@codexo/exojs-tilemap').TileMap} per level.
|
|
13
|
+
* - {@link ldtkProjectType} - `loader.load(ldtkProjectType.asset('world.ldtk'))`
|
|
14
|
+
* returns the world layout and tileset atlases only, for games that load
|
|
15
|
+
* levels on demand.
|
|
16
|
+
*
|
|
17
|
+
* Depends on {@link tilemapExtension} so that snapshot construction always
|
|
18
|
+
* materialises the generic tilemap runtime before the LDtk adapter.
|
|
19
|
+
*
|
|
20
|
+
* Pass it to the application that should have it via
|
|
21
|
+
* `ApplicationOptions.extensions`.
|
|
22
|
+
*/
|
|
19
23
|
const ldtkExtension = Object.freeze({
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// contract here. Runtime behaviour is unaffected.
|
|
24
|
-
assets: [ldtkMapBinding],
|
|
24
|
+
id: "@codexo/exojs-ldtk",
|
|
25
|
+
dependencies: [tilemapExtension],
|
|
26
|
+
assets: [ldtkMapType, ldtkProjectType]
|
|
25
27
|
});
|
|
26
28
|
|
|
29
|
+
//#endregion
|
|
27
30
|
export { ldtkExtension };
|
|
28
|
-
//# sourceMappingURL=ldtkExtension.js.map
|
|
31
|
+
//# sourceMappingURL=ldtkExtension.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ldtkExtension.js","sources":["
|
|
1
|
+
{"version":3,"file":"ldtkExtension.js","names":[],"sources":["../../src/ldtkExtension.ts"],"sourcesContent":["import type { Extension } from '@codexo/exojs/extensions';\nimport { tilemapExtension } from '@codexo/exojs-tilemap';\n\nimport { ldtkMapType, ldtkProjectType } from './ldtkTypes';\n\n/**\n * Default immutable LDtk extension descriptor.\n *\n * Installs two asset types:\n * - {@link ldtkMapType} - `loader.load(ldtkMapType.asset('world.ldtk'))` reads\n * the `.ldtk` document, loads all referenced tileset images, and returns a\n * fully assembled {@link LdtkMap} with one runtime\n * {@link import('@codexo/exojs-tilemap').TileMap} per level.\n * - {@link ldtkProjectType} - `loader.load(ldtkProjectType.asset('world.ldtk'))`\n * returns the world layout and tileset atlases only, for games that load\n * levels on demand.\n *\n * Depends on {@link tilemapExtension} so that snapshot construction always\n * materialises the generic tilemap runtime before the LDtk adapter.\n *\n * Pass it to the application that should have it via\n * `ApplicationOptions.extensions`.\n */\nexport const ldtkExtension: Extension = Object.freeze({\n id: '@codexo/exojs-ldtk',\n dependencies: [tilemapExtension],\n assets: [ldtkMapType, ldtkProjectType],\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,gBAA2B,OAAO,OAAO;CACpD,IAAI;CACJ,cAAc,CAAC,gBAAgB;CAC/B,QAAQ,CAAC,aAAa,eAAe;AACvC,CAAC"}
|
|
@@ -3,7 +3,7 @@ import type { LdtkData, LdtkLevel } from './LdtkData';
|
|
|
3
3
|
* One level from a (possibly multi-world) {@link LdtkData} document, paired
|
|
4
4
|
* with the {@link import('./LdtkData').LdtkWorldData.iid} of the world it
|
|
5
5
|
* belongs to. `worldIid` is `undefined` when the document uses the legacy
|
|
6
|
-
* single-world shape (`data.levels`, no `worlds[]`)
|
|
6
|
+
* single-world shape (`data.levels`, no `worlds[]`) - the overwhelmingly
|
|
7
7
|
* common case.
|
|
8
8
|
*/
|
|
9
9
|
export interface LdtkLevelEntry {
|
|
@@ -17,11 +17,12 @@ export interface LdtkLevelEntry {
|
|
|
17
17
|
* `data.worlds[].levels`, each tagged here with its owning world's `iid`;
|
|
18
18
|
* per the LDtk spec the root `levels` array is kept but EMPTY in this shape).
|
|
19
19
|
*
|
|
20
|
-
* This is the single place that decides which shape a document uses
|
|
20
|
+
* This is the single place that decides which shape a document uses - every
|
|
21
21
|
* consumer that needs "all levels, in document order" ({@link import('./loadLdtkMap').loadLdtkMap}'s
|
|
22
22
|
* external `.ldtkl` resolution, {@link import('./ldtkToTileMap').ldtkToTileMap}'s
|
|
23
23
|
* conversion, and {@link import('./LdtkMap').LdtkMap.getLevelByName}'s lookup)
|
|
24
24
|
* goes through this function rather than re-deriving the single/multi-world
|
|
25
25
|
* detection independently.
|
|
26
26
|
*/
|
|
27
|
-
export declare
|
|
27
|
+
export declare const getLdtkLevelEntries: (data: LdtkData) => readonly LdtkLevelEntry[];
|
|
28
|
+
//# sourceMappingURL=ldtkLevelEntries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ldtkLevelEntries.d.ts","sourceRoot":"","sources":["../../src/ldtkLevelEntries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEtD;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,QAAQ,KAAG,SAAS,cAAc,EAY3E,CAAC"}
|
|
@@ -1,29 +1,33 @@
|
|
|
1
|
+
//#region src/ldtkLevelEntries.ts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
3
|
+
* Flatten a {@link LdtkData} document's levels into one ordered list,
|
|
4
|
+
* abstracting over LDtk's two root shapes: single-world (levels live in the
|
|
5
|
+
* root {@link LdtkData.levels}) and multi-world (levels live in
|
|
6
|
+
* `data.worlds[].levels`, each tagged here with its owning world's `iid`;
|
|
7
|
+
* per the LDtk spec the root `levels` array is kept but EMPTY in this shape).
|
|
8
|
+
*
|
|
9
|
+
* This is the single place that decides which shape a document uses - every
|
|
10
|
+
* consumer that needs "all levels, in document order" ({@link import('./loadLdtkMap').loadLdtkMap}'s
|
|
11
|
+
* external `.ldtkl` resolution, {@link import('./ldtkToTileMap').ldtkToTileMap}'s
|
|
12
|
+
* conversion, and {@link import('./LdtkMap').LdtkMap.getLevelByName}'s lookup)
|
|
13
|
+
* goes through this function rather than re-deriving the single/multi-world
|
|
14
|
+
* detection independently.
|
|
15
|
+
*/
|
|
16
|
+
const getLdtkLevelEntries = (data) => {
|
|
17
|
+
if (data.worlds && data.worlds.length > 0) {
|
|
18
|
+
const entries = [];
|
|
19
|
+
for (const world of data.worlds) for (const level of world.levels) entries.push({
|
|
20
|
+
level,
|
|
21
|
+
worldIid: world.iid
|
|
22
|
+
});
|
|
23
|
+
return entries;
|
|
24
|
+
}
|
|
25
|
+
return data.levels.map((level) => ({
|
|
26
|
+
level,
|
|
27
|
+
worldIid: void 0
|
|
28
|
+
}));
|
|
29
|
+
};
|
|
27
30
|
|
|
31
|
+
//#endregion
|
|
28
32
|
export { getLdtkLevelEntries };
|
|
29
|
-
//# sourceMappingURL=ldtkLevelEntries.js.map
|
|
33
|
+
//# sourceMappingURL=ldtkLevelEntries.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ldtkLevelEntries.js","sources":["
|
|
1
|
+
{"version":3,"file":"ldtkLevelEntries.js","names":[],"sources":["../../src/ldtkLevelEntries.ts"],"sourcesContent":["import type { LdtkData, LdtkLevel } from './LdtkData';\n\n/**\n * One level from a (possibly multi-world) {@link LdtkData} document, paired\n * with the {@link import('./LdtkData').LdtkWorldData.iid} of the world it\n * belongs to. `worldIid` is `undefined` when the document uses the legacy\n * single-world shape (`data.levels`, no `worlds[]`) - the overwhelmingly\n * common case.\n */\nexport interface LdtkLevelEntry {\n readonly level: LdtkLevel;\n readonly worldIid: string | undefined;\n}\n\n/**\n * Flatten a {@link LdtkData} document's levels into one ordered list,\n * abstracting over LDtk's two root shapes: single-world (levels live in the\n * root {@link LdtkData.levels}) and multi-world (levels live in\n * `data.worlds[].levels`, each tagged here with its owning world's `iid`;\n * per the LDtk spec the root `levels` array is kept but EMPTY in this shape).\n *\n * This is the single place that decides which shape a document uses - every\n * consumer that needs \"all levels, in document order\" ({@link import('./loadLdtkMap').loadLdtkMap}'s\n * external `.ldtkl` resolution, {@link import('./ldtkToTileMap').ldtkToTileMap}'s\n * conversion, and {@link import('./LdtkMap').LdtkMap.getLevelByName}'s lookup)\n * goes through this function rather than re-deriving the single/multi-world\n * detection independently.\n */\nexport const getLdtkLevelEntries = (data: LdtkData): readonly LdtkLevelEntry[] => {\n if (data.worlds && data.worlds.length > 0) {\n const entries: LdtkLevelEntry[] = [];\n for (const world of data.worlds) {\n for (const level of world.levels) {\n entries.push({ level, worldIid: world.iid });\n }\n }\n return entries;\n }\n\n return data.levels.map(level => ({ level, worldIid: undefined }));\n};\n"],"mappings":";;;;;;;;;;;;;;;AA4BA,MAAa,uBAAuB,SAA8C;CAChF,IAAI,KAAK,UAAU,KAAK,OAAO,SAAS,GAAG;EACzC,MAAM,UAA4B,CAAC;EACnC,KAAK,MAAM,SAAS,KAAK,QACvB,KAAK,MAAM,SAAS,MAAM,QACxB,QAAQ,KAAK;GAAE;GAAO,UAAU,MAAM;EAAI,CAAC;EAG/C,OAAO;CACT;CAEA,OAAO,KAAK,OAAO,KAAI,WAAU;EAAE;EAAO,UAAU;CAAU,EAAE;AAClE"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { LdtkData } from './LdtkData';
|
|
2
|
+
/** Resolved runtime parallax transform for one LDtk layer instance. */
|
|
3
|
+
export interface LdtkLayerParallax {
|
|
4
|
+
readonly parallaxX: number;
|
|
5
|
+
readonly parallaxY: number;
|
|
6
|
+
readonly parallaxScale: number;
|
|
7
|
+
/** Definition offset plus LDtk's unscaled-parallax centre compensation. */
|
|
8
|
+
readonly offsetX: number;
|
|
9
|
+
/** Definition offset plus LDtk's unscaled-parallax centre compensation. */
|
|
10
|
+
readonly offsetY: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolve the runtime parallax transform for a layer instance. Missing
|
|
14
|
+
* definitions and factors use LDtk's defaults: no shift and scale `1`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const resolveLdtkLayerParallax: (data: LdtkData, layer: {
|
|
17
|
+
readonly layerDefUid: number;
|
|
18
|
+
readonly __cWid: number;
|
|
19
|
+
readonly __cHei: number;
|
|
20
|
+
readonly __gridSize: number;
|
|
21
|
+
}) => LdtkLayerParallax;
|
|
22
|
+
//# sourceMappingURL=ldtkParallax.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ldtkParallax.d.ts","sourceRoot":"","sources":["../../src/ldtkParallax.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,uEAAuE;AACvE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GACnC,MAAM,QAAQ,EACd,OAAO;IACL,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,KACA,iBAaF,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/ldtkParallax.ts
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the runtime parallax transform for a layer instance. Missing
|
|
4
|
+
* definitions and factors use LDtk's defaults: no shift and scale `1`.
|
|
5
|
+
*/
|
|
6
|
+
const resolveLdtkLayerParallax = (data, layer) => {
|
|
7
|
+
const layerDef = data.defs.layers.find((def) => def.uid === layer.layerDefUid);
|
|
8
|
+
const factorX = layerDef?.parallaxFactorX ?? 0;
|
|
9
|
+
const factorY = layerDef?.parallaxFactorY ?? 0;
|
|
10
|
+
const scaling = layerDef?.parallaxScaling ?? true;
|
|
11
|
+
return {
|
|
12
|
+
parallaxX: 1 - factorX,
|
|
13
|
+
parallaxY: 1 - factorY,
|
|
14
|
+
parallaxScale: scaling && factorX !== 0 ? Math.max(.01, 1 - factorX) : 1,
|
|
15
|
+
offsetX: (layerDef?.pxOffsetX ?? 0) + (scaling ? 0 : -layer.__cWid * layer.__gridSize * .5 * factorX),
|
|
16
|
+
offsetY: (layerDef?.pxOffsetY ?? 0) + (scaling ? 0 : -layer.__cHei * layer.__gridSize * .5 * factorY)
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
export { resolveLdtkLayerParallax };
|
|
22
|
+
//# sourceMappingURL=ldtkParallax.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ldtkParallax.js","names":[],"sources":["../../src/ldtkParallax.ts"],"sourcesContent":["// LDtk → runtime parallax conversion.\n//\n// LDtk's `parallaxFactorX`/`parallaxFactorY` (declared on `defs.layers[]`,\n// range `[-1, 1]`) use `0` for normal camera speed. The runtime tilemap model\n// uses the opposite convention: `1` is normal speed, and render code derives\n// the camera-relative shift as `camCenter * (1 - parallaxX)`. Therefore the\n// scroll conversion is `runtimeFactor = 1 - ldtkFactor`.\n//\n// LDtk's editor applies one uniform scale derived from the horizontal factor:\n// `max(0.01, 1 - parallaxFactorX)`. Scaling happens around the layer origin.\n// When scaling is disabled, the editor offsets the unscaled layer by half its\n// dimensions times the factor so its centre follows the same parallax path.\n\nimport type { LdtkData } from './LdtkData';\n\n/** Resolved runtime parallax transform for one LDtk layer instance. */\nexport interface LdtkLayerParallax {\n readonly parallaxX: number;\n readonly parallaxY: number;\n readonly parallaxScale: number;\n /** Definition offset plus LDtk's unscaled-parallax centre compensation. */\n readonly offsetX: number;\n /** Definition offset plus LDtk's unscaled-parallax centre compensation. */\n readonly offsetY: number;\n}\n\n/**\n * Resolve the runtime parallax transform for a layer instance. Missing\n * definitions and factors use LDtk's defaults: no shift and scale `1`.\n */\nexport const resolveLdtkLayerParallax = (\n data: LdtkData,\n layer: {\n readonly layerDefUid: number;\n readonly __cWid: number;\n readonly __cHei: number;\n readonly __gridSize: number;\n },\n): LdtkLayerParallax => {\n const layerDef = data.defs.layers.find(def => def.uid === layer.layerDefUid);\n const factorX = layerDef?.parallaxFactorX ?? 0;\n const factorY = layerDef?.parallaxFactorY ?? 0;\n const scaling = layerDef?.parallaxScaling ?? true;\n\n return {\n parallaxX: 1 - factorX,\n parallaxY: 1 - factorY,\n parallaxScale: scaling && factorX !== 0 ? Math.max(0.01, 1 - factorX) : 1,\n offsetX: (layerDef?.pxOffsetX ?? 0) + (scaling ? 0 : -layer.__cWid * layer.__gridSize * 0.5 * factorX),\n offsetY: (layerDef?.pxOffsetY ?? 0) + (scaling ? 0 : -layer.__cHei * layer.__gridSize * 0.5 * factorY),\n };\n};\n"],"mappings":";;;;;AA8BA,MAAa,4BACX,MACA,UAMsB;CACtB,MAAM,WAAW,KAAK,KAAK,OAAO,MAAK,QAAO,IAAI,QAAQ,MAAM,WAAW;CAC3E,MAAM,UAAU,UAAU,mBAAmB;CAC7C,MAAM,UAAU,UAAU,mBAAmB;CAC7C,MAAM,UAAU,UAAU,mBAAmB;CAE7C,OAAO;EACL,WAAW,IAAI;EACf,WAAW,IAAI;EACf,eAAe,WAAW,YAAY,IAAI,KAAK,IAAI,KAAM,IAAI,OAAO,IAAI;EACxE,UAAU,UAAU,aAAa,MAAM,UAAU,IAAI,CAAC,MAAM,SAAS,MAAM,aAAa,KAAM;EAC9F,UAAU,UAAU,aAAa,MAAM,UAAU,IAAI,CAAC,MAAM,SAAS,MAAM,aAAa,KAAM;CAChG;AACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { MapWorld } from '@codexo/exojs-tilemap';
|
|
2
|
+
import type { LdtkData } from './LdtkData';
|
|
3
|
+
/**
|
|
4
|
+
* Build the format-neutral world model for an LDtk document: one
|
|
5
|
+
* {@link MapWorld} per LDtk world, in document order.
|
|
6
|
+
*
|
|
7
|
+
* A single-world project - the overwhelmingly common shape - yields exactly one
|
|
8
|
+
* unnamed world. A multi-world project yields one per entry of `worlds[]`, each
|
|
9
|
+
* named by its identifier, and they stay separate on purpose: LDtk worlds have independent coordinate spaces, so merging them
|
|
10
|
+
* would make {@link MapWorld.bounds} and {@link MapWorld.getLevelsInBounds}
|
|
11
|
+
* report overlaps that do not exist.
|
|
12
|
+
*
|
|
13
|
+
* {@link MapLevel.index} counts across the whole document, matching the
|
|
14
|
+
* flattened order {@link import('./LdtkMap').LdtkMap.levels} uses.
|
|
15
|
+
*
|
|
16
|
+
* Level metadata only: no layer payload is read, so this is safe to call on a
|
|
17
|
+
* document whose external levels have not been fetched.
|
|
18
|
+
*/
|
|
19
|
+
export declare const ldtkToMapWorld: (data: LdtkData) => readonly MapWorld[];
|
|
20
|
+
//# sourceMappingURL=ldtkToMapWorld.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ldtkToMapWorld.d.ts","sourceRoot":"","sources":["../../src/ldtkToMapWorld.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,KAAK,EAAE,QAAQ,EAAa,MAAM,YAAY,CAAC;AAyCtD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,QAAQ,KAAG,SAAS,QAAQ,EAgBhE,CAAC"}
|