aboutsummaryrefslogtreecommitdiff
path: root/tools/compile_assets/loaders.odin
diff options
context:
space:
mode:
Diffstat (limited to 'tools/compile_assets/loaders.odin')
-rw-r--r--tools/compile_assets/loaders.odin199
1 files changed, 199 insertions, 0 deletions
diff --git a/tools/compile_assets/loaders.odin b/tools/compile_assets/loaders.odin
new file mode 100644
index 0000000..136ba07
--- /dev/null
+++ b/tools/compile_assets/loaders.odin
@@ -0,0 +1,199 @@
+package assets_gen
+
+import os "core:os/os2"
+import "core:fmt"
+import "core:strings"
+import "core:path/filepath"
+import "core:image"
+import "core:image/png"
+import "core:image/qoi"
+
+import ase "aseprite"
+import aseutil "aseprite/utils"
+
+load_map :: proc(path: string, _: ^os.File, _: ^os.File) {
+ line := fmt.aprintf("#load(\"%v\")", path)
+ maps[filepath.stem(path)] = line
+ paths_to_res_type[path] = "Map_Id"
+}
+
+load_tileset :: proc(path: string, _: ^os.File, _: ^os.File) {
+ line := fmt.aprintf("#load(\"%v\")", path)
+ tilesets[filepath.stem(path)] = line
+ paths_to_res_type[path] = "Tileset_Id"
+}
+
+load_qoi :: proc(path: string, qoi: ^os.File, output: ^os.File) {
+ line := fmt.aprintf("{{data = #load(%w)}}", path)
+
+ images[filepath.stem(path)] = line
+ paths_to_res_type[path] = "Image_Id"
+}
+
+load_png :: proc(path: string, png_file: ^os.File, output: ^os.File) {
+ // Convert all PNG files to QOI and store those
+
+ png_bytes, read_err := os.read_entire_file(png_file, context.allocator)
+ if read_err != nil {
+ die("Could not read file (%v)", read_err)
+ }
+ defer delete(png_bytes)
+
+ img, png_err := png.load_from_bytes(png_bytes)
+ if png_err != nil {
+ die("Could not parse file (%v)", png_err)
+ }
+ defer image.destroy(img)
+
+ info, fi_err := os.fstat(png_file, allocator = context.temp_allocator)
+ if fi_err != nil {
+ die("Could not load file info (%v)", fi_err)
+ }
+
+ compiled_path := strings.concatenate(
+ {COMPILED_DIR, filepath.stem(info.name), ".qoi"},
+ allocator = context.temp_allocator,
+ )
+ qoi_err := qoi.save_to_file(compiled_path, img)
+
+ if qoi_err != nil {
+ die("Could not convert PNG to QOI (%v)", qoi_err)
+ }
+
+ absolute_path, abs_ok := filepath.abs(
+ compiled_path,
+ allocator = context.temp_allocator,
+ )
+ if !abs_ok {
+ die("Could not find absolute path to a compiled file (%v)", compiled_path)
+ }
+
+ line := fmt.aprintf("{{data = #load(%w)}}", absolute_path)
+
+ images[filepath.stem(path)] = line
+ paths_to_res_type[path] = "Image_Id"
+}
+
+@(private="file")
+load_sprite_sheet :: proc(path: string, doc: ^ase.Document) {
+ sprite_sheet, ss_err := aseutil.create_sprite_sheet(doc, {
+ size = {int(doc.header.width), int(doc.header.height)},
+ count = int(doc.header.frames),
+ })
+ if ss_err != nil {
+ die(
+ "Could not create sprite sheet from aseprite file %v (%v)",
+ path,
+ ss_err,
+ )
+ }
+ defer aseutil.destroy(sprite_sheet)
+
+ fmt.println("loaded ss")
+
+ pixels := make(
+ []image.RGBA_Pixel,
+ sprite_sheet.width * sprite_sheet.height,
+ allocator = context.temp_allocator,
+ )
+
+ i := 0
+ for i < sprite_sheet.width * sprite_sheet.height {
+ channel := i * 4
+ pixels[i].r = sprite_sheet.data[channel + 0]
+ pixels[i].g = sprite_sheet.data[channel + 1]
+ pixels[i].b = sprite_sheet.data[channel + 2]
+ pixels[i].a = sprite_sheet.data[channel + 3]
+ i += 1
+ }
+
+ img, img_ok := image.pixels_to_image(
+ pixels,
+ sprite_sheet.width,
+ sprite_sheet.height,
+ )
+ if !img_ok {
+ die("Could not create sprite sheet image %v", path)
+ }
+
+ compiled_path := strings.concatenate(
+ {COMPILED_DIR, filepath.stem(path), "-sheet.qoi"},
+ allocator = context.temp_allocator,
+ )
+ qoi_err := qoi.save_to_file(compiled_path, &img)
+
+ if qoi_err != nil {
+ die("Could not save spritesheet %v (%v)", path, qoi_err)
+ }
+
+ absolute_path, abs_ok := filepath.abs(
+ compiled_path,
+ allocator = context.temp_allocator,
+ )
+ if !abs_ok {
+ die("Could not find absolute path to a compiled file (%v)", compiled_path)
+ }
+
+ line := fmt.aprintf("{{data = #load(%w)}}", absolute_path)
+ images[filepath.stem(path)] = line
+ paths_to_res_type[path] = "Image_Id"
+}
+
+@(private="file")
+load_animation :: proc(path: string, doc: ^ase.Document) {
+ tags: map[string]struct{
+ from: i32,
+ to: i32,
+ }
+ defer delete(tags)
+
+ for frame in doc.frames {
+ for chunk in frame.chunks {
+ bin_tags, is_tags := chunk.(ase.Tags_Chunk)
+ if !is_tags {
+ continue
+ }
+
+ for bin_tag in bin_tags {
+ tags[bin_tag.name] = {
+ from = i32(bin_tag.from_frame),
+ to = i32(bin_tag.to_frame),
+ }
+ }
+ }
+ }
+
+ frame_durations := make([]i32, doc.header.frames)
+ defer delete(frame_durations)
+
+ i := 0
+ for frame in doc.frames {
+ frame_durations[i] = i32(frame.header.duration)
+ i += 1
+ }
+
+ line := fmt.aprintf(
+ "{{frame_count = %w, frame_durations = %w, tags = %w}}",
+ len(frame_durations),
+ frame_durations[:],
+ tags,
+ )
+
+ animations[filepath.stem(path)] = line
+}
+
+load_ase :: proc(path: string, ase_file: ^os.File, output: ^os.File) {
+ doc: ase.Document
+ defer ase.destroy_doc(&doc)
+
+ unmarshal_err := ase.unmarshal(&doc, path, alloc = context.temp_allocator)
+ if unmarshal_err != nil {
+ die("Could not unmarshal aseprite file %v (%v)", path, unmarshal_err)
+ }
+
+ // Load sprite sheet
+ load_sprite_sheet(path, &doc)
+
+ // Load animation
+ load_animation(path, &doc)
+}