diff options
Diffstat (limited to 'src/misc.zig')
-rw-r--r-- | src/misc.zig | 64 |
1 files changed, 62 insertions, 2 deletions
diff --git a/src/misc.zig b/src/misc.zig index f9e0628..caa0319 100644 --- a/src/misc.zig +++ b/src/misc.zig @@ -23,8 +23,11 @@ usingnamespace @cImport({ @cInclude("lodepng.h"); }); +const Dir = std.fs.Dir; const al = @import("zeal"); +const allocPrint = std.fmt.allocPrint; const allocator = std.heap.c_allocator; +const count = std.mem.count; const cwd = std.fs.cwd; const data_dir = @import("build_options").data_dir ++ [_]u8{ sep }; const eql = std.mem.eql; @@ -38,6 +41,64 @@ const span = std.mem.span; const std = @import("std"); const tokenize = std.mem.tokenize; +// Don't judge me, take care of me! +const max_size = maxInt(usize); + +/// Read given file to heap, allocated by C allocator. +fn readFile(dir: Dir, comptime fmt: []const u8, args: anytype) ![]const u8 { + const filename = try allocPrint(allocator, fmt, args); + defer allocator.free(filename); + return dir.readFileAlloc(allocator, filename, max_size); +} + +const Frame = extern struct { + joints: [20]extern struct { + x: f32, + y: f32, + z: f32, + }, + speed: f32, +}; + +export fn loadAnimation(name: [*:0]const u8) extern struct { + ptr: [*]Frame, + len: usize, +} { + var dir = cwd().openDir(data_dir ++ "animations", .{}) catch unreachable; + defer dir.close(); + const anim_file = readFile(dir, "{s}.tsv", .{ name }) catch unreachable; + defer allocator.free(anim_file); + const length = count(u8, anim_file, "\t") - 1; + const frames = allocator.alloc(Frame, length) catch unreachable; + + var anim = tokenize(anim_file, "\n"); + _ = anim.next().?; // ignore field names + var i = @as(usize, 0); + while (i < length) : (i += 1) { + var values = tokenize(anim.next().?, "\t"); + const frame_file = readFile(dir, "frames{c}{s}{c}{s}.tsv", .{ + sep, name, sep, values.next().?, // frames/$animation/$frame.tsv + }) catch unreachable; + defer allocator.free(frame_file); + + var frame = tokenize(frame_file, "\n"); + _ = frame.next().?; // ignore field names + var j = @as(usize, 0); + while (frame.next()) |position| { + var coordinates = tokenize(position, "\t"); + frames[i].joints[j].x = parseFloat(f32, coordinates.next().?) + catch unreachable; + frames[i].joints[j].y = parseFloat(f32, coordinates.next().?) + catch unreachable; + frames[i].joints[j].z = parseFloat(f32, coordinates.next().?) + catch unreachable; + j += 1; + } + frames[i].speed = parseFloat(f32, values.next().?) catch unreachable; + } + return .{ .ptr = frames.ptr, .len = frames.len }; +} + /// Parse boolean values. pub fn parseBool(s: []const u8) !bool { if (eql(u8, s, "false")) @@ -138,8 +199,7 @@ fn check(errorString: fn (c_uint) callconv(.C) [*c]const u8, export fn loadTexture(filename: [*:0]const u8) GLuint { var dir = cwd().openDir(data_dir ++ "textures", .{}) catch unreachable; defer dir.close(); - // Don't judge me, take care of me! - var file = dir.readFileAlloc(allocator, span(filename), maxInt(usize)) + const file = dir.readFileAlloc(allocator, span(filename), max_size) catch unreachable; defer allocator.free(file); |