├── .eslintignore
├── .eslintrc.js
├── .github
└── workflows
│ ├── ci.yml
│ └── release.yml
├── .gitignore
├── LICENSE
├── README.md
├── docs
├── assets
│ ├── css
│ │ └── main.css
│ ├── images
│ │ ├── icons.png
│ │ ├── icons@2x.png
│ │ ├── widgets.png
│ │ └── widgets@2x.png
│ └── js
│ │ ├── main.js
│ │ └── search.js
├── classes
│ ├── background.html
│ ├── entity.html
│ ├── enum.html
│ ├── layer.html
│ ├── level.html
│ ├── tileset.html
│ └── world.html
├── enums
│ ├── fieldtype.html
│ ├── layertype.html
│ ├── ldtk.bgpos.html
│ ├── ldtk.editordisplaymode.html
│ ├── ldtk.editordisplaypos.html
│ ├── ldtk.limitbehavior.html
│ ├── ldtk.rendermode.html
│ ├── ldtk.tilerendermode.html
│ ├── ldtk.type.html
│ └── ldtk.worldlayout.html
├── index.html
├── interfaces
│ ├── boolarrayfield.html
│ ├── boolfield.html
│ ├── colorarrayfield.html
│ ├── colorfield.html
│ ├── enumarrayfield.html
│ ├── enumfield.html
│ ├── enumvalue.html
│ ├── filepatharrayfield.html
│ ├── filepathfield.html
│ ├── floatarrayfield.html
│ ├── floatfield.html
│ ├── intarrayfield.html
│ ├── intfield.html
│ ├── intgridvaluedef.html
│ ├── ldtk.definitions.html
│ ├── ldtk.entitydefinition.html
│ ├── ldtk.entityinstance.html
│ ├── ldtk.entityinstancetile.html
│ ├── ldtk.enumdefinition.html
│ ├── ldtk.enumvaluedefinition.html
│ ├── ldtk.fielddefinition.html
│ ├── ldtk.fieldinstance.html
│ ├── ldtk.intgridvaluedefinition.html
│ ├── ldtk.intgridvalueinstance.html
│ ├── ldtk.layerdefinition.html
│ ├── ldtk.layerinstance.html
│ ├── ldtk.level.html
│ ├── ldtk.levelbackgroundposition.html
│ ├── ldtk.neighbourlevel.html
│ ├── ldtk.tileinstance.html
│ ├── ldtk.tilesetdefinition.html
│ ├── ldtk.world.html
│ ├── neighbour.html
│ ├── point.html
│ ├── pointarrayfield.html
│ ├── pointfield.html
│ ├── size.html
│ ├── stringarrayfield.html
│ ├── stringfield.html
│ └── tile.html
└── modules
│ └── ldtk.html
├── jest.config.js
├── package-lock.json
├── package.json
├── rollup.config.js
├── src
├── index.test.ts
├── index.ts
├── typedef.ts
└── util.ts
├── test
├── atlas
│ ├── Cavernas_by_Adam_Saltsman.png
│ ├── Inca_back2_by_Kronbits.png
│ ├── Inca_front_by_Kronbits-extended.png
│ ├── Monsters_and_Minions_by_Beowulf.png
│ ├── RPG Graphics Icons by 7Soul's.png
│ ├── SunnyLand_by_Ansimuz-extended.png
│ └── TopDown_by_deepnight.png
├── test.ldtk
├── test_free.ldtk
├── test_gridvania.ldtk
├── test_gridvania_opt.ldtk
├── test_separate.ldtk
└── test_separate
│ ├── 0000-Level1.ldtkl
│ ├── 0001-Level2.ldtkl
│ ├── 0002-Level3.ldtkl
│ ├── 0003-Level4.ldtkl
│ └── backups
│ └── test_separate___2021-01-24__17-06-54__crash.backup.ldtk
└── tsconfig.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | coverage
4 |
5 | webpack.*.js
6 | jest.config.js
7 | rollup.config.js
8 | .eslintrc.js
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: "@typescript-eslint/parser",
4 | plugins: ["@typescript-eslint"],
5 | extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
6 | rules: {
7 | "@typescript-eslint/no-empty-function": "off",
8 | "@typescript-eslint/no-explicit-any": "off",
9 | "@typescript-eslint/no-non-null-assertion": "off",
10 | "@typescript-eslint/ban-ts-comment": "off",
11 | "@typescript-eslint/no-namespace": "off",
12 | "@typescript-eslint/explicit-module-boundary-types": "off",
13 | "@typescript-eslint/no-var-requires": "off",
14 | "@typescript-eslint/no-inferrable-types": "off",
15 | "no-debugger": "off",
16 | "no-fallthrough": "off",
17 | "no-constant-condition": "off",
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | on: [push, pull_request]
2 |
3 | name: CI
4 |
5 | jobs:
6 | # runs typescript build + test
7 | ts:
8 | name: TypeScript
9 | runs-on: ubuntu-latest
10 | strategy:
11 | matrix:
12 | node_version:
13 | - 14
14 | - 15
15 | steps:
16 | # get code + setup node toolchain
17 | - name: Checkout code
18 | uses: actions/checkout@v2
19 | - name: Get Node toolchain
20 | uses: actions/setup-node@v2
21 | with:
22 | node-version: ${{ matrix.node_version }}
23 |
24 | - name: Cache node modules
25 | uses: actions/cache@v2
26 | env:
27 | cache-name: cache-node-modules
28 | with:
29 | # npm cache files are stored in `~/.npm` on Linux/macOS
30 | path: ~/.npm
31 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
32 | restore-keys: |
33 | ${{ runner.os }}-build-${{ env.cache-name }}-
34 | ${{ runner.os }}-build-
35 | ${{ runner.os }}-
36 |
37 | # install, build, test
38 | - name: Install dependencies
39 | run: npm ci
40 | - name: Build package
41 | run: npm run build
42 | - name: Run tests
43 | run: npm run test
44 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | on:
2 | release:
3 | types: [created]
4 |
5 | name: Node.js Package
6 |
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v2
12 | # Setup .npmrc file to publish to npm
13 | - uses: actions/setup-node@v1
14 | with:
15 | node-version: '14.x'
16 | registry-url: 'https://registry.npmjs.org'
17 |
18 | - name: Cache node modules
19 | uses: actions/cache@v2
20 | env:
21 | cache-name: cache-node-modules
22 | with:
23 | # npm cache files are stored in `~/.npm` on Linux/macOS
24 | path: ~/.npm
25 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
26 | restore-keys: |
27 | ${{ runner.os }}-build-${{ env.cache-name }}-
28 | ${{ runner.os }}-build-
29 | ${{ runner.os }}-
30 |
31 | - name: Install dependencies
32 | run: npm ci
33 | - name: Publish package to NPM
34 | run: npm publish
35 | env:
36 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | .DS_Store
3 | node_modules
4 | coverage
5 | dist
6 | yarn.lock
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2021 Jan Procházka
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ldtk-ts
2 |
3 | [LDtk](https://ldtk.io/) file format type definitions and import wrapper.
4 |
5 | This library provides an API without all the noise of LDtk "editor-only" values,
6 | definitions, etc., combined with many utilities to make usage easier.
7 |
8 | If you just want the type definitions, they're fully compliant with the [schema](https://ldtk.io/files/JSON_SCHEMA.json).
9 |
10 | Documentation is available [here](https://www.jan-prochazka.eu/ldtk-ts).
11 |
12 | ```s
13 | $ npm install ldtk
14 | ```
15 |
16 | ### Usage
17 |
18 | **Basic usage**
19 |
20 | ```ts
21 | import { World } from "ldtk";
22 |
23 | World.loadRaw("assets/world.ldtk").then(async world => {
24 | // You have access to the raw `LDtk` JSON file here
25 | let currentLevel = world.levels[0];
26 | for (const layer of currentLevel.layerInstances) {
27 | console.log(layer);
28 | // the world is your oyster
29 | }
30 | })
31 | ```
32 |
33 | **Using the importer**
34 |
35 | ```ts
36 | import { World, LDtk } from "ldtk";
37 |
38 | World.fromURL("assets/world.ldtk").then(async world => {
39 | let currentLevel = world.levelMap["Level1"];
40 | function loop(time) {
41 | render(currentLevel);
42 |
43 | window.requestAnimationFrame(loop);
44 | }
45 | window.requestAnimationFrame(loop)
46 | });
47 | ```
48 |
49 | ### Versioning table
50 |
51 | LDtk | ldtk-ts
52 | :-----:|:-------:
53 | 0.7.2 | 0.8.6
54 | 0.7.1 | 0.8.5
55 | <0.7.0 | not supported
--------------------------------------------------------------------------------
/docs/assets/images/icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/docs/assets/images/icons.png
--------------------------------------------------------------------------------
/docs/assets/images/icons@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/docs/assets/images/icons@2x.png
--------------------------------------------------------------------------------
/docs/assets/images/widgets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/docs/assets/images/widgets.png
--------------------------------------------------------------------------------
/docs/assets/images/widgets@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/docs/assets/images/widgets@2x.png
--------------------------------------------------------------------------------
/docs/enums/ldtk.tilerendermode.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | TileRenderMode | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
64 |
Enumeration TileRenderMode
65 |
66 |
67 |
68 |
69 |
70 |
71 |
78 |
79 | Index
80 |
81 |
82 |
83 | Enumeration members
84 |
88 |
89 |
90 |
91 |
92 |
93 | Enumeration members
94 |
95 |
96 | Crop
97 | Crop: = "Crop"
98 |
103 |
104 |
105 |
106 | Stretch
107 | Stretch: = "Stretch"
108 |
113 |
114 |
115 |
116 |
222 |
223 |
224 |
246 |
247 |
Generated using TypeDoc
248 |
249 |
250 |
251 |
252 |
--------------------------------------------------------------------------------
/docs/interfaces/boolarrayfield.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | BoolArrayField | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
Interface BoolArrayField
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Hierarchy
70 |
71 | -
72 | BoolArrayField
73 |
74 |
75 |
76 |
77 | Index
78 |
79 |
80 |
81 | Properties
82 |
87 |
88 |
89 |
90 |
91 |
92 | Properties
93 |
94 |
95 | id
96 | id: string
97 |
102 |
103 |
104 |
105 | type
106 |
107 |
112 |
113 |
114 |
115 | value
116 | value: boolean[]
117 |
122 |
123 |
124 |
125 |
249 |
250 |
251 |
273 |
274 |
Generated using TypeDoc
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/docs/interfaces/boolfield.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | BoolField | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
Interface BoolField
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Hierarchy
70 |
71 | -
72 | BoolField
73 |
74 |
75 |
76 |
77 | Index
78 |
79 |
80 |
81 | Properties
82 |
87 |
88 |
89 |
90 |
91 |
92 | Properties
93 |
94 |
95 | id
96 | id: string
97 |
102 |
103 |
104 |
105 | type
106 |
107 |
112 |
113 |
114 |
115 | value
116 | value: null | boolean
117 |
122 |
123 |
124 |
125 |
249 |
250 |
251 |
273 |
274 |
Generated using TypeDoc
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/docs/interfaces/colorarrayfield.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ColorArrayField | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
Interface ColorArrayField
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Hierarchy
70 |
71 | -
72 | ColorArrayField
73 |
74 |
75 |
76 |
77 | Index
78 |
79 |
80 |
81 | Properties
82 |
87 |
88 |
89 |
90 |
91 |
92 | Properties
93 |
94 |
95 | id
96 | id: string
97 |
102 |
103 |
104 |
105 | type
106 |
107 |
112 |
113 |
114 |
115 | value
116 | value: string[]
117 |
122 |
123 |
124 |
125 |
249 |
250 |
251 |
273 |
274 |
Generated using TypeDoc
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/docs/interfaces/colorfield.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ColorField | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
Interface ColorField
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Hierarchy
70 |
71 | -
72 | ColorField
73 |
74 |
75 |
76 |
77 | Index
78 |
79 |
80 |
81 | Properties
82 |
87 |
88 |
89 |
90 |
91 |
92 | Properties
93 |
94 |
95 | id
96 | id: string
97 |
102 |
103 |
104 |
105 | type
106 |
107 |
112 |
113 |
114 |
115 | value
116 | value: null | string
117 |
122 |
123 |
124 |
125 |
249 |
250 |
251 |
273 |
274 |
Generated using TypeDoc
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/docs/interfaces/floatarrayfield.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | FloatArrayField | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
Interface FloatArrayField
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Hierarchy
70 |
71 | -
72 | FloatArrayField
73 |
74 |
75 |
76 |
77 | Index
78 |
79 |
80 |
81 | Properties
82 |
87 |
88 |
89 |
90 |
91 |
92 | Properties
93 |
94 |
95 | id
96 | id: string
97 |
102 |
103 |
104 |
105 | type
106 |
107 |
112 |
113 |
114 |
115 | value
116 | value: number[]
117 |
122 |
123 |
124 |
125 |
249 |
250 |
251 |
273 |
274 |
Generated using TypeDoc
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/docs/interfaces/floatfield.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | FloatField | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
Interface FloatField
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Hierarchy
70 |
71 | -
72 | FloatField
73 |
74 |
75 |
76 |
77 | Index
78 |
79 |
80 |
81 | Properties
82 |
87 |
88 |
89 |
90 |
91 |
92 | Properties
93 |
94 |
95 | id
96 | id: string
97 |
102 |
103 |
104 |
105 | type
106 |
107 |
112 |
113 |
114 |
115 | value
116 | value: null | number
117 |
122 |
123 |
124 |
125 |
249 |
250 |
251 |
273 |
274 |
Generated using TypeDoc
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/docs/interfaces/intarrayfield.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | IntArrayField | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
Interface IntArrayField
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Hierarchy
70 |
71 | -
72 | IntArrayField
73 |
74 |
75 |
76 |
77 | Index
78 |
79 |
80 |
81 | Properties
82 |
87 |
88 |
89 |
90 |
91 |
92 | Properties
93 |
94 |
95 | id
96 | id: string
97 |
102 |
103 |
104 |
105 | type
106 |
107 |
112 |
113 |
114 |
115 | value
116 | value: number[]
117 |
122 |
123 |
124 |
125 |
249 |
250 |
251 |
273 |
274 |
Generated using TypeDoc
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/docs/interfaces/intfield.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | IntField | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
Interface IntField
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Hierarchy
70 |
71 | -
72 | IntField
73 |
74 |
75 |
76 |
77 | Index
78 |
79 |
80 |
81 | Properties
82 |
87 |
88 |
89 |
90 |
91 |
92 | Properties
93 |
94 |
95 | id
96 | id: string
97 |
102 |
103 |
104 |
105 | type
106 |
107 |
112 |
113 |
114 |
115 | value
116 | value: null | number
117 |
122 |
123 |
124 |
125 |
249 |
250 |
251 |
273 |
274 |
Generated using TypeDoc
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/docs/interfaces/intgridvaluedef.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | IntGridValueDef | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
Interface IntGridValueDef
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Hierarchy
70 |
71 | -
72 | IntGridValueDef
73 |
74 |
75 |
76 |
77 | Index
78 |
79 |
80 |
81 | Properties
82 |
86 |
87 |
88 |
89 |
90 |
91 | Properties
92 |
93 |
94 | color
95 | color: string
96 |
101 |
106 |
107 |
108 |
109 | id
110 | id: null | string
111 |
116 |
121 |
122 |
123 |
124 |
245 |
246 |
247 |
269 |
270 |
Generated using TypeDoc
271 |
272 |
273 |
274 |
275 |
--------------------------------------------------------------------------------
/docs/interfaces/neighbour.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Neighbour | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
Interface Neighbour
62 |
63 |
64 |
65 |
66 |
67 |
68 |
76 |
77 | Hierarchy
78 |
79 | -
80 | Neighbour
81 |
82 |
83 |
84 |
85 | Index
86 |
87 |
88 |
89 | Properties
90 |
94 |
95 |
96 |
97 |
98 |
99 | Properties
100 |
101 |
102 | dir
103 | dir: "n" | "s" | "w" | "e"
104 |
109 |
110 |
111 |
112 | level
113 |
114 |
119 |
120 |
121 |
122 |
243 |
244 |
245 |
267 |
268 |
Generated using TypeDoc
269 |
270 |
271 |
272 |
273 |
--------------------------------------------------------------------------------
/docs/interfaces/point.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Point | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | -
55 | ldtk
56 |
57 | -
58 | Point
59 |
60 |
61 |
Interface Point
62 |
63 |
64 |
65 |
66 |
67 |
68 |
75 |
76 | Hierarchy
77 |
78 | -
79 | Point
80 |
81 |
82 |
83 |
84 | Index
85 |
86 |
87 |
88 | Properties
89 |
93 |
94 |
95 |
96 |
97 |
98 | Properties
99 |
100 |
101 | x
102 | x: number
103 |
108 |
109 |
110 |
111 | y
112 | y: number
113 |
118 |
119 |
120 |
121 |
242 |
243 |
244 |
266 |
267 |
Generated using TypeDoc
268 |
269 |
270 |
271 |
272 |
--------------------------------------------------------------------------------
/docs/interfaces/pointfield.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | PointField | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
Interface PointField
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Hierarchy
70 |
71 | -
72 | PointField
73 |
74 |
75 |
76 |
77 | Index
78 |
79 |
80 |
81 | Properties
82 |
87 |
88 |
89 |
90 |
91 |
92 | Properties
93 |
94 |
95 | id
96 | id: string
97 |
102 |
103 |
104 |
105 | type
106 |
107 |
112 |
113 |
114 |
115 | value
116 |
117 |
122 |
123 |
124 |
125 |
249 |
250 |
251 |
273 |
274 |
Generated using TypeDoc
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/docs/interfaces/size.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Size | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | -
55 | ldtk
56 |
57 | -
58 | Size
59 |
60 |
61 |
Interface Size
62 |
63 |
64 |
65 |
66 |
67 |
68 |
75 |
83 |
84 | Index
85 |
86 |
87 |
88 | Properties
89 |
93 |
94 |
95 |
96 |
97 |
98 | Properties
99 |
100 |
101 | height
102 | height: number
103 |
108 |
109 |
110 |
111 | width
112 | width: number
113 |
118 |
119 |
120 |
121 |
242 |
243 |
244 |
266 |
267 |
Generated using TypeDoc
268 |
269 |
270 |
271 |
272 |
--------------------------------------------------------------------------------
/docs/interfaces/stringfield.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | StringField | ldtk
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | - Preparing search index...
24 | - The search index is not available
25 |
26 |
ldtk
27 |
28 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
Interface StringField
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Hierarchy
70 |
71 | -
72 | StringField
73 |
74 |
75 |
76 |
77 | Index
78 |
79 |
80 |
81 | Properties
82 |
87 |
88 |
89 |
90 |
91 |
92 | Properties
93 |
94 |
95 | id
96 | id: string
97 |
102 |
103 |
104 |
105 | type
106 |
107 |
112 |
113 |
114 |
115 | value
116 | value: null | string
117 |
122 |
123 |
124 |
125 |
249 |
250 |
251 |
273 |
274 |
Generated using TypeDoc
275 |
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | roots: ["/src"],
3 | transform: {
4 | "^.+\\.ts?$": "ts-jest",
5 | },
6 | testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.ts?$",
7 | testEnvironment: "node",
8 | moduleFileExtensions: ["ts", "js"],
9 | moduleDirectories: ["node_modules", "src"],
10 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ldtk",
3 | "version": "0.8.7",
4 | "description": "Importer for the LDtk project file format",
5 | "author": "Jan Procházka",
6 | "license": "MIT",
7 | "homepage": "https://github.com/jprochazk/ldtk-ts",
8 | "repository": {
9 | "type": "git",
10 | "url": "git+https://github.com/jprochazk/ldtk-ts.git"
11 | },
12 | "bugs": {
13 | "url": "https://github.com/jprochazk/ldtk-ts/issues"
14 | },
15 | "keywords": [
16 | "ldtk",
17 | "parse",
18 | "parser"
19 | ],
20 | "main": "dist/index.cjs.js",
21 | "module": "dist/index.esm.js",
22 | "browser": "dist/index.umd.js",
23 | "types": "dist/index.d.ts",
24 | "files": [
25 | "/dist",
26 | "LICENSE"
27 | ],
28 | "scripts": {
29 | "test": "jest",
30 | "build": "rollup -c",
31 | "prepare": "npm run build",
32 | "build-docs": "typedoc src/index.ts --readme none"
33 | },
34 | "devDependencies": {
35 | "@rollup/plugin-commonjs": "^15.1.0",
36 | "@rollup/plugin-json": "^4.1.0",
37 | "@rollup/plugin-node-resolve": "^9.0.0",
38 | "@types/jest": "^26.0.20",
39 | "@typescript-eslint/eslint-plugin": "^4.14.1",
40 | "@typescript-eslint/parser": "^4.14.1",
41 | "eslint": "^7.18.0",
42 | "jest": "^26.6.3",
43 | "node-fetch": "^2.6.1",
44 | "rollup": "^2.38.0",
45 | "rollup-plugin-terser": "^7.0.2",
46 | "rollup-plugin-typescript2": "^0.27.3",
47 | "ts-jest": "^26.4.4",
48 | "tslib": "^2.1.0",
49 | "typedoc": "^0.20.19",
50 | "typescript": "^4.1.3"
51 | },
52 | "dependencies": {}
53 | }
54 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import typescript from "rollup-plugin-typescript2";
2 | import json from "@rollup/plugin-json";
3 | import { terser } from "rollup-plugin-terser";
4 | import pkg from "./package.json";
5 |
6 | export default [
7 | // UMD, CJS, ESM
8 | {
9 | input: "src/index.ts",
10 | plugins: [
11 | json(),
12 | typescript({
13 | typescript: require("typescript"),
14 | }),
15 | terser({
16 | output: {
17 | comments: false,
18 | },
19 | }),
20 | ],
21 | output: [
22 | { exports: "named", file: pkg.main, format: "cjs" },
23 | { file: pkg.module, format: "es" },
24 | { name: "packet", file: pkg.browser, format: "umd" },
25 | ],
26 | },
27 | ];
28 |
--------------------------------------------------------------------------------
/src/index.test.ts:
--------------------------------------------------------------------------------
1 | import { World, LDtk, EnumField, Field } from "./index";
2 | import * as fs from "fs";
3 |
4 | const fetch = (path: string): T => JSON.parse(fs.readFileSync(path, { encoding: "utf-8" }));
5 |
6 | // we want to be inside the `test` directory so that
7 | // loading relative-path assets works correctly
8 | process.chdir("test");
9 |
10 | /**
11 | * Joins two arrays into an array of tuples.
12 | * If the two array lengths don't match, the extra
13 | * values from the longer one are paired with `null` values.
14 | *
15 | * ```
16 | * zip([0, 1, 2], ['a', 'b', 'c']) // [[0, 'a'], [1, 'b'], [2, 'c']]
17 | * zip([0, 1], ['a', 'b', 'c']) // [[0, 'a'], [1, 'b'], [null, 'c']]
18 | * ```
19 | */
20 | function zip(a: A[], b: B[]) {
21 | const zipped: [A | null, B | null][] = [];
22 | for (let i = 0, len = a.length > b.length ? a.length : b.length; i < len; ++i) {
23 | zipped.push([a[i] ?? null, b[i] ?? null]);
24 | }
25 | return zipped;
26 | }
27 |
28 | function compareFields(o: LDtk.FieldInstance, p: Field) {
29 | // type check abbreviation
30 | const T = (name: string) => o.__type.includes(name);
31 | // TODO: separate test for type transformation
32 | // just check values here
33 | const o_val = o.__value as any;
34 | const p_val = p.value as any;
35 | switch (true) {
36 | // simple comparison - most can be compared
37 | // with just expect.toEqual
38 | case T("Int"): /* @fallthrough */
39 | case T("Float"): /* @fallthrough */
40 | case T("String"): /* @fallthrough */
41 | case T("Bool"): /* @fallthrough */
42 | case T("Color"): /* @fallthrough */
43 | case T("FilePath"):
44 | expect(o_val).toEqual(p_val);
45 | break;
46 | // array special-cases
47 | case T("Array"):
48 | switch (true) {
49 | case T("Point"):
50 | zip(o_val, p_val).forEach(([o, p]) =>
51 | o == null
52 | // if o is null, p should be too
53 | ? expect(p).toBeNull()
54 | // otherwise their fields should match
55 | : (expect(o.cx).toEqual(p.x), expect(o.cy).toEqual(p.y)));
56 | break;
57 | case T("Enum"):
58 | expect(T((p as EnumField).ref.id)).toEqual(true);
59 | break;
60 | }
61 | break;
62 | // non-array special cases
63 | case !T("Array"):
64 | switch (true) {
65 | case T("Point"):
66 | o_val == null
67 | ? expect(p_val).toBeNull()
68 | : (expect(o_val.cx).toEqual(p_val.x), expect(o_val.cy).toEqual(p_val.y))
69 | break;
70 | case T("Enum"):
71 | expect(T((p as EnumField).ref.id)).toEqual(true);
72 | }
73 | break;
74 | }
75 | }
76 |
77 | describe("importer", () => {
78 | it("full API", () => { // Compares official Full API sample data with the processed data.
79 | const data = fetch("test.ldtk");
80 | const world = World.fromJSON(data);
81 |
82 | expect(world.bgColor).toEqual(data.bgColor);
83 | expect(world.layout).toEqual(data.worldLayout);
84 | expect(world.externalLevels).toEqual(data.externalLevels);
85 | // enums
86 | expect(data.defs!.enums.length).toEqual(world.enums.length);
87 | for (let enumIdx = 0; enumIdx < data.defs!.enums.length; ++enumIdx) {
88 | const o_enum = data.defs!.enums[enumIdx];
89 | const p_enum = world.enums[enumIdx];
90 | expect(p_enum.id).toEqual(o_enum.identifier);
91 | expect(p_enum.uid).toEqual(o_enum.uid);
92 | zip(o_enum.values, p_enum.values).forEach(([o, p]) => (
93 | expect(o?.id).toEqual(p?.id),
94 | expect(o?.__tileSrcRect[0]).toEqual(p?.tileSrcRect.x),
95 | expect(o?.__tileSrcRect[1]).toEqual(p?.tileSrcRect.y),
96 | expect(o?.__tileSrcRect[2]).toEqual(p?.tileSrcRect.width),
97 | expect(o?.__tileSrcRect[3]).toEqual(p?.tileSrcRect.height)));
98 | expect(o_enum.iconTilesetUid).toEqual(p_enum.tileset?.uid);
99 | }
100 | // tilesets
101 | expect(data.defs!.tilesets.length).toEqual(world.tilesets.length);
102 | for (let tilesetIdx = 0; tilesetIdx < data.defs!.tilesets.length; ++tilesetIdx) {
103 | const o_tileset = data.defs!.tilesets[tilesetIdx];
104 | const p_tileset = world.tilesets[tilesetIdx];
105 | expect(p_tileset.id).toEqual(o_tileset.identifier)
106 | expect(p_tileset.uid).toEqual(o_tileset.uid)
107 | expect(p_tileset.size.width).toEqual(o_tileset.pxWid);
108 | expect(p_tileset.size.height).toEqual(o_tileset.pxHei);
109 | expect(p_tileset.gridSize).toEqual(o_tileset.tileGridSize);
110 | expect(p_tileset.spacing).toEqual(o_tileset.spacing);
111 | expect(p_tileset.padding).toEqual(o_tileset.padding);
112 | expect(p_tileset.path).toEqual(o_tileset.relPath);
113 | }
114 | // levels
115 | expect(data.levels.length).toEqual(world.levels.length);
116 | for (let levelIdx = 0; levelIdx < data.levels.length; ++levelIdx) {
117 | // prefix 'o_' = original data
118 | // prefix 'p_' = processed data
119 | const o_level = data.levels[levelIdx];
120 | const p_level = world.levels[levelIdx];
121 | expect(p_level.id).toEqual(o_level.identifier);
122 | expect(p_level.uid).toEqual(o_level.uid);
123 | expect(p_level.background.color).toEqual(o_level.__bgColor);
124 | expect(p_level.background.path).toEqual(o_level.bgRelPath);
125 | expect(p_level.background.pivot.x).toEqual(o_level.bgPivotX);
126 | expect(p_level.background.pivot.y).toEqual(o_level.bgPivotY);
127 | expect(p_level.background.pos).toEqual(o_level.__bgPos);
128 | expect(p_level.size.width).toEqual(o_level.pxWid);
129 | expect(p_level.size.height).toEqual(o_level.pxHei);
130 | zip(o_level.__neighbours, p_level.neighbours).forEach(([o, p]) => (
131 | expect(o?.dir).toEqual(p?.dir),
132 | expect(o?.levelUid).toEqual(p?.level.uid)));
133 | if (o_level.layerInstances != null) {
134 | expect(o_level.layerInstances.length).toEqual(p_level.layers.length);
135 | for (let layerIdx = 0; layerIdx < o_level.layerInstances.length; ++layerIdx) {
136 | const o_layer = o_level.layerInstances[layerIdx];
137 | const p_layer = p_level.layers[layerIdx];
138 | expect(p_layer.gridSize).toEqual(o_layer.__gridSize);
139 | expect(p_layer.opacity).toEqual(o_layer.__opacity);
140 | expect(p_layer.pxTotalOffset.x).toEqual(o_layer.__pxTotalOffsetX);
141 | expect(p_layer.pxTotalOffset.y).toEqual(o_layer.__pxTotalOffsetY);
142 | expect(p_layer.uid).toEqual(o_layer.layerDefUid);
143 | expect(p_layer.size.width).toEqual(o_layer.__cWid);
144 | expect(p_layer.size.height).toEqual(o_layer.__cHei);
145 | expect(p_layer.type).toEqual(o_layer.__type);
146 | expect(p_layer.tileset?.uid ?? null).toEqual(o_layer.__tilesetDefUid);
147 | if (o_layer.__type === "AutoLayer") {
148 | // auto layer tiles aren't preprocessed
149 | expect(p_layer.autoLayerTiles).not.toBeNull();
150 | expect(o_layer.autoLayerTiles).toEqual(p_layer.autoLayerTiles);
151 | }
152 | else if (o_layer.__type === "Entities") {
153 | expect(p_layer.entities).not.toBeNull();
154 | expect(o_layer.entityInstances.length).toEqual(p_layer.entities!.length);
155 | for (let entityIdx = 0; entityIdx < o_layer.entityInstances.length; ++entityIdx) {
156 | const o_entity = o_layer.entityInstances[entityIdx];
157 | const p_entity = p_layer.entities![entityIdx];
158 | expect(o_entity.fieldInstances.length).toEqual(Object.keys(p_entity.fields).length);
159 | for (const o_field of o_entity.fieldInstances) {
160 | const p_field = p_entity.fields[o_field.__identifier];
161 | // field must exist
162 | expect(p_field != null).toEqual(true);
163 | compareFields(o_field, p_field);
164 | }
165 |
166 | }
167 | }
168 | else if (o_layer.__type === "Tiles") {
169 | // grid tiles aren't preprocessed
170 | expect(p_layer.gridTiles).not.toBeNull();
171 | expect(o_layer.gridTiles).toEqual(p_layer.gridTiles);
172 | }
173 | else if (o_layer.__type === "IntGrid") {
174 | // TODO
175 | expect(p_layer.intGrid).not.toBeNull();
176 | for (let intGridIdx = 0; intGridIdx < o_layer.intGrid.length; ++intGridIdx) {
177 | const o_igValue = o_layer.intGrid[intGridIdx];
178 | const y = Math.floor(o_igValue.coordId / o_layer.__cWid);
179 | const x = o_igValue.coordId - y * o_layer.__cWid;
180 | const p_igValue = p_layer.intGrid![x][y];
181 | expect(o_igValue.v).toEqual(p_igValue);
182 | }
183 | }
184 | }
185 | }
186 | }
187 | });
188 | it("gridvania", () => {
189 | const data = fetch("test_gridvania.ldtk");
190 | World.fromJSON(data);
191 | });
192 | it("free layout", () => {
193 | const data = fetch("test_free.ldtk");
194 | World.fromJSON(data);
195 | });
196 | it("separate files", async () => {
197 | const data = fetch("test_separate.ldtk");
198 | const world = World.fromJSON(data);
199 | // separate files start with 0 levels
200 | expect(world.levels.length).toEqual(0);
201 | // load one
202 | await world.loadLevel("Level1");
203 | expect(world.levels.length).toEqual(1);
204 | // no duplicates
205 | await world.loadLevel("Level1");
206 | expect(world.levels.length).toEqual(1);
207 | // load the rest
208 | await world.loadLevels();
209 | expect(world.levels.length).toEqual(data.levels.length);
210 | });
211 | });
--------------------------------------------------------------------------------
/src/util.ts:
--------------------------------------------------------------------------------
1 | const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
2 |
3 | const loadJSON = (() => {
4 | if (isBrowser) {
5 | return async function loadJSON(path: string): Promise {
6 | const data = await fetch(path);
7 | return await data.json();
8 | }
9 | } else {
10 | const fs = require("fs");
11 | return async function loadJSON(path: string): Promise {
12 | return new Promise((resolve, reject) => {
13 | fs.readFile(path, { encoding: "utf-8" }, (err: NodeJS.ErrnoException, data: string) => {
14 | if (err != null) reject(err)
15 | resolve(JSON.parse(data));
16 | })
17 | });
18 | }
19 | }
20 | })();
21 |
22 | export {
23 | isBrowser,
24 | loadJSON
25 | };
26 |
--------------------------------------------------------------------------------
/test/atlas/Cavernas_by_Adam_Saltsman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/Cavernas_by_Adam_Saltsman.png
--------------------------------------------------------------------------------
/test/atlas/Inca_back2_by_Kronbits.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/Inca_back2_by_Kronbits.png
--------------------------------------------------------------------------------
/test/atlas/Inca_front_by_Kronbits-extended.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/Inca_front_by_Kronbits-extended.png
--------------------------------------------------------------------------------
/test/atlas/Monsters_and_Minions_by_Beowulf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/Monsters_and_Minions_by_Beowulf.png
--------------------------------------------------------------------------------
/test/atlas/RPG Graphics Icons by 7Soul's.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/RPG Graphics Icons by 7Soul's.png
--------------------------------------------------------------------------------
/test/atlas/SunnyLand_by_Ansimuz-extended.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/SunnyLand_by_Ansimuz-extended.png
--------------------------------------------------------------------------------
/test/atlas/TopDown_by_deepnight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jprochazk/ldtk-ts/0a74d43593125401c05a37a017af5b05e145bec3/test/atlas/TopDown_by_deepnight.png
--------------------------------------------------------------------------------
/test/test_separate/0002-Level3.ldtkl:
--------------------------------------------------------------------------------
1 | {
2 | "__header__": {
3 | "fileType": "LDtk Project JSON",
4 | "app": "LDtk",
5 | "doc": "https://ldtk.io/json",
6 | "schema": "https://ldtk.io/files/JSON_SCHEMA.json",
7 | "appAuthor": "Sebastien 'deepnight' Benard",
8 | "appVersion": "0.7.2",
9 | "url": "https://ldtk.io"
10 | },
11 | "identifier": "Level3",
12 | "uid": 33,
13 | "worldX": 0,
14 | "worldY": 768,
15 | "pxWid": 256,
16 | "pxHei": 160,
17 | "__bgColor": "#373852",
18 | "bgColor": null,
19 | "bgRelPath": null,
20 | "bgPos": null,
21 | "bgPivotX": 0.5,
22 | "bgPivotY": 0.5,
23 | "__bgPos": null,
24 | "externalRelPath": null,
25 | "layerInstances": [
26 | {
27 | "__identifier": "IntGrid_8px_grid",
28 | "__type": "IntGrid",
29 | "__cWid": 32,
30 | "__cHei": 20,
31 | "__gridSize": 8,
32 | "__opacity": 1,
33 | "__pxTotalOffsetX": 0,
34 | "__pxTotalOffsetY": 0,
35 | "__tilesetDefUid": null,
36 | "__tilesetRelPath": null,
37 | "levelId": 33,
38 | "layerDefUid": 34,
39 | "pxOffsetX": 0,
40 | "pxOffsetY": 0,
41 | "intGrid": [],
42 | "autoLayerTiles": [],
43 | "seed": 9843615,
44 | "gridTiles": [],
45 | "entityInstances": []
46 | },
47 | {
48 | "__identifier": "Entities",
49 | "__type": "Entities",
50 | "__cWid": 16,
51 | "__cHei": 10,
52 | "__gridSize": 16,
53 | "__opacity": 1,
54 | "__pxTotalOffsetX": 0,
55 | "__pxTotalOffsetY": 0,
56 | "__tilesetDefUid": null,
57 | "__tilesetRelPath": null,
58 | "levelId": 33,
59 | "layerDefUid": 13,
60 | "pxOffsetX": 0,
61 | "pxOffsetY": 0,
62 | "intGrid": [],
63 | "autoLayerTiles": [],
64 | "seed": 8894473,
65 | "gridTiles": [],
66 | "entityInstances": []
67 | },
68 | {
69 | "__identifier": "PureAutoLayer",
70 | "__type": "AutoLayer",
71 | "__cWid": 16,
72 | "__cHei": 10,
73 | "__gridSize": 16,
74 | "__opacity": 1,
75 | "__pxTotalOffsetX": 0,
76 | "__pxTotalOffsetY": 0,
77 | "__tilesetDefUid": 2,
78 | "__tilesetRelPath": "atlas/Inca_front_by_Kronbits-extended.png",
79 | "levelId": 33,
80 | "layerDefUid": 26,
81 | "pxOffsetX": 0,
82 | "pxOffsetY": 0,
83 | "intGrid": [],
84 | "autoLayerTiles": [],
85 | "seed": 106526,
86 | "gridTiles": [],
87 | "entityInstances": []
88 | },
89 | {
90 | "__identifier": "IntGrid_classic",
91 | "__type": "IntGrid",
92 | "__cWid": 16,
93 | "__cHei": 10,
94 | "__gridSize": 16,
95 | "__opacity": 1,
96 | "__pxTotalOffsetX": 0,
97 | "__pxTotalOffsetY": 0,
98 | "__tilesetDefUid": null,
99 | "__tilesetRelPath": null,
100 | "levelId": 33,
101 | "layerDefUid": 1,
102 | "pxOffsetX": 0,
103 | "pxOffsetY": 0,
104 | "intGrid": [
105 | { "coordId": 20, "v": 0 },
106 | { "coordId": 21, "v": 0 },
107 | { "coordId": 22, "v": 0 },
108 | { "coordId": 23, "v": 0 },
109 | { "coordId": 24, "v": 0 },
110 | { "coordId": 25, "v": 0 },
111 | { "coordId": 26, "v": 0 },
112 | { "coordId": 27, "v": 0 },
113 | { "coordId": 65, "v": 1 },
114 | { "coordId": 78, "v": 1 },
115 | { "coordId": 81, "v": 1 },
116 | { "coordId": 94, "v": 1 },
117 | { "coordId": 132, "v": 0 },
118 | { "coordId": 133, "v": 0 },
119 | { "coordId": 134, "v": 0 },
120 | { "coordId": 135, "v": 0 },
121 | { "coordId": 136, "v": 0 },
122 | { "coordId": 137, "v": 0 },
123 | { "coordId": 138, "v": 0 },
124 | { "coordId": 139, "v": 0 }
125 | ],
126 | "autoLayerTiles": [],
127 | "seed": 3262174,
128 | "gridTiles": [],
129 | "entityInstances": []
130 | },
131 | {
132 | "__identifier": "IntGrid_with_rules",
133 | "__type": "IntGrid",
134 | "__cWid": 16,
135 | "__cHei": 10,
136 | "__gridSize": 16,
137 | "__opacity": 1,
138 | "__pxTotalOffsetX": 0,
139 | "__pxTotalOffsetY": 0,
140 | "__tilesetDefUid": 2,
141 | "__tilesetRelPath": "atlas/Inca_front_by_Kronbits-extended.png",
142 | "levelId": 33,
143 | "layerDefUid": 3,
144 | "pxOffsetX": 0,
145 | "pxOffsetY": 0,
146 | "intGrid": [
147 | { "coordId": 52, "v": 0 },
148 | { "coordId": 53, "v": 0 },
149 | { "coordId": 54, "v": 0 },
150 | { "coordId": 55, "v": 0 },
151 | { "coordId": 56, "v": 0 },
152 | { "coordId": 57, "v": 0 },
153 | { "coordId": 58, "v": 0 },
154 | { "coordId": 59, "v": 0 },
155 | { "coordId": 68, "v": 0 },
156 | { "coordId": 69, "v": 0 },
157 | { "coordId": 70, "v": 0 },
158 | { "coordId": 71, "v": 0 },
159 | { "coordId": 72, "v": 0 },
160 | { "coordId": 73, "v": 0 },
161 | { "coordId": 74, "v": 0 },
162 | { "coordId": 75, "v": 0 },
163 | { "coordId": 84, "v": 0 },
164 | { "coordId": 85, "v": 0 },
165 | { "coordId": 86, "v": 0 },
166 | { "coordId": 87, "v": 0 },
167 | { "coordId": 88, "v": 0 },
168 | { "coordId": 89, "v": 0 },
169 | { "coordId": 90, "v": 0 },
170 | { "coordId": 91, "v": 0 },
171 | { "coordId": 100, "v": 0 },
172 | { "coordId": 101, "v": 0 },
173 | { "coordId": 102, "v": 0 },
174 | { "coordId": 103, "v": 0 },
175 | { "coordId": 104, "v": 0 },
176 | { "coordId": 105, "v": 0 },
177 | { "coordId": 106, "v": 0 },
178 | { "coordId": 107, "v": 0 }
179 | ],
180 | "autoLayerTiles": [
181 | { "px": [80,48], "src": [0,112], "f": 0, "t": 140, "d": [5,53] },
182 | { "px": [112,48], "src": [0,112], "f": 0, "t": 140, "d": [5,55] },
183 | { "px": [144,48], "src": [0,112], "f": 0, "t": 140, "d": [5,57] },
184 | { "px": [80,64], "src": [0,112], "f": 0, "t": 140, "d": [5,69] },
185 | { "px": [112,64], "src": [0,112], "f": 0, "t": 140, "d": [5,71] },
186 | { "px": [144,64], "src": [0,112], "f": 0, "t": 140, "d": [5,73] },
187 | { "px": [176,64], "src": [0,112], "f": 0, "t": 140, "d": [5,75] },
188 | { "px": [64,80], "src": [0,112], "f": 0, "t": 140, "d": [5,84] },
189 | { "px": [80,80], "src": [0,112], "f": 0, "t": 140, "d": [5,85] },
190 | { "px": [96,80], "src": [0,112], "f": 0, "t": 140, "d": [5,86] },
191 | { "px": [112,80], "src": [0,112], "f": 0, "t": 140, "d": [5,87] },
192 | { "px": [128,80], "src": [0,112], "f": 0, "t": 140, "d": [5,88] },
193 | { "px": [144,80], "src": [0,112], "f": 0, "t": 140, "d": [5,89] },
194 | { "px": [160,80], "src": [0,112], "f": 0, "t": 140, "d": [5,90] },
195 | { "px": [176,80], "src": [0,112], "f": 0, "t": 140, "d": [5,91] },
196 | { "px": [80,96], "src": [0,112], "f": 0, "t": 140, "d": [5,101] },
197 | { "px": [112,96], "src": [0,112], "f": 0, "t": 140, "d": [5,103] },
198 | { "px": [144,96], "src": [0,112], "f": 0, "t": 140, "d": [5,105] },
199 | { "px": [176,48], "src": [64,128], "f": 1, "t": 164, "d": [7,59] },
200 | { "px": [176,96], "src": [64,128], "f": 3, "t": 164, "d": [7,107] },
201 | { "px": [64,64], "src": [128,0], "f": 0, "t": 8, "d": [6,68] },
202 | { "px": [64,80], "src": [128,16], "f": 0, "t": 28, "d": [6,68] },
203 | { "px": [80,64], "src": [144,0], "f": 0, "t": 9, "d": [6,68] },
204 | { "px": [80,80], "src": [144,16], "f": 0, "t": 29, "d": [6,68] },
205 | { "px": [96,64], "src": [128,0], "f": 0, "t": 8, "d": [6,70] },
206 | { "px": [96,80], "src": [128,16], "f": 0, "t": 28, "d": [6,70] },
207 | { "px": [112,64], "src": [144,0], "f": 0, "t": 9, "d": [6,70] },
208 | { "px": [112,80], "src": [144,16], "f": 0, "t": 29, "d": [6,70] },
209 | { "px": [128,64], "src": [128,0], "f": 0, "t": 8, "d": [6,72] },
210 | { "px": [128,80], "src": [128,16], "f": 0, "t": 28, "d": [6,72] },
211 | { "px": [144,64], "src": [144,0], "f": 0, "t": 9, "d": [6,72] },
212 | { "px": [144,80], "src": [144,16], "f": 0, "t": 29, "d": [6,72] },
213 | { "px": [160,64], "src": [128,0], "f": 0, "t": 8, "d": [6,74] },
214 | { "px": [160,80], "src": [128,16], "f": 0, "t": 28, "d": [6,74] },
215 | { "px": [176,64], "src": [144,0], "f": 0, "t": 9, "d": [6,74] },
216 | { "px": [176,80], "src": [144,16], "f": 0, "t": 29, "d": [6,74] },
217 | { "px": [64,48], "src": [64,80], "f": 0, "t": 104, "d": [9,52] },
218 | { "px": [80,48], "src": [80,80], "f": 0, "t": 105, "d": [9,52] },
219 | { "px": [96,48], "src": [64,80], "f": 0, "t": 104, "d": [9,54] },
220 | { "px": [112,48], "src": [80,80], "f": 0, "t": 105, "d": [9,54] },
221 | { "px": [128,48], "src": [64,80], "f": 0, "t": 104, "d": [9,56] },
222 | { "px": [144,48], "src": [80,80], "f": 0, "t": 105, "d": [9,56] },
223 | { "px": [160,48], "src": [64,80], "f": 0, "t": 104, "d": [9,58] },
224 | { "px": [176,48], "src": [80,80], "f": 0, "t": 105, "d": [9,58] },
225 | { "px": [64,96], "src": [64,80], "f": 0, "t": 104, "d": [8,100] },
226 | { "px": [80,96], "src": [80,80], "f": 0, "t": 105, "d": [8,100] },
227 | { "px": [96,96], "src": [64,80], "f": 0, "t": 104, "d": [8,102] },
228 | { "px": [112,96], "src": [80,80], "f": 0, "t": 105, "d": [8,102] },
229 | { "px": [128,96], "src": [64,80], "f": 0, "t": 104, "d": [8,104] },
230 | { "px": [144,96], "src": [80,80], "f": 0, "t": 105, "d": [8,104] },
231 | { "px": [160,96], "src": [64,80], "f": 0, "t": 104, "d": [8,106] },
232 | { "px": [176,96], "src": [80,80], "f": 0, "t": 105, "d": [8,106] }
233 | ],
234 | "seed": 5440332,
235 | "gridTiles": [],
236 | "entityInstances": []
237 | },
238 | {
239 | "__identifier": "Tiles",
240 | "__type": "Tiles",
241 | "__cWid": 16,
242 | "__cHei": 10,
243 | "__gridSize": 16,
244 | "__opacity": 1,
245 | "__pxTotalOffsetX": 0,
246 | "__pxTotalOffsetY": 0,
247 | "__tilesetDefUid": 2,
248 | "__tilesetRelPath": "atlas/Inca_front_by_Kronbits-extended.png",
249 | "levelId": 33,
250 | "layerDefUid": 14,
251 | "pxOffsetX": 0,
252 | "pxOffsetY": 0,
253 | "intGrid": [],
254 | "autoLayerTiles": [],
255 | "seed": 5395320,
256 | "gridTiles": [
257 | { "px": [16,16], "src": [32,0], "f": 0, "t": 2, "d": [17] },
258 | { "px": [32,16], "src": [48,0], "f": 0, "t": 3, "d": [18] },
259 | { "px": [208,16], "src": [32,32], "f": 0, "t": 42, "d": [29] },
260 | { "px": [224,16], "src": [48,32], "f": 0, "t": 43, "d": [30] },
261 | { "px": [16,32], "src": [32,16], "f": 0, "t": 22, "d": [33] },
262 | { "px": [32,32], "src": [48,16], "f": 0, "t": 23, "d": [34] },
263 | { "px": [208,32], "src": [32,48], "f": 0, "t": 62, "d": [45] },
264 | { "px": [224,32], "src": [48,48], "f": 0, "t": 63, "d": [46] },
265 | { "px": [16,112], "src": [64,32], "f": 0, "t": 44, "d": [113] },
266 | { "px": [32,112], "src": [80,32], "f": 0, "t": 45, "d": [114] },
267 | { "px": [208,112], "src": [96,0], "f": 0, "t": 6, "d": [125] },
268 | { "px": [224,112], "src": [112,0], "f": 0, "t": 7, "d": [126] },
269 | { "px": [16,128], "src": [64,48], "f": 0, "t": 64, "d": [129] },
270 | { "px": [32,128], "src": [80,48], "f": 0, "t": 65, "d": [130] },
271 | { "px": [208,128], "src": [96,16], "f": 0, "t": 26, "d": [141] },
272 | { "px": [224,128], "src": [112,16], "f": 0, "t": 27, "d": [142] }
273 | ],
274 | "entityInstances": []
275 | }
276 | ],
277 | "__neighbours": [ { "levelUid": 36, "dir": "s" }, { "levelUid": 32, "dir": "n" } ]
278 | }
--------------------------------------------------------------------------------
/test/test_separate/0003-Level4.ldtkl:
--------------------------------------------------------------------------------
1 | {
2 | "__header__": {
3 | "fileType": "LDtk Project JSON",
4 | "app": "LDtk",
5 | "doc": "https://ldtk.io/json",
6 | "schema": "https://ldtk.io/files/JSON_SCHEMA.json",
7 | "appAuthor": "Sebastien 'deepnight' Benard",
8 | "appVersion": "0.7.2",
9 | "url": "https://ldtk.io"
10 | },
11 | "identifier": "Level4",
12 | "uid": 36,
13 | "worldX": 0,
14 | "worldY": 960,
15 | "pxWid": 256,
16 | "pxHei": 256,
17 | "__bgColor": "#373852",
18 | "bgColor": null,
19 | "bgRelPath": "Inca_back2_by_Kronbits.png",
20 | "bgPos": "Contain",
21 | "bgPivotX": 0.5,
22 | "bgPivotY": 0.5,
23 | "__bgPos": null,
24 | "externalRelPath": null,
25 | "layerInstances": [
26 | {
27 | "__identifier": "IntGrid_8px_grid",
28 | "__type": "IntGrid",
29 | "__cWid": 32,
30 | "__cHei": 32,
31 | "__gridSize": 8,
32 | "__opacity": 1,
33 | "__pxTotalOffsetX": 0,
34 | "__pxTotalOffsetY": 0,
35 | "__tilesetDefUid": null,
36 | "__tilesetRelPath": null,
37 | "levelId": 36,
38 | "layerDefUid": 34,
39 | "pxOffsetX": 0,
40 | "pxOffsetY": 0,
41 | "intGrid": [],
42 | "autoLayerTiles": [],
43 | "seed": 3866698,
44 | "gridTiles": [],
45 | "entityInstances": []
46 | },
47 | {
48 | "__identifier": "Entities",
49 | "__type": "Entities",
50 | "__cWid": 16,
51 | "__cHei": 16,
52 | "__gridSize": 16,
53 | "__opacity": 1,
54 | "__pxTotalOffsetX": 0,
55 | "__pxTotalOffsetY": 0,
56 | "__tilesetDefUid": null,
57 | "__tilesetRelPath": null,
58 | "levelId": 36,
59 | "layerDefUid": 13,
60 | "pxOffsetX": 0,
61 | "pxOffsetY": 0,
62 | "intGrid": [],
63 | "autoLayerTiles": [],
64 | "seed": 3655473,
65 | "gridTiles": [],
66 | "entityInstances": [{ "__identifier": "Labels", "__grid": [8,1], "__pivot": [0.5,0.5], "__tile": null, "defUid": 10, "px": [129,24], "fieldInstances": [
67 | {
68 | "__identifier": "text",
69 | "__value": "Level background image",
70 | "__type": "String",
71 | "defUid": 11,
72 | "realEditorValues": [{
73 | "id": "V_String",
74 | "params": ["Level background image"]
75 | }]
76 | },
77 | { "__identifier": "color", "__value": "#7F95AB", "__type": "Color", "defUid": 12, "realEditorValues": [] }
78 | ] }]
79 | },
80 | {
81 | "__identifier": "PureAutoLayer",
82 | "__type": "AutoLayer",
83 | "__cWid": 16,
84 | "__cHei": 16,
85 | "__gridSize": 16,
86 | "__opacity": 1,
87 | "__pxTotalOffsetX": 0,
88 | "__pxTotalOffsetY": 0,
89 | "__tilesetDefUid": 2,
90 | "__tilesetRelPath": "atlas/Inca_front_by_Kronbits-extended.png",
91 | "levelId": 36,
92 | "layerDefUid": 26,
93 | "pxOffsetX": 0,
94 | "pxOffsetY": 0,
95 | "intGrid": [],
96 | "autoLayerTiles": [],
97 | "seed": 5193927,
98 | "gridTiles": [],
99 | "entityInstances": []
100 | },
101 | {
102 | "__identifier": "IntGrid_classic",
103 | "__type": "IntGrid",
104 | "__cWid": 16,
105 | "__cHei": 16,
106 | "__gridSize": 16,
107 | "__opacity": 1,
108 | "__pxTotalOffsetX": 0,
109 | "__pxTotalOffsetY": 0,
110 | "__tilesetDefUid": null,
111 | "__tilesetRelPath": null,
112 | "levelId": 36,
113 | "layerDefUid": 1,
114 | "pxOffsetX": 0,
115 | "pxOffsetY": 0,
116 | "intGrid": [],
117 | "autoLayerTiles": [],
118 | "seed": 6618746,
119 | "gridTiles": [],
120 | "entityInstances": []
121 | },
122 | {
123 | "__identifier": "IntGrid_with_rules",
124 | "__type": "IntGrid",
125 | "__cWid": 16,
126 | "__cHei": 16,
127 | "__gridSize": 16,
128 | "__opacity": 1,
129 | "__pxTotalOffsetX": 0,
130 | "__pxTotalOffsetY": 0,
131 | "__tilesetDefUid": 2,
132 | "__tilesetRelPath": "atlas/Inca_front_by_Kronbits-extended.png",
133 | "levelId": 36,
134 | "layerDefUid": 3,
135 | "pxOffsetX": 0,
136 | "pxOffsetY": 0,
137 | "intGrid": [],
138 | "autoLayerTiles": [],
139 | "seed": 7313278,
140 | "gridTiles": [],
141 | "entityInstances": []
142 | },
143 | {
144 | "__identifier": "Tiles",
145 | "__type": "Tiles",
146 | "__cWid": 16,
147 | "__cHei": 16,
148 | "__gridSize": 16,
149 | "__opacity": 1,
150 | "__pxTotalOffsetX": 0,
151 | "__pxTotalOffsetY": 0,
152 | "__tilesetDefUid": 2,
153 | "__tilesetRelPath": "atlas/Inca_front_by_Kronbits-extended.png",
154 | "levelId": 36,
155 | "layerDefUid": 14,
156 | "pxOffsetX": 0,
157 | "pxOffsetY": 0,
158 | "intGrid": [],
159 | "autoLayerTiles": [],
160 | "seed": 4655507,
161 | "gridTiles": [],
162 | "entityInstances": []
163 | }
164 | ],
165 | "__neighbours": [{ "levelUid": 33, "dir": "n" }]
166 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
4 | "module": "es6" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
5 | "lib": ["ES2017", "ES7", "ES6", "DOM"],
6 | "declaration": true,
7 | "declarationDir": "./dist",
8 | "outDir": "./dist" /* Redirect output structure to the directory. */,
9 | "strict": true /* Enable all strict type-checking options. */,
10 | "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
11 | "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
12 | "baseUrl": "./src" /* Base directory to resolve non-absolute module names. */,
13 | //"types": [],
14 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
15 | "moduleResolution": "node",
16 | "downlevelIteration": true,
17 | },
18 | "include": ["src"],
19 | "exclude": ["node_modules"]
20 | }
21 |
--------------------------------------------------------------------------------
Possible values: "Crop", "Stretch"
75 |