diff options
Diffstat (limited to 'tools/compile_assets')
| -rw-r--r-- | tools/compile_assets/loaders.odin | 5 | ||||
| -rw-r--r-- | tools/compile_assets/main.odin | 19 | ||||
| -rw-r--r-- | tools/compile_assets/tiled.odin | 175 |
3 files changed, 149 insertions, 50 deletions
diff --git a/tools/compile_assets/loaders.odin b/tools/compile_assets/loaders.odin index 097c483..eadbc44 100644 --- a/tools/compile_assets/loaders.odin +++ b/tools/compile_assets/loaders.odin @@ -21,7 +21,10 @@ load_room :: proc(path: string, file: ^os.File, _: ^os.File) { } load_tileset :: proc(path: string, _: ^os.File, _: ^os.File) { - load_json_tileset(path) + tileset_name := filepath.stem(path) + if tileset_name not_in tileset_gids { + load_json_tileset(path) + } } load_qoi :: proc(path: string, qoi: ^os.File, output: ^os.File) { diff --git a/tools/compile_assets/main.odin b/tools/compile_assets/main.odin index 67121fd..d8d8942 100644 --- a/tools/compile_assets/main.odin +++ b/tools/compile_assets/main.odin @@ -4,6 +4,7 @@ import os "core:os/os2" import "core:fmt" import "core:path/filepath" import "core:strings" +import "core:strconv" import "core:sort" COMPILED_DIR :: ".compiled-res/" @@ -29,9 +30,6 @@ Animation_Id :: enum { Room_Id :: enum { <room-enum>} -Tileset_Id :: enum { -<tileset-enum>} - Object_Type :: enum { <object-types>} @@ -44,9 +42,6 @@ animations: [Animation_Id]Animation_Resource = { rooms: [Room_Id]Room_Resource = { <room-load>} -tilesets: [Tileset_Id]Tileset_Resource = { -<tileset-load>} - tiles: []Tile_Resource = { <tiles-load>} @@ -57,7 +52,6 @@ Resource_Id :: union { Image_Id, Animation_Id, Room_Id, - Tileset_Id, } path_to_resource_id: map[string]Resource_Id = { @@ -69,7 +63,7 @@ animations: map[string]string rooms: map[string]string tiles: [dynamic]string -tilesets: map[string]string +loaded_tilesets: map[string]struct{} world: [dynamic]string @@ -311,21 +305,24 @@ main :: proc() { content = create_enum(content, "<image-enum>", images) content = create_enum(content, "<anim-enum>", animations) content = create_enum(content, "<room-enum>", rooms) - content = create_enum(content, "<tileset-enum>", tilesets) content = create_loads(content, "images", "<image-load>", images) content = create_loads(content, "animations", "<anim-load>", animations) content = create_loads(content, "rooms", "<room-load>", rooms) - content = create_loads(content, "tilesets", "<tileset-load>", tilesets) tile_loads := "" for tile, i in tiles { - if i == 0 { + if i == 0 || tile == "" { continue } + buf: [4]u8 + i_str := strconv.write_int(buf[:], i64(i), 10) + tile_loads = strings.concatenate({ tile_loads, " ", + i_str, + " = ", tile, ",\n", }, allocator = context.temp_allocator) diff --git a/tools/compile_assets/tiled.odin b/tools/compile_assets/tiled.odin index a5b6bed..196cb49 100644 --- a/tools/compile_assets/tiled.odin +++ b/tools/compile_assets/tiled.odin @@ -5,6 +5,8 @@ import "core:fmt" import "core:encoding/json" import "core:path/filepath" import "core:strings" +import "core:math/bits" +import "core:strconv" Rect :: struct { start: [2]f32, @@ -70,7 +72,7 @@ Json_Layer :: struct { Json_Object :: struct { ellipse: bool, - gid: i32, + gid: u32, width: f64, height: f64, id: i32, @@ -240,7 +242,35 @@ Gids :: struct { last: u32, } -gids: map[string]Gids +tileset_gids: map[string]Gids + +load_json_color :: proc(hex_str: string) -> [4]f32 { + if len(hex_str) == 0 { + return {0, 0, 0, 1} + } + + hex, hex_ok := strconv.parse_u64(hex_str[1:], 16) + if !hex_ok { + return {0, 0, 0, 1} + } + + a := u8((hex >> 24) & 0xFF) + r := u8((hex >> 16) & 0xFF) + g := u8((hex >> 8) & 0xFF) + b := u8(hex & 0xFF) + + if len(hex_str[1:]) == 2*3 { + // If there wasn't an alpha channel included, assume max + a = bits.U8_MAX + } + + return { + f32(r) / bits.U8_MAX, + f32(g) / bits.U8_MAX, + f32(b) / bits.U8_MAX, + f32(a) / bits.U8_MAX, + } +} load_json_world :: proc(path: string) { json_text, read_err := os.read_entire_file(path, context.temp_allocator) @@ -277,13 +307,13 @@ load_json_world :: proc(path: string) { } create_tile :: proc( - tileset_enum: string, + image_enum: string, rect: Rect, collisions: []Rect, ) -> string { line := fmt.aprintf( - "{{tileset=.%v, rect=%w, id=%w, collisions=%w}}", - tileset_enum, + "{{image=.%v, rect=%w, id=%w, collisions=%w}}", + image_enum, rect, len(tiles), collisions, @@ -292,7 +322,54 @@ create_tile :: proc( return line } +load_json_imageset :: proc(path: string, json_dat: Json_Tileset) { + last_id: i32 = 0 + + for tile in json_dat.tiles { + image_enum := strings.to_ada_case( + filepath.stem(tile.image), + context.temp_allocator, + ) + + collisions := make([dynamic]Rect, context.temp_allocator) + + for object in tile.objectgroup.objects { + append( + &collisions, + Rect{ + start = {f32(object.x), f32(object.y)}, + size = {f32(object.width), f32(object.height)} + }, + ) + } + + // Fill in any gaps with dummy tiles + // TODO: Find a solution that doesn't involve filling my exe with zeroed + // data + for i in 1..<(tile.id - last_id) { + append(&tiles, "") + } + + create_tile( + image_enum, + Rect{ + start = {0, 0}, + size = {f32(tile.imagewidth), f32(tile.imageheight)}, + }, + collisions[:], + ) + + last_id = tile.id + } +} + load_json_tileset :: proc(path: string) { + if filepath.stem(path) in loaded_tilesets { + return + } + + loaded_tilesets[filepath.stem(path)] = {} + json_text, read_err := os.read_entire_file(path, context.temp_allocator) if read_err != nil { die("Could not load tileset %v (%v)", path, read_err) @@ -308,30 +385,29 @@ load_json_tileset :: proc(path: string) { die("Failed to parse tileset %v (%v)", path, unmarshal_err) } - tileset_enum := strings.to_ada_case( - filepath.stem(path), - allocator = context.temp_allocator, - ) - - image_enum := strings.to_ada_case( - filepath.stem(json_dat.image), - allocator = context.temp_allocator, - ) - - tiles_x := json_dat.imagewidth / json_dat.tilewidth - tiles_y := json_dat.imageheight / json_dat.tileheight - - local_tiles := make([dynamic]string, allocator = context.temp_allocator) - - tile_size: [2]f32 = {f32(json_dat.tilewidth), f32(json_dat.tileheight)} - first_gid := u32(len(tiles)) - gids[filepath.stem(path)] = { + tileset_gids[filepath.stem(path)] = { first = first_gid, last = u32(len(tiles) + int(json_dat.tilecount)), } + // No image found; this is a image set + if json_dat.imagewidth == 0 && + json_dat.imageheight == 0 && + json_dat.image == "" { + load_json_imageset(path, json_dat) + + gids := &tileset_gids[filepath.stem(path)] + gids.last = u32(len(tiles)) + return + } + + image_enum := strings.to_ada_case( + filepath.stem(json_dat.image), + allocator = context.temp_allocator, + ) + collisions := make([][dynamic]Rect, json_dat.tilecount) defer { for collision in collisions { @@ -353,26 +429,25 @@ load_json_tileset :: proc(path: string) { } } + tiles_x := json_dat.imagewidth / json_dat.tilewidth + tiles_y := json_dat.imageheight / json_dat.tileheight + tile_size := [2]f32{f32(json_dat.tilewidth), f32(json_dat.tileheight)} + for y in 0..<tiles_y { for x in 0..<tiles_x { - append(&local_tiles, create_tile( - tileset_enum, + create_tile( + image_enum, Rect{ start = {f32(x * json_dat.tilewidth), f32(y * json_dat.tileheight)}, size = tile_size, }, collisions[y * tiles_x + x][:], - )) + ) } } - gids := make([]u32, len(local_tiles), context.temp_allocator) - for tile, i in local_tiles { - gids[i] = first_gid + u32(i) - } - - line := fmt.aprintf("{{tiles=%w, image=.%v}}", gids, image_enum) - tilesets[filepath.stem(path)] = line + gids := &tileset_gids[filepath.stem(path)] + gids.last = u32(len(tiles)) } load_json_room :: proc(path: string, file: ^os.File) { @@ -396,6 +471,8 @@ load_json_room :: proc(path: string, file: ^os.File) { tile_width := json_dat.tilewidth tile_height := json_dat.tileheight + + color := load_json_color(json_dat.backgroundcolor) tiled_to_real_gid: map[i32]u32 defer delete(tiled_to_real_gid) @@ -404,14 +481,14 @@ load_json_room :: proc(path: string, file: ^os.File) { id: i32 = 1 for tileset in json_dat.tilesets { tileset_name := filepath.stem(tileset.source) - gid, exists := gids[tileset_name] + gid, exists := tileset_gids[tileset_name] if !exists { load_json_tileset(strings.concatenate({ filepath.dir(path, context.temp_allocator), "/", tileset.source, })) - gid = gids[tileset_name] + gid = tileset_gids[tileset_name] } for i in gid.first..<gid.last { @@ -449,7 +526,8 @@ load_json_room :: proc(path: string, file: ^os.File) { parallax := [2]f32{f32(layer.parallaxx), f32(layer.parallaxy)} for obj in layer.objects { - type_name := strings.to_ada_case(obj.type) + obj_type := obj.type if obj.type != "" else "prop" + type_name := strings.to_ada_case(obj_type) // `object_type_names` now owns `type_name`; freed in main if type_name in object_type_names { @@ -491,9 +569,29 @@ load_json_room :: proc(path: string, file: ^os.File) { properties[property.name] = value } + tile_id: Maybe(u32) = nil + if obj.gid != 0 { + flip_flags := (obj.gid & 0x80000000) >> 28 + + if flip_flags & 0b1000 != 0 { + size.x *= -1 + } + if flip_flags & 0b0100 != 0 { + size.y *= -1 + } + + tiled_id := (obj.gid << 4) >> 4 + + fmt.printfln("%032b %v %v %032b %x", obj.gid, obj.gid, tiled_id, flip_flags, flip_flags) + + tile_id = tiled_to_real_gid[i32(tiled_id)] + // tile_id = u32(obj.gid) + } + line := fmt.tprintf( - "{{type = .%v, pos = %w, size = %w, parallax = %w, properties = %w}}", + "{{type = .%v, tile_id = %v, pos = %w, size = %w, parallax = %w, properties = %w}}", type_name, + tile_id, pos, size, parallax, @@ -518,13 +616,14 @@ load_json_room :: proc(path: string, file: ^os.File) { } line := fmt.aprintf( - "{{width=%v, height=%v, tile_width=%v, tile_height=%v, layers=%w, objects={{%v}}, background_image=nil}}", + "{{width=%v, height=%v, tile_width=%v, tile_height=%v, layers=%w, objects={{%v}}, background_color=Color%w, background_images={{}} }}", width, height, tile_width, tile_height, layers[:], objects_arr_str, + color, ) rooms[filepath.stem(path)] = line } |
