@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,1193 @@
1
+ 'use strict';
2
+
3
+ var PlatformExporter = require('./PlatformExporter.js');
4
+ var CSharpExporter = require('../scripting/exporters/CSharpExporter.js');
5
+ var GraphToAST = require('../scripting/GraphToAST.js');
6
+
7
+ /* ────────────────────────────────────────────────────────────────
8
+ Unity Package Exporter
9
+
10
+ Exports Nice2Dev projects to Unity .unitypackage format.
11
+ Generates C# scripts, prefabs, scenes, and materials.
12
+ ──────────────────────────────────────────────────────────────── */
13
+ /* ── Unity Exporter Class ─────────────────────────────────────── */
14
+ class UnityExporter extends PlatformExporter.PlatformExporter {
15
+ constructor() {
16
+ super(...arguments);
17
+ this.platformId = 'unity';
18
+ this.platformInfo = {
19
+ id: 'unity',
20
+ name: 'Unity',
21
+ description: 'Professional game engine for 2D and 3D games',
22
+ website: 'https://unity.com',
23
+ features: [
24
+ '2d-rendering',
25
+ '3d-rendering',
26
+ 'physics-2d',
27
+ 'physics-3d',
28
+ 'audio',
29
+ 'networking',
30
+ 'ui-system',
31
+ 'visual-scripting',
32
+ 'particles',
33
+ 'animation',
34
+ 'vr-ar',
35
+ ],
36
+ supportedAssets: [
37
+ 'sprite',
38
+ 'tileset',
39
+ 'audio',
40
+ 'font',
41
+ 'script',
42
+ 'scene',
43
+ 'prefab',
44
+ 'material',
45
+ 'shader',
46
+ 'animation',
47
+ 'particleSystem',
48
+ ],
49
+ exportFormats: ['.unitypackage', '.prefab', '.unity', '.cs'],
50
+ };
51
+ this.csharpExporter = new CSharpExporter.CSharpExporter();
52
+ this.graphToAST = new GraphToAST.GraphToAST();
53
+ this.guidMap = new Map();
54
+ this.fileIdCounter = 100000;
55
+ }
56
+ async doExport(project, options) {
57
+ const unity = options.platformOptions;
58
+ const projectName = options.projectName || project.name;
59
+ const ns = (unity === null || unity === void 0 ? void 0 : unity.namespace) || this.toValidNamespace(projectName);
60
+ // Generate GUIDs for all assets
61
+ this.generateGuids(project);
62
+ // 1. Generate project structure
63
+ await this.exportProjectSettings(project, options, unity);
64
+ // 2. Export scripts
65
+ await this.exportScripts(project, options, ns);
66
+ // 3. Export prefabs
67
+ await this.exportPrefabs(project, options);
68
+ // 4. Export scenes
69
+ await this.exportScenes(project, options);
70
+ // 5. Export materials
71
+ await this.exportMaterials(project, options, unity);
72
+ // 6. Export assets (sprites, audio, etc.)
73
+ await this.exportAssets(project, options);
74
+ // 7. Generate assembly definition
75
+ if ((unity === null || unity === void 0 ? void 0 : unity.generateAsmdef) !== false) {
76
+ this.exportAssemblyDefinition(projectName, ns);
77
+ }
78
+ // 8. Generate Nice2Dev runtime bridge
79
+ if ((unity === null || unity === void 0 ? void 0 : unity.includeRuntime) !== false) {
80
+ this.exportRuntimeBridge(ns);
81
+ }
82
+ // 9. Generate manifest for .unitypackage
83
+ this.exportPackageManifest(project);
84
+ }
85
+ /* ── Project Settings ───────────────────────────────────────── */
86
+ async exportProjectSettings(project, options, unity) {
87
+ var _a;
88
+ // ProjectSettings.asset
89
+ const settings = `%YAML 1.1
90
+ %TAG !u! tag:unity3d.com,2011:
91
+ --- !u!129 &1
92
+ PlayerSettings:
93
+ productName: ${project.name}
94
+ companyName: ${project.author || 'Nice2Dev'}
95
+ defaultScreenWidth: ${project.settings.resolution.width}
96
+ defaultScreenHeight: ${project.settings.resolution.height}
97
+ runInBackground: 1
98
+ colorSpace: 1
99
+ activeInputHandler: 2
100
+ targetGpuSkinning: 1`;
101
+ this.addTextFile(`ProjectSettings/ProjectSettings.asset`, settings);
102
+ this.addTextFile(`ProjectSettings/ProjectSettings.asset.meta`, this.createMetaFile('project-settings'));
103
+ // Physics2DSettings.asset
104
+ if ((_a = project.settings.physics) === null || _a === void 0 ? void 0 : _a.enabled) {
105
+ const gravity = project.settings.physics.gravity;
106
+ const physics2d = `%YAML 1.1
107
+ %TAG !u! tag:unity3d.com,2011:
108
+ --- !u!19 &1
109
+ Physics2DSettings:
110
+ m_Gravity: {x: ${gravity.x}, y: ${gravity.y}}
111
+ m_DefaultMaterial: {fileID: 0}
112
+ m_VelocityIterations: 8
113
+ m_PositionIterations: 3`;
114
+ this.addTextFile(`ProjectSettings/Physics2DSettings.asset`, physics2d);
115
+ }
116
+ }
117
+ /* ── Scripts ────────────────────────────────────────────────── */
118
+ async exportScripts(project, options, namespace) {
119
+ for (const script of project.scripts) {
120
+ try {
121
+ const ast = this.graphToAST.convert(script);
122
+ const result = this.csharpExporter.export(ast, {
123
+ namespace,
124
+ includeDebugComments: options.debug,
125
+ });
126
+ for (const file of result.files) {
127
+ const path = `Assets/Scripts/${file.path}`;
128
+ this.addTextFile(path, file.content);
129
+ this.addTextFile(`${path}.meta`, this.createScriptMetaFile(script.id));
130
+ }
131
+ }
132
+ catch (error) {
133
+ this.addWarning('SCRIPT_EXPORT_ERROR', `Failed to export script "${script.name}": ${error}`, 'Check visual script for errors');
134
+ }
135
+ }
136
+ }
137
+ /* ── Prefabs ────────────────────────────────────────────────── */
138
+ async exportPrefabs(project, options) {
139
+ for (const prefab of project.prefabs) {
140
+ const yaml = this.createPrefabYAML(prefab, project);
141
+ const path = `Assets/Prefabs/${this.sanitizeFileName(prefab.name)}.prefab`;
142
+ this.addTextFile(path, yaml);
143
+ this.addTextFile(`${path}.meta`, this.createMetaFile(prefab.id));
144
+ }
145
+ }
146
+ createPrefabYAML(prefab, project) {
147
+ var _a, _b, _c, _d, _e, _f, _g, _h;
148
+ const objects = [];
149
+ const rootId = this.nextFileId();
150
+ const transformId = this.nextFileId();
151
+ const gameObjectId = this.nextFileId();
152
+ // PrefabInstance header
153
+ objects.push({
154
+ fileID: rootId,
155
+ classID: 1001, // PrefabInstance
156
+ type: 'PrefabInstance',
157
+ properties: {
158
+ m_ObjectHideFlags: 0,
159
+ m_CorrespondingSourceObject: { fileID: 0 },
160
+ m_PrefabInstance: { fileID: 0 },
161
+ m_PrefabAsset: { fileID: 0 },
162
+ },
163
+ });
164
+ // Root GameObject
165
+ objects.push({
166
+ fileID: gameObjectId,
167
+ classID: 1, // GameObject
168
+ type: 'GameObject',
169
+ properties: {
170
+ m_ObjectHideFlags: 0,
171
+ m_Name: prefab.name,
172
+ m_IsActive: 1,
173
+ m_Layer: 0,
174
+ m_Tag: 'Untagged',
175
+ },
176
+ });
177
+ // Transform component
178
+ objects.push({
179
+ fileID: transformId,
180
+ classID: 4, // Transform
181
+ type: 'Transform',
182
+ properties: {
183
+ m_LocalRotation: { x: 0, y: 0, z: 0, w: 1 },
184
+ m_LocalPosition: {
185
+ x: (_b = (_a = prefab.entity.position) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0,
186
+ y: (_d = (_c = prefab.entity.position) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 0,
187
+ z: 0,
188
+ },
189
+ m_LocalScale: { x: (_f = (_e = prefab.entity.scale) === null || _e === void 0 ? void 0 : _e.x) !== null && _f !== void 0 ? _f : 1, y: (_h = (_g = prefab.entity.scale) === null || _g === void 0 ? void 0 : _g.y) !== null && _h !== void 0 ? _h : 1, z: 1 },
190
+ m_Children: [],
191
+ m_Father: { fileID: 0 },
192
+ m_RootOrder: 0,
193
+ },
194
+ });
195
+ // Add components based on entity type
196
+ this.addEntityComponents(prefab.entity, objects, gameObjectId, project);
197
+ return this.serializeUnityYAML({ objects });
198
+ }
199
+ /* ── Scenes ─────────────────────────────────────────────────── */
200
+ async exportScenes(project, options) {
201
+ for (const scene of project.scenes) {
202
+ const yaml = this.createSceneYAML(scene, project);
203
+ const path = `Assets/Scenes/${this.sanitizeFileName(scene.name)}.unity`;
204
+ this.addTextFile(path, yaml);
205
+ this.addTextFile(`${path}.meta`, this.createMetaFile(scene.id));
206
+ }
207
+ }
208
+ createSceneYAML(scene, project) {
209
+ var _a;
210
+ const objects = [];
211
+ // Scene settings (OcclusionCullingSettings, RenderSettings, etc.)
212
+ this.addSceneSettings(objects, project);
213
+ // Create hierarchy of GameObjects
214
+ for (const entity of scene.entities) {
215
+ this.createGameObjectHierarchy(entity, objects, project, null);
216
+ }
217
+ // Handle tilemaps
218
+ for (const tilemap of (_a = scene.tilemaps) !== null && _a !== void 0 ? _a : []) {
219
+ this.createTilemapGameObject(tilemap, objects, project);
220
+ }
221
+ return this.serializeUnityYAML({ objects });
222
+ }
223
+ addSceneSettings(objects, project) {
224
+ // OcclusionCullingSettings
225
+ objects.push({
226
+ fileID: 1,
227
+ classID: 29,
228
+ type: 'OcclusionCullingSettings',
229
+ properties: {},
230
+ });
231
+ // RenderSettings
232
+ const bgColor = this.parseColor(project.settings.backgroundColor);
233
+ objects.push({
234
+ fileID: 2,
235
+ classID: 104,
236
+ type: 'RenderSettings',
237
+ properties: {
238
+ m_AmbientSkyColor: bgColor,
239
+ m_AmbientEquatorColor: bgColor,
240
+ m_AmbientGroundColor: bgColor,
241
+ },
242
+ });
243
+ // LightmapSettings
244
+ objects.push({
245
+ fileID: 3,
246
+ classID: 157,
247
+ type: 'LightmapSettings',
248
+ properties: {},
249
+ });
250
+ // NavMeshSettings
251
+ objects.push({
252
+ fileID: 4,
253
+ classID: 196,
254
+ type: 'NavMeshSettings',
255
+ properties: {},
256
+ });
257
+ }
258
+ createGameObjectHierarchy(entity, objects, project, parentTransformId) {
259
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
260
+ const gameObjectId = this.nextFileId();
261
+ const transformId = this.nextFileId();
262
+ // GameObject
263
+ objects.push({
264
+ fileID: gameObjectId,
265
+ classID: 1,
266
+ type: 'GameObject',
267
+ properties: {
268
+ m_ObjectHideFlags: 0,
269
+ m_Name: entity.name,
270
+ m_IsActive: 1,
271
+ m_Layer: 0,
272
+ m_Tag: 'Untagged',
273
+ },
274
+ });
275
+ // Process children for transform hierarchy
276
+ const childTransformIds = [];
277
+ if (entity.children) {
278
+ for (const child of entity.children) {
279
+ const childTransformId = this.createGameObjectHierarchy(child, objects, project, transformId);
280
+ childTransformIds.push(childTransformId);
281
+ }
282
+ }
283
+ // Transform component
284
+ const isRectTransform = entity.components.some((c) => c.type === 'ui-text' || c.type === 'ui-button' || c.type === 'ui-image');
285
+ objects.push({
286
+ fileID: transformId,
287
+ classID: isRectTransform ? 224 : 4, // RectTransform or Transform
288
+ type: isRectTransform ? 'RectTransform' : 'Transform',
289
+ properties: {
290
+ m_GameObject: { fileID: gameObjectId },
291
+ m_LocalRotation: {
292
+ x: 0,
293
+ y: 0,
294
+ z: Math.sin(((_a = entity.rotation) !== null && _a !== void 0 ? _a : 0) / 2),
295
+ w: Math.cos(((_b = entity.rotation) !== null && _b !== void 0 ? _b : 0) / 2),
296
+ },
297
+ m_LocalPosition: { x: (_d = (_c = entity.position) === null || _c === void 0 ? void 0 : _c.x) !== null && _d !== void 0 ? _d : 0, y: (_f = (_e = entity.position) === null || _e === void 0 ? void 0 : _e.y) !== null && _f !== void 0 ? _f : 0, z: 0 },
298
+ m_LocalScale: { x: (_h = (_g = entity.scale) === null || _g === void 0 ? void 0 : _g.x) !== null && _h !== void 0 ? _h : 1, y: (_k = (_j = entity.scale) === null || _j === void 0 ? void 0 : _j.y) !== null && _k !== void 0 ? _k : 1, z: 1 },
299
+ m_Children: childTransformIds.map((id) => ({ fileID: id })),
300
+ m_Father: parentTransformId ? { fileID: parentTransformId } : { fileID: 0 },
301
+ m_RootOrder: 0,
302
+ },
303
+ });
304
+ // Add other components
305
+ this.addEntityComponents(entity, objects, gameObjectId, project);
306
+ return transformId;
307
+ }
308
+ addEntityComponents(entity, objects, gameObjectId, project) {
309
+ var _a;
310
+ for (const component of entity.components) {
311
+ const props = (_a = component.properties) !== null && _a !== void 0 ? _a : {};
312
+ switch (component.type) {
313
+ case 'sprite':
314
+ this.addSpriteRenderer(objects, gameObjectId, props);
315
+ break;
316
+ case 'rigidbody-2d':
317
+ this.addRigidbody2D(objects, gameObjectId, props);
318
+ break;
319
+ case 'box-collider-2d':
320
+ this.addBoxCollider2D(objects, gameObjectId, props);
321
+ break;
322
+ case 'circle-collider-2d':
323
+ this.addCircleCollider2D(objects, gameObjectId, props);
324
+ break;
325
+ case 'audio-source':
326
+ this.addAudioSource(objects, gameObjectId, props);
327
+ break;
328
+ case 'animator':
329
+ this.addAnimator(objects, gameObjectId, props);
330
+ break;
331
+ case 'ui-text':
332
+ this.addUIText(objects, gameObjectId, props);
333
+ break;
334
+ case 'ui-image':
335
+ this.addUIImage(objects, gameObjectId, props);
336
+ break;
337
+ case 'ui-button':
338
+ this.addUIButton(objects, gameObjectId, props);
339
+ break;
340
+ case 'particle-system':
341
+ this.addParticleSystem(objects, gameObjectId, props);
342
+ break;
343
+ default:
344
+ this.addWarning('UNKNOWN_COMPONENT', `Unknown component type "${component.type}" on entity "${entity.name}"`, 'Component will be skipped');
345
+ }
346
+ }
347
+ // Add script component if entity has one
348
+ if (entity.scriptId) {
349
+ this.addScriptComponent(objects, gameObjectId, entity.scriptId);
350
+ }
351
+ }
352
+ /* ── Component Generators ───────────────────────────────────── */
353
+ addSpriteRenderer(objects, gameObjectId, props) {
354
+ var _a, _b;
355
+ const componentId = this.nextFileId();
356
+ const spriteId = props.spriteId;
357
+ objects.push({
358
+ fileID: componentId,
359
+ classID: 212, // SpriteRenderer
360
+ type: 'SpriteRenderer',
361
+ properties: {
362
+ m_GameObject: { fileID: gameObjectId },
363
+ m_Enabled: 1,
364
+ m_Sprite: spriteId
365
+ ? { fileID: 21300000, guid: this.guidMap.get(spriteId) || '', type: 3 }
366
+ : { fileID: 0 },
367
+ m_Color: this.parseColor((_a = props.color) !== null && _a !== void 0 ? _a : '#ffffff'),
368
+ m_FlipX: props.flipX ? 1 : 0,
369
+ m_FlipY: props.flipY ? 1 : 0,
370
+ m_SortingLayerID: 0,
371
+ m_SortingOrder: (_b = props.sortingOrder) !== null && _b !== void 0 ? _b : 0,
372
+ },
373
+ });
374
+ }
375
+ addRigidbody2D(objects, gameObjectId, props) {
376
+ var _a, _b, _c, _d;
377
+ const componentId = this.nextFileId();
378
+ objects.push({
379
+ fileID: componentId,
380
+ classID: 50, // Rigidbody2D
381
+ type: 'Rigidbody2D',
382
+ properties: {
383
+ m_GameObject: { fileID: gameObjectId },
384
+ m_BodyType: props.type === 'static' ? 2 : props.type === 'kinematic' ? 1 : 0,
385
+ m_Mass: (_a = props.mass) !== null && _a !== void 0 ? _a : 1,
386
+ m_LinearDrag: (_b = props.linearDrag) !== null && _b !== void 0 ? _b : 0,
387
+ m_AngularDrag: (_c = props.angularDrag) !== null && _c !== void 0 ? _c : 0.05,
388
+ m_GravityScale: (_d = props.gravityScale) !== null && _d !== void 0 ? _d : 1,
389
+ m_FreezeRotation: props.freezeRotation ? 1 : 0,
390
+ m_Interpolate: 0,
391
+ m_SleepingMode: 1,
392
+ m_CollisionDetection: 0,
393
+ },
394
+ });
395
+ }
396
+ addBoxCollider2D(objects, gameObjectId, props) {
397
+ var _a, _b, _c, _d;
398
+ const componentId = this.nextFileId();
399
+ objects.push({
400
+ fileID: componentId,
401
+ classID: 61, // BoxCollider2D
402
+ type: 'BoxCollider2D',
403
+ properties: {
404
+ m_GameObject: { fileID: gameObjectId },
405
+ m_IsTrigger: props.isTrigger ? 1 : 0,
406
+ m_Size: { x: (_a = props.width) !== null && _a !== void 0 ? _a : 1, y: (_b = props.height) !== null && _b !== void 0 ? _b : 1 },
407
+ m_Offset: { x: (_c = props.offsetX) !== null && _c !== void 0 ? _c : 0, y: (_d = props.offsetY) !== null && _d !== void 0 ? _d : 0 },
408
+ },
409
+ });
410
+ }
411
+ addCircleCollider2D(objects, gameObjectId, props) {
412
+ var _a, _b, _c;
413
+ const componentId = this.nextFileId();
414
+ objects.push({
415
+ fileID: componentId,
416
+ classID: 58, // CircleCollider2D
417
+ type: 'CircleCollider2D',
418
+ properties: {
419
+ m_GameObject: { fileID: gameObjectId },
420
+ m_IsTrigger: props.isTrigger ? 1 : 0,
421
+ m_Radius: (_a = props.radius) !== null && _a !== void 0 ? _a : 0.5,
422
+ m_Offset: { x: (_b = props.offsetX) !== null && _b !== void 0 ? _b : 0, y: (_c = props.offsetY) !== null && _c !== void 0 ? _c : 0 },
423
+ },
424
+ });
425
+ }
426
+ addAudioSource(objects, gameObjectId, props) {
427
+ var _a, _b, _c;
428
+ const componentId = this.nextFileId();
429
+ const audioClipId = props.clipId;
430
+ objects.push({
431
+ fileID: componentId,
432
+ classID: 82, // AudioSource
433
+ type: 'AudioSource',
434
+ properties: {
435
+ m_GameObject: { fileID: gameObjectId },
436
+ m_Enabled: 1,
437
+ m_AudioClip: audioClipId
438
+ ? { fileID: 8300000, guid: this.guidMap.get(audioClipId) || '', type: 3 }
439
+ : { fileID: 0 },
440
+ m_PlayOnAwake: props.playOnAwake ? 1 : 0,
441
+ m_Loop: props.loop ? 1 : 0,
442
+ m_Volume: (_a = props.volume) !== null && _a !== void 0 ? _a : 1,
443
+ m_Pitch: (_b = props.pitch) !== null && _b !== void 0 ? _b : 1,
444
+ m_SpatialBlend: (_c = props.spatialBlend) !== null && _c !== void 0 ? _c : 0,
445
+ },
446
+ });
447
+ }
448
+ addAnimator(objects, gameObjectId, props) {
449
+ var _a;
450
+ const componentId = this.nextFileId();
451
+ const controllerId = props.controllerId;
452
+ objects.push({
453
+ fileID: componentId,
454
+ classID: 95, // Animator
455
+ type: 'Animator',
456
+ properties: {
457
+ m_GameObject: { fileID: gameObjectId },
458
+ m_Enabled: 1,
459
+ m_Controller: controllerId
460
+ ? { fileID: 9100000, guid: this.guidMap.get(controllerId) || '', type: 2 }
461
+ : { fileID: 0 },
462
+ m_ApplyRootMotion: props.applyRootMotion ? 1 : 0,
463
+ m_UpdateMode: 0,
464
+ m_CullingMode: (_a = props.cullingMode) !== null && _a !== void 0 ? _a : 0,
465
+ },
466
+ });
467
+ }
468
+ addUIText(objects, gameObjectId, props) {
469
+ var _a, _b, _c;
470
+ const componentId = this.nextFileId();
471
+ // Using TextMeshProUGUI instead of legacy Text
472
+ objects.push({
473
+ fileID: componentId,
474
+ classID: 114, // MonoBehaviour (TextMeshProUGUI)
475
+ type: 'MonoBehaviour',
476
+ properties: {
477
+ m_GameObject: { fileID: gameObjectId },
478
+ m_Enabled: 1,
479
+ m_Script: { fileID: 11500000, guid: 'f4688fdb7df04437aeb418b961361dc5', type: 3 }, // TMP_Text
480
+ m_Text: (_a = props.text) !== null && _a !== void 0 ? _a : '',
481
+ m_FontSize: (_b = props.fontSize) !== null && _b !== void 0 ? _b : 24,
482
+ m_FontColor: this.parseColor((_c = props.color) !== null && _c !== void 0 ? _c : '#ffffff'),
483
+ m_TextAlignment: this.getTextAlignment(props.alignment),
484
+ },
485
+ });
486
+ }
487
+ addUIImage(objects, gameObjectId, props) {
488
+ var _a, _b;
489
+ const componentId = this.nextFileId();
490
+ const spriteId = props.spriteId;
491
+ objects.push({
492
+ fileID: componentId,
493
+ classID: 114, // Image
494
+ type: 'Image',
495
+ properties: {
496
+ m_GameObject: { fileID: gameObjectId },
497
+ m_Enabled: 1,
498
+ m_Sprite: spriteId
499
+ ? { fileID: 21300000, guid: this.guidMap.get(spriteId) || '', type: 3 }
500
+ : { fileID: 0 },
501
+ m_Color: this.parseColor((_a = props.color) !== null && _a !== void 0 ? _a : '#ffffff'),
502
+ m_RaycastTarget: props.raycastTarget !== false ? 1 : 0,
503
+ m_Type: (_b = props.imageType) !== null && _b !== void 0 ? _b : 0, // Simple
504
+ m_FillCenter: 1,
505
+ m_PreserveAspect: props.preserveAspect ? 1 : 0,
506
+ },
507
+ });
508
+ }
509
+ addUIButton(objects, gameObjectId, props) {
510
+ const componentId = this.nextFileId();
511
+ objects.push({
512
+ fileID: componentId,
513
+ classID: 114, // Button
514
+ type: 'Button',
515
+ properties: {
516
+ m_GameObject: { fileID: gameObjectId },
517
+ m_Enabled: 1,
518
+ m_Interactable: props.interactable !== false ? 1 : 0,
519
+ m_TargetGraphic: { fileID: 0 },
520
+ m_OnClick: { m_PersistentCalls: { m_Calls: [] } },
521
+ },
522
+ });
523
+ }
524
+ addParticleSystem(objects, gameObjectId, props) {
525
+ var _a, _b, _c, _d, _e, _f;
526
+ const componentId = this.nextFileId();
527
+ objects.push({
528
+ fileID: componentId,
529
+ classID: 198, // ParticleSystem
530
+ type: 'ParticleSystem',
531
+ properties: {
532
+ m_GameObject: { fileID: gameObjectId },
533
+ m_Duration: (_a = props.duration) !== null && _a !== void 0 ? _a : 5,
534
+ m_Looping: props.looping ? 1 : 0,
535
+ m_Prewarm: props.prewarm ? 1 : 0,
536
+ m_StartDelay: { value: (_b = props.startDelay) !== null && _b !== void 0 ? _b : 0 },
537
+ m_PlayOnAwake: props.playOnAwake !== false ? 1 : 0,
538
+ m_StartSpeed: { value: (_c = props.startSpeed) !== null && _c !== void 0 ? _c : 5 },
539
+ m_StartSize: { value: (_d = props.startSize) !== null && _d !== void 0 ? _d : 1 },
540
+ m_StartColor: this.parseColor((_e = props.startColor) !== null && _e !== void 0 ? _e : '#ffffff'),
541
+ m_MaxParticles: (_f = props.maxParticles) !== null && _f !== void 0 ? _f : 1000,
542
+ },
543
+ });
544
+ }
545
+ addScriptComponent(objects, gameObjectId, scriptId) {
546
+ const componentId = this.nextFileId();
547
+ const scriptGuid = this.guidMap.get(scriptId);
548
+ if (!scriptGuid) {
549
+ this.addWarning('SCRIPT_NOT_FOUND', `Script "${scriptId}" not found for entity`);
550
+ return;
551
+ }
552
+ objects.push({
553
+ fileID: componentId,
554
+ classID: 114, // MonoBehaviour
555
+ type: 'MonoBehaviour',
556
+ properties: {
557
+ m_GameObject: { fileID: gameObjectId },
558
+ m_Enabled: 1,
559
+ m_Script: { fileID: 11500000, guid: scriptGuid, type: 3 },
560
+ },
561
+ });
562
+ }
563
+ /* ── Tilemaps ───────────────────────────────────────────────── */
564
+ createTilemapGameObject(tilemap, objects, project) {
565
+ const gameObjectId = this.nextFileId();
566
+ const transformId = this.nextFileId();
567
+ const gridId = this.nextFileId();
568
+ // Grid GameObject (parent)
569
+ objects.push({
570
+ fileID: gameObjectId,
571
+ classID: 1,
572
+ type: 'GameObject',
573
+ properties: {
574
+ m_ObjectHideFlags: 0,
575
+ m_Name: tilemap.name,
576
+ m_IsActive: 1,
577
+ m_Layer: 0,
578
+ m_Tag: 'Untagged',
579
+ },
580
+ });
581
+ // Grid component
582
+ objects.push({
583
+ fileID: gridId,
584
+ classID: 156, // Grid
585
+ type: 'Grid',
586
+ properties: {
587
+ m_GameObject: { fileID: gameObjectId },
588
+ m_CellSize: { x: tilemap.tileSize, y: tilemap.tileSize, z: 0 },
589
+ m_CellGap: { x: 0, y: 0, z: 0 },
590
+ m_CellLayout: 0, // Rectangle
591
+ m_CellSwizzle: 0, // XYZ
592
+ },
593
+ });
594
+ // Transform for grid
595
+ objects.push({
596
+ fileID: transformId,
597
+ classID: 4,
598
+ type: 'Transform',
599
+ properties: {
600
+ m_GameObject: { fileID: gameObjectId },
601
+ m_LocalRotation: { x: 0, y: 0, z: 0, w: 1 },
602
+ m_LocalPosition: { x: 0, y: 0, z: 0 },
603
+ m_LocalScale: { x: 1, y: 1, z: 1 },
604
+ m_Children: [],
605
+ m_Father: { fileID: 0 },
606
+ m_RootOrder: 0,
607
+ },
608
+ });
609
+ // Create Tilemap layer objects
610
+ for (let i = 0; i < tilemap.layers.length; i++) {
611
+ this.createTilemapLayer(tilemap.layers[i], tilemap, objects, transformId, project);
612
+ }
613
+ }
614
+ createTilemapLayer(layer, tilemap, objects, parentTransformId, project) {
615
+ const gameObjectId = this.nextFileId();
616
+ const transformId = this.nextFileId();
617
+ const tilemapId = this.nextFileId();
618
+ const rendererId = this.nextFileId();
619
+ // Layer GameObject
620
+ objects.push({
621
+ fileID: gameObjectId,
622
+ classID: 1,
623
+ type: 'GameObject',
624
+ properties: {
625
+ m_Name: layer.name,
626
+ m_IsActive: layer.visible ? 1 : 0,
627
+ },
628
+ });
629
+ // Transform
630
+ objects.push({
631
+ fileID: transformId,
632
+ classID: 4,
633
+ type: 'Transform',
634
+ properties: {
635
+ m_GameObject: { fileID: gameObjectId },
636
+ m_Father: { fileID: parentTransformId },
637
+ },
638
+ });
639
+ // Tilemap component
640
+ objects.push({
641
+ fileID: tilemapId,
642
+ classID: 156, // Tilemap
643
+ type: 'Tilemap',
644
+ properties: {
645
+ m_GameObject: { fileID: gameObjectId },
646
+ m_Size: { x: tilemap.width, y: tilemap.height, z: 1 },
647
+ m_TileAssets: [], // Would reference TileBase assets
648
+ m_TileMatrixArray: [],
649
+ m_TileColorArray: [],
650
+ },
651
+ });
652
+ // TilemapRenderer
653
+ objects.push({
654
+ fileID: rendererId,
655
+ classID: 156, // TilemapRenderer
656
+ type: 'TilemapRenderer',
657
+ properties: {
658
+ m_GameObject: { fileID: gameObjectId },
659
+ m_Enabled: 1,
660
+ m_SortingLayerID: 0,
661
+ m_SortingOrder: 0,
662
+ m_ChunkSize: { x: 32, y: 32, z: 1 },
663
+ },
664
+ });
665
+ }
666
+ /* ── Materials ──────────────────────────────────────────────── */
667
+ async exportMaterials(project, options, unity) {
668
+ const materials = project.assets.filter((a) => a.type === 'material');
669
+ for (const material of materials) {
670
+ const matYaml = this.createMaterialYAML(material, unity === null || unity === void 0 ? void 0 : unity.useURP);
671
+ const path = `Assets/Materials/${this.sanitizeFileName(material.name)}.mat`;
672
+ this.addTextFile(path, matYaml);
673
+ this.addTextFile(`${path}.meta`, this.createMetaFile(material.id));
674
+ }
675
+ }
676
+ createMaterialYAML(material, useURP) {
677
+ var _a, _b;
678
+ const shaderGuid = useURP
679
+ ? '933532a4fcc9baf4fa0491de14d08ed7' // Universal Render Pipeline/Lit
680
+ : '0000000000000000f000000000000000'; // Standard
681
+ const color = (_b = (_a = material.metadata) === null || _a === void 0 ? void 0 : _a.color) !== null && _b !== void 0 ? _b : '#ffffff';
682
+ const rgba = this.parseColor(color);
683
+ return `%YAML 1.1
684
+ %TAG !u! tag:unity3d.com,2011:
685
+ --- !u!21 &2100000
686
+ Material:
687
+ serializedVersion: 8
688
+ m_ObjectHideFlags: 0
689
+ m_CorrespondingSourceObject: {fileID: 0}
690
+ m_PrefabInstance: {fileID: 0}
691
+ m_PrefabAsset: {fileID: 0}
692
+ m_Name: ${material.name}
693
+ m_Shader: {fileID: 46, guid: ${shaderGuid}, type: 2}
694
+ m_Parent: {fileID: 0}
695
+ m_Color: ${JSON.stringify(rgba)}`;
696
+ }
697
+ /* ── Assets ─────────────────────────────────────────────────── */
698
+ async exportAssets(project, options) {
699
+ for (const asset of project.assets) {
700
+ switch (asset.type) {
701
+ case 'sprite':
702
+ this.exportSpriteAsset(asset);
703
+ break;
704
+ case 'audio':
705
+ this.exportAudioAsset(asset);
706
+ break;
707
+ case 'font':
708
+ this.exportFontAsset(asset);
709
+ break;
710
+ case 'tileset':
711
+ this.exportTilesetAsset(asset);
712
+ break;
713
+ case 'animation':
714
+ this.exportAnimationAsset(asset);
715
+ break;
716
+ }
717
+ }
718
+ }
719
+ exportSpriteAsset(asset) {
720
+ // Create .meta file for sprite import settings
721
+ const meta = `fileFormatVersion: 2
722
+ guid: ${this.guidMap.get(asset.id)}
723
+ TextureImporter:
724
+ internalIDToNameTable: []
725
+ externalObjects: {}
726
+ serializedVersion: 12
727
+ mipmaps:
728
+ mipMapMode: 0
729
+ enableMipMap: 0
730
+ bumpmap:
731
+ convertToNormalMap: 0
732
+ isReadable: 0
733
+ streamingMipmaps: 0
734
+ spriteMode: 1
735
+ spriteExtrude: 1
736
+ spriteMeshType: 1
737
+ alignment: 0
738
+ spritePivot: {x: 0.5, y: 0.5}
739
+ spritePixelsToUnits: 100
740
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
741
+ spriteGenerateFallbackPhysicsShape: 1
742
+ alphaUsage: 1
743
+ alphaIsTransparency: 1
744
+ spriteTessellationDetail: -1
745
+ textureType: 8
746
+ textureShape: 1
747
+ filterMode: 0
748
+ maxTextureSize: 2048
749
+ textureCompression: 1`;
750
+ const path = `Assets/Sprites/${this.sanitizeFileName(asset.name)}`;
751
+ // Note: actual image file would be copied from source
752
+ this.addTextFile(`${path}.meta`, meta);
753
+ }
754
+ exportAudioAsset(asset) {
755
+ const meta = `fileFormatVersion: 2
756
+ guid: ${this.guidMap.get(asset.id)}
757
+ AudioImporter:
758
+ externalObjects: {}
759
+ serializedVersion: 7
760
+ defaultSettings:
761
+ loadType: 0
762
+ sampleRateSetting: 0
763
+ sampleRateOverride: 44100
764
+ compressionFormat: 1
765
+ quality: 1
766
+ conversionMode: 0
767
+ forceToMono: 0
768
+ normalize: 1
769
+ preloadAudioData: 1
770
+ loadInBackground: 0
771
+ ambisonic: 0
772
+ 3D: 1`;
773
+ const path = `Assets/Audio/${this.sanitizeFileName(asset.name)}`;
774
+ this.addTextFile(`${path}.meta`, meta);
775
+ }
776
+ exportFontAsset(asset) {
777
+ const meta = `fileFormatVersion: 2
778
+ guid: ${this.guidMap.get(asset.id)}
779
+ TrueTypeFontImporter:
780
+ externalObjects: {}
781
+ serializedVersion: 4
782
+ fontSize: 16
783
+ forceTextureCase: -2
784
+ characterSpacing: 0
785
+ characterPadding: 1
786
+ includeFontData: 1
787
+ fontNames:
788
+ - ${asset.name}
789
+ fallbackFontReferences: []
790
+ customCharacters:
791
+ fontRenderingMode: 0
792
+ ascentCalculationMode: 1`;
793
+ const path = `Assets/Fonts/${this.sanitizeFileName(asset.name)}`;
794
+ this.addTextFile(`${path}.meta`, meta);
795
+ }
796
+ exportTilesetAsset(asset) {
797
+ // Export as Tileset Palette
798
+ const palette = `%YAML 1.1
799
+ %TAG !u! tag:unity3d.com,2011:
800
+ --- !u!114 &11400000
801
+ MonoBehaviour:
802
+ m_ObjectHideFlags: 0
803
+ m_Name: ${asset.name}
804
+ m_EditorClassIdentifier:
805
+ m_Tileset: {fileID: 0}`;
806
+ const path = `Assets/Tilesets/${this.sanitizeFileName(asset.name)}.asset`;
807
+ this.addTextFile(path, palette);
808
+ this.addTextFile(`${path}.meta`, this.createMetaFile(asset.id));
809
+ }
810
+ exportAnimationAsset(asset) {
811
+ const meta = asset.metadata || {};
812
+ const frameRate = meta.frameRate || 12;
813
+ // Basic Animation Clip
814
+ const clip = `%YAML 1.1
815
+ %TAG !u! tag:unity3d.com,2011:
816
+ --- !u!74 &7400000
817
+ AnimationClip:
818
+ m_ObjectHideFlags: 0
819
+ m_Name: ${asset.name}
820
+ serializedVersion: 7
821
+ m_Legacy: 0
822
+ m_Compressed: 0
823
+ m_UseHighQualityCurve: 1
824
+ m_RotationCurves: []
825
+ m_CompressedRotationCurves: []
826
+ m_EulerCurves: []
827
+ m_PositionCurves: []
828
+ m_ScaleCurves: []
829
+ m_FloatCurves: []
830
+ m_PPtrCurves: []
831
+ m_SampleRate: ${frameRate}
832
+ m_WrapMode: 0
833
+ m_Bounds:
834
+ m_Center: {x: 0, y: 0, z: 0}
835
+ m_Extent: {x: 0, y: 0, z: 0}
836
+ m_ClipBindingConstant:
837
+ genericBindings: []
838
+ pptrCurveMapping: []
839
+ m_Events: []`;
840
+ const path = `Assets/Animations/${this.sanitizeFileName(asset.name)}.anim`;
841
+ this.addTextFile(path, clip);
842
+ this.addTextFile(`${path}.meta`, this.createMetaFile(asset.id));
843
+ }
844
+ /* ── Assembly Definition ────────────────────────────────────── */
845
+ exportAssemblyDefinition(projectName, namespace) {
846
+ const asmdef = {
847
+ name: namespace,
848
+ rootNamespace: namespace,
849
+ references: ['Unity.TextMeshPro', 'Unity.InputSystem'],
850
+ includePlatforms: [],
851
+ excludePlatforms: [],
852
+ allowUnsafeCode: false,
853
+ overrideReferences: false,
854
+ precompiledReferences: [],
855
+ autoReferenced: true,
856
+ defineConstraints: [],
857
+ versionDefines: [],
858
+ noEngineReferences: false,
859
+ };
860
+ const path = `Assets/Scripts/${namespace}.asmdef`;
861
+ this.addTextFile(path, JSON.stringify(asmdef, null, 2));
862
+ this.addTextFile(`${path}.meta`, this.createMetaFile('asmdef'));
863
+ }
864
+ /* ── Runtime Bridge ─────────────────────────────────────────── */
865
+ exportRuntimeBridge(namespace) {
866
+ const bridge = `using UnityEngine;
867
+ using System;
868
+ using System.Collections;
869
+ using System.Collections.Generic;
870
+
871
+ namespace ${namespace}.Runtime
872
+ {
873
+ /// <summary>
874
+ /// Bridge between Nice2Dev runtime and Unity systems.
875
+ /// Auto-generated by Nice2Dev export.
876
+ /// </summary>
877
+ public static class Nice2DevBridge
878
+ {
879
+ private static Dictionary<string, GameObject> _entityMap = new();
880
+ private static Dictionary<string, Action<object>> _eventHandlers = new();
881
+
882
+ /// <summary>
883
+ /// Register an entity for cross-reference.
884
+ /// </summary>
885
+ public static void RegisterEntity(string id, GameObject obj)
886
+ {
887
+ _entityMap[id] = obj;
888
+ }
889
+
890
+ /// <summary>
891
+ /// Get entity by ID.
892
+ /// </summary>
893
+ public static GameObject GetEntity(string id)
894
+ {
895
+ return _entityMap.TryGetValue(id, out var obj) ? obj : null;
896
+ }
897
+
898
+ /// <summary>
899
+ /// Emit a custom event.
900
+ /// </summary>
901
+ public static void EmitEvent(string eventName, object data = null)
902
+ {
903
+ if (_eventHandlers.TryGetValue(eventName, out var handler))
904
+ {
905
+ handler?.Invoke(data);
906
+ }
907
+ }
908
+
909
+ /// <summary>
910
+ /// Subscribe to a custom event.
911
+ /// </summary>
912
+ public static void OnEvent(string eventName, Action<object> handler)
913
+ {
914
+ if (!_eventHandlers.ContainsKey(eventName))
915
+ {
916
+ _eventHandlers[eventName] = handler;
917
+ }
918
+ else
919
+ {
920
+ _eventHandlers[eventName] += handler;
921
+ }
922
+ }
923
+
924
+ /// <summary>
925
+ /// Unsubscribe from a custom event.
926
+ /// </summary>
927
+ public static void OffEvent(string eventName, Action<object> handler)
928
+ {
929
+ if (_eventHandlers.ContainsKey(eventName))
930
+ {
931
+ _eventHandlers[eventName] -= handler;
932
+ }
933
+ }
934
+
935
+ /// <summary>
936
+ /// Wait for seconds (coroutine helper).
937
+ /// </summary>
938
+ public static IEnumerator Wait(float seconds)
939
+ {
940
+ yield return new WaitForSeconds(seconds);
941
+ }
942
+
943
+ /// <summary>
944
+ /// Spawn a prefab at position.
945
+ /// </summary>
946
+ public static GameObject Spawn(GameObject prefab, Vector2 position)
947
+ {
948
+ return UnityEngine.Object.Instantiate(prefab, new Vector3(position.x, position.y, 0), Quaternion.identity);
949
+ }
950
+
951
+ /// <summary>
952
+ /// Destroy an entity.
953
+ /// </summary>
954
+ public static void Destroy(GameObject obj, float delay = 0f)
955
+ {
956
+ if (delay > 0)
957
+ {
958
+ UnityEngine.Object.Destroy(obj, delay);
959
+ }
960
+ else
961
+ {
962
+ UnityEngine.Object.Destroy(obj);
963
+ }
964
+ }
965
+
966
+ /// <summary>
967
+ /// Play audio clip.
968
+ /// </summary>
969
+ public static void PlaySound(AudioClip clip, float volume = 1f)
970
+ {
971
+ AudioSource.PlayClipAtPoint(clip, Camera.main.transform.position, volume);
972
+ }
973
+
974
+ /// <summary>
975
+ /// Get input axis.
976
+ /// </summary>
977
+ public static float GetAxis(string axisName)
978
+ {
979
+ return Input.GetAxis(axisName);
980
+ }
981
+
982
+ /// <summary>
983
+ /// Check if key is pressed.
984
+ /// </summary>
985
+ public static bool IsKeyPressed(KeyCode key)
986
+ {
987
+ return Input.GetKey(key);
988
+ }
989
+
990
+ /// <summary>
991
+ /// Check if key was just pressed.
992
+ /// </summary>
993
+ public static bool IsKeyJustPressed(KeyCode key)
994
+ {
995
+ return Input.GetKeyDown(key);
996
+ }
997
+
998
+ /// <summary>
999
+ /// Get mouse position in world space.
1000
+ /// </summary>
1001
+ public static Vector2 GetMouseWorldPosition()
1002
+ {
1003
+ if (Camera.main == null) return Vector2.zero;
1004
+ return Camera.main.ScreenToWorldPoint(Input.mousePosition);
1005
+ }
1006
+
1007
+ /// <summary>
1008
+ /// Linear interpolation.
1009
+ /// </summary>
1010
+ public static float Lerp(float a, float b, float t)
1011
+ {
1012
+ return Mathf.Lerp(a, b, t);
1013
+ }
1014
+
1015
+ /// <summary>
1016
+ /// Random float between min and max.
1017
+ /// </summary>
1018
+ public static float Random(float min, float max)
1019
+ {
1020
+ return UnityEngine.Random.Range(min, max);
1021
+ }
1022
+
1023
+ /// <summary>
1024
+ /// Random int between min and max (exclusive).
1025
+ /// </summary>
1026
+ public static int RandomInt(int min, int max)
1027
+ {
1028
+ return UnityEngine.Random.Range(min, max);
1029
+ }
1030
+ }
1031
+ }`;
1032
+ const path = `Assets/Scripts/Runtime/Nice2DevBridge.cs`;
1033
+ this.addTextFile(path, bridge);
1034
+ this.addTextFile(`${path}.meta`, this.createScriptMetaFile('nice2dev-bridge'));
1035
+ }
1036
+ /* ── Package Manifest ───────────────────────────────────────── */
1037
+ exportPackageManifest(project) {
1038
+ // Create .unitypackage manifest
1039
+ const manifest = {
1040
+ packageName: project.name,
1041
+ version: project.version,
1042
+ exportedAt: new Date().toISOString(),
1043
+ files: this.files.map((f) => f.path),
1044
+ };
1045
+ this.addTextFile('package.json', JSON.stringify(manifest, null, 2));
1046
+ }
1047
+ /* ── YAML Serialization ─────────────────────────────────────── */
1048
+ serializeUnityYAML(yaml) {
1049
+ let output = `%YAML 1.1
1050
+ %TAG !u! tag:unity3d.com,2011:
1051
+ `;
1052
+ for (const obj of yaml.objects) {
1053
+ output += `--- !u!${obj.classID} &${obj.fileID}\n`;
1054
+ output += `${obj.type}:\n`;
1055
+ output += this.serializeYAMLObject(obj.properties, 1);
1056
+ }
1057
+ return output;
1058
+ }
1059
+ serializeYAMLObject(obj, indent) {
1060
+ const spaces = ' '.repeat(indent);
1061
+ let output = '';
1062
+ for (const [key, value] of Object.entries(obj)) {
1063
+ if (value === null || value === undefined) {
1064
+ output += `${spaces}${key}: \n`;
1065
+ }
1066
+ else if (typeof value === 'object' && !Array.isArray(value)) {
1067
+ const inner = value;
1068
+ if (Object.keys(inner).length === 0) {
1069
+ output += `${spaces}${key}: {}\n`;
1070
+ }
1071
+ else if ('fileID' in inner) {
1072
+ output += `${spaces}${key}: {fileID: ${inner.fileID}${inner.guid ? `, guid: ${inner.guid}` : ''}${inner.type ? `, type: ${inner.type}` : ''}}\n`;
1073
+ }
1074
+ else if ('x' in inner && 'y' in inner) {
1075
+ const z = 'z' in inner ? `, z: ${inner.z}` : '';
1076
+ const w = 'w' in inner ? `, w: ${inner.w}` : '';
1077
+ output += `${spaces}${key}: {x: ${inner.x}, y: ${inner.y}${z}${w}}\n`;
1078
+ }
1079
+ else if ('r' in inner && 'g' in inner) {
1080
+ output += `${spaces}${key}: {r: ${inner.r}, g: ${inner.g}, b: ${inner.b}, a: ${inner.a}}\n`;
1081
+ }
1082
+ else {
1083
+ output += `${spaces}${key}:\n`;
1084
+ output += this.serializeYAMLObject(inner, indent + 1);
1085
+ }
1086
+ }
1087
+ else if (Array.isArray(value)) {
1088
+ if (value.length === 0) {
1089
+ output += `${spaces}${key}: []\n`;
1090
+ }
1091
+ else {
1092
+ output += `${spaces}${key}:\n`;
1093
+ for (const item of value) {
1094
+ if (typeof item === 'object' && item !== null) {
1095
+ output += `${spaces}- `;
1096
+ const itemStr = this.serializeYAMLObject(item, indent + 1);
1097
+ output += itemStr.trim().replace(/\n/g, `\n${spaces} `) + '\n';
1098
+ }
1099
+ else {
1100
+ output += `${spaces}- ${item}\n`;
1101
+ }
1102
+ }
1103
+ }
1104
+ }
1105
+ else {
1106
+ output += `${spaces}${key}: ${value}\n`;
1107
+ }
1108
+ }
1109
+ return output;
1110
+ }
1111
+ /* ── Utility Methods ────────────────────────────────────────── */
1112
+ generateGuids(project) {
1113
+ for (const script of project.scripts) {
1114
+ this.guidMap.set(script.id, this.generateGUID());
1115
+ }
1116
+ for (const asset of project.assets) {
1117
+ this.guidMap.set(asset.id, this.generateGUID());
1118
+ }
1119
+ for (const prefab of project.prefabs) {
1120
+ this.guidMap.set(prefab.id, this.generateGUID());
1121
+ }
1122
+ for (const scene of project.scenes) {
1123
+ this.guidMap.set(scene.id, this.generateGUID());
1124
+ }
1125
+ }
1126
+ generateGUID() {
1127
+ // Unity uses 32-character hex GUIDs
1128
+ return 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'.replace(/x/g, () => Math.floor(Math.random() * 16).toString(16));
1129
+ }
1130
+ nextFileId() {
1131
+ return this.fileIdCounter++;
1132
+ }
1133
+ createMetaFile(id) {
1134
+ const guid = this.guidMap.get(id) || this.generateGUID();
1135
+ return `fileFormatVersion: 2
1136
+ guid: ${guid}
1137
+ NativeFormatImporter:
1138
+ externalObjects: {}
1139
+ mainObjectFileID: 0`;
1140
+ }
1141
+ createScriptMetaFile(scriptId) {
1142
+ const guid = this.guidMap.get(scriptId) || this.generateGUID();
1143
+ return `fileFormatVersion: 2
1144
+ guid: ${guid}
1145
+ MonoImporter:
1146
+ externalObjects: {}
1147
+ serializedVersion: 2
1148
+ defaultReferences: []
1149
+ executionOrder: 0
1150
+ icon: {instanceID: 0}`;
1151
+ }
1152
+ parseColor(hex) {
1153
+ const clean = hex.replace('#', '');
1154
+ const r = parseInt(clean.slice(0, 2), 16) / 255;
1155
+ const g = parseInt(clean.slice(2, 4), 16) / 255;
1156
+ const b = parseInt(clean.slice(4, 6), 16) / 255;
1157
+ const a = clean.length > 6 ? parseInt(clean.slice(6, 8), 16) / 255 : 1;
1158
+ return { r, g, b, a };
1159
+ }
1160
+ sanitizeFileName(name) {
1161
+ return name.replace(/[^a-zA-Z0-9_-]/g, '_');
1162
+ }
1163
+ toValidNamespace(name) {
1164
+ return name.replace(/[^a-zA-Z0-9]/g, '').replace(/^[0-9]/, '_$&');
1165
+ }
1166
+ getTextAlignment(alignment) {
1167
+ switch (alignment) {
1168
+ case 'left':
1169
+ return 257;
1170
+ case 'center':
1171
+ return 258;
1172
+ case 'right':
1173
+ return 260;
1174
+ case 'top-left':
1175
+ return 257;
1176
+ case 'top-center':
1177
+ return 258;
1178
+ case 'top-right':
1179
+ return 260;
1180
+ case 'bottom-left':
1181
+ return 4097;
1182
+ case 'bottom-center':
1183
+ return 4098;
1184
+ case 'bottom-right':
1185
+ return 4100;
1186
+ default:
1187
+ return 258; // center
1188
+ }
1189
+ }
1190
+ }
1191
+
1192
+ exports.UnityExporter = UnityExporter;
1193
+ //# sourceMappingURL=UnityExporter.js.map