diff options
Diffstat (limited to 'src/tiled')
| -rw-r--r-- | src/tiled/json.odin | 208 | ||||
| -rw-r--r-- | src/tiled/tiled.odin | 628 | ||||
| -rw-r--r-- | src/tiled/world.odin | 88 |
3 files changed, 0 insertions, 924 deletions
diff --git a/src/tiled/json.odin b/src/tiled/json.odin deleted file mode 100644 index 874430e..0000000 --- a/src/tiled/json.odin +++ /dev/null @@ -1,208 +0,0 @@ -package tiled - -Json_Map :: struct { - backgroundcolor: string, - class: string, - compressionlevel: i32, - width: i32, - height: i32, - infinite: bool, - layers: []Json_Layer, - nextlayerid: i32, - nextobjectid: i32, - orientation: string, - parallaxoriginx: f64, - parallaxoriginy: f64, - properties: []Json_Property, - renderorder: string, - staggeraxis: string, - staggerindex: string, - tilewidth: i32, - tileheight: i32, - tilesets: []Json_Tile_Set, -} - -Json_Layer :: struct { - class: string, - compression: string, - data: union { - []i32, - string, - }, - draworder: string, - encoding: string, - id: i32, - image: string, - image_width: i32, - image_height: i32, - layers: []Json_Layer, - // locked: bool, - name: string, - objects: []Json_Object, - offsetx: f64, - offsety: f64, - opacity: f32, - parallaxx: f64, - parallaxy: f64, - properties: []Json_Property, - repeatx: bool, - repeaty: bool, - tintcolor: string, - transparentcolor: string, - type: string, - visible: bool, - x: i32, - y: i32, - width: i32, - height: i32, -} - -Json_Object :: struct { - ellipse: bool, - gid: i32, - width: f64, - height: f64, - id: i32, - name: string, - point: bool, - polygon: []Json_Point, - polyline: []Json_Point, - properties: []Json_Property, - rotation: f64, - template: string, - text: Maybe(struct { - fontfamily: string, - color: string, - text: string, - halign: string, - valign: string, - pixelsize: i32, - wrap: bool, - underline: bool, - bold: bool, - italic: bool, - kerning: bool, - strikeout: bool, - }), - type: string, - visible: bool, - x: f64, - y: f64, -} - -Json_Tile_Set :: struct { - background_color: string, - class: string, - rows: i32, - columns: i32, - fillmode: string, - firstgid: i32, - grid: Maybe(Json_Grid), - image: string, - imagewidth: i32, - imageheight: i32, - margin: i32, - name: string, - objectalignment: string, - properties: []Json_Property, - source: string, - spacing: i32, - terrains: []Json_Terrain, - tilecount: i32, - tilewidth: i32, - tileheight: i32, - tileoffset: Json_Tile_Offset, - tilerendersize: string, - tiles: []Json_Tile, - transformations: Json_Transformations, - transparentcolor: string, - type: string, - wangsets: []Json_Wang_Set, -} - -Json_Grid :: struct { - width: i32, - height: i32, - orientation: string, -} - -Json_Tile_Offset :: struct { - x: i32, - y: i32, -} - -Json_Transformations :: struct { - hflip: bool, - vflip: bool, - rotate: bool, - preferuntransformed: bool, -} - -Json_Tile :: struct { - animation: []Json_Frame, - id: i32, - image: string, - imagewidth: i32, - imageheight: i32, - x: i32, - y: i32, - width: i32, - height: i32, - objectgroup: Json_Layer, - probability: f64, - properties: []Json_Property, - terrain: []i32, - type: string, -} - -Json_Frame :: struct { - duration: i32, - tileid: i32, -} - -Json_Terrain :: struct { - name: string, - properties: []Json_Property, - tile: i32, -} - -Json_Wang_Set :: struct { - class: string, - colors: []Json_Wang_Color, - name: string, - properties: []Json_Property, - tile: i32, - type: string, - wangtiles: []Json_Wang_Tile, -} - -Json_Wang_Color :: struct { - class: string, - color: string, - name: string, - probability: f64, - properties: []Json_Property, - tile: i32, -} - -Json_Wang_Tile :: struct { - tileid: i32, - wangid: []u8, -} - -Json_Object_Template :: struct { - tileset: Maybe(Json_Tile_Set), - object: Json_Object, -} - -Json_Property :: struct { - name: string, - type: string, - propertytype: string, - value: any, -} - -Json_Point :: struct { - x: f64, - y: f64, -} diff --git a/src/tiled/tiled.odin b/src/tiled/tiled.odin deleted file mode 100644 index d84c296..0000000 --- a/src/tiled/tiled.odin +++ /dev/null @@ -1,628 +0,0 @@ -package tiled - -import os "core:os/os2" -import mem "core:mem" -import strings "core:strings" -import "core:path/filepath" -import "core:log" -import "core:encoding/json" - -import rl "vendor:raylib" - -Color :: [4]f32 - -Error :: enum { - NONE = 0, - COULD_NOT_LOAD, - NON_ORTHOGONAL_NOT_SUPPORTED, - INFINITE_NOT_SUPPORTED, - ELLIPSE_OBJ_NOT_SUPPORTED, - POLYGON_OBJ_NOT_SUPPORTED, - POLYLINE_OBJ_NOT_SUPPORTED, - TEXT_OBJ_NOT_SUPPORTED, -} - -Axis :: enum { - X, - Y, -} - -Properties :: map[string]any - -Map :: struct { - // Currently, only orthogonal maps are allowed. Any non-orthogonal maps - // throw an error. - // Infinite maps will also throw an error for now. - - background_color: Color, - class: string, - - width: i32, - height: i32, - - layers: []Layer, - - next_layer_id: i32, - next_object_id: i32, - - parallax_origin_x: f64, - parallax_origin_y: f64, - - properties: Properties, - - // stagger_axis: Axis, - // stagger_offset: i32, // To replace stagger index. - - tile_width: i32, - tile_height: i32, - - tile_sets: []Tile_Set, - - tiles: [dynamic]Tile, -} - -Layer :: struct { - // Layers that aren't visible are entirely ignored. - name: string, - properties: Properties, - - parallax_x: f64, - parallax_y: f64, - - tint: Color, - id: i32, - - layer: union #no_nil { - Tile_Layer, - Image_Layer, - Object_Layer, - } -} - -Tile_Layer :: struct { - // Data will automatically become uncompressed. - width: i32, - height: i32, - data: []i32, -} - -Image_Layer :: struct { - texture: rl.Texture2D, - transparent_color: Color, - repeat_x: bool, - repeat_y: bool, -} - -Object_Layer :: []Object - -Object_Type :: enum { - POINT, - TILE, - RECT, -} - -Object :: struct { - // For now, anything that *isn't* one of these is ignored and - // a warning is thrown: - // - Point - // - Tile - // - Rectangle - // - // Objects that aren't visible will be ignored entirely. - - type: Object_Type, - name: string, - class: string, - properties: Properties, - position: [2]f32, - size: [2]f32, - tile_id: i32, -} - -Tile_Set :: struct { - // For now, any autotiling information is ignored. - - properties: Properties, - - rows: i32, - columns: i32, - - first_gid: i32, - - texture: rl.Texture2D, - margin: i32, - spacing: i32, - - tile_count: i32, - tile_width: i32, - tile_height: i32, - tile_offset: [2]i32, // in pixels - - tiles: []i32, // array of GIDs -} - -Tile :: struct { - // For now, animations are ignored. Support in the future is somewhat likely. - // And similar to above, autotiling information is ignored. - - is_image_collection: bool, - - tile_set: i32, // index for the tile set in Map - - id: i32, - gid: i32, - - texture: Maybe(rl.Texture2D), // If the tile is part of an image collection. - - // Where on the texture is this tile - src_start: [2]i32, - src_size: [2]i32, - - object_group: Layer, // Object layer for collisions. - - properties: Properties, -} - -load_map :: proc(path: string) -> (Map, Error) { - defer free_all(context.temp_allocator) - - jmap_text, read_err := os.read_entire_file(path, context.temp_allocator) - if read_err != nil { - log.errorf("Failed to read file %v (%v)", path, read_err) - return {}, .COULD_NOT_LOAD - } - - jmap: Json_Map - unmarshal_err := json.unmarshal( - jmap_text, - &jmap, - allocator = context.temp_allocator, - ) - if unmarshal_err != nil { - log.errorf("Failed to unmarshal file %v (%v)", path, unmarshal_err) - return {}, .COULD_NOT_LOAD - } - - // log.debug(jmap) - - tmap: Map - err := convert_json_map(jmap, &tmap, path) - if err != .NONE { - return {}, err - } - return tmap, .NONE -} - -delete_map :: proc(tmap: Map) { - delete(tmap.class) - delete(tmap.properties) - - for layer in tmap.layers { - delete_layer(layer) - } - delete(tmap.layers) - - for tile_set in tmap.tile_sets { - delete(tile_set.properties) - delete(tile_set.tiles) // all tiles are deleted later - rl.UnloadTexture(tile_set.texture) - } - delete(tmap.tile_sets) - - for tile in tmap.tiles { - delete(tile.properties) - - if tile.texture != nil { - rl.UnloadTexture(tile.texture.(rl.Texture2D)) - } - - delete_layer(tile.object_group) - } - delete(tmap.tiles) -} - -@(private) -delete_layer :: proc(layer: Layer) { - delete(layer.name) - delete(layer.properties) - - switch l in layer.layer { - case Tile_Layer: - delete(l.data) - case Image_Layer: - rl.UnloadTexture(l.texture) - case Object_Layer: - for obj in l { - delete(obj.name) - delete(obj.class) - delete(obj.properties) - } - delete(l) - } -} - -@(private) -convert_json_color :: proc(jcolor: string) -> Color { - return Color{1, 1, 1, 1} -} - -@(private) -convert_json_properties :: proc(jprops: []Json_Property) -> Properties { - props := make(Properties) - - for jprop in jprops { - props[jprop.name] = jprop.value - } - - return props -} - -@(private) -convert_json_map :: proc(jmap: Json_Map, tmap: ^Map, path: string) -> Error { - // ensure the map is orthogonal - if strings.compare(jmap.orientation, "orthogonal") != 0 { - return .NON_ORTHOGONAL_NOT_SUPPORTED - } - - // ensure the map is not infinite - if jmap.infinite { - return .INFINITE_NOT_SUPPORTED - } - - tmap.background_color = convert_json_color(jmap.backgroundcolor) - tmap.class = strings.clone(jmap.class) - - tmap.width = jmap.width - tmap.height = jmap.height - - tmap.tile_width = jmap.tilewidth - tmap.tile_height = jmap.tileheight - - tmap.next_layer_id = jmap.nextlayerid - tmap.next_object_id = jmap.nextobjectid - - tmap.parallax_origin_x = jmap.parallaxoriginx - tmap.parallax_origin_y = jmap.parallaxoriginy - - tmap.properties = convert_json_properties(jmap.properties) - - // TODO: flatten groups - layer_count := len(jmap.layers) - for jlayer in jmap.layers { - layer_count += len(jlayer.layers) // take into consideration groups - } - - tmap.layers = make([]Layer, layer_count) - current_index := 0 - - for jlayer in jmap.layers { - if !jlayer.visible { - continue // ignore hidden layers - } - - // FIXME: Some duplicated code down here - if strings.compare(jlayer.type, "group") == 0 { - for jlayer2 in jlayer.layers { - if !jlayer2.visible { - continue // ignore hidden layers - } - - layer, err := convert_json_layer(jlayer2) - if err != .NONE { - return err - } - tmap.layers[current_index] = layer - current_index += 1 - } - continue - } - - layer, err := convert_json_layer(jlayer) - if err != .NONE { - return err - } - tmap.layers[current_index] = layer - current_index += 1 - } - - tmap.tile_sets = make([]Tile_Set, len(jmap.tilesets)) - - res_dir := filepath.dir(path, allocator = context.temp_allocator) - - for jtile_set, i in jmap.tilesets { - tile_set, err := convert_json_tile_set(tmap, res_dir, jtile_set) - if err != .NONE { - return err - } - tmap.tile_sets[i] = tile_set - - for j in 0..<len(tmap.tiles) { - tmap.tiles[int(tile_set.first_gid) + j].tile_set = i32(i) - } - } - - return .NONE -} - -Map_Iterate_Callback :: proc(i32, i32, Tile, Tile_Set) - -iterate_map_tiles :: proc(tmap: Map, callback: Map_Iterate_Callback) { - for layer in tmap.layers { - tile_layer, ok := layer.layer.(Tile_Layer) - if !ok { - continue - } - - x: i32 = 0 - y: i32 = 0 - - for cell, i in tile_layer.data { - if cell > 0 { - tile := tmap.tiles[cell - 1] - tile_set := tmap.tile_sets[tile.tile_set] - callback(x, y, tile, tile_set) - } - - x += tmap.tile_width - if x > (tmap.width - 1) * tmap.tile_width { - x = 0 - y += tmap.tile_height - } - } - } -} - -test_cells :: proc(tmap: Map) { - for layer in tmap.layers { - tile_layer, ok := layer.layer.(Tile_Layer) - if !ok { - continue - } - - x: i32 = 0 - y: i32 = 0 - - for cell, i in tile_layer.data { - if cell > 0 { - log.debug(i, [2]i32{x, y}, cell) - } - - x += tmap.tile_width - if x > (tmap.width - 1) * tmap.tile_width { - x = 0 - y += tmap.tile_height - } - } - } -} - -draw_map :: proc(tmap: Map) { - draw_tile :: proc(x: i32, y: i32, tile: Tile, tile_set: Tile_Set) { - rl.DrawTexturePro( - tile_set.texture, - rl.Rectangle{ - x = f32(tile.src_start.x), - y = f32(tile.src_start.y), - width = f32(tile.src_size.x), - height = f32(tile.src_size.y), - }, - rl.Rectangle{ - x = f32(x), - y = f32(y), - width = f32(tile.src_size.x), - height = f32(tile.src_size.y), - }, - {0, 0}, - 0, - rl.WHITE, - ) - } - - iterate_map_tiles(tmap, draw_tile) -} - -@(private) -load_image :: proc(filename: string, res_dir: string) -> rl.Texture2D { - path := strings.concatenate({res_dir, "/", filename}) - defer delete(path) - - byte_path := make([]u8, len(path) + 1, context.temp_allocator) - copy(byte_path, path) - byte_path[len(path)] = 0 - return rl.LoadTexture(transmute(cstring)&byte_path[0]) -} - -@(private) -convert_json_layer :: proc(jlayer: Json_Layer) -> (Layer, Error) { - // TODO: uncompress tile data - - layer: Layer - - layer.name = strings.clone(jlayer.name) - - layer.parallax_x = jlayer.parallaxx - layer.parallax_y = jlayer.parallaxy - - layer.id = jlayer.id - - layer.tint = convert_json_color(jlayer.tintcolor) - - layer.properties = convert_json_properties(jlayer.properties) - - switch jlayer.type { - case "tilelayer": - tile_layer := Tile_Layer{ - width = jlayer.width, - height = jlayer.height, - } - - data := jlayer.data.([]i32) - tile_layer.data = make([]i32, len(data)) - copy(tile_layer.data, data) - - layer.layer = tile_layer - - case "objectgroup": - obj_layer := make(Object_Layer, len(jlayer.objects)) - - for jobj, i in jlayer.objects { - if !jobj.visible { - continue // ignore hidden objects - } - - obj, err := convert_json_object(jobj) - if err != .NONE { - return {}, err - } - obj_layer[i] = obj - } - - layer.layer = obj_layer - - case "imagelayer": - image_layer := Image_Layer{ - texture = load_image(jlayer.image, "res"), - transparent_color = convert_json_color(jlayer.transparentcolor), - repeat_x = jlayer.repeatx, - repeat_y = jlayer.repeaty, - } - - layer.layer = image_layer - - case "group": - // groups are handled elsewhere - } - - return layer, .NONE -} - -@(private) -convert_json_object :: proc(jobj: Json_Object) -> (Object, Error) { - obj: Object - - if jobj.ellipse { - return {}, .ELLIPSE_OBJ_NOT_SUPPORTED - } - if jobj.polygon != nil { - return {}, .POLYGON_OBJ_NOT_SUPPORTED - } - if jobj.polyline != nil { - return {}, .POLYLINE_OBJ_NOT_SUPPORTED - } - if jobj.text != nil { - return {}, .TEXT_OBJ_NOT_SUPPORTED - } - - obj.position = { - f32(jobj.x), - f32(jobj.y), - } - obj.size = { - f32(jobj.width), - f32(jobj.height), - } - obj.tile_id = jobj.gid - - obj.name = strings.clone(jobj.name) - obj.class = strings.clone(jobj.type) - obj.properties = convert_json_properties(jobj.properties) - - return obj, .NONE -} - -@(private) -convert_json_tile_set :: proc( - tmap: ^Map, - res_dir: string, - jtile_set: Json_Tile_Set, -) -> (Tile_Set, Error) { - if len(jtile_set.source) > 0 { - // Tileset links somewhere else - path := strings.concatenate({res_dir, "/", jtile_set.source}) - defer delete(path) - - data, err := os.read_entire_file(path, allocator = context.temp_allocator) - if err != nil { - log.errorf("Could not load external tile set '%v'", path) - return {}, .COULD_NOT_LOAD - } - - new_jtile_set: Json_Tile_Set - marshal_err := json.unmarshal( - data, - &new_jtile_set, - allocator = context.temp_allocator, - ) - if marshal_err != nil { - log.errorf("Could not unmarshal external tile set '%v'", path) - return {}, .COULD_NOT_LOAD - } - - return convert_json_tile_set(tmap, res_dir, new_jtile_set) - } - - tile_set: Tile_Set - - tile_set.rows = jtile_set.rows - tile_set.columns = jtile_set.columns - - tile_set.first_gid = jtile_set.firstgid - - tile_set.texture = load_image(jtile_set.image, res_dir) - tile_set.margin = jtile_set.margin - tile_set.spacing = jtile_set.spacing - - tile_set.tile_count = jtile_set.tilecount - tile_set.tile_width = jtile_set.tilewidth - tile_set.tile_height = jtile_set.tileheight - tile_set.tile_offset = { - jtile_set.tileoffset.x, - jtile_set.tileoffset.y, - } - - tile_set.properties = convert_json_properties(jtile_set.properties) - - tile_set.tiles = make([]i32, jtile_set.tilecount) - - // Ignore margin and spacing for now - // TODO: account for margin and spacing - tile_x := tile_set.texture.width / tile_set.tile_width - tile_y := tile_set.texture.height / tile_set.tile_height - - current_index := 0 - for y in 0..<tile_y { - for x in 0..<tile_x { - tile: Tile - - tile.id = i32(current_index) - - tile.src_start = { - x * tile_set.tile_width, - y * tile_set.tile_height, - } - tile.src_size = { - tile_set.tile_width, - tile_set.tile_height, - } - - current_index += 1 - - tile.gid = i32(len(tmap.tiles)) - append(&tmap.tiles, tile) - - tile_set.tiles[current_index - 1] = tile.gid - } - } - - for jtile in jtile_set.tiles { - ttile := &tmap.tiles[tile_set.tiles[jtile.id]] - object_group, err := convert_json_layer(jtile.objectgroup) - if err != .NONE { - return {}, err - } - ttile.object_group = object_group - ttile.properties = convert_json_properties(jtile.properties) - } - - return tile_set, .NONE -} diff --git a/src/tiled/world.odin b/src/tiled/world.odin deleted file mode 100644 index 0a13716..0000000 --- a/src/tiled/world.odin +++ /dev/null @@ -1,88 +0,0 @@ -package tiled - -import os "core:os/os2" -import "core:log" -import "core:encoding/json" -import "core:path/filepath" -import "core:strings" - -World_Room :: struct { - file_name: string `json:"fileName"`, - x: i32, - y: i32, - width: i32, - height: i32, -} - -res_dir: string -world: []World_Room -current_room: struct { - tmap: Map, - using room: World_Room, -} - -load_world :: proc(path: string) -> bool { - world_text, read_err := os.read_entire_file(path, context.temp_allocator) - if read_err != nil { - log.errorf("Failed to read file %v (%v)", path, read_err) - return false - } - - jworld: struct { - maps: []World_Room, - } - unmarshal_err := json.unmarshal( - world_text, - &jworld, - ) - if unmarshal_err != nil { - log.errorf("Failed to unmarshal file %v (%v)", path, unmarshal_err) - return false - } - - world = jworld.maps - res_dir = filepath.dir(path) - - return true -} - -delete_world :: proc() { - for room in world { - delete(room.file_name) - } - - delete_map(current_room.tmap) - delete(world) - delete(res_dir) -} - -open_new_room_at :: proc(pos: [2]i32) -> bool { - pos := pos - pos += {current_room.room.x, current_room.room.y} - - log.debug("trying to change room...", pos) - for room in world { - if strings.compare(room.file_name, current_room.room.file_name) == 0 { - continue - } - - if pos.x >= room.x && pos.x <= room.x + room.width \ - && pos.y >= room.y && pos.y <= room.y + room.height { - delete_map(current_room.tmap) - - path := strings.concatenate( - {res_dir, "/", room.file_name}, - allocator = context.temp_allocator, - ) - new_map, err := load_map(path) - if err != .NONE { - log.error("could not load new room") - return false - } - current_room.tmap = new_map - current_room.room = room - return true - } - } - return false -} |
