wip polymorphic modules

This commit is contained in:
David Allemang
2024-07-10 17:27:40 -04:00
parent 53cbe35a97
commit 0efc931006
8 changed files with 208 additions and 219 deletions

View File

@@ -5,24 +5,24 @@ const Bus = @import("nu/Bus.zig");
const Render = @import("nu/Render.zig"); const Render = @import("nu/Render.zig");
const ImGui = @import("nu/ImGui.zig"); const ImGui = @import("nu/ImGui.zig");
pub fn init(alloc: std.mem.Allocator) !void { pub fn module() nu.Module {
_ = alloc; return nu.Module{
.name = "App",
// .dependencies = &.{ Render.module(), ImGui.module() },
.setup = setup,
.teardown = teardown,
.update = update,
};
} }
pub fn connect() !void { pub fn setup(_: std.mem.Allocator) !void {
try ImGui.hooks.frame.register(nu_imgui_frame); try ImGui.gui.register(gui);
} }
pub fn deinit() void {} pub fn teardown() void {}
// pub fn nu_frame() void {} pub fn update() !void {}
// pub fn nu_events(events: []const Bus.Event) void { pub fn gui() void {
// std.debug.print("{any}\n", .{events});
// }
// pub fn nu_render_present(_: Render.au.CommandBufferProxy) void {}
pub fn nu_imgui_frame() void {
ImGui.igShowMetricsWindow(null); ImGui.igShowMetricsWindow(null);
} }

View File

