222 lines
5.6 KiB
Odin
222 lines
5.6 KiB
Odin
package main
|
|
|
|
import "base:runtime"
|
|
import "core:encoding/json"
|
|
import "core:fmt"
|
|
import "core:os"
|
|
|
|
Map_File :: struct {
|
|
compression_level: int `json:"compressionlevel"`,
|
|
height: int `json:"height"`,
|
|
infinite: bool `json:"infinite"`,
|
|
layers: []Layer `json:"layers"`,
|
|
next_layer_id: int `json:"nextlayerid"`,
|
|
next_object_id: int `json:"nextobjectid"`,
|
|
orientation: string `json:"orientation"`,
|
|
render_order: string `json:"renderorder"`,
|
|
tiled_version: string `json:"tiledversion"`,
|
|
tile_height: int `json:"tileheight"`,
|
|
tile_sets: []Tileset `json:"tilesets"`,
|
|
tile_width: int `json:"tilewidth"`,
|
|
type: string `json:"type"`,
|
|
version: string `json:"version"`,
|
|
width: int `json:"width"`,
|
|
}
|
|
|
|
Layer :: struct {
|
|
data: []int `json:"data"`,
|
|
height: int `json:"height"`,
|
|
id: int `json:"id"`,
|
|
name: string `json:"name"`,
|
|
opacity: f32 `json:"opacity"`,
|
|
type: string `json:"type"`,
|
|
visible: bool `json:"visible"`,
|
|
width: int `json:"width"`,
|
|
x: int `json:"x"`,
|
|
y: int `json:"y"`,
|
|
}
|
|
|
|
Tileset :: struct {
|
|
first_gid: int `json:"firstgid"`,
|
|
source: string `json:"source"`,
|
|
}
|
|
|
|
Tileset_File :: struct {
|
|
columns: int `json:"columns"`,
|
|
image: string `json:"image"`,
|
|
image_height: int `json:"imageheight"`,
|
|
image_width: int `json:"imagewidth"`,
|
|
margin: int `json:"margin"`,
|
|
name: string `json:"name"`,
|
|
spacing: int `json:"spacing"`,
|
|
tile_count: int `json:"tilecount"`,
|
|
tiled_version: string `json:"tiledversion"`,
|
|
tile_height: int `json:"tileheight"`,
|
|
tile_width: int `json:"tilewidth"`,
|
|
type: string `json:"type"`,
|
|
version: string `json:"version"`,
|
|
}
|
|
|
|
Tileset_Load_Error_Type :: enum {
|
|
None,
|
|
Err_Loading_File,
|
|
Err_Unmarshal,
|
|
}
|
|
|
|
Tileset_Load_Error :: struct {
|
|
type: Tileset_Load_Error_Type,
|
|
msg: string,
|
|
}
|
|
|
|
Tileset_Data :: struct {
|
|
name: string,
|
|
image: string,
|
|
tile_width: i32,
|
|
tile_height: i32,
|
|
columns: i32,
|
|
rows: i32,
|
|
margin: i32,
|
|
spacing: i32,
|
|
tile_count: i32,
|
|
}
|
|
|
|
Map_Load_Error_Type :: enum {
|
|
None,
|
|
Err_Loading_File,
|
|
Err_Unmarshal,
|
|
}
|
|
|
|
Map_Load_Error :: struct {
|
|
type: Map_Load_Error_Type,
|
|
msg: string,
|
|
}
|
|
|
|
Map :: struct {
|
|
width: i32,
|
|
height: i32,
|
|
layers: []Layer_Data,
|
|
}
|
|
|
|
Layer_Data :: struct {
|
|
data: [][]i32,
|
|
}
|
|
|
|
load_map :: proc(
|
|
path: string,
|
|
allocator: runtime.Allocator,
|
|
) -> (
|
|
map_out: Map,
|
|
err: Map_Load_Error,
|
|
) {
|
|
|
|
context.allocator = allocator
|
|
|
|
cfg_data, os_err := os.read_entire_file(path, context.allocator)
|
|
if os_err != os.General_Error.None {
|
|
return {}, Map_Load_Error{type = .Err_Loading_File, msg = fmt.aprintf("Error reading file: %v (%v)", path, os_err)}
|
|
}
|
|
|
|
unm_map: Map_File
|
|
unm_err := json.unmarshal(cfg_data, &unm_map)
|
|
if unm_err != nil {
|
|
return {}, Map_Load_Error{type = .Err_Unmarshal, msg = fmt.aprintf("Error unmarshalling file: %v (%v)\nOnly Tiled version 1.11.2 is supported", path, unm_err)}
|
|
}
|
|
|
|
assert(!unm_map.infinite, "Infinite maps are not supported")
|
|
assert(
|
|
unm_map.orientation == "orthogonal",
|
|
"Only orthogonal maps are supported",
|
|
)
|
|
assert(
|
|
unm_map.render_order == "right-down",
|
|
"Only right-down maps are supported",
|
|
)
|
|
assert(
|
|
unm_map.tile_height == 16 && unm_map.tile_width == 16,
|
|
"Only 16x16 tiles are supported",
|
|
)
|
|
|
|
|
|
if len(unm_map.layers) == 0 {
|
|
return {}, Map_Load_Error{type = .Err_Unmarshal, msg = fmt.aprintf("No layers found in file: %v", path)}
|
|
}
|
|
if len(unm_map.tile_sets) == 0 {
|
|
return {}, Map_Load_Error{type = .Err_Unmarshal, msg = fmt.aprintf("No tilesets found in file: %v", path)}
|
|
}
|
|
for layer in unm_map.layers {
|
|
assert(
|
|
layer.type == "tilelayer",
|
|
"Only layers with type 'tilelayer' are supported",
|
|
)
|
|
}
|
|
|
|
map_out.width = i32(unm_map.width)
|
|
map_out.height = i32(unm_map.height)
|
|
|
|
|
|
map_out.layers = make([]Layer_Data, len(unm_map.layers))
|
|
for &out, li in map_out.layers {
|
|
src := unm_map.layers[li]
|
|
out.data = make([][]i32, src.height)
|
|
for row in 0 ..< src.height {
|
|
out.data[row] = make([]i32, src.width)
|
|
for col in 0 ..< src.width {
|
|
out.data[row][col] = i32(src.data[row * src.width + col])
|
|
}
|
|
}
|
|
}
|
|
|
|
// for layer in unm_map.layers {
|
|
// for tile, tile_id in layer.data {
|
|
// map_out.data[tile_id / layer.width][tile_id % layer.width] = i32(
|
|
// tile,
|
|
// )
|
|
// }
|
|
// }
|
|
|
|
return
|
|
}
|
|
|
|
load_tileset :: proc(
|
|
path: string,
|
|
allocator: runtime.Allocator,
|
|
) -> (
|
|
tileset_out: Tileset_Data,
|
|
err: Tileset_Load_Error,
|
|
) {
|
|
|
|
context.allocator = allocator
|
|
|
|
cfg_data, os_err := os.read_entire_file(path, context.allocator)
|
|
if os_err != os.General_Error.None {
|
|
return {}, Tileset_Load_Error{type = .Err_Loading_File, msg = fmt.aprintf("Error reading file: %v (%v)", path, os_err)}
|
|
}
|
|
|
|
unm: Tileset_File
|
|
unm_err := json.unmarshal(cfg_data, &unm)
|
|
if unm_err != nil {
|
|
return {}, Tileset_Load_Error{type = .Err_Unmarshal, msg = fmt.aprintf("Error unmarshalling file: %v (%v)\nOnly Tiled version 1.11.2 is supported", path, unm_err)}
|
|
}
|
|
|
|
assert(unm.type == "tileset", "Only files with type 'tileset' are supported")
|
|
assert(
|
|
unm.tile_height > 0 && unm.tile_width > 0,
|
|
"Only positive tile sizes are supported",
|
|
)
|
|
assert(unm.columns > 0, "Tileset must have at least one column")
|
|
|
|
tileset_out.name = unm.name
|
|
tileset_out.image = unm.image
|
|
tileset_out.tile_width = i32(unm.tile_width)
|
|
tileset_out.tile_height = i32(unm.tile_height)
|
|
tileset_out.columns = i32(unm.columns)
|
|
tileset_out.rows = i32(
|
|
(unm.image_height - 2 * unm.margin + unm.spacing) / (unm.tile_height + unm.spacing),
|
|
)
|
|
tileset_out.margin = i32(unm.margin)
|
|
tileset_out.spacing = i32(unm.spacing)
|
|
tileset_out.tile_count = i32(unm.tile_count)
|
|
|
|
return
|
|
}
|