@nice2dev/game-engine 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/dist/cjs/ai/BehaviorTree.js +1215 -0
  2. package/dist/cjs/ai/BehaviorTree.js.map +1 -0
  3. package/dist/cjs/ai/StateMachine.js +783 -0
  4. package/dist/cjs/ai/StateMachine.js.map +1 -0
  5. package/dist/cjs/editor/ShaderGraph.js +1616 -0
  6. package/dist/cjs/editor/ShaderGraph.js.map +1 -0
  7. package/dist/cjs/editor/TimelineEditor.js +819 -0
  8. package/dist/cjs/editor/TimelineEditor.js.map +1 -0
  9. package/dist/cjs/export/GodotExporter.js +1102 -0
  10. package/dist/cjs/export/GodotExporter.js.map +1 -0
  11. package/dist/cjs/export/PlatformExporter.js +236 -0
  12. package/dist/cjs/export/PlatformExporter.js.map +1 -0
  13. package/dist/cjs/export/ThreeJSExporter.js +1116 -0
  14. package/dist/cjs/export/ThreeJSExporter.js.map +1 -0
  15. package/dist/cjs/export/UnityExporter.js +1193 -0
  16. package/dist/cjs/export/UnityExporter.js.map +1 -0
  17. package/dist/cjs/export/WebExporter.js +1036 -0
  18. package/dist/cjs/export/WebExporter.js.map +1 -0
  19. package/dist/cjs/export/index.js +58 -0
  20. package/dist/cjs/export/index.js.map +1 -0
  21. package/dist/cjs/import/AsepriteImporter.js +761 -0
  22. package/dist/cjs/import/AsepriteImporter.js.map +1 -0
  23. package/dist/cjs/import/DragonBonesImporter.js +499 -0
  24. package/dist/cjs/import/DragonBonesImporter.js.map +1 -0
  25. package/dist/cjs/import/GameMakerImporter.js +559 -0
  26. package/dist/cjs/import/GameMakerImporter.js.map +1 -0
  27. package/dist/cjs/import/GodotSceneImporter.js +824 -0
  28. package/dist/cjs/import/GodotSceneImporter.js.map +1 -0
  29. package/dist/cjs/import/LDtkImporter.js +481 -0
  30. package/dist/cjs/import/LDtkImporter.js.map +1 -0
  31. package/dist/cjs/import/Live2DImporter.js +553 -0
  32. package/dist/cjs/import/Live2DImporter.js.map +1 -0
  33. package/dist/cjs/import/NdgFormat.js +499 -0
  34. package/dist/cjs/import/NdgFormat.js.map +1 -0
  35. package/dist/cjs/import/OgmoImporter.js +529 -0
  36. package/dist/cjs/import/OgmoImporter.js.map +1 -0
  37. package/dist/cjs/import/RPGMakerImporter.js +520 -0
  38. package/dist/cjs/import/RPGMakerImporter.js.map +1 -0
  39. package/dist/cjs/import/SceneImporter.js +449 -0
  40. package/dist/cjs/import/SceneImporter.js.map +1 -0
  41. package/dist/cjs/import/SpineImporter.js +583 -0
  42. package/dist/cjs/import/SpineImporter.js.map +1 -0
  43. package/dist/cjs/import/SpriterImporter.js +652 -0
  44. package/dist/cjs/import/SpriterImporter.js.map +1 -0
  45. package/dist/cjs/import/TiledMapImporter.js +859 -0
  46. package/dist/cjs/import/TiledMapImporter.js.map +1 -0
  47. package/dist/cjs/import/UnitySceneImporter.js +732 -0
  48. package/dist/cjs/import/UnitySceneImporter.js.map +1 -0
  49. package/dist/cjs/import/index.js +305 -0
  50. package/dist/cjs/import/index.js.map +1 -0
  51. package/dist/cjs/index.js +201 -0
  52. package/dist/cjs/index.js.map +1 -1
  53. package/dist/cjs/scripting/GraphToAST.js +567 -0
  54. package/dist/cjs/scripting/GraphToAST.js.map +1 -0
  55. package/dist/cjs/scripting/LanguageExporter.js +321 -0
  56. package/dist/cjs/scripting/LanguageExporter.js.map +1 -0
  57. package/dist/cjs/scripting/ScriptAST.js +67 -0
  58. package/dist/cjs/scripting/ScriptAST.js.map +1 -0
  59. package/dist/cjs/scripting/VisualScripting2.js +1140 -0
  60. package/dist/cjs/scripting/VisualScripting2.js.map +1 -0
  61. package/dist/cjs/scripting/exporters/CSharpExporter.js +503 -0
  62. package/dist/cjs/scripting/exporters/CSharpExporter.js.map +1 -0
  63. package/dist/cjs/scripting/exporters/GDScriptExporter.js +452 -0
  64. package/dist/cjs/scripting/exporters/GDScriptExporter.js.map +1 -0
  65. package/dist/cjs/scripting/exporters/LuaExporter.js +457 -0
  66. package/dist/cjs/scripting/exporters/LuaExporter.js.map +1 -0
  67. package/dist/cjs/scripting/exporters/PythonExporter.js +565 -0
  68. package/dist/cjs/scripting/exporters/PythonExporter.js.map +1 -0
  69. package/dist/cjs/scripting/exporters/RustExporter.js +525 -0
  70. package/dist/cjs/scripting/exporters/RustExporter.js.map +1 -0
  71. package/dist/cjs/scripting/exporters/TypeScriptExporter.js +570 -0
  72. package/dist/cjs/scripting/exporters/TypeScriptExporter.js.map +1 -0
  73. package/dist/cjs/systems/ParticleSystem2.js +1478 -0
  74. package/dist/cjs/systems/ParticleSystem2.js.map +1 -0
  75. package/dist/esm/ai/BehaviorTree.js +1186 -0
  76. package/dist/esm/ai/BehaviorTree.js.map +1 -0
  77. package/dist/esm/ai/StateMachine.js +767 -0
  78. package/dist/esm/ai/StateMachine.js.map +1 -0
  79. package/dist/esm/editor/ShaderGraph.js +1606 -0
  80. package/dist/esm/editor/ShaderGraph.js.map +1 -0
  81. package/dist/esm/editor/TimelineEditor.js +800 -0
  82. package/dist/esm/editor/TimelineEditor.js.map +1 -0
  83. package/dist/esm/export/GodotExporter.js +1100 -0
  84. package/dist/esm/export/GodotExporter.js.map +1 -0
  85. package/dist/esm/export/PlatformExporter.js +230 -0
  86. package/dist/esm/export/PlatformExporter.js.map +1 -0
  87. package/dist/esm/export/ThreeJSExporter.js +1114 -0
  88. package/dist/esm/export/ThreeJSExporter.js.map +1 -0
  89. package/dist/esm/export/UnityExporter.js +1191 -0
  90. package/dist/esm/export/UnityExporter.js.map +1 -0
  91. package/dist/esm/export/WebExporter.js +1033 -0
  92. package/dist/esm/export/WebExporter.js.map +1 -0
  93. package/dist/esm/export/index.js +44 -0
  94. package/dist/esm/export/index.js.map +1 -0
  95. package/dist/esm/import/AsepriteImporter.js +759 -0
  96. package/dist/esm/import/AsepriteImporter.js.map +1 -0
  97. package/dist/esm/import/DragonBonesImporter.js +496 -0
  98. package/dist/esm/import/DragonBonesImporter.js.map +1 -0
  99. package/dist/esm/import/GameMakerImporter.js +556 -0
  100. package/dist/esm/import/GameMakerImporter.js.map +1 -0
  101. package/dist/esm/import/GodotSceneImporter.js +822 -0
  102. package/dist/esm/import/GodotSceneImporter.js.map +1 -0
  103. package/dist/esm/import/LDtkImporter.js +479 -0
  104. package/dist/esm/import/LDtkImporter.js.map +1 -0
  105. package/dist/esm/import/Live2DImporter.js +550 -0
  106. package/dist/esm/import/Live2DImporter.js.map +1 -0
  107. package/dist/esm/import/NdgFormat.js +490 -0
  108. package/dist/esm/import/NdgFormat.js.map +1 -0
  109. package/dist/esm/import/OgmoImporter.js +526 -0
  110. package/dist/esm/import/OgmoImporter.js.map +1 -0
  111. package/dist/esm/import/RPGMakerImporter.js +517 -0
  112. package/dist/esm/import/RPGMakerImporter.js.map +1 -0
  113. package/dist/esm/import/SceneImporter.js +441 -0
  114. package/dist/esm/import/SceneImporter.js.map +1 -0
  115. package/dist/esm/import/SpineImporter.js +580 -0
  116. package/dist/esm/import/SpineImporter.js.map +1 -0
  117. package/dist/esm/import/SpriterImporter.js +649 -0
  118. package/dist/esm/import/SpriterImporter.js.map +1 -0
  119. package/dist/esm/import/TiledMapImporter.js +857 -0
  120. package/dist/esm/import/TiledMapImporter.js.map +1 -0
  121. package/dist/esm/import/UnitySceneImporter.js +730 -0
  122. package/dist/esm/import/UnitySceneImporter.js.map +1 -0
  123. package/dist/esm/import/index.js +279 -0
  124. package/dist/esm/import/index.js.map +1 -0
  125. package/dist/esm/index.js +36 -0
  126. package/dist/esm/index.js.map +1 -1
  127. package/dist/esm/scripting/GraphToAST.js +564 -0
  128. package/dist/esm/scripting/GraphToAST.js.map +1 -0
  129. package/dist/esm/scripting/LanguageExporter.js +311 -0
  130. package/dist/esm/scripting/LanguageExporter.js.map +1 -0
  131. package/dist/esm/scripting/ScriptAST.js +52 -0
  132. package/dist/esm/scripting/ScriptAST.js.map +1 -0
  133. package/dist/esm/scripting/VisualScripting2.js +1130 -0
  134. package/dist/esm/scripting/VisualScripting2.js.map +1 -0
  135. package/dist/esm/scripting/exporters/CSharpExporter.js +501 -0
  136. package/dist/esm/scripting/exporters/CSharpExporter.js.map +1 -0
  137. package/dist/esm/scripting/exporters/GDScriptExporter.js +450 -0
  138. package/dist/esm/scripting/exporters/GDScriptExporter.js.map +1 -0
  139. package/dist/esm/scripting/exporters/LuaExporter.js +455 -0
  140. package/dist/esm/scripting/exporters/LuaExporter.js.map +1 -0
  141. package/dist/esm/scripting/exporters/PythonExporter.js +563 -0
  142. package/dist/esm/scripting/exporters/PythonExporter.js.map +1 -0
  143. package/dist/esm/scripting/exporters/RustExporter.js +523 -0
  144. package/dist/esm/scripting/exporters/RustExporter.js.map +1 -0
  145. package/dist/esm/scripting/exporters/TypeScriptExporter.js +568 -0
  146. package/dist/esm/scripting/exporters/TypeScriptExporter.js.map +1 -0
  147. package/dist/esm/systems/ParticleSystem2.js +1471 -0
  148. package/dist/esm/systems/ParticleSystem2.js.map +1 -0
  149. package/dist/types/ai/BehaviorTree.d.ts +375 -0
  150. package/dist/types/ai/StateMachine.d.ts +296 -0
  151. package/dist/types/editor/ShaderGraph.d.ts +207 -0
  152. package/dist/types/editor/TimelineEditor.d.ts +393 -0
  153. package/dist/types/export/GodotExporter.d.ts +56 -0
  154. package/dist/types/export/PlatformExporter.d.ts +201 -0
  155. package/dist/types/export/ThreeJSExporter.d.ts +40 -0
  156. package/dist/types/export/UnityExporter.d.ts +69 -0
  157. package/dist/types/export/WebExporter.d.ts +58 -0
  158. package/dist/types/export/index.d.ts +19 -0
  159. package/dist/types/import/AsepriteImporter.d.ts +46 -0
  160. package/dist/types/import/DragonBonesImporter.d.ts +331 -0
  161. package/dist/types/import/GameMakerImporter.d.ts +375 -0
  162. package/dist/types/import/GodotSceneImporter.d.ts +34 -0
  163. package/dist/types/import/LDtkImporter.d.ts +177 -0
  164. package/dist/types/import/Live2DImporter.d.ts +237 -0
  165. package/dist/types/import/NdgFormat.d.ts +387 -0
  166. package/dist/types/import/OgmoImporter.d.ts +237 -0
  167. package/dist/types/import/RPGMakerImporter.d.ts +186 -0
  168. package/dist/types/import/SceneImporter.d.ts +276 -0
  169. package/dist/types/import/SpineImporter.d.ts +372 -0
  170. package/dist/types/import/SpriterImporter.d.ts +230 -0
  171. package/dist/types/import/TiledMapImporter.d.ts +57 -0
  172. package/dist/types/import/UnitySceneImporter.d.ts +87 -0
  173. package/dist/types/import/index.d.ts +59 -0
  174. package/dist/types/index.d.ts +29 -17
  175. package/dist/types/scripting/GraphToAST.d.ts +55 -0
  176. package/dist/types/scripting/LanguageExporter.d.ts +136 -0
  177. package/dist/types/scripting/ScriptAST.d.ts +312 -0
  178. package/dist/types/scripting/VisualScripting2.d.ts +353 -0
  179. package/dist/types/scripting/exporters/CSharpExporter.d.ts +44 -0
  180. package/dist/types/scripting/exporters/GDScriptExporter.d.ts +46 -0
  181. package/dist/types/scripting/exporters/LuaExporter.d.ts +46 -0
  182. package/dist/types/scripting/exporters/PythonExporter.d.ts +49 -0
  183. package/dist/types/scripting/exporters/RustExporter.d.ts +46 -0
  184. package/dist/types/scripting/exporters/TypeScriptExporter.d.ts +48 -0
  185. package/dist/types/scripting/exporters/index.d.ts +8 -0
  186. package/dist/types/scripting/index.d.ts +11 -0
  187. package/dist/types/systems/ParticleSystem2.d.ts +646 -0
  188. package/package.json +3 -3