@@ -23,30 +23,32 @@ pub const nu_options: nu.Options = .{
pub const nu_driver = nu.Window; pub const nu_driver = nu.Window;
pub const nu_modules = .{ pub const nu_modules = .{
App,
nu.ImGui,
nu.Render, nu.Render,
nu.ImGui,
App,
}; };
pub fn main() !void { pub const main = nu.main;
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.detectLeaks();
const alloc = gpa.allocator();
nu.init(alloc); // pub fn main() !void {
defer nu.deinit(); // var gpa = std.heap.GeneralPurposeAllocator(.{}){};
// defer _ = gpa.detectLeaks();
try nu.Window.init(alloc); // const alloc = gpa.allocator();
defer nu.Window.deinit(); //
// nu.init(alloc);
try nu.Render.init(alloc); // defer nu.deinit();
defer nu.Render.deinit(); //
// try nu.Window.init(alloc);
try nu.ImGui.init(alloc); // defer nu.Window.deinit();
defer nu.ImGui.deinit(); //
// try nu.Render.init(alloc);
try App.init(alloc); // defer nu.Render.deinit();
defer App.deinit(); //
// try nu.ImGui.init(alloc);
try nu.run(alloc); // defer nu.ImGui.deinit();
} //
// try App.init(alloc);
// defer App.deinit();
//
// try nu.run(alloc);
// }

View File

@@ -8,91 +8,80 @@ pub const ImGui = @import("nu/ImGui.zig");
pub const Bus = @import("nu/Bus.zig"); pub const Bus = @import("nu/Bus.zig");
pub const Hook = @import("nu/hooks.zig").Hook; pub const Hook = @import("nu/hooks.zig").Hook;
pub const Options = struct { const Config = struct {
window: Window.Options = .{}, window: Window.Config = .{},
render: Render.Options = .{}, render: Render.Config = .{},
imgui: ImGui.Options = .{},
}; };
pub const options: Options = if (@hasDecl(root, "nu_options")) root.nu_options else .{}; pub const config: Config = if (@hasDecl(root, "nu_config")) root.nu_config else .{};
pub const modules = root.nu_modules;
pub const driver = root.nu_driver;
pub const Hooks = struct { pub const Module = struct {
pub const Enter = Hook(fn () void); // todo dependencies
pub const Events = Hook(fn ([]Bus.Event) void); name: []const u8,
pub const Frame = Hook(fn () anyerror!void); setup: *const fn (alloc: std.mem.Allocator) anyerror!void,
pub const Close = Hook(fn () void); teardown: *const fn () void,
update: ?*const fn () anyerror!void = null,
enter: Enter, frame: ?*const fn () anyerror!void = null,
events: Events, dependencies: []const Module = &.{},
frame: Frame,
close: Close,
}; };
pub var hooks: Hooks = undefined; pub const Driver = struct {
module: Module,
next: *const fn () bool, // events? callbacks?
};
pub fn init(alloc: std.mem.Allocator) void { fn enable(modules: *std.StringArrayHashMap(Module), module: Module) void {
hooks = .{ // this doesn't handle dependencies correctly. need to do real topological sort.
.enter = Hooks.Enter.init(alloc),
.events = Hooks.Events.init(alloc), if (modules.contains(module.name)) return;
.frame = Hooks.Frame.init(alloc), for (module.dependencies) |dep| enable(modules, dep);
.close = Hooks.Close.init(alloc), modules.putNoClobber(module.name, module) catch @panic("OOM");
}
pub fn main() void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const alloc = gpa.allocator();
var modules = std.StringArrayHashMap(Module).init(alloc);
defer modules.deinit();
const driver = root.nu_driver.driver();
enable(&modules, driver.module);
inline for (root.nu_modules) |mod| {
enable(&modules, mod.module());
}
for (modules.values()) |mod| {
std.log.debug("{s}.setup", .{mod.name});
mod.setup(alloc) catch |err| {
std.debug.panic("Module {s} setup error: {!}", .{ mod.name, err });
}; };
} }
defer {
pub fn deinit() void { var rev = std.mem.reverseIterator(modules.values());
hooks.enter.deinit(); while (rev.next()) |mod| {
hooks.events.deinit(); std.log.debug("{s}.teardown", .{mod.name});
hooks.frame.deinit(); mod.teardown();
hooks.close.deinit(); }
}
pub fn run(alloc: std.mem.Allocator) !void {
// todo hooks should execute in priority order; then hook.register accepts a "priority" argument.
inline for (modules) |module| {
try module.connect();
} }
hooks.enter.invoke(.{}); std.log.info("Loaded modules: {s}", .{modules.keys()});
while (driver.next()) |events| { while (driver.next()) {
if (events.len > 0) { for (modules.values()) |mod| {
hooks.events.invoke(.{events}); if (mod.update) |update| {
update() catch |err| {
std.debug.panic("Module {s} update event error: {!}", .{ mod.name, err });
};
}
} }
// todo frame timer for (modules.values()) |mod| {
const frame_results = try hooks.frame.invoke(alloc, .{}); if (mod.frame) |frame| {
defer alloc.free(frame_results); frame() catch |err| {
for (frame_results) |result| result catch |err| return err; std.debug.panic("Module {s} frame event error: {!}", .{ mod.name, err });
};
// todo fixed timestep }
}
} }
hooks.close.invoke(.{});
} }
// // todo specify hook type.
// // - special handling for error unions
// // - allow per-hook state somehow declared in the handler
//
// pub fn invoke_hook(comptime name: []const u8, args: anytype) !void {
// inline for (modules) |module| {
// if (@hasDecl(module, name)) {
// try invoke(@field(module, name), args);
// }
// }
// }
//
// fn invoke(func: anytype, args: anytype) !void {
// if (@typeInfo(@TypeOf(func)).Fn.return_type) |R| {
// switch (@typeInfo(R)) {
// .ErrorUnion => try @call(.auto, func, args),
// .Void => @call(.auto, func, args),
// else => {
// @compileLog(func, @typeInfo(R));
// @compileError("Invalid hook return type. Must be void or !void.");
// },
// }
// }
// }

View File

