wired/map2src.zig

275 lines
10 KiB
Zig
Raw Normal View History

2022-01-15 02:46:15 -07:00
const std = @import("std");
2022-01-31 00:31:02 -07:00
const PropertyType = enum { @"bool", @"int" };
2022-01-17 21:33:47 -07:00
const Property = struct {
name: []const u8 = &.{},
@"type": PropertyType = .@"bool",
2022-01-31 00:31:02 -07:00
value: union(PropertyType) { @"bool": bool, @"int": i64 },
2022-01-17 21:33:47 -07:00
};
2022-01-15 13:58:08 -07:00
const Point = struct {
x: f64 = 0,
y: f64 = 0,
};
const Object = struct {
height: f64 = 0,
2022-01-15 13:58:08 -07:00
id: u64 = 0,
2022-01-23 06:19:41 -07:00
gid: u64 = 0,
2022-01-15 13:58:08 -07:00
name: []const u8,
2022-01-19 00:17:11 -07:00
point: bool = false,
polyline: []Point = &.{},
2022-01-17 21:33:47 -07:00
properties: []Property = &.{},
2022-01-15 13:58:08 -07:00
rotation: f64 = 0,
2022-01-23 06:19:41 -07:00
@"type": enum { wire, source, door, spawn, focus, coin },
2022-01-15 13:58:08 -07:00
visible: bool = true,
width: f64 = 0,
2022-01-15 13:58:08 -07:00
x: f64 = 0,
y: f64 = 0,
};
2022-01-15 02:46:15 -07:00
const Layer = struct {
2022-01-15 13:58:08 -07:00
data: []u64 = &.{},
objects: []Object = &.{},
height: u64 = 0,
2022-01-15 02:46:15 -07:00
id: u64,
name: []const u8,
2022-01-15 13:58:08 -07:00
draworder: enum { topdown, none } = .none,
2022-01-15 02:46:15 -07:00
opacity: u64,
2022-01-15 13:58:08 -07:00
@"type": enum { tilelayer, objectgroup },
2022-01-15 02:46:15 -07:00
visible: bool,
2022-01-15 13:58:08 -07:00
width: u64 = 0,
2022-01-15 02:46:15 -07:00
x: i64,
y: i64,
};
const MapType = struct {
compressionlevel: i64 = -1,
2022-01-20 01:26:00 -07:00
editorsettings: struct { chunksize: struct { height: usize = 0, width: usize = 0 } = .{} } = .{},
2022-01-15 02:46:15 -07:00
height: u64 = 0,
infinite: bool = false,
layers: []Layer,
nextlayerid: u64 = 0,
nextobjectid: u64 = 0,
orientation: enum { orthogonal } = .orthogonal,
renderorder: enum { @"right-down" } = .@"right-down",
tiledversion: []const u8 = "",
tileheight: u64 = 0,
tilesets: []struct { firstgid: u64, source: []const u8 },
tilewidth: u64 = 0,
@"type": enum { map } = .map,
version: []const u8 = "",
width: u64 = 0,
};
const KB = 1024;
2022-01-23 06:19:41 -07:00
var heap: [256 * KB]u8 = undefined;
2022-01-15 02:46:15 -07:00
var fba = std.heap.FixedBufferAllocator.init(&heap);
var alloc = fba.allocator();
2022-01-17 13:48:46 -07:00
var verbose = true;
2022-01-15 02:46:15 -07:00
pub fn main() anyerror!void {
2022-01-17 13:48:46 -07:00
do() catch |e| switch (e) {
error.NoOutputName => showHelp("No output filename supplied"),
else => return e,
};
}
pub fn showHelp(msg: []const u8) void {
std.log.info("{s}\n map2src <output> input1...", .{msg});
}
2022-01-15 02:46:15 -07:00
2022-01-17 13:48:46 -07:00
pub fn do() !void {
2022-01-15 02:46:15 -07:00
var argsIter = std.process.args();
2022-01-17 13:48:46 -07:00
const cwd = std.fs.cwd();
2022-01-15 02:46:15 -07:00
const progName = (try argsIter.next(alloc)) orelse "";
defer alloc.free(progName);
2022-01-17 13:48:46 -07:00
if (verbose) std.log.info("{s}", .{progName});
const outputName = (try argsIter.next(alloc)) orelse return error.NoOutputName;
defer alloc.free(outputName);
var output = try cwd.createFile(outputName, .{});
defer output.close();
2022-01-15 02:46:15 -07:00
while (try argsIter.next(alloc)) |arg| {
defer alloc.free(arg);
2022-01-17 13:48:46 -07:00
if (verbose) std.log.info("{s}", .{arg});
2022-01-23 06:19:41 -07:00
var filebuffer: [64 * KB]u8 = undefined;
2022-01-15 02:46:15 -07:00
var filecontents = try cwd.readFile(arg, &filebuffer);
@setEvalBranchQuota(10000);
var tokenstream = std.json.TokenStream.init(filecontents);
const options = std.json.ParseOptions{ .allocator = fba.allocator() };
const map = try std.json.parse(MapType, &tokenstream, options);
defer std.json.parseFree(MapType, map, options);
2022-01-15 13:58:08 -07:00
var outlist = std.ArrayList(u8).init(alloc);
defer outlist.deinit();
try outlist.appendSlice("const std = @import(\"std\");\n");
try outlist.appendSlice("const Vec2 = std.meta.Vector(2,i32);\n");
try outlist.appendSlice("const AABB = struct {pos: Vec2, size: Vec2};\n");
2022-01-31 00:31:02 -07:00
try outlist.appendSlice("const Wire = struct { p1: Vec2, p2: Vec2, a1: bool, a2: bool, divisions: u8 };\n");
2022-01-15 13:58:08 -07:00
2022-01-20 01:26:00 -07:00
var outbuffer: [16 * KB]u8 = undefined;
2022-01-15 13:58:08 -07:00
for (map.layers) |layer| {
switch (layer.@"type") {
.tilelayer => {
2022-01-20 01:26:00 -07:00
var outcontent = try std.fmt.bufPrint(
&outbuffer,
"pub const {2s}_size: Vec2 = Vec2{{ {}, {} }};\npub const {s}: [{}]u8 = .{any};\n",
.{ layer.width, layer.height, layer.name, layer.data.len, layer.data },
);
2022-01-15 13:58:08 -07:00
_ = try outlist.appendSlice(outcontent);
},
.objectgroup => {
2022-01-19 00:17:11 -07:00
var wirelist = std.ArrayList(Object).init(alloc);
defer wirelist.deinit();
var doorlist = std.ArrayList(Object).init(alloc);
defer doorlist.deinit();
2022-01-23 06:19:41 -07:00
var coinlist = std.ArrayList(Object).init(alloc);
defer coinlist.deinit();
2022-01-19 00:17:11 -07:00
var sourcelist = std.ArrayList(Object).init(alloc);
defer sourcelist.deinit();
2022-01-15 13:58:08 -07:00
var focilist = std.ArrayList(Object).init(alloc);
defer focilist.deinit();
2022-01-15 13:58:08 -07:00
for (layer.objects) |obj| {
2022-01-19 00:17:11 -07:00
switch (obj.@"type") {
.wire => try wirelist.append(obj),
.door => try doorlist.append(obj),
2022-01-23 06:19:41 -07:00
.coin => try coinlist.append(obj),
2022-01-19 00:17:11 -07:00
.source => try sourcelist.append(obj),
.focus => try focilist.append(obj),
2022-01-20 01:26:00 -07:00
.spawn => try appendSpawn(&outlist, obj),
2022-01-15 13:58:08 -07:00
}
}
2022-01-19 00:17:11 -07:00
try appendWires(&outlist, wirelist);
try appendDoors(&outlist, doorlist);
2022-01-23 06:19:41 -07:00
try appendCoins(&outlist, coinlist);
2022-01-19 00:17:11 -07:00
try appendSources(&outlist, sourcelist);
try appendFoci(&outlist, focilist);
2022-01-15 13:58:08 -07:00
},
}
}
2022-01-17 13:48:46 -07:00
if (verbose) std.log.info("{s}", .{outlist.items});
2022-01-15 13:58:08 -07:00
_ = try output.writeAll(outlist.items);
2022-01-15 02:46:15 -07:00
}
}
2022-01-19 00:17:11 -07:00
2022-01-31 00:31:02 -07:00
pub fn length(vec: std.meta.Vector(2, i64)) i64 {
var squared = vec * vec;
return @intCast(i64, std.math.sqrt(@intCast(u64, @reduce(.Add, squared))));
}
2022-01-19 00:17:11 -07:00
pub fn appendWires(outlist: *std.ArrayList(u8), wirelist: std.ArrayList(Object)) !void {
var outbuffer: [4 * KB]u8 = undefined;
var outcontent = try std.fmt.bufPrint(&outbuffer, "pub const wire: [{}]Wire = [_]Wire{{", .{wirelist.items.len});
try outlist.appendSlice(outcontent);
for (wirelist.items) |obj| {
var a1 = true;
var a2 = true;
2022-01-31 00:31:02 -07:00
var p1: std.meta.Vector(2, i64) = .{ 0, 0 };
var p2: std.meta.Vector(2, i64) = .{ 0, 0 };
var divisions: ?i64 = null;
2022-01-19 00:17:11 -07:00
for (obj.properties) |p| {
if (std.mem.eql(u8, p.name, "anchor1")) a1 = p.value.@"bool";
if (std.mem.eql(u8, p.name, "anchor2")) a2 = p.value.@"bool";
2022-01-31 00:31:02 -07:00
if (std.mem.eql(u8, p.name, "divisions")) divisions = p.value.@"int";
2022-01-19 00:17:11 -07:00
}
for (obj.polyline) |point, i| {
2022-01-31 00:31:02 -07:00
switch (i) {
0 => p1 = .{ @floatToInt(i64, obj.x + point.x), @floatToInt(i64, obj.y + point.y) },
1 => p2 = .{ @floatToInt(i64, obj.x + point.x), @floatToInt(i64, obj.y + point.y) },
else => return error.TooManyPoints,
}
2022-01-19 00:17:11 -07:00
}
2022-01-31 00:31:02 -07:00
divisions = divisions orelse std.math.max(2, @divTrunc(length(p2 - p1), 6));
var of = try std.fmt.bufPrint(
&outbuffer,
".{{ .a1 = {}, .a2 = {}, .divisions = {}, .p1 = Vec2{{ {}, {} }}, .p2 = Vec2{{ {}, {} }} }}, ",
.{ a1, a2, divisions, p1[0], p1[1], p2[0], p2[1] },
);
try outlist.appendSlice(of);
2022-01-19 00:17:11 -07:00
}
try outlist.appendSlice("};\n");
}
pub fn appendDoors(outlist: *std.ArrayList(u8), doorlist: std.ArrayList(Object)) !void {
var outbuffer: [4 * KB]u8 = undefined;
var outcontent = try std.fmt.bufPrint(&outbuffer, "pub const doors: [{}]Vec2 = [_]Vec2{{", .{doorlist.items.len});
try outlist.appendSlice(outcontent);
for (doorlist.items) |obj| {
var doorf = try std.fmt.bufPrint(&outbuffer, "Vec2{{ {}, {} }},", .{ @floatToInt(i32, @divTrunc(obj.x, 8)), @floatToInt(i32, @divTrunc(obj.y, 8)) });
try outlist.appendSlice(doorf);
}
try outlist.appendSlice("};\n");
}
pub fn appendSources(outlist: *std.ArrayList(u8), sourcelist: std.ArrayList(Object)) !void {
var outbuffer: [4 * KB]u8 = undefined;
var outcontent = try std.fmt.bufPrint(&outbuffer, "pub const sources: [{}]Vec2 = [_]Vec2{{", .{sourcelist.items.len});
try outlist.appendSlice(outcontent);
for (sourcelist.items) |obj| {
var sourcef = try std.fmt.bufPrint(&outbuffer, "Vec2{{ {}, {} }},", .{ @floatToInt(i32, @divTrunc(obj.x, 8)), @floatToInt(i32, @divTrunc(obj.y, 8)) });
try outlist.appendSlice(sourcef);
}
try outlist.appendSlice("};\n");
}
2022-01-20 01:26:00 -07:00
2022-01-23 06:19:41 -07:00
pub fn appendCoins(outlist: *std.ArrayList(u8), coinlist: std.ArrayList(Object)) !void {
var outbuffer: [4 * KB]u8 = undefined;
2022-01-23 06:19:41 -07:00
var outcontent = try std.fmt.bufPrint(&outbuffer, "pub const coins: [{}]Vec2 = [_]Vec2{{", .{coinlist.items.len});
try outlist.appendSlice(outcontent);
2022-01-23 06:19:41 -07:00
for (coinlist.items) |obj| {
var sourcef = try std.fmt.bufPrint(&outbuffer, "Vec2{{ {}, {} }},", .{ @floatToInt(i32, @divTrunc(obj.x, 8)), @floatToInt(i32, @divTrunc(obj.y - 8, 8)) });
try outlist.appendSlice(sourcef);
}
try outlist.appendSlice("};\n");
}
pub fn appendFoci(outlist: *std.ArrayList(u8), focilist: std.ArrayList(Object)) !void {
var outbuffer: [4 * KB]u8 = undefined;
var outcontent = try std.fmt.bufPrint(&outbuffer, "pub const focus: [{}]AABB = [_]AABB{{", .{focilist.items.len});
try outlist.appendSlice(outcontent);
for (focilist.items) |obj| {
var sourcef = try std.fmt.bufPrint(
&outbuffer,
"AABB{{ .pos = Vec2{{ {}, {} }}, .size = Vec2{{ {}, {} }} }}",
.{
@floatToInt(i32, @divTrunc(obj.x, 8)),
@floatToInt(i32, @divTrunc(obj.y, 8)),
@floatToInt(i32, @divTrunc(obj.width, 8)),
@floatToInt(i32, @divTrunc(obj.height, 8)),
},
);
try outlist.appendSlice(sourcef);
}
try outlist.appendSlice("};\n");
}
2022-01-20 01:26:00 -07:00
pub fn appendSpawn(outlist: *std.ArrayList(u8), spawn: Object) !void {
var outbuffer: [4 * KB]u8 = undefined;
var outcontent = try std.fmt.bufPrint(
&outbuffer,
"pub const spawn: Vec2 = Vec2{{ {}, {} }};\n",
.{
@floatToInt(i32, @divTrunc(spawn.x, 8)),
@floatToInt(i32, @divTrunc(spawn.y, 8)),
},
);
try outlist.appendSlice(outcontent);
}