@@ -0,0 +1,857 @@
1
+ import { SceneImporter, parseXML } from './SceneImporter.js';
2
+
3
+ /**
4
+ * @file TiledMapImporter.ts
5
+ * @description Import Tiled Map Editor files (.tmx, .tsx)
6
+ * PRO-1.3: Scene Format Interoperability
7
+ *
8
+ * Supports:
9
+ * - Tiled Map files (.tmx, .tmj)
10
+ * - Tileset files (.tsx, .tsj)
11
+ * - Template files (.tx, .tj)
12
+ * - World files (.world)
13
+ *
14
+ * Features:
15
+ * - Tile layers
16
+ * - Object layers
17
+ * - Image layers
18
+ * - Group layers
19
+ * - Animations
20
+ * - Custom properties
21
+ * - Collision shapes
22
+ */
23
+ // ============================================================
24
+ // Tiled Map Importer
25
+ // ============================================================
26
+ class TiledMapImporter extends SceneImporter {
27
+ constructor() {
28
+ super('tiled');
29
+ this.tilesets = new Map();
30
+ this.tilesetsById = new Map();
31
+ }
32
+ async import(options) {
33
+ const startTime = Date.now();
34
+ this.options = options;
35
+ this.clearMessages();
36
+ this.tilesets.clear();
37
+ this.tilesetsById.clear();
38
+ const errors = await this.validate(options.sourcePath);
39
+ if (errors.some((e) => e.fatal)) {
40
+ return {
41
+ ...this.createEmptyResult(),
42
+ errors: errors,
43
+ };
44
+ }
45
+ const scenes = [];
46
+ const assets = [];
47
+ try {
48
+ const content = await this.readFile(options.sourcePath);
49
+ const isJson = options.sourcePath.endsWith('.tmj') || options.sourcePath.endsWith('.json');
50
+ const map = isJson ? this.parseJsonMap(content) : this.parseXmlMap(content);
51
+ if (map) {
52
+ // Parse external tilesets
53
+ await this.loadExternalTilesets(map, options.sourcePath);
54
+ const parsed = this.convertTiledMapToScene(map);
55
+ const niceScene = this.convertParsedToNiceScene(parsed);
56
+ scenes.push(niceScene);
57
+ const extractedAssets = this.extractAssets(map);
58
+ assets.push(...extractedAssets);
59
+ }
60
+ }
61
+ catch (error) {
62
+ this.addError('IMPORT_ERROR', `Failed to import: ${error}`, options.sourcePath, undefined, true);
63
+ }
64
+ return this.createResult(scenes, assets, startTime);
65
+ }
66
+ async parseFile(content, filePath) {
67
+ const stringContent = typeof content === 'string' ? content : new TextDecoder().decode(content);
68
+ const isJson = filePath.endsWith('.tmj') || filePath.endsWith('.json');
69
+ const map = isJson ? this.parseJsonMap(stringContent) : this.parseXmlMap(stringContent);
70
+ if (!map)
71
+ return null;
72
+ return this.convertTiledMapToScene(map);
73
+ }
74
+ async validate(sourcePath) {
75
+ const errors = [];
76
+ if (!this.canHandle(sourcePath)) {
77
+ errors.push({
78
+ code: 'INVALID_FORMAT',
79
+ message: `File ${sourcePath} is not a valid Tiled file`,
80
+ file: sourcePath,
81
+ fatal: true,
82
+ });
83
+ }
84
+ return errors;
85
+ }
86
+ // ----------------------------------------
87
+ // Tiled Parsing
88
+ // ----------------------------------------
89
+ parseJsonMap(content) {
90
+ try {
91
+ const json = JSON.parse(content);
92
+ return this.normalizeJsonMap(json);
93
+ }
94
+ catch (error) {
95
+ this.addError('JSON_PARSE_ERROR', `Failed to parse JSON: ${error}`);
96
+ return null;
97
+ }
98
+ }
99
+ normalizeJsonMap(json) {
100
+ var _a, _b;
101
+ return {
102
+ version: String(json.version || '1.0'),
103
+ tiledVersion: String(json.tiledversion || ''),
104
+ orientation: json.orientation || 'orthogonal',
105
+ renderOrder: json.renderorder || 'right-down',
106
+ width: Number(json.width) || 0,
107
+ height: Number(json.height) || 0,
108
+ tileWidth: Number(json.tilewidth) || 0,
109
+ tileHeight: Number(json.tileheight) || 0,
110
+ infinite: Boolean(json.infinite),
111
+ backgroundColor: json.backgroundcolor ? String(json.backgroundcolor) : undefined,
112
+ nextLayerId: Number(json.nextlayerid) || 0,
113
+ nextObjectId: Number(json.nextobjectid) || 0,
114
+ parallaxOriginX: json.parallaxoriginx ? Number(json.parallaxoriginx) : undefined,
115
+ parallaxOriginY: json.parallaxoriginy ? Number(json.parallaxoriginy) : undefined,
116
+ tilesets: ((_a = json.tilesets) === null || _a === void 0 ? void 0 : _a.map((ts) => this.normalizeJsonTileset(ts))) || [],
117
+ layers: ((_b = json.layers) === null || _b === void 0 ? void 0 : _b.map((l) => this.normalizeJsonLayer(l))) || [],
118
+ properties: this.normalizeProperties(json.properties),
119
+ hexSideLength: json.hexsidelength ? Number(json.hexsidelength) : undefined,
120
+ staggerAxis: json.staggeraxis,
121
+ staggerIndex: json.staggerindex,
122
+ };
123
+ }
124
+ normalizeJsonTileset(json) {
125
+ const tileset = {
126
+ firstGid: Number(json.firstgid) || 0,
127
+ source: json.source ? String(json.source) : undefined,
128
+ name: String(json.name || ''),
129
+ tileWidth: Number(json.tilewidth) || 0,
130
+ tileHeight: Number(json.tileheight) || 0,
131
+ spacing: Number(json.spacing) || 0,
132
+ margin: Number(json.margin) || 0,
133
+ tileCount: Number(json.tilecount) || 0,
134
+ columns: Number(json.columns) || 0,
135
+ image: json.image ? String(json.image) : undefined,
136
+ imageWidth: json.imagewidth ? Number(json.imagewidth) : undefined,
137
+ imageHeight: json.imageheight ? Number(json.imageheight) : undefined,
138
+ transparentColor: json.transparentcolor ? String(json.transparentcolor) : undefined,
139
+ properties: this.normalizeProperties(json.properties),
140
+ };
141
+ if (json.tiles) {
142
+ tileset.tiles = json.tiles.map((t) => this.normalizeJsonTile(t));
143
+ }
144
+ if (json.tileoffset) {
145
+ const offset = json.tileoffset;
146
+ tileset.tileOffset = { x: Number(offset.x) || 0, y: Number(offset.y) || 0 };
147
+ }
148
+ return tileset;
149
+ }
150
+ normalizeJsonTile(json) {
151
+ var _a;
152
+ const tile = {
153
+ id: Number(json.id) || 0,
154
+ type: json.type ? String(json.type) : undefined,
155
+ properties: this.normalizeProperties(json.properties),
156
+ };
157
+ if (json.animation) {
158
+ tile.animation = json.animation.map((f) => ({
159
+ tileId: Number(f.tileid),
160
+ duration: Number(f.duration),
161
+ }));
162
+ }
163
+ if (json.objectgroup) {
164
+ const og = json.objectgroup;
165
+ tile.objectGroup = {
166
+ drawOrder: String(og.draworder || 'index'),
167
+ id: Number(og.id) || 0,
168
+ name: String(og.name || ''),
169
+ objects: ((_a = og.objects) === null || _a === void 0 ? void 0 : _a.map((o) => this.normalizeJsonObject(o))) || [],
170
+ };
171
+ }
172
+ return tile;
173
+ }
174
+ normalizeJsonLayer(json) {
175
+ var _a;
176
+ const layer = {
177
+ id: Number(json.id) || 0,
178
+ name: String(json.name || ''),
179
+ type: json.type || 'tilelayer',
180
+ visible: json.visible !== false,
181
+ opacity: json.opacity !== undefined ? Number(json.opacity) : 1,
182
+ offsetX: Number(json.offsetx) || 0,
183
+ offsetY: Number(json.offsety) || 0,
184
+ parallaxX: json.parallaxx !== undefined ? Number(json.parallaxx) : 1,
185
+ parallaxY: json.parallaxy !== undefined ? Number(json.parallaxy) : 1,
186
+ tintColor: json.tintcolor ? String(json.tintcolor) : undefined,
187
+ locked: json.locked ? Boolean(json.locked) : undefined,
188
+ class: json.class ? String(json.class) : undefined,
189
+ properties: this.normalizeProperties(json.properties),
190
+ };
191
+ // Tile layer specific
192
+ if (json.type === 'tilelayer') {
193
+ layer.width = Number(json.width) || 0;
194
+ layer.height = Number(json.height) || 0;
195
+ layer.data = json.data;
196
+ layer.encoding = json.encoding;
197
+ layer.compression = json.compression;
198
+ if (json.chunks) {
199
+ layer.chunks = json.chunks.map((c) => {
200
+ const chunk = c;
201
+ return {
202
+ x: Number(chunk.x),
203
+ y: Number(chunk.y),
204
+ width: Number(chunk.width),
205
+ height: Number(chunk.height),
206
+ data: chunk.data,
207
+ };
208
+ });
209
+ }
210
+ }
211
+ // Object layer specific
212
+ if (json.type === 'objectgroup') {
213
+ layer.objects =
214
+ ((_a = json.objects) === null || _a === void 0 ? void 0 : _a.map((o) => this.normalizeJsonObject(o))) || [];
215
+ layer.drawOrder = json.draworder || 'topdown';
216
+ layer.color = json.color ? String(json.color) : undefined;
217
+ }
218
+ // Image layer specific
219
+ if (json.type === 'imagelayer') {
220
+ layer.image = json.image ? String(json.image) : undefined;
221
+ layer.repeatX = json.repeatx ? Boolean(json.repeatx) : undefined;
222
+ layer.repeatY = json.repeaty ? Boolean(json.repeaty) : undefined;
223
+ }
224
+ // Group layer specific
225
+ if (json.type === 'group' && json.layers) {
226
+ layer.layers = json.layers.map((l) => this.normalizeJsonLayer(l));
227
+ }
228
+ return layer;
229
+ }
230
+ normalizeJsonObject(json) {
231
+ return {
232
+ id: Number(json.id) || 0,
233
+ name: String(json.name || ''),
234
+ type: String(json.type || json.class || ''),
235
+ x: Number(json.x) || 0,
236
+ y: Number(json.y) || 0,
237
+ width: Number(json.width) || 0,
238
+ height: Number(json.height) || 0,
239
+ rotation: Number(json.rotation) || 0,
240
+ visible: json.visible !== false,
241
+ gid: json.gid ? Number(json.gid) : undefined,
242
+ template: json.template ? String(json.template) : undefined,
243
+ point: json.point ? Boolean(json.point) : undefined,
244
+ ellipse: json.ellipse ? Boolean(json.ellipse) : undefined,
245
+ polygon: json.polygon,
246
+ polyline: json.polyline,
247
+ text: json.text,
248
+ properties: this.normalizeProperties(json.properties),
249
+ };
250
+ }
251
+ normalizeProperties(props) {
252
+ if (!props)
253
+ return undefined;
254
+ return props.map((p) => {
255
+ const prop = p;
256
+ return {
257
+ name: String(prop.name || ''),
258
+ type: prop.type || 'string',
259
+ value: prop.value,
260
+ propertyType: prop.propertytype ? String(prop.propertytype) : undefined,
261
+ };
262
+ });
263
+ }
264
+ parseXmlMap(content) {
265
+ try {
266
+ const xml = parseXML(content);
267
+ return this.normalizeXmlMap(xml);
268
+ }
269
+ catch (error) {
270
+ this.addError('XML_PARSE_ERROR', `Failed to parse XML: ${error}`);
271
+ return null;
272
+ }
273
+ }
274
+ normalizeXmlMap(xml) {
275
+ const map = {
276
+ version: xml.attributes.version || '1.0',
277
+ tiledVersion: xml.attributes.tiledversion || '',
278
+ orientation: xml.attributes.orientation || 'orthogonal',
279
+ renderOrder: xml.attributes.renderorder || 'right-down',
280
+ width: parseInt(xml.attributes.width || '0', 10),
281
+ height: parseInt(xml.attributes.height || '0', 10),
282
+ tileWidth: parseInt(xml.attributes.tilewidth || '0', 10),
283
+ tileHeight: parseInt(xml.attributes.tileheight || '0', 10),
284
+ infinite: xml.attributes.infinite === '1',
285
+ backgroundColor: xml.attributes.backgroundcolor,
286
+ nextLayerId: parseInt(xml.attributes.nextlayerid || '0', 10),
287
+ nextObjectId: parseInt(xml.attributes.nextobjectid || '0', 10),
288
+ tilesets: [],
289
+ layers: [],
290
+ properties: this.parseXmlProperties(xml.children.find((c) => c.name === 'properties')),
291
+ };
292
+ // Parse tilesets
293
+ for (const child of xml.children.filter((c) => c.name === 'tileset')) {
294
+ map.tilesets.push(this.normalizeXmlTileset(child));
295
+ }
296
+ // Parse layers
297
+ for (const child of xml.children) {
298
+ if (['layer', 'objectgroup', 'imagelayer', 'group'].includes(child.name)) {
299
+ map.layers.push(this.normalizeXmlLayer(child));
300
+ }
301
+ }
302
+ return map;
303
+ }
304
+ normalizeXmlTileset(xml) {
305
+ const tileset = {
306
+ firstGid: parseInt(xml.attributes.firstgid || '0', 10),
307
+ source: xml.attributes.source,
308
+ name: xml.attributes.name || '',
309
+ tileWidth: parseInt(xml.attributes.tilewidth || '0', 10),
310
+ tileHeight: parseInt(xml.attributes.tileheight || '0', 10),
311
+ spacing: parseInt(xml.attributes.spacing || '0', 10),
312
+ margin: parseInt(xml.attributes.margin || '0', 10),
313
+ tileCount: parseInt(xml.attributes.tilecount || '0', 10),
314
+ columns: parseInt(xml.attributes.columns || '0', 10),
315
+ properties: this.parseXmlProperties(xml.children.find((c) => c.name === 'properties')),
316
+ };
317
+ // Image
318
+ const image = xml.children.find((c) => c.name === 'image');
319
+ if (image) {
320
+ tileset.image = image.attributes.source;
321
+ tileset.imageWidth = parseInt(image.attributes.width || '0', 10);
322
+ tileset.imageHeight = parseInt(image.attributes.height || '0', 10);
323
+ tileset.transparentColor = image.attributes.trans;
324
+ }
325
+ // Tiles
326
+ const tiles = xml.children.filter((c) => c.name === 'tile');
327
+ if (tiles.length > 0) {
328
+ tileset.tiles = tiles.map((t) => this.normalizeXmlTile(t));
329
+ }
330
+ // Tile offset
331
+ const offset = xml.children.find((c) => c.name === 'tileoffset');
332
+ if (offset) {
333
+ tileset.tileOffset = {
334
+ x: parseInt(offset.attributes.x || '0', 10),
335
+ y: parseInt(offset.attributes.y || '0', 10),
336
+ };
337
+ }
338
+ return tileset;
339
+ }
340
+ normalizeXmlTile(xml) {
341
+ const tile = {
342
+ id: parseInt(xml.attributes.id || '0', 10),
343
+ type: xml.attributes.type,
344
+ properties: this.parseXmlProperties(xml.children.find((c) => c.name === 'properties')),
345
+ };
346
+ // Animation
347
+ const animation = xml.children.find((c) => c.name === 'animation');
348
+ if (animation) {
349
+ tile.animation = animation.children
350
+ .filter((c) => c.name === 'frame')
351
+ .map((f) => ({
352
+ tileId: parseInt(f.attributes.tileid || '0', 10),
353
+ duration: parseInt(f.attributes.duration || '0', 10),
354
+ }));
355
+ }
356
+ // Collision (objectgroup)
357
+ const objectGroup = xml.children.find((c) => c.name === 'objectgroup');
358
+ if (objectGroup) {
359
+ tile.objectGroup = {
360
+ drawOrder: objectGroup.attributes.draworder || 'index',
361
+ id: parseInt(objectGroup.attributes.id || '0', 10),
362
+ name: objectGroup.attributes.name || '',
363
+ objects: objectGroup.children
364
+ .filter((c) => c.name === 'object')
365
+ .map((o) => this.normalizeXmlObject(o)),
366
+ };
367
+ }
368
+ return tile;
369
+ }
370
+ normalizeXmlLayer(xml) {
371
+ const type = this.getLayerType(xml.name);
372
+ const layer = {
373
+ id: parseInt(xml.attributes.id || '0', 10),
374
+ name: xml.attributes.name || '',
375
+ type,
376
+ visible: xml.attributes.visible !== '0',
377
+ opacity: parseFloat(xml.attributes.opacity || '1'),
378
+ offsetX: parseFloat(xml.attributes.offsetx || '0'),
379
+ offsetY: parseFloat(xml.attributes.offsety || '0'),
380
+ parallaxX: parseFloat(xml.attributes.parallaxx || '1'),
381
+ parallaxY: parseFloat(xml.attributes.parallaxy || '1'),
382
+ tintColor: xml.attributes.tintcolor,
383
+ locked: xml.attributes.locked === '1',
384
+ class: xml.attributes.class,
385
+ properties: this.parseXmlProperties(xml.children.find((c) => c.name === 'properties')),
386
+ };
387
+ // Tile layer
388
+ if (type === 'tilelayer') {
389
+ layer.width = parseInt(xml.attributes.width || '0', 10);
390
+ layer.height = parseInt(xml.attributes.height || '0', 10);
391
+ const dataNode = xml.children.find((c) => c.name === 'data');
392
+ if (dataNode) {
393
+ layer.encoding = dataNode.attributes.encoding;
394
+ layer.compression = dataNode.attributes.compression;
395
+ if (layer.encoding === 'csv' || !layer.encoding) {
396
+ // CSV data
397
+ layer.data = dataNode.text.split(',').map((s) => parseInt(s.trim(), 10));
398
+ }
399
+ else if (layer.encoding === 'base64') {
400
+ // Base64 encoded - would need decompression for gzip/zlib
401
+ // For now, store as warning
402
+ this.addWarning('BASE64_DATA', 'Base64 encoded tile data requires decompression', xml.attributes.name);
403
+ }
404
+ // Chunks for infinite maps
405
+ const chunks = dataNode.children.filter((c) => c.name === 'chunk');
406
+ if (chunks.length > 0) {
407
+ layer.chunks = chunks.map((c) => ({
408
+ x: parseInt(c.attributes.x || '0', 10),
409
+ y: parseInt(c.attributes.y || '0', 10),
410
+ width: parseInt(c.attributes.width || '0', 10),
411
+ height: parseInt(c.attributes.height || '0', 10),
412
+ data: c.text.split(',').map((s) => parseInt(s.trim(), 10)),
413
+ }));
414
+ }
415
+ }
416
+ }
417
+ // Object layer
418
+ if (type === 'objectgroup') {
419
+ layer.objects = xml.children
420
+ .filter((c) => c.name === 'object')
421
+ .map((o) => this.normalizeXmlObject(o));
422
+ layer.drawOrder = xml.attributes.draworder || 'topdown';
423
+ layer.color = xml.attributes.color;
424
+ }
425
+ // Image layer
426
+ if (type === 'imagelayer') {
427
+ const image = xml.children.find((c) => c.name === 'image');
428
+ if (image) {
429
+ layer.image = image.attributes.source;
430
+ }
431
+ layer.repeatX = xml.attributes.repeatx === '1';
432
+ layer.repeatY = xml.attributes.repeaty === '1';
433
+ }
434
+ // Group layer
435
+ if (type === 'group') {
436
+ layer.layers = [];
437
+ for (const child of xml.children) {
438
+ if (['layer', 'objectgroup', 'imagelayer', 'group'].includes(child.name)) {
439
+ layer.layers.push(this.normalizeXmlLayer(child));
440
+ }
441
+ }
442
+ }
443
+ return layer;
444
+ }
445
+ normalizeXmlObject(xml) {
446
+ const obj = {
447
+ id: parseInt(xml.attributes.id || '0', 10),
448
+ name: xml.attributes.name || '',
449
+ type: xml.attributes.type || xml.attributes.class || '',
450
+ x: parseFloat(xml.attributes.x || '0'),
451
+ y: parseFloat(xml.attributes.y || '0'),
452
+ width: parseFloat(xml.attributes.width || '0'),
453
+ height: parseFloat(xml.attributes.height || '0'),
454
+ rotation: parseFloat(xml.attributes.rotation || '0'),
455
+ visible: xml.attributes.visible !== '0',
456
+ gid: xml.attributes.gid ? parseInt(xml.attributes.gid, 10) : undefined,
457
+ template: xml.attributes.template,
458
+ properties: this.parseXmlProperties(xml.children.find((c) => c.name === 'properties')),
459
+ };
460
+ // Point
461
+ if (xml.children.some((c) => c.name === 'point')) {
462
+ obj.point = true;
463
+ }
464
+ // Ellipse
465
+ if (xml.children.some((c) => c.name === 'ellipse')) {
466
+ obj.ellipse = true;
467
+ }
468
+ // Polygon
469
+ const polygon = xml.children.find((c) => c.name === 'polygon');
470
+ if (polygon && polygon.attributes.points) {
471
+ obj.polygon = this.parsePoints(polygon.attributes.points);
472
+ }
473
+ // Polyline
474
+ const polyline = xml.children.find((c) => c.name === 'polyline');
475
+ if (polyline && polyline.attributes.points) {
476
+ obj.polyline = this.parsePoints(polyline.attributes.points);
477
+ }
478
+ // Text
479
+ const text = xml.children.find((c) => c.name === 'text');
480
+ if (text) {
481
+ obj.text = {
482
+ text: text.text || '',
483
+ fontFamily: text.attributes.fontfamily || 'sans-serif',
484
+ pixelSize: parseInt(text.attributes.pixelsize || '16', 10),
485
+ wrap: text.attributes.wrap === '1',
486
+ color: text.attributes.color || '#000000',
487
+ bold: text.attributes.bold === '1',
488
+ italic: text.attributes.italic === '1',
489
+ underline: text.attributes.underline === '1',
490
+ strikeout: text.attributes.strikeout === '1',
491
+ kerning: text.attributes.kerning !== '0',
492
+ halign: text.attributes.halign || 'left',
493
+ valign: text.attributes.valign || 'top',
494
+ };
495
+ }
496
+ return obj;
497
+ }
498
+ parseXmlProperties(xml) {
499
+ if (!xml)
500
+ return undefined;
501
+ return xml.children
502
+ .filter((c) => c.name === 'property')
503
+ .map((p) => ({
504
+ name: p.attributes.name || '',
505
+ type: p.attributes.type || 'string',
506
+ value: this.parsePropertyValue(p.attributes.value || p.text, p.attributes.type),
507
+ propertyType: p.attributes.propertytype,
508
+ }));
509
+ }
510
+ parsePropertyValue(value, type) {
511
+ switch (type) {
512
+ case 'int':
513
+ return parseInt(value, 10);
514
+ case 'float':
515
+ return parseFloat(value);
516
+ case 'bool':
517
+ return value === 'true';
518
+ default:
519
+ return value;
520
+ }
521
+ }
522
+ parsePoints(pointsStr) {
523
+ return pointsStr.split(' ').map((p) => {
524
+ const [x, y] = p.split(',').map((v) => parseFloat(v));
525
+ return { x, y };
526
+ });
527
+ }
528
+ getLayerType(xmlName) {
529
+ switch (xmlName) {
530
+ case 'layer':
531
+ return 'tilelayer';
532
+ case 'objectgroup':
533
+ return 'objectgroup';
534
+ case 'imagelayer':
535
+ return 'imagelayer';
536
+ case 'group':
537
+ return 'group';
538
+ default:
539
+ return 'tilelayer';
540
+ }
541
+ }
542
+ async loadExternalTilesets(map, mapPath) {
543
+ const basePath = mapPath.substring(0, mapPath.lastIndexOf('/') + 1);
544
+ for (const tileset of map.tilesets) {
545
+ if (tileset.source) {
546
+ try {
547
+ const tilesetPath = basePath + tileset.source;
548
+ const content = await this.readFile(tilesetPath);
549
+ const isJson = tileset.source.endsWith('.tsj') || tileset.source.endsWith('.json');
550
+ let externalTileset;
551
+ if (isJson) {
552
+ const json = JSON.parse(content);
553
+ externalTileset = this.normalizeJsonTileset(json);
554
+ }
555
+ else {
556
+ const xml = parseXML(content);
557
+ const tilesetNode = xml.name === 'tileset' ? xml : xml.children.find((c) => c.name === 'tileset');
558
+ if (tilesetNode) {
559
+ externalTileset = this.normalizeXmlTileset(tilesetNode);
560
+ }
561
+ else {
562
+ continue;
563
+ }
564
+ }
565
+ // Merge external tileset data
566
+ Object.assign(tileset, externalTileset, { firstGid: tileset.firstGid });
567
+ }
568
+ catch (error) {
569
+ this.addWarning('TILESET_LOAD_ERROR', `Failed to load external tileset: ${tileset.source}`, tileset.source);
570
+ }
571
+ }
572
+ // Index tileset by first gid
573
+ this.tilesets.set(tileset.name, tileset);
574
+ this.tilesetsById.set(tileset.firstGid, tileset);
575
+ }
576
+ }
577
+ // ----------------------------------------
578
+ // Conversion
579
+ // ----------------------------------------
580
+ convertTiledMapToScene(map) {
581
+ const layers = [];
582
+ const entities = [];
583
+ let zIndex = 0;
584
+ this.processLayers(map.layers, layers, entities, zIndex);
585
+ return {
586
+ name: 'TiledMap',
587
+ width: map.width * map.tileWidth,
588
+ height: map.height * map.tileHeight,
589
+ backgroundColor: map.backgroundColor || '#000000',
590
+ layers,
591
+ entities,
592
+ properties: {
593
+ orientation: map.orientation,
594
+ renderOrder: map.renderOrder,
595
+ tileWidth: map.tileWidth,
596
+ tileHeight: map.tileHeight,
597
+ infinite: map.infinite,
598
+ ...this.convertProperties(map.properties),
599
+ },
600
+ };
601
+ }
602
+ processLayers(layers, outLayers, outEntities, zIndex) {
603
+ for (const layer of layers) {
604
+ if (layer.type === 'group' && layer.layers) {
605
+ zIndex = this.processLayers(layer.layers, outLayers, outEntities, zIndex);
606
+ }
607
+ else {
608
+ outLayers.push(this.convertLayer(layer, zIndex));
609
+ // Extract objects as entities
610
+ if (layer.type === 'objectgroup' && layer.objects) {
611
+ for (const obj of layer.objects) {
612
+ outEntities.push(this.convertObject(obj, layer.name, zIndex));
613
+ }
614
+ }
615
+ zIndex++;
616
+ }
617
+ }
618
+ return zIndex;
619
+ }
620
+ convertLayer(layer, zIndex) {
621
+ const parsedLayer = {
622
+ name: layer.name,
623
+ type: this.mapLayerType(layer.type),
624
+ visible: layer.visible,
625
+ opacity: layer.opacity,
626
+ offsetX: layer.offsetX,
627
+ offsetY: layer.offsetY,
628
+ parallaxX: layer.parallaxX,
629
+ parallaxY: layer.parallaxY,
630
+ zIndex,
631
+ properties: this.convertProperties(layer.properties),
632
+ };
633
+ // Tile data
634
+ if (layer.type === 'tilelayer' && layer.data) {
635
+ parsedLayer.data = {
636
+ width: layer.width || 0,
637
+ height: layer.height || 0,
638
+ tileWidth: 0, // Will be set from tileset
639
+ tileHeight: 0,
640
+ tiles: layer.data,
641
+ };
642
+ }
643
+ return parsedLayer;
644
+ }
645
+ mapLayerType(type) {
646
+ switch (type) {
647
+ case 'tilelayer':
648
+ return 'tile';
649
+ case 'objectgroup':
650
+ return 'object';
651
+ case 'imagelayer':
652
+ return 'image';
653
+ case 'group':
654
+ return 'group';
655
+ default:
656
+ return 'object';
657
+ }
658
+ }
659
+ convertObject(obj, layerName, zIndex) {
660
+ const components = [];
661
+ // Determine shape type
662
+ if (obj.polygon) {
663
+ components.push({
664
+ type: 'PolygonCollider',
665
+ data: {
666
+ points: obj.polygon,
667
+ isTrigger: false,
668
+ },
669
+ });
670
+ }
671
+ else if (obj.polyline) {
672
+ components.push({
673
+ type: 'EdgeCollider',
674
+ data: {
675
+ points: obj.polyline,
676
+ },
677
+ });
678
+ }
679
+ else if (obj.ellipse) {
680
+ components.push({
681
+ type: 'CircleCollider',
682
+ data: {
683
+ radius: Math.max(obj.width, obj.height) / 2,
684
+ isTrigger: false,
685
+ },
686
+ });
687
+ }
688
+ else if (obj.point) {
689
+ components.push({
690
+ type: 'Point',
691
+ data: {},
692
+ });
693
+ }
694
+ else if (obj.text) {
695
+ components.push({
696
+ type: 'Text',
697
+ data: {
698
+ text: obj.text.text,
699
+ fontFamily: obj.text.fontFamily,
700
+ fontSize: obj.text.pixelSize,
701
+ color: obj.text.color,
702
+ bold: obj.text.bold,
703
+ italic: obj.text.italic,
704
+ align: obj.text.halign,
705
+ valign: obj.text.valign,
706
+ wrap: obj.text.wrap,
707
+ },
708
+ });
709
+ }
710
+ else if (obj.gid) {
711
+ // Tile object
712
+ const tileset = this.findTilesetForGid(obj.gid);
713
+ if (tileset) {
714
+ const localId = obj.gid - tileset.firstGid;
715
+ components.push({
716
+ type: 'Sprite',
717
+ data: {
718
+ tileset: tileset.name,
719
+ tileId: localId,
720
+ width: obj.width,
721
+ height: obj.height,
722
+ },
723
+ });
724
+ }
725
+ }
726
+ else {
727
+ // Rectangle
728
+ components.push({
729
+ type: 'BoxCollider',
730
+ data: {
731
+ width: obj.width,
732
+ height: obj.height,
733
+ isTrigger: false,
734
+ },
735
+ });
736
+ }
737
+ return {
738
+ id: obj.id.toString(),
739
+ name: obj.name || `Object_${obj.id}`,
740
+ type: obj.type || 'TiledObject',
741
+ x: obj.x,
742
+ y: obj.y,
743
+ width: obj.width,
744
+ height: obj.height,
745
+ rotation: obj.rotation,
746
+ scaleX: 1,
747
+ scaleY: 1,
748
+ visible: obj.visible,
749
+ components,
750
+ children: [],
751
+ properties: {
752
+ layer: layerName,
753
+ zIndex,
754
+ ...this.convertProperties(obj.properties),
755
+ },
756
+ };
757
+ }
758
+ findTilesetForGid(gid) {
759
+ // Clear flip flags
760
+ const tileId = gid & 0x0fffffff;
761
+ let result = null;
762
+ let maxFirstGid = 0;
763
+ for (const [_, tileset] of this.tilesetsById) {
764
+ if (tileset.firstGid <= tileId && tileset.firstGid > maxFirstGid) {
765
+ maxFirstGid = tileset.firstGid;
766
+ result = tileset;
767
+ }
768
+ }
769
+ return result;
770
+ }
771
+ convertProperties(props) {
772
+ if (!props)
773
+ return {};
774
+ const result = {};
775
+ for (const prop of props) {
776
+ result[prop.name] = prop.value;
777
+ }
778
+ return result;
779
+ }
780
+ extractAssets(map) {
781
+ var _a;
782
+ const assets = [];
783
+ // Extract tileset images
784
+ for (const tileset of map.tilesets) {
785
+ if (tileset.image) {
786
+ assets.push({
787
+ id: this.generateId(),
788
+ name: tileset.name,
789
+ type: 'tileset',
790
+ path: tileset.image,
791
+ data: {
792
+ tileWidth: tileset.tileWidth,
793
+ tileHeight: tileset.tileHeight,
794
+ tileCount: tileset.tileCount,
795
+ columns: tileset.columns,
796
+ margin: tileset.margin,
797
+ spacing: tileset.spacing,
798
+ firstGid: tileset.firstGid,
799
+ tiles: (_a = tileset.tiles) === null || _a === void 0 ? void 0 : _a.map((t) => {
800
+ var _a;
801
+ return ({
802
+ id: t.id,
803
+ type: t.type,
804
+ animation: t.animation,
805
+ collision: (_a = t.objectGroup) === null || _a === void 0 ? void 0 : _a.objects,
806
+ });
807
+ }),
808
+ },
809
+ });
810
+ }
811
+ }
812
+ // Extract image layer images
813
+ for (const layer of this.flattenLayers(map.layers)) {
814
+ if (layer.type === 'imagelayer' && layer.image) {
815
+ assets.push({
816
+ id: this.generateId(),
817
+ name: layer.name + '_image',
818
+ type: 'texture',
819
+ path: layer.image,
820
+ data: {
821
+ repeatX: layer.repeatX,
822
+ repeatY: layer.repeatY,
823
+ },
824
+ });
825
+ }
826
+ }
827
+ return assets;
828
+ }
829
+ flattenLayers(layers) {
830
+ const result = [];
831
+ for (const layer of layers) {
832
+ result.push(layer);
833
+ if (layer.type === 'group' && layer.layers) {
834
+ result.push(...this.flattenLayers(layer.layers));
835
+ }
836
+ }
837
+ return result;
838
+ }
839
+ // ----------------------------------------
840
+ // Helper Methods
841
+ // ----------------------------------------
842
+ async readFile(path) {
843
+ var _a;
844
+ if (typeof globalThis.process !== 'undefined' && ((_a = globalThis.process.versions) === null || _a === void 0 ? void 0 : _a.node)) {
845
+ const fs = await import('fs');
846
+ return fs.readFileSync(path, 'utf-8');
847
+ }
848
+ else if (typeof fetch !== 'undefined') {
849
+ const response = await fetch(path);
850
+ return response.text();
851
+ }
852
+ throw new Error('Unable to read file in current environment');
853
+ }
854
+ }
855
+
856
+ export { TiledMapImporter };
857
+ //# sourceMappingURL=TiledMapImporter.js.map