@@ -13,23 +13,33 @@ const Window = @import("Window.zig");
const im = @import("cimgui"); const im = @import("cimgui");
pub usingnamespace im; pub usingnamespace im;
pub const Options = struct {}; pub const Config = struct {};
const config = nu.config.imgui;
pub const Hooks = struct { pub fn module() nu.Module {
pub const Frame = Hook(fn () void); return nu.Module{
frame: Frame, .name = "ImGui",
}; // .dependencies = &.{Render.module()},
.setup = setup,
.teardown = teardown,
.update = update,
};
}
pub fn loader_wrapper(procname: [*c]const u8, _: ?*anyopaque) callconv(.C) vk.PfnVoidFunction { pub fn loader_wrapper(procname: [*c]const u8, _: ?*anyopaque) callconv(.C) vk.PfnVoidFunction {
return au.glfwGetInstanceProcAddress(au.I.handle, procname); return au.glfwGetInstanceProcAddress(au.I.handle, procname);
} }
pub var gui: Hook(fn () void) = undefined;
var ctx: *im.ImGuiContext = undefined; var ctx: *im.ImGuiContext = undefined;
var descriptor_pool: vk.DescriptorPool = undefined; var descriptor_pool: vk.DescriptorPool = undefined;
pub var hooks: Hooks = undefined; pub fn setup(alloc: std.mem.Allocator) !void {
gui = @TypeOf(gui).init(alloc);
errdefer gui.deinit();
try Render.present.register(present);
pub fn init(alloc: std.mem.Allocator) !void {
ctx = im.igCreateContext(null) orelse { ctx = im.igCreateContext(null) orelse {
return error.igCreateContextFailed; return error.igCreateContextFailed;
}; };
@@ -64,7 +74,7 @@ pub fn init(alloc: std.mem.Allocator) !void {
.DescriptorPool = @ptrFromInt(@intFromEnum(descriptor_pool)), .DescriptorPool = @ptrFromInt(@intFromEnum(descriptor_pool)),
.RenderPass = null, .RenderPass = null,
.MinImageCount = 2, .MinImageCount = 2,
.ImageCount = @intCast(nu.options.render.frames_in_flight), .ImageCount = @intCast(nu.config.render.frames_in_flight),
.PipelineRenderingCreateInfo = @bitCast(vk.PipelineRenderingCreateInfo{ .PipelineRenderingCreateInfo = @bitCast(vk.PipelineRenderingCreateInfo{
.view_mask = 0, .view_mask = 0,
.depth_attachment_format = .undefined, .depth_attachment_format = .undefined,
@@ -85,38 +95,30 @@ pub fn init(alloc: std.mem.Allocator) !void {
if (!im.impl.ImGui_ImplVulkan_CreateFontsTexture()) { if (!im.impl.ImGui_ImplVulkan_CreateFontsTexture()) {
return error.igVulkanFontTextureFailed; return error.igVulkanFontTextureFailed;
} }
hooks = .{
.frame = Hooks.Frame.init(alloc),
};
errdefer hooks.frame.deinit();
} }
pub fn deinit() void { pub fn teardown() void {
hooks.frame.deinit(); au.D.deviceWaitIdle() catch |err| std.debug.panic("Device wait failed: {!}", .{err});
im.impl.ImGui_ImplVulkan_Shutdown(); im.impl.ImGui_ImplVulkan_Shutdown();
au.D.destroyDescriptorPool(descriptor_pool, null); au.D.destroyDescriptorPool(descriptor_pool, null);
im.impl.ImGui_ImplGlfw_Shutdown(); im.impl.ImGui_ImplGlfw_Shutdown();
im.igDestroyContext(ctx); im.igDestroyContext(ctx);
gui.deinit();
} }
pub fn connect() !void { pub fn update() !void {
try nu.hooks.frame.register(nu_frame);
try Render.hooks.present.register(nu_render_present);
}
pub fn nu_frame() !void {
im.impl.ImGui_ImplGlfw_NewFrame(); im.impl.ImGui_ImplGlfw_NewFrame();
im.impl.ImGui_ImplVulkan_NewFrame(); im.impl.ImGui_ImplVulkan_NewFrame();
im.igNewFrame(); im.igNewFrame();
hooks.frame.invoke(.{}); gui.invoke(.{});
im.igEndFrame(); im.igEndFrame();
im.igRender(); im.igRender();
} }
pub fn nu_render_present(cmd: au.CommandBufferProxy) void { pub fn present(cmd: au.CommandBufferProxy) void {
im.impl.ImGui_ImplVulkan_RenderDrawData( im.impl.ImGui_ImplVulkan_RenderDrawData(
@ptrCast(im.igGetDrawData()), @ptrCast(im.igGetDrawData()),
@ptrFromInt(@intFromEnum(cmd.handle)), @ptrFromInt(@intFromEnum(cmd.handle)),

View File

@@ -9,9 +9,7 @@ const vk = @import("vk");
const nu = @import("../nu.zig"); const nu = @import("../nu.zig");
const au = @import("Render/au.zig"); const au = @import("Render/au.zig");
const Hook = @import("hooks.zig").Hook; pub const Config = struct {
pub const Options = struct {
app_name: [*:0]const u8 = "nu-au-app", app_name: [*:0]const u8 = "nu-au-app",
app_version: struct { app_version: struct {
variant: u3 = 0, variant: u3 = 0,
@@ -27,20 +25,29 @@ pub const Options = struct {
patch: u12 = 0, patch: u12 = 0,
} = .{}, } = .{},
frames_in_flight: u8 = 3, frames_in_flight: u8 = 3,
use_debug_messenger: bool = switch (builtin.mode) {
.Debug, .ReleaseSafe => true,
.ReleaseSmall, .ReleaseFast => false,
},
}; };
const config = nu.config.render;
pub const Hooks = struct { pub fn module() nu.Module {
pub const Present = Hook(fn (au.CommandBufferProxy) void); return nu.Module{
.name = "Render",
present: Present, .setup = setup,
}; .teardown = teardown,
.frame = frame,
pub var hooks: Hooks = undefined; .dependencies = &.{nu.Window.driver().module},
};
}
var sc: au.SwapChain = undefined; var sc: au.SwapChain = undefined;
var flights: au.Flights = undefined; var flights: au.Flights = undefined;
pub fn init(alloc: std.mem.Allocator) !void { pub var present: nu.Hook(fn (au.CommandBufferProxy) void) = undefined;
pub fn setup(alloc: std.mem.Allocator) !void {
// todo pick apart au into helpers; not a sub-module filled with its own globals. // todo pick apart au into helpers; not a sub-module filled with its own globals.
try au.init(alloc); try au.init(alloc);
errdefer au.deinit(); errdefer au.deinit();
@@ -48,26 +55,22 @@ pub fn init(alloc: std.mem.Allocator) !void {
sc = try au.SwapChain.init(alloc); sc = try au.SwapChain.init(alloc);
errdefer sc.deinit(); errdefer sc.deinit();
flights = try au.Flights.init(alloc, nu.options.render.frames_in_flight); flights = try au.Flights.init(alloc, config.frames_in_flight);
errdefer flights.deinit(); errdefer flights.deinit();
hooks = .{ .present = Hooks.Present.init(alloc) }; present = @TypeOf(present).init(alloc);
errdefer hooks.present.deinit(); errdefer present.deinit();
} }
pub fn deinit() void { pub fn teardown() void {
hooks.present.deinit(); au.D.deviceWaitIdle() catch |err| std.debug.panic("Device wait failed: {!}", .{err});
errdefer present.deinit();
flights.deinit(); flights.deinit();
sc.deinit(); sc.deinit();
au.deinit(); au.deinit();
} }
pub fn connect() !void { pub fn frame() !void {
try nu.hooks.frame.register(nu_frame);
try nu.hooks.close.register(nu_close);
}
pub fn nu_frame() !void {
const flight: au.Flights.Flight = flights.next(); const flight: au.Flights.Flight = flights.next();
try flight.wait(); try flight.wait();
@@ -95,7 +98,8 @@ pub fn nu_frame() !void {
// todo manage frame in flight state for each hook; pass the current flight in as context. // todo manage frame in flight state for each hook; pass the current flight in as context.
// will need some comptime -> anytype mapping. // will need some comptime -> anytype mapping.
hooks.present.invoke(.{cmd});
present.invoke(.{cmd});
target.end_rendering(cmd); target.end_rendering(cmd);
try cmd.endCommandBuffer(); try cmd.endCommandBuffer();
@@ -126,9 +130,3 @@ pub fn nu_frame() !void {
} }
} }
} }
pub fn nu_close() void {
au.D.deviceWaitIdle() catch |err| {
std.debug.panic("Device wait failed: {!}", .{err});
};
}

View File

@@ -8,10 +8,7 @@ pub const SwapChain = @import("au/SwapChain.zig");
pub const Flights = @import("au/Flights.zig"); pub const Flights = @import("au/Flights.zig");
pub const VkAllocator = @import("au/VkAllocator.zig"); pub const VkAllocator = @import("au/VkAllocator.zig");
pub const use_debug_messenger = switch (builtin.mode) { const config = nu.config.render;
.Debug, .ReleaseSafe => true,
.ReleaseSmall, .ReleaseFast => false,
};
pub const apis: []const vk.ApiInfo = &.{ pub const apis: []const vk.ApiInfo = &.{
vk.features.version_1_0, vk.features.version_1_0,
@@ -21,7 +18,7 @@ pub const apis: []const vk.ApiInfo = &.{
vk.extensions.khr_surface, vk.extensions.khr_surface,
vk.extensions.khr_swapchain, vk.extensions.khr_swapchain,
vk.extensions.khr_dynamic_rendering, vk.extensions.khr_dynamic_rendering,
if (use_debug_messenger) vk.extensions.ext_debug_utils else .{}, if (config.use_debug_messenger) vk.extensions.ext_debug_utils else .{},
}; };
pub const device_extensions: []const [*:0]const u8 = &.{ pub const device_extensions: []const [*:0]const u8 = &.{
@@ -82,7 +79,7 @@ fn init_base() !void {
if (glfwVulkanSupported() != nu.Window.c.GLFW_TRUE) if (glfwVulkanSupported() != nu.Window.c.GLFW_TRUE)
return error.glfwNoVulkan; return error.glfwNoVulkan;
if (use_debug_messenger) { if (config.use_debug_messenger) {
_bw = try BaseWrapper.load(glfwGetInstanceProcAddress); _bw = try BaseWrapper.load(glfwGetInstanceProcAddress);
} else { } else {
_bw = BaseWrapper.loadNoFail(glfwGetInstanceProcAddress); _bw = BaseWrapper.loadNoFail(glfwGetInstanceProcAddress);
@@ -98,7 +95,7 @@ fn init_instance(alloc: std.mem.Allocator) !void {
var layers = std.ArrayList([*:0]const u8).init(alloc); var layers = std.ArrayList([*:0]const u8).init(alloc);
defer layers.deinit(); defer layers.deinit();
if (use_debug_messenger) { if (config.use_debug_messenger) {
try extensions.appendSlice(&.{ try extensions.appendSlice(&.{
vk.extensions.ext_debug_utils.name, vk.extensions.ext_debug_utils.name,
}); });
@@ -132,19 +129,19 @@ fn init_instance(alloc: std.mem.Allocator) !void {
_instance = try B.createInstance(&.{ _instance = try B.createInstance(&.{
.p_application_info = &.{ .p_application_info = &.{
.p_application_name = nu.options.render.app_name, .p_application_name = config.app_name,
.application_version = vk.makeApiVersion( .application_version = vk.makeApiVersion(
nu.options.render.app_version.variant, config.app_version.variant,
nu.options.render.app_version.major, config.app_version.major,
nu.options.render.app_version.minor, config.app_version.minor,
nu.options.render.app_version.patch, config.app_version.patch,
), ),
.p_engine_name = nu.options.render.engine_name, .p_engine_name = config.engine_name,
.engine_version = vk.makeApiVersion( .engine_version = vk.makeApiVersion(
nu.options.render.engine_version.variant, config.engine_version.variant,
nu.options.render.engine_version.major, config.engine_version.major,
nu.options.render.engine_version.minor, config.engine_version.minor,
nu.options.render.engine_version.patch, config.engine_version.patch,
), ),
.api_version = vk.API_VERSION_1_3, .api_version = vk.API_VERSION_1_3,
}, },
@@ -152,10 +149,10 @@ fn init_instance(alloc: std.mem.Allocator) !void {
.pp_enabled_extension_names = extensions.items.ptr, .pp_enabled_extension_names = extensions.items.ptr,
.enabled_layer_count = @intCast(layers.items.len), .enabled_layer_count = @intCast(layers.items.len),
.pp_enabled_layer_names = layers.items.ptr, .pp_enabled_layer_names = layers.items.ptr,
.p_next = if (use_debug_messenger) &mci else null, .p_next = if (config.use_debug_messenger) &mci else null,
}, null); }, null);
if (use_debug_messenger) { if (config.use_debug_messenger) {
_iw = try InstanceWrapper.load(_instance, _bw.dispatch.vkGetInstanceProcAddr); _iw = try InstanceWrapper.load(_instance, _bw.dispatch.vkGetInstanceProcAddr);
} else { } else {
_iw = InstanceWrapper.loadNoFail(_instance, _bw.dispatch.vkGetInstanceProcAddr); _iw = InstanceWrapper.loadNoFail(_instance, _bw.dispatch.vkGetInstanceProcAddr);
@@ -306,7 +303,7 @@ fn init_device(alloc: std.mem.Allocator) !void {
}, },
}, null); }, null);
if (use_debug_messenger) { if (config.use_debug_messenger) {
_dw = try DeviceWrapper.load(_device, _iw.dispatch.vkGetDeviceProcAddr); _dw = try DeviceWrapper.load(_device, _iw.dispatch.vkGetDeviceProcAddr);
} else { } else {
_dw = DeviceWrapper.loadNoFail(_device, _iw.dispatch.vkGetDeviceProcAddr); _dw = DeviceWrapper.loadNoFail(_device, _iw.dispatch.vkGetDeviceProcAddr);

View File

@@ -13,61 +13,62 @@ pub const c = @cImport({
pub const Bus = @import("Bus.zig"); pub const Bus = @import("Bus.zig");
pub const Options = struct { pub const Config = struct {
title: [*:0]const u8 = "Hello World", title: [*:0]const u8 = "Hello World",
width: u32 = 1280, width: u32 = 1280,
height: u32 = 720, height: u32 = 720,
x11_class_name: [*:0]const u8 = "floating_window", x11_class_name: [*:0]const u8 = "floating_window",
x11_instance_name: [*:0]const u8 = "floating_window", x11_instance_name: [*:0]const u8 = "floating_window",
unfocused_wait: f32 = 1.0 / 20.0,
}; };
const config: Config = nu.config.window;
var bus: Bus = undefined; // todo bus should probably move to engine. pub fn driver() nu.Driver {
pub var handle: *c.GLFWwindow = undefined; return nu.Driver{
var unfocused_rate: f32 = 1.0 / 20.0; .module = .{
.name = "Window",
pub fn init(alloc: std.mem.Allocator) !void { .dependencies = &.{}, // todo bus
if (c.glfwInit() != c.GLFW_TRUE) .setup = setup,
return error.glfwInitFailed; .teardown = teardown,
errdefer c.glfwTerminate(); },
.next = next,
bus = Bus.init(alloc); };
errdefer bus.deinit();
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
c.glfwWindowHintString(c.GLFW_X11_CLASS_NAME, nu.options.window.x11_class_name);
c.glfwWindowHintString(c.GLFW_X11_INSTANCE_NAME, nu.options.window.x11_instance_name);
handle = c.glfwCreateWindow(
@intCast(nu.options.window.width),
@intCast(nu.options.window.height),
nu.options.window.title,
null,
null,
) orelse
return error.glfWCreateWindowFailed;
errdefer c.glfwDestroyWindow(handle);
bus.connect(handle);
errdefer bus.disconnect(handle);
} }
pub fn deinit() void { pub var handle: *c.GLFWwindow = undefined;
bus.deinit();
pub fn setup(_: std.mem.Allocator) !void {
if (c.glfwInit() != c.GLFW_TRUE) std.debug.panic("GLFW Init Failed", .{});
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
c.glfwWindowHintString(c.GLFW_X11_CLASS_NAME, config.x11_class_name);
c.glfwWindowHintString(c.GLFW_X11_INSTANCE_NAME, config.x11_instance_name);
handle = c.glfwCreateWindow(
@intCast(config.width),
@intCast(config.height),
config.title,
null,
null,
) orelse std.debug.panic("GLFW Create Window Failed", .{});
// bus.connect(handle);
// errdefer bus.disconnect(handle);
}
pub fn teardown() void {
c.glfwDestroyWindow(handle); c.glfwDestroyWindow(handle);
c.glfwTerminate(); c.glfwTerminate();
} }
pub fn next() ?[]Bus.Event { pub fn next() bool {
bus.clear();
if (c.glfwWindowShouldClose(handle) == c.GLFW_TRUE) if (c.glfwWindowShouldClose(handle) == c.GLFW_TRUE)
return null; return false;
if (c.glfwGetWindowAttrib(handle, c.GLFW_FOCUSED) == c.GLFW_TRUE) { if (c.glfwGetWindowAttrib(handle, c.GLFW_FOCUSED) == c.GLFW_TRUE) {
c.glfwPollEvents(); c.glfwPollEvents();
} else { } else {
c.glfwWaitEventsTimeout(unfocused_rate); c.glfwWaitEventsTimeout(config.unfocused_wait);
} }
return bus.events.items; return true;
} }

View File

@@ -28,7 +28,7 @@ pub fn Hook(ftype: type) type {
_ = self.handlers.orderedRemove(f); _ = self.handlers.orderedRemove(f);
} }
fn invoke(self: Self, args: anytype) void { pub fn invoke(self: Self, args: anytype) void {
for (self.handlers.keys()) |handler| { for (self.handlers.keys()) |handler| {
@call(.auto, handler, args); @call(.auto, handler, args);
} }
@@ -57,7 +57,7 @@ pub fn Hook(ftype: type) type {
_ = self.handlers.orderedRemove(f); _ = self.handlers.orderedRemove(f);
} }
fn invoke(self: Self, alloc: std.mem.Allocator, args: anytype) ![]Result { pub fn invoke(self: Self, alloc: std.mem.Allocator, args: anytype) ![]Result {
const results = try alloc.alloc(Result, self.handlers.count()); const results = try alloc.alloc(Result, self.handlers.count());
for (self.handlers.keys(), results) |handler, *result| { for (self.handlers.keys(), results) |handler, *result| {
result.* = @call(.auto, handler, args); result.* = @call(.auto, handler, args);