aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/compile_assets/loaders.odin5
-rw-r--r--tools/compile_assets/main.odin19
-rw-r--r--tools/compile_assets/tiled.odin175
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
}