Parse ldtk file without error
parent
c9daf228ad
commit
c8c86dd11d
177
src/LDtk.zig
177
src/LDtk.zig
|
@ -1,57 +1,50 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn parse(allocator: std.mem.Allocator, json_string: []const u8) !Root {
|
// pub fn parse(parser: *std.json.Parser, json_string: []const u8) !std.json.Value {
|
||||||
@setEvalBranchQuota(10_0000);
|
// const value_tree = try parser.parse(json_string);
|
||||||
var tokens = std.json.TokenStream.init(json_string);
|
// value_tree.root.dump();
|
||||||
const root = try std.json.parse(Root, &tokens, .{ .allocator = allocator });
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parseFree(allocator: std.mem.Allocator, root: Root) void {
|
// const root_obj = switch (value_tree.root) {
|
||||||
std.json.parseFree(Root, root, .{ .allocator = allocator });
|
// .Object => |obj| obj,
|
||||||
}
|
// else => return error.InvalidRoot,
|
||||||
|
// };
|
||||||
|
// _ = root_obj;
|
||||||
|
// // const root = Root {
|
||||||
|
// // name: root_obj.get("name") orelse error.InvalidRoot,
|
||||||
|
// // version: root_obj.get("jsonVersion") orelse error.InvalidRoot,
|
||||||
|
// // defaultPivotX: root_obj.get("defaultPivotX") orelse error.InvalidRoot,
|
||||||
|
// // defaultPivotY: root_obj.get("defaultPivotY") orelse error.InvalidRoot,
|
||||||
|
// // defaultGridSize: root_obj.get("defaultGridSize") orelse error.InvalidRoot,
|
||||||
|
// // name: root_obj.get("name") orelse error.InvalidRoot,
|
||||||
|
// // };
|
||||||
|
|
||||||
|
// return Root{};
|
||||||
|
// }
|
||||||
|
|
||||||
/// 1. LDtk Json root
|
/// 1. LDtk Json root
|
||||||
const Root = struct {
|
pub const Root = struct {
|
||||||
__header__: __Header__,
|
|
||||||
|
|
||||||
name: []const u8,
|
|
||||||
jsonVersion: u64,
|
|
||||||
defaultPivotX: f64,
|
|
||||||
defaultPivotY: f64,
|
|
||||||
defaultGridSize: u64,
|
|
||||||
bgColor: []const u8,
|
bgColor: []const u8,
|
||||||
nextUid: u64,
|
defs: ?Definitions = null,
|
||||||
|
externalLevels: bool,
|
||||||
defs: Definitions,
|
jsonVersion: []const u8,
|
||||||
|
|
||||||
levels: []Level,
|
levels: []Level,
|
||||||
|
worldGridHeight: ?i64 = null,
|
||||||
worldGridHeight: ?u64 = null,
|
worldGridWidth: ?i64 = null,
|
||||||
worldGridWidth: ?u64 = null,
|
|
||||||
worldLayout: ?WorldLayout = null,
|
worldLayout: ?WorldLayout = null,
|
||||||
worlds: []World,
|
worlds: ?[]World = null,
|
||||||
};
|
|
||||||
|
|
||||||
const __Header__ = struct {
|
|
||||||
fileType: []const u8,
|
|
||||||
app: []const u8,
|
|
||||||
appAuthor: []const u8,
|
|
||||||
appVersion: []const u8,
|
|
||||||
url: []const u8,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 1.1. World
|
/// 1.1. World
|
||||||
const World = struct {
|
pub const World = struct {
|
||||||
identifier: []const u8,
|
identifier: []const u8,
|
||||||
iid: []const u8,
|
iid: []const u8,
|
||||||
levels: []Level,
|
levels: []Level,
|
||||||
worldGridHeight: u64,
|
worldGridHeight: i64,
|
||||||
worldGridWidth: u64,
|
worldGridWidth: i64,
|
||||||
worldLayout: WorldLayout,
|
worldLayout: WorldLayout,
|
||||||
};
|
};
|
||||||
|
|
||||||
const WorldLayout = enum {
|
pub const WorldLayout = enum {
|
||||||
Free,
|
Free,
|
||||||
GridVania,
|
GridVania,
|
||||||
LinearHorizontal,
|
LinearHorizontal,
|
||||||
|
@ -59,59 +52,61 @@ const WorldLayout = enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 2. Level
|
/// 2. Level
|
||||||
const Level = struct {
|
pub const Level = struct {
|
||||||
__bgColor: []const u8,
|
__bgColor: ?[]const u8,
|
||||||
__bgPos: ?struct {
|
__bgPos: ?struct {
|
||||||
cropRect: [4]f64,
|
cropRect: [4]f64,
|
||||||
scale: [2]f64,
|
scale: [2]f64,
|
||||||
topLeftPx: [2]i64,
|
topLeftPx: [2]i64,
|
||||||
},
|
},
|
||||||
__neighbours: []struct {
|
__neighbours: []Neighbour,
|
||||||
dir: []const u8,
|
|
||||||
levelIid: []const u8,
|
|
||||||
levelUid: ?u64 = null,
|
|
||||||
},
|
|
||||||
bgRelPath: ?[]const u8,
|
bgRelPath: ?[]const u8,
|
||||||
externalRelPath: ?[]const u8,
|
externalRelPath: ?[]const u8,
|
||||||
fieldInstances: []FieldInstance,
|
fieldInstances: []FieldInstance,
|
||||||
identifier: []const u8,
|
identifier: []const u8,
|
||||||
iid: []const u8,
|
iid: []const u8,
|
||||||
layerInstances: ?[]LayerInstance,
|
layerInstances: ?[]LayerInstance,
|
||||||
pxHei: u64,
|
pxHei: i64,
|
||||||
pxWid: u64,
|
pxWid: i64,
|
||||||
uid: u64,
|
uid: i64,
|
||||||
worldDepth: i64,
|
worldDepth: i64,
|
||||||
worldX: i64,
|
worldX: i64,
|
||||||
worldY: i64,
|
worldY: i64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Neighbour = struct {
|
||||||
|
dir: []const u8,
|
||||||
|
levelIid: []const u8,
|
||||||
|
levelUid: ?i64 = null,
|
||||||
|
};
|
||||||
|
|
||||||
/// 2.1. Layer instance
|
/// 2.1. Layer instance
|
||||||
const LayerInstance = struct {
|
const LayerInstance = struct {
|
||||||
__cHei: u64,
|
__cHei: i64,
|
||||||
__cWid: u64,
|
__cWid: i64,
|
||||||
__gridSize: u64,
|
__gridSize: i64,
|
||||||
__identifier: []const u8,
|
__identifier: []const u8,
|
||||||
__opacity: f64,
|
__opacity: f64,
|
||||||
__pxTotalOffsetX: i64,
|
__pxTotalOffsetX: i64,
|
||||||
__pxTotalOffsetY: i64,
|
__pxTotalOffsetY: i64,
|
||||||
__tilesetDefUid: ?u64,
|
__tilesetDefUid: ?i64,
|
||||||
__tilesetRelPath: ?[]const u8,
|
__tilesetRelPath: ?[]const u8,
|
||||||
__type: []const u8,
|
__type: []const u8,
|
||||||
autoLayerTiles: []TileInstance,
|
autoLayerTiles: []TileInstance,
|
||||||
entityInstances: []EntityInstance,
|
entityInstances: []EntityInstance,
|
||||||
gridTiles: []TileInstance,
|
gridTiles: []TileInstance,
|
||||||
iid: []const u8,
|
iid: []const u8,
|
||||||
intGridCsv: []u64,
|
intGridCsv: []i64,
|
||||||
layerDefUid: u64,
|
layerDefUid: i64,
|
||||||
levelId: u64,
|
levelId: i64,
|
||||||
overrideTilesetUid: ?u64,
|
overrideTilesetUid: ?i64,
|
||||||
pxOffsetX: u64,
|
pxOffsetX: i64,
|
||||||
pxOffsetY: u64,
|
pxOffsetY: i64,
|
||||||
visible: bool,
|
visible: bool,
|
||||||
/// WARNING: this deprecated value is no longer exported since version 1.0.0
|
/// WARNING: this deprecated value is no longer exported since version 1.0.0
|
||||||
/// Replaced by: intGridCsv
|
/// Replaced by: intGridCsv
|
||||||
intGrid: ?[][]const u8 = null,
|
intGrid: ?[][]const u8 = null,
|
||||||
// seed: u64,
|
// seed: i64,
|
||||||
// autoTiles: []AutoTile,
|
// autoTiles: []AutoTile,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -127,7 +122,7 @@ const TileInstance = struct {
|
||||||
f: FlipBits,
|
f: FlipBits,
|
||||||
px: [2]i64,
|
px: [2]i64,
|
||||||
src: [2]i64,
|
src: [2]i64,
|
||||||
t: u64,
|
t: i64,
|
||||||
};
|
};
|
||||||
|
|
||||||
const FlipBits = enum(u4) {
|
const FlipBits = enum(u4) {
|
||||||
|
@ -145,23 +140,23 @@ const EntityInstance = struct {
|
||||||
__smartColor: []const u8,
|
__smartColor: []const u8,
|
||||||
__tags: [][]const u8,
|
__tags: [][]const u8,
|
||||||
__tile: ?TilesetRectangle,
|
__tile: ?TilesetRectangle,
|
||||||
defUid: u64,
|
defUid: i64,
|
||||||
fieldInstances: []FieldInstance,
|
fieldInstances: []FieldInstance,
|
||||||
height: u64,
|
height: i64,
|
||||||
iid: []const u8,
|
iid: []const u8,
|
||||||
px: [2]i64,
|
px: [2]i64,
|
||||||
width: u64,
|
width: i64,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 2.4. Field Instance
|
/// 2.4. Field Instance
|
||||||
const FieldInstance = struct {
|
pub const FieldInstance = struct {
|
||||||
__identifier: []const u8,
|
__identifier: []const u8,
|
||||||
__tile: ?TilesetRectangle,
|
__tile: ?TilesetRectangle,
|
||||||
// TODO: type and value have many possible values and are not always strings.
|
// TODO: type and value have many possible values and are not always strings.
|
||||||
// Figure out if we can use JSON.parse for this
|
// Figure out if we can use JSON.parse for this
|
||||||
__type: []const u8,
|
__type: []const u8,
|
||||||
__value: []const u8,
|
__value: []const u8,
|
||||||
defUid: u64,
|
defUid: i64,
|
||||||
};
|
};
|
||||||
|
|
||||||
const FieldType = union(enum) {
|
const FieldType = union(enum) {
|
||||||
|
@ -209,11 +204,11 @@ const LayerDefinition = struct {
|
||||||
Tiles,
|
Tiles,
|
||||||
AutoLayer,
|
AutoLayer,
|
||||||
},
|
},
|
||||||
autoSourceLayerDefUid: ?u64,
|
autoSourceLayerDefUid: ?i64,
|
||||||
displayOpacity: f64,
|
displayOpacity: f64,
|
||||||
gridSize: u64,
|
gridSize: i64,
|
||||||
identifier: []const u8,
|
identifier: []const u8,
|
||||||
intGridValues: []struct { color: []const u8, identifier: ?[]const u8, value: u64 },
|
intGridValues: []struct { color: []const u8, identifier: ?[]const u8, value: i64 },
|
||||||
parallaxFactorX: f64,
|
parallaxFactorX: f64,
|
||||||
parallaxFactorY: f64,
|
parallaxFactorY: f64,
|
||||||
parallaxScaling: bool,
|
parallaxScaling: bool,
|
||||||
|
@ -222,12 +217,12 @@ const LayerDefinition = struct {
|
||||||
/// Reference to the default Tileset UID used by this layer definition.
|
/// Reference to the default Tileset UID used by this layer definition.
|
||||||
/// WARNING: some layer instances might use a different tileset. So most of the time, you should probably use the __tilesetDefUid value found in layer instances.
|
/// WARNING: some layer instances might use a different tileset. So most of the time, you should probably use the __tilesetDefUid value found in layer instances.
|
||||||
/// NOTE: since version 1.0.0, the old autoTilesetDefUid was removed and merged into this value.
|
/// NOTE: since version 1.0.0, the old autoTilesetDefUid was removed and merged into this value.
|
||||||
tilesetDefUid: ?u64,
|
tilesetDefUid: ?i64,
|
||||||
/// Unique Int identifier
|
/// Unique Int identifier
|
||||||
uid: u64,
|
uid: i64,
|
||||||
/// WARNING: this deprecated value will be removed completely on version 1.2.0+
|
/// WARNING: this deprecated value will be removed completely on version 1.2.0+
|
||||||
/// Replaced by: tilesetDefUid
|
/// Replaced by: tilesetDefUid
|
||||||
autoTilesetDefUid: ?u64 = null,
|
autoTilesetDefUid: ?i64 = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 3.1.1. Auto-layer rule definition
|
/// 3.1.1. Auto-layer rule definition
|
||||||
|
@ -236,19 +231,19 @@ const AutoLayerRuleDefinition = opaque {};
|
||||||
/// 3.2. Entity definition
|
/// 3.2. Entity definition
|
||||||
const EntityDefinition = struct {
|
const EntityDefinition = struct {
|
||||||
color: []const u8,
|
color: []const u8,
|
||||||
height: u64,
|
height: i64,
|
||||||
identifier: []const u8,
|
identifier: []const u8,
|
||||||
nineSliceBorders: [4]i64,
|
nineSliceBorders: [4]i64,
|
||||||
pivotX: f64,
|
pivotX: f64,
|
||||||
pivotY: f64,
|
pivotY: f64,
|
||||||
tileRect: TilesetRectangle,
|
tileRect: TilesetRectangle,
|
||||||
tileRenderMode: enum { Cover, FitInside, Repeat, Stretch, FullSizeCropped, FullSizeUncropped, NineSlice },
|
tileRenderMode: enum { Cover, FitInside, Repeat, Stretch, FullSizeCropped, FullSizeUncropped, NineSlice },
|
||||||
tilesetId: ?u64,
|
tilesetId: ?i64,
|
||||||
uid: u64,
|
uid: i64,
|
||||||
width: u64,
|
width: i64,
|
||||||
/// WARNING: this deprecated value will be removed completely on version 1.2.0+
|
/// WARNING: this deprecated value will be removed completely on version 1.2.0+
|
||||||
/// Replaced by tileRect
|
/// Replaced by tileRect
|
||||||
tileId: ?u64 = null,
|
tileId: ?i64 = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 3.2.1. Field definition
|
/// 3.2.1. Field definition
|
||||||
|
@ -256,52 +251,52 @@ const FieldDefinition = []const u8;
|
||||||
|
|
||||||
/// 3.2.2. Tileset rectangle
|
/// 3.2.2. Tileset rectangle
|
||||||
const TilesetRectangle = struct {
|
const TilesetRectangle = struct {
|
||||||
h: u64,
|
h: i64,
|
||||||
tilesetUid: u64,
|
tilesetUid: i64,
|
||||||
w: u64,
|
w: i64,
|
||||||
x: i64,
|
x: i64,
|
||||||
y: i64,
|
y: i64,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 3.3. Tileset definition
|
/// 3.3. Tileset definition
|
||||||
const TilesetDefinition = struct {
|
const TilesetDefinition = struct {
|
||||||
__cHei: u64,
|
__cHei: i64,
|
||||||
__cWid: u64,
|
__cWid: i64,
|
||||||
customData: []struct {
|
customData: []struct {
|
||||||
data: []const u8,
|
data: []const u8,
|
||||||
tileId: u64,
|
tileId: i64,
|
||||||
},
|
},
|
||||||
embedAtlas: ?enum { LdtkIcons },
|
embedAtlas: ?enum { LdtkIcons },
|
||||||
enumTags: []struct {
|
enumTags: []struct {
|
||||||
enumValueId: []const u8,
|
enumValueId: []const u8,
|
||||||
tileIds: []u64,
|
tileIds: []i64,
|
||||||
},
|
},
|
||||||
identifier: []const u8,
|
identifier: []const u8,
|
||||||
padding: i64,
|
padding: i64,
|
||||||
pxHei: u64,
|
pxHei: i64,
|
||||||
pxWid: u64,
|
pxWid: i64,
|
||||||
relPath: ?[]const u8,
|
relPath: ?[]const u8,
|
||||||
spacing: i64,
|
spacing: i64,
|
||||||
tags: [][]const u8,
|
tags: [][]const u8,
|
||||||
tagsSourceEnumUid: ?u64,
|
tagsSourceEnumUid: ?i64,
|
||||||
tileGridSize: u64,
|
tileGridSize: i64,
|
||||||
uid: u64,
|
uid: i64,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 3.4. Enum definition
|
/// 3.4. Enum definition
|
||||||
const EnumDefinition = struct {
|
const EnumDefinition = struct {
|
||||||
externalRelPath: ?[]const u8,
|
externalRelPath: ?[]const u8,
|
||||||
iconTilesetUid: ?u64,
|
iconTilesetUid: ?i64,
|
||||||
identifier: []const u8,
|
identifier: []const u8,
|
||||||
tags: [][]const u8,
|
tags: [][]const u8,
|
||||||
uid: u64,
|
uid: i64,
|
||||||
values: []EnumValueDefinition,
|
values: []EnumValueDefinition,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 3.4.1. Enum value definition
|
/// 3.4.1. Enum value definition
|
||||||
const EnumValueDefinition = struct {
|
const EnumValueDefinition = struct {
|
||||||
__tileSrcRect: ?[4]i64,
|
__tileSrcRect: ?[4]i64,
|
||||||
color: u64,
|
color: i64,
|
||||||
id: []const u8,
|
id: []const u8,
|
||||||
tileId: ?u64,
|
tileId: ?i64,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
{
|
|
||||||
|
|
||||||
"__header__" : { // Some information header
|
|
||||||
"fileType": "LDtk Project JSON",
|
|
||||||
"app": "LDtk",
|
|
||||||
"appAuthor": "Sebastien Benard",
|
|
||||||
"appVersion": "0.6.3",
|
|
||||||
"url": "..."
|
|
||||||
},
|
|
||||||
|
|
||||||
// Global project settings
|
|
||||||
"name" : "My empty project",
|
|
||||||
"jsonVersion" : 1,
|
|
||||||
"defaultPivotX" : 0.0,
|
|
||||||
"defaultPivotY" : 0.0,
|
|
||||||
"defaultGridSize" : 16,
|
|
||||||
"bgColor" : "#7F8093",
|
|
||||||
"nextUid" : 1,
|
|
||||||
|
|
||||||
"defs" : { // These are elements definitions
|
|
||||||
"layers" : [],
|
|
||||||
"entities" : [],
|
|
||||||
"tilesets" : [],
|
|
||||||
"enums" : [],
|
|
||||||
"externalEnums" : []
|
|
||||||
},
|
|
||||||
|
|
||||||
"levels" : [ // Actual level data
|
|
||||||
{
|
|
||||||
"identifier" : "Level",
|
|
||||||
"uid" : 0,
|
|
||||||
"pxWid" : 256,
|
|
||||||
"pxHei" : 256,
|
|
||||||
"layerInstances" : [] // "null" if levels are separated
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
|
143
src/main.zig
143
src/main.zig
|
@ -3,7 +3,144 @@ const testing = std.testing;
|
||||||
const LDtk = @import("LDtk.zig");
|
const LDtk = @import("LDtk.zig");
|
||||||
|
|
||||||
test "load default/empty ldtk file" {
|
test "load default/empty ldtk file" {
|
||||||
const empty_ldtk = @embedFile("empty.ldtk");
|
const empty_ldtk = @embedFile("test.ldtk");
|
||||||
const world = try LDtk.parse(testing.allocator, empty_ldtk);
|
|
||||||
_ = world;
|
var parser = std.json.Parser.init(testing.allocator, false);
|
||||||
|
defer parser.deinit();
|
||||||
|
|
||||||
|
var value_tree = try parser.parse(empty_ldtk);
|
||||||
|
defer value_tree.deinit();
|
||||||
|
|
||||||
|
value_tree.root.dump();
|
||||||
|
|
||||||
|
// Seperate root for easier access
|
||||||
|
const root = object(value_tree.root) orelse return error.InvalidRoot;
|
||||||
|
|
||||||
|
// Pull out the more complicated structures
|
||||||
|
// const defs = object(root.get("defs")) orelse return error.InvalidDefs;
|
||||||
|
const levels = array(root.get("levels")) orelse return error.InvalidLevels;
|
||||||
|
|
||||||
|
// const ldtk_defs = try extract_defs(testing.allocator, defs);
|
||||||
|
// defer testing.allocator.free(ldtk_defs);
|
||||||
|
const ldtk_levels = try extract_levels(testing.allocator, levels);
|
||||||
|
defer testing.allocator.free(ldtk_levels);
|
||||||
|
|
||||||
|
var ldtk_root = LDtk.Root {
|
||||||
|
.bgColor = string(root.get("bgColor")) orelse return error.InvalidBGColor,
|
||||||
|
// .defs = ldtk_defs,
|
||||||
|
.externalLevels = boolean(root.get("externalLevels")) orelse return error.InvalidExternalLevels,
|
||||||
|
.jsonVersion = string(root.get("jsonVersion")) orelse return error.InvalidJsonVersion,
|
||||||
|
.levels = ldtk_levels,
|
||||||
|
.worldGridHeight = integer(root.get("worldGridHeight")) orelse return error.InvalidHeight,
|
||||||
|
.worldGridWidth = integer(root.get("worldGridWidth")) orelse return error.InvalidWidth,
|
||||||
|
.worldLayout = enum_from_value(LDtk.WorldLayout, root.get("worldLayout")) orelse return error.InvalidWorldLayout,
|
||||||
|
};
|
||||||
|
if (array(root.get("worlds"))) |worlds| {
|
||||||
|
const ldtk_worlds = try extract_worlds(testing.allocator, worlds);
|
||||||
|
defer testing.allocator.free(ldtk_worlds);
|
||||||
|
ldtk_root.worlds = ldtk_worlds;
|
||||||
|
}
|
||||||
|
_ = ldtk_root;
|
||||||
|
|
||||||
|
std.log.warn("\n{?}\n", .{ ldtk_root });
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn extract_defs(alloc: std.mem.Allocator, defs_obj: std.json.Value) !LDtk.Definitions {
|
||||||
|
// // TODO
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn extract_worlds(alloc: std.mem.Allocator, worlds: std.json.Array) ![]LDtk.World {
|
||||||
|
var ldtk_worlds = try std.ArrayList(LDtk.World).initCapacity(alloc, worlds.items.len);
|
||||||
|
for (worlds.items) |world_value| {
|
||||||
|
const world_obj = object(world_value) orelse return error.InvalidWorld;
|
||||||
|
const levels_obj = array(world_obj.get("levels")) orelse return error.InvalidWorldLevels;
|
||||||
|
const levels = try extract_levels(alloc, levels_obj);
|
||||||
|
ldtk_worlds.appendAssumeCapacity(.{
|
||||||
|
.identifier = string(world_obj.get("identifier")) orelse return error.InvalidIdentifier,
|
||||||
|
.iid = string(world_obj.get("iid")) orelse return error.InvalidIID,
|
||||||
|
.levels = levels,
|
||||||
|
.worldGridHeight = integer(world_obj.get("worldGridHeight")) orelse return error.InvalidWorldGridHeight,
|
||||||
|
.worldGridWidth = integer(world_obj.get("worldGridHeight")) orelse return error.InvalidWorldGridHeight,
|
||||||
|
.worldLayout = enum_from_value(LDtk.WorldLayout, world_obj.get("worldLayout")) orelse return error.InvalidWorldLayout,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return ldtk_worlds.toOwnedSlice();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_levels(alloc: std.mem.Allocator, levels: std.json.Array) ![]LDtk.Level {
|
||||||
|
var ldtk_levels = try std.ArrayList(LDtk.Level).initCapacity(alloc, levels.items.len);
|
||||||
|
defer ldtk_levels.deinit(); // levels will be returned using toOwnedSlice
|
||||||
|
for (levels.items) |level_value| {
|
||||||
|
const level_obj = object(level_value) orelse return error.InvalidLevel;
|
||||||
|
ldtk_levels.appendAssumeCapacity(.{
|
||||||
|
.__bgColor = string(level_obj.get("__bgColor")),
|
||||||
|
// TODO
|
||||||
|
.__bgPos = null,
|
||||||
|
// TODO
|
||||||
|
.__neighbours = &[_]LDtk.Neighbour{},
|
||||||
|
.bgRelPath = string(level_obj.get("bgRelPath")),
|
||||||
|
.externalRelPath = string(level_obj.get("externalRelPath")),
|
||||||
|
// TODO
|
||||||
|
.fieldInstances = &[_]LDtk.FieldInstance{},
|
||||||
|
.identifier = string(level_obj.get("identifier")) orelse return error.InvalidIdentifier,
|
||||||
|
.iid = string(level_obj.get("iid")) orelse return error.InvalidIID,
|
||||||
|
// TODO
|
||||||
|
.layerInstances = null,
|
||||||
|
.pxHei = integer(level_obj.get("pxHei")) orelse return error.InvalidPxHei,
|
||||||
|
.pxWid = integer(level_obj.get("pxWid")) orelse return error.InvalidPxWid,
|
||||||
|
.uid = integer(level_obj.get("uid")) orelse return error.InvalidUID,
|
||||||
|
.worldDepth = integer(level_obj.get("worldDepth")) orelse return error.InvalidWorldDepth,
|
||||||
|
.worldX = integer(level_obj.get("worldX")) orelse return error.InvalidWorldX,
|
||||||
|
.worldY = integer(level_obj.get("worldY")) orelse return error.InvalidWorldY,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return ldtk_levels.toOwnedSlice();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn object(value_opt: ?std.json.Value) ?std.json.ObjectMap {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.Object => |obj| obj,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn array(value_opt: ?std.json.Value) ?std.json.Array {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.Array => |arr| arr,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string(value_opt: ?std.json.Value) ?[]const u8 {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.String => |str| str,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn boolean(value_opt: ?std.json.Value) ?bool {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.Bool => |b| b,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn integer(value_opt: ?std.json.Value) ?i64 {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.Integer => |int| int,
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enum_from_value(comptime T: type, value_opt: ?std.json.Value) ?T {
|
||||||
|
const value = value_opt orelse return null;
|
||||||
|
return switch (value) {
|
||||||
|
.String => |str| std.meta.stringToEnum(T, str),
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
{
|
||||||
|
"__header__": {
|
||||||
|
"fileType": "LDtk Project JSON",
|
||||||
|
"app": "LDtk",
|
||||||
|
"doc": "https://ldtk.io/json",
|
||||||
|
"schema": "https://ldtk.io/files/JSON_SCHEMA.json",
|
||||||
|
"appAuthor": "Sebastien 'deepnight' Benard",
|
||||||
|
"appVersion": "1.1.3",
|
||||||
|
"url": "https://ldtk.io"
|
||||||
|
},
|
||||||
|
"jsonVersion": "1.1.3",
|
||||||
|
"appBuildId": 458364,
|
||||||
|
"nextUid": 1,
|
||||||
|
"identifierStyle": "Capitalize",
|
||||||
|
"worldLayout": "Free",
|
||||||
|
"worldGridWidth": 256,
|
||||||
|
"worldGridHeight": 256,
|
||||||
|
"defaultLevelWidth": 256,
|
||||||
|
"defaultLevelHeight": 256,
|
||||||
|
"defaultPivotX": 0,
|
||||||
|
"defaultPivotY": 0,
|
||||||
|
"defaultGridSize": 16,
|
||||||
|
"bgColor": "#40465B",
|
||||||
|
"defaultLevelBgColor": "#696A79",
|
||||||
|
"minifyJson": false,
|
||||||
|
"externalLevels": false,
|
||||||
|
"exportTiled": false,
|
||||||
|
"simplifiedExport": false,
|
||||||
|
"imageExportMode": "None",
|
||||||
|
"pngFilePattern": null,
|
||||||
|
"backupOnSave": false,
|
||||||
|
"backupLimit": 10,
|
||||||
|
"levelNamePattern": "Level_%idx",
|
||||||
|
"tutorialDesc": null,
|
||||||
|
"flags": [],
|
||||||
|
"defs": { "layers": [], "entities": [], "tilesets": [], "enums": [], "externalEnums": [], "levelFields": [] },
|
||||||
|
"levels": [
|
||||||
|
{
|
||||||
|
"identifier": "Level_0",
|
||||||
|
"iid": "c0773b00-02f0-11ed-bf2c-25905856c5d2",
|
||||||
|
"uid": 0,
|
||||||
|
"worldX": 0,
|
||||||
|
"worldY": 0,
|
||||||
|
"worldDepth": 0,
|
||||||
|
"pxWid": 256,
|
||||||
|
"pxHei": 256,
|
||||||
|
"__bgColor": "#696A79",
|
||||||
|
"bgColor": null,
|
||||||
|
"useAutoIdentifier": true,
|
||||||
|
"bgRelPath": null,
|
||||||
|
"bgPos": null,
|
||||||
|
"bgPivotX": 0.5,
|
||||||
|
"bgPivotY": 0.5,
|
||||||
|
"__smartColor": "#ADADB5",
|
||||||
|
"__bgPos": null,
|
||||||
|
"externalRelPath": null,
|
||||||
|
"fieldInstances": [],
|
||||||
|
"layerInstances": [],
|
||||||
|
"__neighbours": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"worlds": []
|
||||||
|
}
|
Loading…
Reference in New Issue