Backlog/projects/tools/toolbox/animationStore.zig

166 lines
4.6 KiB
Zig

allocator: std.mem.Allocator,
gltfs: std.StringHashMapUnmanaged(GltfData) = .{},
stringArena: std.heap.ArenaAllocator,
filesToProcess: std.ArrayListUnmanaged(FileToProcess) = .{},
animations: std.ArrayListUnmanaged(AnimationData) = .{},
browser: *AnimationDataBrowser,
const AnimationDataBrowser = extras.browser.Browser(AnimationData);
pub const AnimationData = struct {
name: []const u8,
pub fn fileName(self: *@This()) []const u8 {
return self.name;
}
pub fn getModTime(self: *@This()) []const u8 {
_ = self;
return "0";
}
};
pub const FileToProcess = struct {
path: []const u8,
};
pub const GltfAnimationData = struct {
name: []const u8,
};
pub const GltfData = struct {
filePath: []u8,
animations: std.ArrayListUnmanaged(GltfAnimationData) = .{},
};
pub fn create(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This());
self.* = .{
.allocator = allocator,
.stringArena = std.heap.ArenaAllocator.init(allocator),
.browser = try AnimationDataBrowser.create(allocator),
};
self.browser.sameWindow = true;
self.browser.setList(&self.animations.items);
try self.setupCallbacks();
try self.initialLoad();
return self;
}
pub fn setupCallbacks(self: *@This()) !void {
platform.watchPath("content/");
try core.fs().addAnyWatchCallback(fileChangedCallback, self);
}
pub fn scanAll(self: *@This(), dir_path: []const u8) !void {
var dir = try std.fs.cwd().openDir(dir_path, .{ .iterate = true });
defer dir.close();
var it = dir.iterate();
while (try it.next()) |entry| {
const full_path = try std.fs.path.join(self.allocator, &.{ dir_path, entry.name });
defer self.allocator.free(full_path);
if (entry.kind == .directory) {
if (std.mem.eql(u8, entry.name, "_shaders")) {
continue;
}
try self.scanAll(full_path); // Recursive call for subdirectories
} else if (entry.kind == .file) {
// core.engine_log("processing file: {s}", .{entry.name});
var pathAsName = core.MakeName(full_path);
try self.filesToProcess.append(self.allocator, .{ .path = pathAsName.utf8() });
}
}
}
pub fn initialLoad(self: *@This()) !void {
try self.scanAll("content/");
}
pub fn fileChangedCallback(path: []const u8, ctx: ?*anyopaque) void {
const self: *@This() = @ptrCast(@alignCast(ctx.?));
// core.engine_log("file change seen {s}", .{path});
//
var name = core.MakeName(path);
self.filesToProcess.append(self.allocator, .{ .path = name.utf8() }) catch {};
// self.updatePath(path) catch return;
}
fn salloc(self: *@This()) std.mem.Allocator {
return self.stringArena.allocator();
}
pub fn updatePath(self: *@This(), path: []const u8) !void {
core.engine_log("updating Path: {s}", .{path});
if (std.mem.endsWith(u8, path, ".ozz")) {}
if (std.mem.endsWith(u8, path, ".gltf")) {
// 1. check if there is a .cook file
// if there is a .cook file
// then dont load, no further actions needed
const pathstr = try std.fmt.allocPrint(self.salloc(), "{s}.cook", .{path[0 .. path.len - 5]});
defer self.salloc().free(pathstr);
core.engine_log("checking path: {s}", .{pathstr});
if (!core.fs().fileExists(pathstr)) {
const dir = try std.fs.cwd().openDir(p2.getDir(pathstr), .{ .iterate = true });
try cook.generateAllCookFiles(self.allocator, dir);
}
try self.animations.append(self.allocator, .{ .name = path });
//var name = core.MakeName(pathstr);
// if there is a cook file
// var mapping = try core.fs().loadFile(path);
// zgltf.init(self.allocator);
// core.fs().unmap(mapping);
}
}
pub fn tickDisplay(self: *@This()) void {
self.browser.tickDisplay();
}
pub fn tick(self: *@This()) void {
const start = core.getEngineTime();
while (self.filesToProcess.pop()) |pop| {
const now = core.getEngineTime();
if (now - start > 0.050) {
break;
}
self.updatePath(pop.path) catch unreachable;
}
}
pub fn destroy(self: *@This()) void {
self.browser.destroy();
self.allocator.destroy(self);
}
const std = @import("std");
const api = @import("backlog");
const imgui = api.imgui;
const ig = api.imgui.api;
const p2 = core.algorithm;
const core = api.core;
const sys = api.sys;
const zgltf = core.zgltf;
const assets = api.assets;
const cook = assets.cook;
const platform = api.platform;
const extras = @import("gameExtras");