summary refs log tree commit diff
path: root/src/misc.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/misc.zig')
-rw-r--r--src/misc.zig64
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);