Backlog/engine/imgui/src/utils/TopBar.zig

134 lines
3.8 KiB
Zig

pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "game.TopBar");
pub const Slack = core.SlackStruct(@This(), 256);
allocator: std.mem.Allocator,
arena: std.heap.ArenaAllocator,
windowsMenu: std.ArrayListUnmanaged(*MenuEntry) = .{},
entriesByName: std.AutoHashMapUnmanaged(u32, *MenuEntry) = .{},
menuOpen: bool = false,
pub fn create(allocator: std.mem.Allocator) !*@This() {
const self = try Slack.create(allocator);
self.* = .{
.allocator = allocator,
.arena = std.heap.ArenaAllocator.init(allocator),
};
try self.addWindowsMenu(.{
.name = "sample window",
.vtable = &NeonObjectTable,
.open = false,
.ctx = self,
.windowFunction = windowOpen,
});
return self;
}
pub fn setEntryOpen(self: *@This(), name: []const u8, open: ?bool) void {
var n = core.MakeName(name);
const x = self.entriesByName.get(n.handle()).?;
if (open) |o| {
x.open = o;
} else {
x.open = !x.open;
}
}
pub fn addMenuObject(self: *@This(), ptr: anytype, comptime name: []const u8) !void {
const T = @TypeOf(ptr.*);
try self.addWindowsMenu(.{
.vtable = &T.NeonObjectTable,
.name = name,
.ctx = ptr,
.windowFunction = T.windowOpen,
});
}
pub fn windowOpen(entry: *MenuEntry, dt: f64) void {
_ = dt;
ig.showDemoWindow(&entry.open);
}
pub fn addWindowsMenu(self: *@This(), entry: MenuEntry) !void {
const new = try self.arena.allocator().create(MenuEntry);
new.* = entry;
var name = core.MakeName(entry.name);
if (self.entriesByName.getEntry(name.handle())) |e| {
core.logDisplay("TopBar", "{s} already registered, updating menu entry instead", .{entry.name});
e.value_ptr.*.* = entry;
} else {
try self.windowsMenu.append(self.arena.allocator(), new);
try self.entriesByName.put(self.arena.allocator(), name.handle(), new);
}
}
pub fn tick(self: *@This(), dt: f64) void {
if (!self.menuOpen) {
return;
}
if (ig.beginMainMenuBar()) {
if (ig.beginMenu("Windows..", true)) {
for (self.windowsMenu.items) |entry| {
if (ig.menuItem_Bool(entry.name.ptr, null, entry.open, true)) {
entry.open = !entry.open;
}
}
ig.endMenu();
}
if (ig.beginMenu("Operations", true)) {
if (ig.menuItem_Bool("Recompile", null, false, true)) {
core.engine_log("recompiling in DEBUG mode", .{});
var success = true;
_ = core.shell.runCmd(self.allocator, &.{ "zig", "build", "install" }, ".") catch {
core.graphics_logs("compile failed!");
success = false;
};
if (success)
core.graphics_logs("compile completed");
}
ig.endMenu();
}
ig.endMainMenuBar();
for (self.windowsMenu.items) |entry| {
if (entry.open) {
entry.updateFunc();
entry.windowFunction(entry, dt);
}
}
}
}
pub fn destroy(self: *@This()) void {
self.arena.deinit();
self.allocator.destroy(Slack.fromPtr(self));
}
pub const MenuEntry = struct {
name: []const u8,
open: bool = false,
ctx: ?*anyopaque,
windowFunction: *const fn (*MenuEntry, f64) void,
vtable: *core.EngineObjectVTable,
version: i32 = -1,
pub fn updateFunc(self: *@This()) void {
if (self.vtable.version != self.version) {
const func = self.vtable.findFunc("windowOpen");
self.windowFunction = @ptrCast(@alignCast(func));
self.version = self.vtable.version;
}
}
};
const ig = @import("../imgui.zig").api;
const std = @import("std");
const core = @import("core");