@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.
- package/dist/cjs/ai/BehaviorTree.js +1215 -0
- package/dist/cjs/ai/BehaviorTree.js.map +1 -0
- package/dist/cjs/ai/StateMachine.js +783 -0
- package/dist/cjs/ai/StateMachine.js.map +1 -0
- package/dist/cjs/editor/ShaderGraph.js +1616 -0
- package/dist/cjs/editor/ShaderGraph.js.map +1 -0
- package/dist/cjs/editor/TimelineEditor.js +819 -0
- package/dist/cjs/editor/TimelineEditor.js.map +1 -0
- package/dist/cjs/export/GodotExporter.js +1102 -0
- package/dist/cjs/export/GodotExporter.js.map +1 -0
- package/dist/cjs/export/PlatformExporter.js +236 -0
- package/dist/cjs/export/PlatformExporter.js.map +1 -0
- package/dist/cjs/export/ThreeJSExporter.js +1116 -0
- package/dist/cjs/export/ThreeJSExporter.js.map +1 -0
- package/dist/cjs/export/UnityExporter.js +1193 -0
- package/dist/cjs/export/UnityExporter.js.map +1 -0
- package/dist/cjs/export/WebExporter.js +1036 -0
- package/dist/cjs/export/WebExporter.js.map +1 -0
- package/dist/cjs/export/index.js +58 -0
- package/dist/cjs/export/index.js.map +1 -0
- package/dist/cjs/import/AsepriteImporter.js +761 -0
- package/dist/cjs/import/AsepriteImporter.js.map +1 -0
- package/dist/cjs/import/DragonBonesImporter.js +499 -0
- package/dist/cjs/import/DragonBonesImporter.js.map +1 -0
- package/dist/cjs/import/GameMakerImporter.js +559 -0
- package/dist/cjs/import/GameMakerImporter.js.map +1 -0
- package/dist/cjs/import/GodotSceneImporter.js +824 -0
- package/dist/cjs/import/GodotSceneImporter.js.map +1 -0
- package/dist/cjs/import/LDtkImporter.js +481 -0
- package/dist/cjs/import/LDtkImporter.js.map +1 -0
- package/dist/cjs/import/Live2DImporter.js +553 -0
- package/dist/cjs/import/Live2DImporter.js.map +1 -0
- package/dist/cjs/import/NdgFormat.js +499 -0
- package/dist/cjs/import/NdgFormat.js.map +1 -0
- package/dist/cjs/import/OgmoImporter.js +529 -0
- package/dist/cjs/import/OgmoImporter.js.map +1 -0
- package/dist/cjs/import/RPGMakerImporter.js +520 -0
- package/dist/cjs/import/RPGMakerImporter.js.map +1 -0
- package/dist/cjs/import/SceneImporter.js +449 -0
- package/dist/cjs/import/SceneImporter.js.map +1 -0
- package/dist/cjs/import/SpineImporter.js +583 -0
- package/dist/cjs/import/SpineImporter.js.map +1 -0
- package/dist/cjs/import/SpriterImporter.js +652 -0
- package/dist/cjs/import/SpriterImporter.js.map +1 -0
- package/dist/cjs/import/TiledMapImporter.js +859 -0
- package/dist/cjs/import/TiledMapImporter.js.map +1 -0
- package/dist/cjs/import/UnitySceneImporter.js +732 -0
- package/dist/cjs/import/UnitySceneImporter.js.map +1 -0
- package/dist/cjs/import/index.js +305 -0
- package/dist/cjs/import/index.js.map +1 -0
- package/dist/cjs/index.js +201 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/scripting/GraphToAST.js +567 -0
- package/dist/cjs/scripting/GraphToAST.js.map +1 -0
- package/dist/cjs/scripting/LanguageExporter.js +321 -0
- package/dist/cjs/scripting/LanguageExporter.js.map +1 -0
- package/dist/cjs/scripting/ScriptAST.js +67 -0
- package/dist/cjs/scripting/ScriptAST.js.map +1 -0
- package/dist/cjs/scripting/VisualScripting2.js +1140 -0
- package/dist/cjs/scripting/VisualScripting2.js.map +1 -0
- package/dist/cjs/scripting/exporters/CSharpExporter.js +503 -0
- package/dist/cjs/scripting/exporters/CSharpExporter.js.map +1 -0
- package/dist/cjs/scripting/exporters/GDScriptExporter.js +452 -0
- package/dist/cjs/scripting/exporters/GDScriptExporter.js.map +1 -0
- package/dist/cjs/scripting/exporters/LuaExporter.js +457 -0
- package/dist/cjs/scripting/exporters/LuaExporter.js.map +1 -0
- package/dist/cjs/scripting/exporters/PythonExporter.js +565 -0
- package/dist/cjs/scripting/exporters/PythonExporter.js.map +1 -0
- package/dist/cjs/scripting/exporters/RustExporter.js +525 -0
- package/dist/cjs/scripting/exporters/RustExporter.js.map +1 -0
- package/dist/cjs/scripting/exporters/TypeScriptExporter.js +570 -0
- package/dist/cjs/scripting/exporters/TypeScriptExporter.js.map +1 -0
- package/dist/cjs/systems/ParticleSystem2.js +1478 -0
- package/dist/cjs/systems/ParticleSystem2.js.map +1 -0
- package/dist/esm/ai/BehaviorTree.js +1186 -0
- package/dist/esm/ai/BehaviorTree.js.map +1 -0
- package/dist/esm/ai/StateMachine.js +767 -0
- package/dist/esm/ai/StateMachine.js.map +1 -0
- package/dist/esm/editor/ShaderGraph.js +1606 -0
- package/dist/esm/editor/ShaderGraph.js.map +1 -0
- package/dist/esm/editor/TimelineEditor.js +800 -0
- package/dist/esm/editor/TimelineEditor.js.map +1 -0
- package/dist/esm/export/GodotExporter.js +1100 -0
- package/dist/esm/export/GodotExporter.js.map +1 -0
- package/dist/esm/export/PlatformExporter.js +230 -0
- package/dist/esm/export/PlatformExporter.js.map +1 -0
- package/dist/esm/export/ThreeJSExporter.js +1114 -0
- package/dist/esm/export/ThreeJSExporter.js.map +1 -0
- package/dist/esm/export/UnityExporter.js +1191 -0
- package/dist/esm/export/UnityExporter.js.map +1 -0
- package/dist/esm/export/WebExporter.js +1033 -0
- package/dist/esm/export/WebExporter.js.map +1 -0
- package/dist/esm/export/index.js +44 -0
- package/dist/esm/export/index.js.map +1 -0
- package/dist/esm/import/AsepriteImporter.js +759 -0
- package/dist/esm/import/AsepriteImporter.js.map +1 -0
- package/dist/esm/import/DragonBonesImporter.js +496 -0
- package/dist/esm/import/DragonBonesImporter.js.map +1 -0
- package/dist/esm/import/GameMakerImporter.js +556 -0
- package/dist/esm/import/GameMakerImporter.js.map +1 -0
- package/dist/esm/import/GodotSceneImporter.js +822 -0
- package/dist/esm/import/GodotSceneImporter.js.map +1 -0
- package/dist/esm/import/LDtkImporter.js +479 -0
- package/dist/esm/import/LDtkImporter.js.map +1 -0
- package/dist/esm/import/Live2DImporter.js +550 -0
- package/dist/esm/import/Live2DImporter.js.map +1 -0
- package/dist/esm/import/NdgFormat.js +490 -0
- package/dist/esm/import/NdgFormat.js.map +1 -0
- package/dist/esm/import/OgmoImporter.js +526 -0
- package/dist/esm/import/OgmoImporter.js.map +1 -0
- package/dist/esm/import/RPGMakerImporter.js +517 -0
- package/dist/esm/import/RPGMakerImporter.js.map +1 -0
- package/dist/esm/import/SceneImporter.js +441 -0
- package/dist/esm/import/SceneImporter.js.map +1 -0
- package/dist/esm/import/SpineImporter.js +580 -0
- package/dist/esm/import/SpineImporter.js.map +1 -0
- package/dist/esm/import/SpriterImporter.js +649 -0
- package/dist/esm/import/SpriterImporter.js.map +1 -0
- package/dist/esm/import/TiledMapImporter.js +857 -0
- package/dist/esm/import/TiledMapImporter.js.map +1 -0
- package/dist/esm/import/UnitySceneImporter.js +730 -0
- package/dist/esm/import/UnitySceneImporter.js.map +1 -0
- package/dist/esm/import/index.js +279 -0
- package/dist/esm/import/index.js.map +1 -0
- package/dist/esm/index.js +36 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/scripting/GraphToAST.js +564 -0
- package/dist/esm/scripting/GraphToAST.js.map +1 -0
- package/dist/esm/scripting/LanguageExporter.js +311 -0
- package/dist/esm/scripting/LanguageExporter.js.map +1 -0
- package/dist/esm/scripting/ScriptAST.js +52 -0
- package/dist/esm/scripting/ScriptAST.js.map +1 -0
- package/dist/esm/scripting/VisualScripting2.js +1130 -0
- package/dist/esm/scripting/VisualScripting2.js.map +1 -0
- package/dist/esm/scripting/exporters/CSharpExporter.js +501 -0
- package/dist/esm/scripting/exporters/CSharpExporter.js.map +1 -0
- package/dist/esm/scripting/exporters/GDScriptExporter.js +450 -0
- package/dist/esm/scripting/exporters/GDScriptExporter.js.map +1 -0
- package/dist/esm/scripting/exporters/LuaExporter.js +455 -0
- package/dist/esm/scripting/exporters/LuaExporter.js.map +1 -0
- package/dist/esm/scripting/exporters/PythonExporter.js +563 -0
- package/dist/esm/scripting/exporters/PythonExporter.js.map +1 -0
- package/dist/esm/scripting/exporters/RustExporter.js +523 -0
- package/dist/esm/scripting/exporters/RustExporter.js.map +1 -0
- package/dist/esm/scripting/exporters/TypeScriptExporter.js +568 -0
- package/dist/esm/scripting/exporters/TypeScriptExporter.js.map +1 -0
- package/dist/esm/systems/ParticleSystem2.js +1471 -0
- package/dist/esm/systems/ParticleSystem2.js.map +1 -0
- package/dist/types/ai/BehaviorTree.d.ts +375 -0
- package/dist/types/ai/StateMachine.d.ts +296 -0
- package/dist/types/editor/ShaderGraph.d.ts +207 -0
- package/dist/types/editor/TimelineEditor.d.ts +393 -0
- package/dist/types/export/GodotExporter.d.ts +56 -0
- package/dist/types/export/PlatformExporter.d.ts +201 -0
- package/dist/types/export/ThreeJSExporter.d.ts +40 -0
- package/dist/types/export/UnityExporter.d.ts +69 -0
- package/dist/types/export/WebExporter.d.ts +58 -0
- package/dist/types/export/index.d.ts +19 -0
- package/dist/types/import/AsepriteImporter.d.ts +46 -0
- package/dist/types/import/DragonBonesImporter.d.ts +331 -0
- package/dist/types/import/GameMakerImporter.d.ts +375 -0
- package/dist/types/import/GodotSceneImporter.d.ts +34 -0
- package/dist/types/import/LDtkImporter.d.ts +177 -0
- package/dist/types/import/Live2DImporter.d.ts +237 -0
- package/dist/types/import/NdgFormat.d.ts +387 -0
- package/dist/types/import/OgmoImporter.d.ts +237 -0
- package/dist/types/import/RPGMakerImporter.d.ts +186 -0
- package/dist/types/import/SceneImporter.d.ts +276 -0
- package/dist/types/import/SpineImporter.d.ts +372 -0
- package/dist/types/import/SpriterImporter.d.ts +230 -0
- package/dist/types/import/TiledMapImporter.d.ts +57 -0
- package/dist/types/import/UnitySceneImporter.d.ts +87 -0
- package/dist/types/import/index.d.ts +59 -0
- package/dist/types/index.d.ts +29 -17
- package/dist/types/scripting/GraphToAST.d.ts +55 -0
- package/dist/types/scripting/LanguageExporter.d.ts +136 -0
- package/dist/types/scripting/ScriptAST.d.ts +312 -0
- package/dist/types/scripting/VisualScripting2.d.ts +353 -0
- package/dist/types/scripting/exporters/CSharpExporter.d.ts +44 -0
- package/dist/types/scripting/exporters/GDScriptExporter.d.ts +46 -0
- package/dist/types/scripting/exporters/LuaExporter.d.ts +46 -0
- package/dist/types/scripting/exporters/PythonExporter.d.ts +49 -0
- package/dist/types/scripting/exporters/RustExporter.d.ts +46 -0
- package/dist/types/scripting/exporters/TypeScriptExporter.d.ts +48 -0
- package/dist/types/scripting/exporters/index.d.ts +8 -0
- package/dist/types/scripting/index.d.ts +11 -0
- package/dist/types/systems/ParticleSystem2.d.ts +646 -0
- package/package.json +3 -3
|
@@ -0,0 +1,759 @@
|
|
|
1
|
+
import { SceneImporter } from './SceneImporter.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file AsepriteImporter.ts
|
|
5
|
+
* @description Import Aseprite sprite editor files (.aseprite, .ase)
|
|
6
|
+
* PRO-1.3: Scene Format Interoperability
|
|
7
|
+
*
|
|
8
|
+
* Supports:
|
|
9
|
+
* - Aseprite binary format (.aseprite, .ase)
|
|
10
|
+
* - Aseprite JSON export format
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - Layers (normal, group, reference)
|
|
14
|
+
* - Frames and animation
|
|
15
|
+
* - Tags (animation clips)
|
|
16
|
+
* - Slices (9-slice, pivot)
|
|
17
|
+
* - Palette
|
|
18
|
+
* - Cel data
|
|
19
|
+
* - Blend modes
|
|
20
|
+
*/
|
|
21
|
+
// ============================================================
|
|
22
|
+
// Aseprite Chunk Types
|
|
23
|
+
// ============================================================
|
|
24
|
+
const CHUNK_TYPES = {
|
|
25
|
+
LAYER: 0x2004,
|
|
26
|
+
CEL: 0x2005,
|
|
27
|
+
EXTERNAL_FILES: 0x2008,
|
|
28
|
+
TAGS: 0x2018,
|
|
29
|
+
PALETTE: 0x2019,
|
|
30
|
+
SLICE: 0x2022};
|
|
31
|
+
const BLEND_MODES = [
|
|
32
|
+
'normal',
|
|
33
|
+
'multiply',
|
|
34
|
+
'screen',
|
|
35
|
+
'overlay',
|
|
36
|
+
'darken',
|
|
37
|
+
'lighten',
|
|
38
|
+
'color-dodge',
|
|
39
|
+
'color-burn',
|
|
40
|
+
'hard-light',
|
|
41
|
+
'soft-light',
|
|
42
|
+
'difference',
|
|
43
|
+
'exclusion',
|
|
44
|
+
'hue',
|
|
45
|
+
'saturation',
|
|
46
|
+
'color',
|
|
47
|
+
'luminosity',
|
|
48
|
+
'addition',
|
|
49
|
+
'subtract',
|
|
50
|
+
'divide',
|
|
51
|
+
];
|
|
52
|
+
// ============================================================
|
|
53
|
+
// Aseprite Importer
|
|
54
|
+
// ============================================================
|
|
55
|
+
class AsepriteImporter extends SceneImporter {
|
|
56
|
+
constructor() {
|
|
57
|
+
super('aseprite');
|
|
58
|
+
this.aseFile = null;
|
|
59
|
+
}
|
|
60
|
+
async import(options) {
|
|
61
|
+
const startTime = Date.now();
|
|
62
|
+
this.options = options;
|
|
63
|
+
this.clearMessages();
|
|
64
|
+
this.aseFile = null;
|
|
65
|
+
const errors = await this.validate(options.sourcePath);
|
|
66
|
+
if (errors.some((e) => e.fatal)) {
|
|
67
|
+
return {
|
|
68
|
+
...this.createEmptyResult(),
|
|
69
|
+
errors: errors,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const scenes = [];
|
|
73
|
+
const assets = [];
|
|
74
|
+
try {
|
|
75
|
+
const content = await this.readFile(options.sourcePath);
|
|
76
|
+
// Detect format: binary or JSON
|
|
77
|
+
if (typeof content === 'string') {
|
|
78
|
+
// JSON export
|
|
79
|
+
const json = JSON.parse(content);
|
|
80
|
+
const spriteSheet = this.parseJsonExport(json, options.sourcePath);
|
|
81
|
+
assets.push(this.createSpriteSheetAsset(spriteSheet, json.meta.image));
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
// Binary format
|
|
85
|
+
this.aseFile = this.parseBinaryFile(content);
|
|
86
|
+
if (this.aseFile) {
|
|
87
|
+
// Create sprite sheet asset
|
|
88
|
+
const spriteSheet = this.createSpriteSheetFromBinary();
|
|
89
|
+
assets.push(this.createSpriteSheetAsset(spriteSheet, options.sourcePath));
|
|
90
|
+
// Create palette asset if indexed color
|
|
91
|
+
if (this.aseFile.header.colorDepth === 8) {
|
|
92
|
+
assets.push(this.createPaletteAsset());
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Create a pseudo-scene for the sprite
|
|
97
|
+
if (this.aseFile || assets.length > 0) {
|
|
98
|
+
const scene = this.createSpriteScene(options.sourcePath);
|
|
99
|
+
scenes.push(scene);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
this.addError('IMPORT_ERROR', `Failed to import: ${error}`, options.sourcePath, undefined, true);
|
|
104
|
+
}
|
|
105
|
+
return this.createResult(scenes, assets, startTime);
|
|
106
|
+
}
|
|
107
|
+
async parseFile(content, filePath) {
|
|
108
|
+
if (typeof content === 'string') {
|
|
109
|
+
try {
|
|
110
|
+
const json = JSON.parse(content);
|
|
111
|
+
const spriteSheet = this.parseJsonExport(json, filePath);
|
|
112
|
+
return {
|
|
113
|
+
id: this.generateId(),
|
|
114
|
+
name: spriteSheet.name,
|
|
115
|
+
type: 'animation',
|
|
116
|
+
path: json.meta.image,
|
|
117
|
+
metadata: {
|
|
118
|
+
frames: spriteSheet.frames,
|
|
119
|
+
animations: spriteSheet.animations,
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
catch (_a) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Binary parsing returns scene with sprite entity
|
|
128
|
+
this.aseFile = this.parseBinaryFile(content);
|
|
129
|
+
if (this.aseFile) {
|
|
130
|
+
return this.createSpriteScene(filePath);
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
async validate(sourcePath) {
|
|
135
|
+
const errors = [];
|
|
136
|
+
if (!this.canHandle(sourcePath)) {
|
|
137
|
+
errors.push({
|
|
138
|
+
code: 'INVALID_FORMAT',
|
|
139
|
+
message: `File ${sourcePath} is not a valid Aseprite file`,
|
|
140
|
+
file: sourcePath,
|
|
141
|
+
fatal: true,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return errors;
|
|
145
|
+
}
|
|
146
|
+
// ----------------------------------------
|
|
147
|
+
// JSON Export Parsing
|
|
148
|
+
// ----------------------------------------
|
|
149
|
+
parseJsonExport(json, filePath) {
|
|
150
|
+
const frames = [];
|
|
151
|
+
const animations = {};
|
|
152
|
+
// Parse frames (can be object or array)
|
|
153
|
+
const frameEntries = Array.isArray(json.frames)
|
|
154
|
+
? json.frames.map((f, i) => [`frame_${i}`, f])
|
|
155
|
+
: Object.entries(json.frames);
|
|
156
|
+
for (const [name, frameData] of frameEntries) {
|
|
157
|
+
frames.push({
|
|
158
|
+
name,
|
|
159
|
+
x: frameData.frame.x,
|
|
160
|
+
y: frameData.frame.y,
|
|
161
|
+
width: frameData.frame.w,
|
|
162
|
+
height: frameData.frame.h,
|
|
163
|
+
sourceWidth: frameData.sourceSize.w,
|
|
164
|
+
sourceHeight: frameData.sourceSize.h,
|
|
165
|
+
offsetX: frameData.spriteSourceSize.x,
|
|
166
|
+
offsetY: frameData.spriteSourceSize.y,
|
|
167
|
+
trimmed: frameData.trimmed,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
// Parse frame tags as animations
|
|
171
|
+
if (json.meta.frameTags) {
|
|
172
|
+
for (const tag of json.meta.frameTags) {
|
|
173
|
+
const animFrames = [];
|
|
174
|
+
for (let i = tag.from; i <= tag.to; i++) {
|
|
175
|
+
const frame = frameEntries[i][1];
|
|
176
|
+
animFrames.push({
|
|
177
|
+
index: i,
|
|
178
|
+
duration: frame.duration,
|
|
179
|
+
x: frameEntries[i][1].frame.x,
|
|
180
|
+
y: frameEntries[i][1].frame.y,
|
|
181
|
+
width: frameEntries[i][1].frame.w,
|
|
182
|
+
height: frameEntries[i][1].frame.h,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
animations[tag.name] = {
|
|
186
|
+
name: tag.name,
|
|
187
|
+
frames: animFrames,
|
|
188
|
+
loop: true, // Determine from direction
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// If no tags, create a default animation with all frames
|
|
193
|
+
if (Object.keys(animations).length === 0 && frames.length > 0) {
|
|
194
|
+
const allFrames = frameEntries.map(([_, f], index) => ({
|
|
195
|
+
index,
|
|
196
|
+
duration: f.duration,
|
|
197
|
+
x: f.frame.x,
|
|
198
|
+
y: f.frame.y,
|
|
199
|
+
width: f.frame.w,
|
|
200
|
+
height: f.frame.h,
|
|
201
|
+
}));
|
|
202
|
+
animations['default'] = {
|
|
203
|
+
name: 'default',
|
|
204
|
+
frames: allFrames,
|
|
205
|
+
loop: true,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
name: filePath.substring(filePath.lastIndexOf('/') + 1).replace(/\.\w+$/, ''),
|
|
210
|
+
imagePath: json.meta.image,
|
|
211
|
+
frames,
|
|
212
|
+
animations,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
// ----------------------------------------
|
|
216
|
+
// Binary Format Parsing
|
|
217
|
+
// ----------------------------------------
|
|
218
|
+
parseBinaryFile(buffer) {
|
|
219
|
+
const view = new DataView(buffer);
|
|
220
|
+
let offset = 0;
|
|
221
|
+
// Read header
|
|
222
|
+
const header = this.readHeader(view, offset);
|
|
223
|
+
offset += 128; // Header is always 128 bytes
|
|
224
|
+
if (header.magicNumber !== 0xa5e0) {
|
|
225
|
+
this.addError('INVALID_MAGIC', 'Invalid Aseprite file magic number');
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
const file = {
|
|
229
|
+
header,
|
|
230
|
+
frames: [],
|
|
231
|
+
palette: { size: 0, colors: [], firstColorIndex: 0, lastColorIndex: 0 },
|
|
232
|
+
layers: [],
|
|
233
|
+
tags: [],
|
|
234
|
+
slices: [],
|
|
235
|
+
};
|
|
236
|
+
// Read frames
|
|
237
|
+
for (let f = 0; f < header.frames; f++) {
|
|
238
|
+
const frame = this.readFrame(view, offset, file);
|
|
239
|
+
file.frames.push(frame);
|
|
240
|
+
offset += this.getFrameSize(view, offset);
|
|
241
|
+
}
|
|
242
|
+
// Build layer hierarchy
|
|
243
|
+
this.buildLayerHierarchy(file.layers);
|
|
244
|
+
return file;
|
|
245
|
+
}
|
|
246
|
+
readHeader(view, offset) {
|
|
247
|
+
return {
|
|
248
|
+
fileSize: view.getUint32(offset, true),
|
|
249
|
+
magicNumber: view.getUint16(offset + 4, true),
|
|
250
|
+
frames: view.getUint16(offset + 6, true),
|
|
251
|
+
width: view.getUint16(offset + 8, true),
|
|
252
|
+
height: view.getUint16(offset + 10, true),
|
|
253
|
+
colorDepth: view.getUint16(offset + 12, true),
|
|
254
|
+
flags: view.getUint32(offset + 14, true),
|
|
255
|
+
speed: view.getUint16(offset + 18, true),
|
|
256
|
+
transparentIndex: view.getUint8(offset + 28),
|
|
257
|
+
numColors: view.getUint16(offset + 32, true),
|
|
258
|
+
pixelWidth: view.getUint8(offset + 34),
|
|
259
|
+
pixelHeight: view.getUint8(offset + 35),
|
|
260
|
+
gridX: view.getInt16(offset + 36, true),
|
|
261
|
+
gridY: view.getInt16(offset + 38, true),
|
|
262
|
+
gridWidth: view.getUint16(offset + 40, true),
|
|
263
|
+
gridHeight: view.getUint16(offset + 42, true),
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
readFrame(view, offset, file) {
|
|
267
|
+
view.getUint32(offset, true);
|
|
268
|
+
const frameMagic = view.getUint16(offset + 4, true);
|
|
269
|
+
if (frameMagic !== 0xf1fa) {
|
|
270
|
+
this.addWarning('INVALID_FRAME_MAGIC', `Invalid frame magic at offset ${offset}`);
|
|
271
|
+
}
|
|
272
|
+
const oldChunks = view.getUint16(offset + 6, true);
|
|
273
|
+
const duration = view.getUint16(offset + 8, true);
|
|
274
|
+
const newChunks = view.getUint32(offset + 12, true);
|
|
275
|
+
const numChunks = newChunks === 0 ? oldChunks : newChunks;
|
|
276
|
+
const frame = {
|
|
277
|
+
duration,
|
|
278
|
+
chunks: [],
|
|
279
|
+
cels: [],
|
|
280
|
+
};
|
|
281
|
+
let chunkOffset = offset + 16;
|
|
282
|
+
for (let c = 0; c < numChunks; c++) {
|
|
283
|
+
const chunkSize = view.getUint32(chunkOffset, true);
|
|
284
|
+
const chunkType = view.getUint16(chunkOffset + 4, true);
|
|
285
|
+
const chunkData = new Uint8Array(view.buffer, chunkOffset + 6, chunkSize - 6);
|
|
286
|
+
this.processChunk(chunkType, chunkData, frame, file);
|
|
287
|
+
frame.chunks.push({
|
|
288
|
+
type: chunkType,
|
|
289
|
+
data: chunkData.buffer,
|
|
290
|
+
});
|
|
291
|
+
chunkOffset += chunkSize;
|
|
292
|
+
}
|
|
293
|
+
return frame;
|
|
294
|
+
}
|
|
295
|
+
getFrameSize(view, offset) {
|
|
296
|
+
return view.getUint32(offset, true);
|
|
297
|
+
}
|
|
298
|
+
processChunk(type, data, frame, file) {
|
|
299
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
300
|
+
switch (type) {
|
|
301
|
+
case CHUNK_TYPES.LAYER:
|
|
302
|
+
file.layers.push(this.readLayerChunk(view));
|
|
303
|
+
break;
|
|
304
|
+
case CHUNK_TYPES.CEL:
|
|
305
|
+
frame.cels.push(this.readCelChunk(view, data, file.header));
|
|
306
|
+
break;
|
|
307
|
+
case CHUNK_TYPES.TAGS:
|
|
308
|
+
file.tags.push(...this.readTagsChunk(view));
|
|
309
|
+
break;
|
|
310
|
+
case CHUNK_TYPES.PALETTE:
|
|
311
|
+
file.palette = this.readPaletteChunk(view);
|
|
312
|
+
break;
|
|
313
|
+
case CHUNK_TYPES.SLICE:
|
|
314
|
+
file.slices.push(this.readSliceChunk(view));
|
|
315
|
+
break;
|
|
316
|
+
case CHUNK_TYPES.EXTERNAL_FILES:
|
|
317
|
+
file.externalFiles = this.readExternalFilesChunk(view);
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
readLayerChunk(view) {
|
|
322
|
+
const flags = view.getUint16(0, true);
|
|
323
|
+
const typeNum = view.getUint16(2, true);
|
|
324
|
+
const childLevel = view.getUint16(4, true);
|
|
325
|
+
// Skip default width/height at 6 and 8
|
|
326
|
+
const blendModeNum = view.getUint16(10, true);
|
|
327
|
+
const opacity = view.getUint8(12);
|
|
328
|
+
// Skip 3 reserved bytes
|
|
329
|
+
const nameLength = view.getUint16(16, true);
|
|
330
|
+
const name = this.readString(view, 18, nameLength);
|
|
331
|
+
let tilesetIndex;
|
|
332
|
+
if (typeNum === 2 && view.byteLength > 18 + nameLength) {
|
|
333
|
+
tilesetIndex = view.getUint32(18 + nameLength, true);
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
flags,
|
|
337
|
+
type: typeNum === 0 ? 'normal' : typeNum === 1 ? 'group' : 'tilemap',
|
|
338
|
+
childLevel,
|
|
339
|
+
blendMode: BLEND_MODES[blendModeNum] || 'normal',
|
|
340
|
+
opacity,
|
|
341
|
+
name,
|
|
342
|
+
tilesetIndex,
|
|
343
|
+
visible: (flags & 0x0001) !== 0,
|
|
344
|
+
editable: (flags & 0x0002) !== 0,
|
|
345
|
+
lockMovement: (flags & 0x0004) !== 0,
|
|
346
|
+
background: (flags & 0x0008) !== 0,
|
|
347
|
+
continuous: (flags & 0x0010) !== 0,
|
|
348
|
+
collapsed: (flags & 0x0020) !== 0,
|
|
349
|
+
reference: (flags & 0x0040) !== 0,
|
|
350
|
+
children: [],
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
readCelChunk(view, data, header) {
|
|
354
|
+
const layerIndex = view.getUint16(0, true);
|
|
355
|
+
const x = view.getInt16(2, true);
|
|
356
|
+
const y = view.getInt16(4, true);
|
|
357
|
+
const opacity = view.getUint8(6);
|
|
358
|
+
const celType = view.getUint16(7, true);
|
|
359
|
+
const zIndex = view.getInt16(9, true);
|
|
360
|
+
const cel = {
|
|
361
|
+
layerIndex,
|
|
362
|
+
x,
|
|
363
|
+
y,
|
|
364
|
+
opacity,
|
|
365
|
+
celType: celType === 0
|
|
366
|
+
? 'raw'
|
|
367
|
+
: celType === 1
|
|
368
|
+
? 'linked'
|
|
369
|
+
: celType === 2
|
|
370
|
+
? 'compressed'
|
|
371
|
+
: 'compressed-tilemap',
|
|
372
|
+
zIndex,
|
|
373
|
+
};
|
|
374
|
+
// Skip 5 reserved bytes, then read type-specific data
|
|
375
|
+
let offset = 16;
|
|
376
|
+
if (celType === 1) {
|
|
377
|
+
// Linked cel
|
|
378
|
+
cel.linkedFrame = view.getUint16(offset, true);
|
|
379
|
+
}
|
|
380
|
+
else if (celType === 0 || celType === 2) {
|
|
381
|
+
// Raw or compressed pixel data
|
|
382
|
+
cel.width = view.getUint16(offset, true);
|
|
383
|
+
cel.height = view.getUint16(offset + 2, true);
|
|
384
|
+
if (celType === 0) {
|
|
385
|
+
// Raw pixels
|
|
386
|
+
const bytesPerPixel = header.colorDepth / 8;
|
|
387
|
+
const pixelCount = cel.width * cel.height * bytesPerPixel;
|
|
388
|
+
cel.pixels = new Uint8Array(data.slice(offset + 4, offset + 4 + pixelCount));
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
// Compressed (zlib)
|
|
392
|
+
// Would need zlib decompression here
|
|
393
|
+
// For now, store compressed data reference
|
|
394
|
+
cel.pixels = new Uint8Array(data.slice(offset + 4));
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
else if (celType === 3) {
|
|
398
|
+
// Compressed tilemap
|
|
399
|
+
cel.width = view.getUint16(offset, true);
|
|
400
|
+
cel.height = view.getUint16(offset + 2, true);
|
|
401
|
+
cel.tileWidth = view.getUint16(offset + 4, true);
|
|
402
|
+
cel.tileHeight = view.getUint16(offset + 6, true);
|
|
403
|
+
// Tile data follows (compressed)
|
|
404
|
+
}
|
|
405
|
+
return cel;
|
|
406
|
+
}
|
|
407
|
+
readTagsChunk(view) {
|
|
408
|
+
const tags = [];
|
|
409
|
+
const numTags = view.getUint16(0, true);
|
|
410
|
+
// Skip 8 reserved bytes
|
|
411
|
+
let offset = 10;
|
|
412
|
+
for (let i = 0; i < numTags; i++) {
|
|
413
|
+
const fromFrame = view.getUint16(offset, true);
|
|
414
|
+
const toFrame = view.getUint16(offset + 2, true);
|
|
415
|
+
const directionNum = view.getUint8(offset + 4);
|
|
416
|
+
const repeat = view.getUint16(offset + 5, true);
|
|
417
|
+
// Skip 6 reserved bytes
|
|
418
|
+
// Skip deprecated RGB bytes at offset + 13
|
|
419
|
+
// Skip 1 extra byte
|
|
420
|
+
const nameLength = view.getUint16(offset + 17, true);
|
|
421
|
+
const name = this.readString(view, offset + 19, nameLength);
|
|
422
|
+
tags.push({
|
|
423
|
+
fromFrame,
|
|
424
|
+
toFrame,
|
|
425
|
+
direction: directionNum === 0
|
|
426
|
+
? 'forward'
|
|
427
|
+
: directionNum === 1
|
|
428
|
+
? 'reverse'
|
|
429
|
+
: directionNum === 2
|
|
430
|
+
? 'pingpong'
|
|
431
|
+
: 'pingpong-reverse',
|
|
432
|
+
repeat,
|
|
433
|
+
name,
|
|
434
|
+
color: { red: 0, green: 0, blue: 0, alpha: 255 },
|
|
435
|
+
});
|
|
436
|
+
offset += 19 + nameLength;
|
|
437
|
+
}
|
|
438
|
+
return tags;
|
|
439
|
+
}
|
|
440
|
+
readPaletteChunk(view) {
|
|
441
|
+
const size = view.getUint32(0, true);
|
|
442
|
+
const firstColorIndex = view.getUint32(4, true);
|
|
443
|
+
const lastColorIndex = view.getUint32(8, true);
|
|
444
|
+
// Skip 8 reserved bytes
|
|
445
|
+
const colors = [];
|
|
446
|
+
let offset = 20;
|
|
447
|
+
for (let i = firstColorIndex; i <= lastColorIndex; i++) {
|
|
448
|
+
const hasName = view.getUint16(offset, true) & 0x0001;
|
|
449
|
+
const red = view.getUint8(offset + 2);
|
|
450
|
+
const green = view.getUint8(offset + 3);
|
|
451
|
+
const blue = view.getUint8(offset + 4);
|
|
452
|
+
const alpha = view.getUint8(offset + 5);
|
|
453
|
+
let name;
|
|
454
|
+
offset += 6;
|
|
455
|
+
if (hasName) {
|
|
456
|
+
const nameLength = view.getUint16(offset, true);
|
|
457
|
+
name = this.readString(view, offset + 2, nameLength);
|
|
458
|
+
offset += 2 + nameLength;
|
|
459
|
+
}
|
|
460
|
+
colors[i] = { red, green, blue, alpha, name };
|
|
461
|
+
}
|
|
462
|
+
return { size, colors, firstColorIndex, lastColorIndex };
|
|
463
|
+
}
|
|
464
|
+
readSliceChunk(view) {
|
|
465
|
+
const numKeys = view.getUint32(0, true);
|
|
466
|
+
const flags = view.getUint32(4, true);
|
|
467
|
+
// Skip 4 reserved bytes
|
|
468
|
+
const nameLength = view.getUint16(12, true);
|
|
469
|
+
const name = this.readString(view, 14, nameLength);
|
|
470
|
+
const has9Slices = (flags & 0x0001) !== 0;
|
|
471
|
+
const hasPivot = (flags & 0x0002) !== 0;
|
|
472
|
+
const keys = [];
|
|
473
|
+
let offset = 14 + nameLength;
|
|
474
|
+
for (let i = 0; i < numKeys; i++) {
|
|
475
|
+
const frameNumber = view.getUint32(offset, true);
|
|
476
|
+
const x = view.getInt32(offset + 4, true);
|
|
477
|
+
const y = view.getInt32(offset + 8, true);
|
|
478
|
+
const width = view.getUint32(offset + 12, true);
|
|
479
|
+
const height = view.getUint32(offset + 16, true);
|
|
480
|
+
offset += 20;
|
|
481
|
+
const key = { frameNumber, x, y, width, height };
|
|
482
|
+
if (has9Slices) {
|
|
483
|
+
key.centerX = view.getInt32(offset, true);
|
|
484
|
+
key.centerY = view.getInt32(offset + 4, true);
|
|
485
|
+
key.centerWidth = view.getUint32(offset + 8, true);
|
|
486
|
+
key.centerHeight = view.getUint32(offset + 12, true);
|
|
487
|
+
offset += 16;
|
|
488
|
+
}
|
|
489
|
+
if (hasPivot) {
|
|
490
|
+
key.pivotX = view.getInt32(offset, true);
|
|
491
|
+
key.pivotY = view.getInt32(offset + 4, true);
|
|
492
|
+
offset += 8;
|
|
493
|
+
}
|
|
494
|
+
keys.push(key);
|
|
495
|
+
}
|
|
496
|
+
return { name, flags, keys, has9Slices, hasPivot };
|
|
497
|
+
}
|
|
498
|
+
readExternalFilesChunk(view) {
|
|
499
|
+
const files = [];
|
|
500
|
+
const numEntries = view.getUint32(0, true);
|
|
501
|
+
// Skip 8 reserved bytes
|
|
502
|
+
let offset = 12;
|
|
503
|
+
for (let i = 0; i < numEntries; i++) {
|
|
504
|
+
const id = view.getUint32(offset, true);
|
|
505
|
+
const typeNum = view.getUint8(offset + 4);
|
|
506
|
+
// Skip 7 reserved bytes
|
|
507
|
+
const pathLength = view.getUint16(offset + 12, true);
|
|
508
|
+
const path = this.readString(view, offset + 14, pathLength);
|
|
509
|
+
const typeMap = {
|
|
510
|
+
0: 'external-palette',
|
|
511
|
+
1: 'external-tileset',
|
|
512
|
+
2: 'extension',
|
|
513
|
+
3: 'extension-property',
|
|
514
|
+
};
|
|
515
|
+
files.push({
|
|
516
|
+
id,
|
|
517
|
+
type: typeMap[typeNum] || 'extension',
|
|
518
|
+
path,
|
|
519
|
+
});
|
|
520
|
+
offset += 14 + pathLength;
|
|
521
|
+
}
|
|
522
|
+
return files;
|
|
523
|
+
}
|
|
524
|
+
readString(view, offset, length) {
|
|
525
|
+
const bytes = new Uint8Array(view.buffer, view.byteOffset + offset, length);
|
|
526
|
+
return new TextDecoder('utf-8').decode(bytes);
|
|
527
|
+
}
|
|
528
|
+
buildLayerHierarchy(layers) {
|
|
529
|
+
const stack = [];
|
|
530
|
+
for (let i = 0; i < layers.length; i++) {
|
|
531
|
+
const layer = layers[i];
|
|
532
|
+
// Pop stack until we find the parent level
|
|
533
|
+
while (stack.length > layer.childLevel) {
|
|
534
|
+
stack.pop();
|
|
535
|
+
}
|
|
536
|
+
// Set parent
|
|
537
|
+
if (stack.length > 0) {
|
|
538
|
+
layer.parent = stack[stack.length - 1];
|
|
539
|
+
layers[layer.parent].children.push(i);
|
|
540
|
+
}
|
|
541
|
+
// Push this layer if it's a group
|
|
542
|
+
if (layer.type === 'group') {
|
|
543
|
+
stack.push(i);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
// ----------------------------------------
|
|
548
|
+
// Conversion
|
|
549
|
+
// ----------------------------------------
|
|
550
|
+
createSpriteSheetFromBinary() {
|
|
551
|
+
if (!this.aseFile) {
|
|
552
|
+
return { name: 'unknown', imagePath: '', frames: [] };
|
|
553
|
+
}
|
|
554
|
+
const frames = [];
|
|
555
|
+
const animations = {};
|
|
556
|
+
// Create frames
|
|
557
|
+
for (let i = 0; i < this.aseFile.frames.length; i++) {
|
|
558
|
+
frames.push({
|
|
559
|
+
name: `frame_${i}`,
|
|
560
|
+
x: 0,
|
|
561
|
+
y: i * this.aseFile.header.height,
|
|
562
|
+
width: this.aseFile.header.width,
|
|
563
|
+
height: this.aseFile.header.height,
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
// Create animations from tags
|
|
567
|
+
for (const tag of this.aseFile.tags) {
|
|
568
|
+
const animFrames = [];
|
|
569
|
+
for (let i = tag.fromFrame; i <= tag.toFrame; i++) {
|
|
570
|
+
animFrames.push({
|
|
571
|
+
index: i,
|
|
572
|
+
duration: this.aseFile.frames[i].duration,
|
|
573
|
+
x: 0,
|
|
574
|
+
y: i * this.aseFile.header.height,
|
|
575
|
+
width: this.aseFile.header.width,
|
|
576
|
+
height: this.aseFile.header.height,
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
animations[tag.name] = {
|
|
580
|
+
name: tag.name,
|
|
581
|
+
frames: animFrames,
|
|
582
|
+
loop: tag.repeat === 0, // 0 means infinite loop
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
// Default animation if no tags
|
|
586
|
+
if (Object.keys(animations).length === 0) {
|
|
587
|
+
const allFrames = this.aseFile.frames.map((f, i) => ({
|
|
588
|
+
index: i,
|
|
589
|
+
duration: f.duration,
|
|
590
|
+
x: 0,
|
|
591
|
+
y: i * this.aseFile.header.height,
|
|
592
|
+
width: this.aseFile.header.width,
|
|
593
|
+
height: this.aseFile.header.height,
|
|
594
|
+
}));
|
|
595
|
+
animations['default'] = {
|
|
596
|
+
name: 'default',
|
|
597
|
+
frames: allFrames,
|
|
598
|
+
loop: true,
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
return {
|
|
602
|
+
name: 'sprite',
|
|
603
|
+
imagePath: '',
|
|
604
|
+
frames,
|
|
605
|
+
animations,
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
createSpriteSheetAsset(spriteSheet, imagePath) {
|
|
609
|
+
var _a, _b, _c, _d, _e;
|
|
610
|
+
return {
|
|
611
|
+
id: this.generateId(),
|
|
612
|
+
name: spriteSheet.name,
|
|
613
|
+
type: 'animation',
|
|
614
|
+
path: imagePath,
|
|
615
|
+
data: {
|
|
616
|
+
frames: spriteSheet.frames,
|
|
617
|
+
animations: spriteSheet.animations,
|
|
618
|
+
width: (_a = this.aseFile) === null || _a === void 0 ? void 0 : _a.header.width,
|
|
619
|
+
height: (_b = this.aseFile) === null || _b === void 0 ? void 0 : _b.header.height,
|
|
620
|
+
colorDepth: (_c = this.aseFile) === null || _c === void 0 ? void 0 : _c.header.colorDepth,
|
|
621
|
+
layers: (_d = this.aseFile) === null || _d === void 0 ? void 0 : _d.layers.map((l) => ({
|
|
622
|
+
name: l.name,
|
|
623
|
+
type: l.type,
|
|
624
|
+
blendMode: l.blendMode,
|
|
625
|
+
opacity: l.opacity,
|
|
626
|
+
visible: l.visible,
|
|
627
|
+
})),
|
|
628
|
+
slices: (_e = this.aseFile) === null || _e === void 0 ? void 0 : _e.slices.map((s) => ({
|
|
629
|
+
name: s.name,
|
|
630
|
+
has9Slices: s.has9Slices,
|
|
631
|
+
hasPivot: s.hasPivot,
|
|
632
|
+
keys: s.keys,
|
|
633
|
+
})),
|
|
634
|
+
},
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
createPaletteAsset() {
|
|
638
|
+
var _a;
|
|
639
|
+
return {
|
|
640
|
+
id: this.generateId(),
|
|
641
|
+
name: 'palette',
|
|
642
|
+
type: 'data',
|
|
643
|
+
path: '',
|
|
644
|
+
data: {
|
|
645
|
+
colors: (_a = this.aseFile) === null || _a === void 0 ? void 0 : _a.palette.colors.map((c) => ({
|
|
646
|
+
r: c.red,
|
|
647
|
+
g: c.green,
|
|
648
|
+
b: c.blue,
|
|
649
|
+
a: c.alpha,
|
|
650
|
+
name: c.name,
|
|
651
|
+
})),
|
|
652
|
+
},
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
createSpriteScene(filePath) {
|
|
656
|
+
var _a, _b, _c, _d, _e;
|
|
657
|
+
const name = filePath.substring(filePath.lastIndexOf('/') + 1).replace(/\.\w+$/, '');
|
|
658
|
+
const width = ((_a = this.aseFile) === null || _a === void 0 ? void 0 : _a.header.width) || 64;
|
|
659
|
+
const height = ((_b = this.aseFile) === null || _b === void 0 ? void 0 : _b.header.height) || 64;
|
|
660
|
+
const entities = [];
|
|
661
|
+
// Create entity for each layer
|
|
662
|
+
if (this.aseFile) {
|
|
663
|
+
for (let i = 0; i < this.aseFile.layers.length; i++) {
|
|
664
|
+
const layer = this.aseFile.layers[i];
|
|
665
|
+
if (layer.type === 'normal') {
|
|
666
|
+
entities.push({
|
|
667
|
+
id: this.generateId(),
|
|
668
|
+
name: layer.name,
|
|
669
|
+
components: [
|
|
670
|
+
{
|
|
671
|
+
type: 'Transform',
|
|
672
|
+
data: { position: { x: 0, y: 0 }, rotation: 0, scale: { x: 1, y: 1 } },
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
type: 'Sprite',
|
|
676
|
+
data: {
|
|
677
|
+
layer: layer.name,
|
|
678
|
+
blendMode: layer.blendMode,
|
|
679
|
+
opacity: layer.opacity / 255,
|
|
680
|
+
},
|
|
681
|
+
},
|
|
682
|
+
],
|
|
683
|
+
children: [],
|
|
684
|
+
tags: ['layer'],
|
|
685
|
+
active: layer.visible,
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
// Add main sprite entity
|
|
691
|
+
entities.unshift({
|
|
692
|
+
id: this.generateId(),
|
|
693
|
+
name: name,
|
|
694
|
+
components: [
|
|
695
|
+
{
|
|
696
|
+
type: 'Transform',
|
|
697
|
+
data: { position: { x: width / 2, y: height / 2 }, rotation: 0, scale: { x: 1, y: 1 } },
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
type: 'AnimatedSprite',
|
|
701
|
+
data: {
|
|
702
|
+
spriteSheet: name,
|
|
703
|
+
currentAnimation: ((_d = (_c = this.aseFile) === null || _c === void 0 ? void 0 : _c.tags[0]) === null || _d === void 0 ? void 0 : _d.name) || 'default',
|
|
704
|
+
playing: true,
|
|
705
|
+
loop: true,
|
|
706
|
+
},
|
|
707
|
+
},
|
|
708
|
+
],
|
|
709
|
+
children: [],
|
|
710
|
+
tags: ['sprite'],
|
|
711
|
+
active: true,
|
|
712
|
+
});
|
|
713
|
+
return {
|
|
714
|
+
id: this.generateId(),
|
|
715
|
+
name,
|
|
716
|
+
entities,
|
|
717
|
+
settings: {
|
|
718
|
+
width,
|
|
719
|
+
height,
|
|
720
|
+
backgroundColor: ((_e = this.aseFile) === null || _e === void 0 ? void 0 : _e.header.colorDepth) === 8
|
|
721
|
+
? this.paletteColorToHex(this.aseFile.header.transparentIndex)
|
|
722
|
+
: '#00000000',
|
|
723
|
+
},
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
paletteColorToHex(index) {
|
|
727
|
+
var _a;
|
|
728
|
+
if (!((_a = this.aseFile) === null || _a === void 0 ? void 0 : _a.palette.colors[index]))
|
|
729
|
+
return '#000000';
|
|
730
|
+
const c = this.aseFile.palette.colors[index];
|
|
731
|
+
return `#${c.red.toString(16).padStart(2, '0')}${c.green.toString(16).padStart(2, '0')}${c.blue.toString(16).padStart(2, '0')}`;
|
|
732
|
+
}
|
|
733
|
+
// ----------------------------------------
|
|
734
|
+
// Helper Methods
|
|
735
|
+
// ----------------------------------------
|
|
736
|
+
async readFile(path) {
|
|
737
|
+
var _a;
|
|
738
|
+
if (typeof globalThis.process !== 'undefined' && ((_a = globalThis.process.versions) === null || _a === void 0 ? void 0 : _a.node)) {
|
|
739
|
+
const fs = await import('fs');
|
|
740
|
+
// Check if it's JSON or binary
|
|
741
|
+
if (path.endsWith('.json')) {
|
|
742
|
+
return fs.readFileSync(path, 'utf-8');
|
|
743
|
+
}
|
|
744
|
+
const buffer = fs.readFileSync(path);
|
|
745
|
+
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
746
|
+
}
|
|
747
|
+
else if (typeof fetch !== 'undefined') {
|
|
748
|
+
const response = await fetch(path);
|
|
749
|
+
if (path.endsWith('.json')) {
|
|
750
|
+
return response.text();
|
|
751
|
+
}
|
|
752
|
+
return response.arrayBuffer();
|
|
753
|
+
}
|
|
754
|
+
throw new Error('Unable to read file in current environment');
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
export { AsepriteImporter };
|
|
759
|
+
//# sourceMappingURL=AsepriteImporter.js.map
|