wip polymorphic modules
This commit is contained in:
26
src/App.zig
26
src/App.zig
@@ -5,24 +5,24 @@ const Bus = @import("nu/Bus.zig");
|
||||
const Render = @import("nu/Render.zig");
|
||||
const ImGui = @import("nu/ImGui.zig");
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator) !void {
|
||||
_ = alloc;
|
||||
pub fn module() nu.Module {
|
||||
return nu.Module{
|
||||
.name = "App",
|
||||
// .dependencies = &.{ Render.module(), ImGui.module() },
|
||||
.setup = setup,
|
||||
.teardown = teardown,
|
||||
.update = update,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn connect() !void {
|
||||
try ImGui.hooks.frame.register(nu_imgui_frame);
|
||||
pub fn setup(_: std.mem.Allocator) !void {
|
||||
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 {
|
||||
// std.debug.print("{any}\n", .{events});
|
||||
// }
|
||||
|
||||
// pub fn nu_render_present(_: Render.au.CommandBufferProxy) void {}
|
||||
|
||||
pub fn nu_imgui_frame() void {
|
||||
pub fn gui() void {
|
||||
ImGui.igShowMetricsWindow(null);
|
||||
}
|
||||
|
48
src/main.zig
48
src/main.zig
@@ -23,30 +23,32 @@ pub const nu_options: nu.Options = .{
|
||||
|
||||
pub const nu_driver = nu.Window;
|
||||
pub const nu_modules = .{
|
||||
App,
|
||||
nu.ImGui,
|
||||
nu.Render,
|
||||
nu.ImGui,
|
||||
App,
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.detectLeaks();
|
||||
const alloc = gpa.allocator();
|
||||
pub const main = nu.main;
|
||||
|
||||
nu.init(alloc);
|
||||
defer nu.deinit();
|
||||
|
||||
try nu.Window.init(alloc);
|
||||
defer nu.Window.deinit();
|
||||
|
||||
try nu.Render.init(alloc);
|
||||
defer nu.Render.deinit();
|
||||
|
||||
try nu.ImGui.init(alloc);
|
||||
defer nu.ImGui.deinit();
|
||||
|
||||
try App.init(alloc);
|
||||
defer App.deinit();
|
||||
|
||||
try nu.run(alloc);
|
||||
}
|
||||
// pub fn main() !void {
|
||||
// var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
// defer _ = gpa.detectLeaks();
|
||||
// const alloc = gpa.allocator();
|
||||
//
|
||||
// nu.init(alloc);
|
||||
// defer nu.deinit();
|
||||
//
|
||||
// try nu.Window.init(alloc);
|
||||
// defer nu.Window.deinit();
|
||||
//
|
||||
// try nu.Render.init(alloc);
|
||||
// defer nu.Render.deinit();
|
||||
//
|
||||
// try nu.ImGui.init(alloc);
|
||||
// defer nu.ImGui.deinit();
|
||||
//
|
||||
// try App.init(alloc);
|
||||
// defer App.deinit();
|
||||
//
|
||||
// try nu.run(alloc);
|
||||
// }
|
||||
|
133
src/nu.zig
133
src/nu.zig
@@ -8,91 +8,80 @@ pub const ImGui = @import("nu/ImGui.zig");
|
||||
pub const Bus = @import("nu/Bus.zig");
|
||||
pub const Hook = @import("nu/hooks.zig").Hook;
|
||||
|
||||
pub const Options = struct {
|
||||
window: Window.Options = .{},
|
||||
render: Render.Options = .{},
|
||||
imgui: ImGui.Options = .{},
|
||||
const Config = struct {
|
||||
window: Window.Config = .{},
|
||||
render: Render.Config = .{},
|
||||
};
|
||||
|
||||
pub const options: Options = if (@hasDecl(root, "nu_options")) root.nu_options else .{};
|
||||
pub const modules = root.nu_modules;
|
||||
pub const driver = root.nu_driver;
|
||||
pub const config: Config = if (@hasDecl(root, "nu_config")) root.nu_config else .{};
|
||||
|
||||
pub const Hooks = struct {
|
||||
pub const Enter = Hook(fn () void);
|
||||
pub const Events = Hook(fn ([]Bus.Event) void);
|
||||
pub const Frame = Hook(fn () anyerror!void);
|
||||
pub const Close = Hook(fn () void);
|
||||
|
||||
enter: Enter,
|
||||
events: Events,
|
||||
frame: Frame,
|
||||
close: Close,
|
||||
pub const Module = struct {
|
||||
// todo dependencies
|
||||
name: []const u8,
|
||||
setup: *const fn (alloc: std.mem.Allocator) anyerror!void,
|
||||
teardown: *const fn () void,
|
||||
update: ?*const fn () anyerror!void = null,
|
||||
frame: ?*const fn () anyerror!void = null,
|
||||
dependencies: []const Module = &.{},
|
||||
};
|
||||
|
||||
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 {
|
||||
hooks = .{
|
||||
.enter = Hooks.Enter.init(alloc),
|
||||
.events = Hooks.Events.init(alloc),
|
||||
.frame = Hooks.Frame.init(alloc),
|
||||
.close = Hooks.Close.init(alloc),
|
||||
};
|
||||
fn enable(modules: *std.StringArrayHashMap(Module), module: Module) void {
|
||||
// this doesn't handle dependencies correctly. need to do real topological sort.
|
||||
|
||||
if (modules.contains(module.name)) return;
|
||||
for (module.dependencies) |dep| enable(modules, dep);
|
||||
modules.putNoClobber(module.name, module) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
hooks.enter.deinit();
|
||||
hooks.events.deinit();
|
||||
hooks.frame.deinit();
|
||||
hooks.close.deinit();
|
||||
}
|
||||
pub fn main() void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
const alloc = gpa.allocator();
|
||||
|
||||
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();
|
||||
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());
|
||||
}
|
||||
|
||||
hooks.enter.invoke(.{});
|
||||
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 {
|
||||
var rev = std.mem.reverseIterator(modules.values());
|
||||
while (rev.next()) |mod| {
|
||||
std.log.debug("{s}.teardown", .{mod.name});
|
||||
mod.teardown();
|
||||
}
|
||||
}
|
||||
|
||||
while (driver.next()) |events| {
|
||||
if (events.len > 0) {
|
||||
hooks.events.invoke(.{events});
|
||||
std.log.info("Loaded modules: {s}", .{modules.keys()});
|
||||
|
||||
while (driver.next()) {
|
||||
for (modules.values()) |mod| {
|
||||
if (mod.update) |update| {
|
||||
update() catch |err| {
|
||||
std.debug.panic("Module {s} update event error: {!}", .{ mod.name, err });
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// todo frame timer
|
||||
const frame_results = try hooks.frame.invoke(alloc, .{});
|
||||
defer alloc.free(frame_results);
|
||||
for (frame_results) |result| result catch |err| return err;
|
||||
|
||||
// todo fixed timestep
|
||||
for (modules.values()) |mod| {
|
||||
if (mod.frame) |frame| {
|
||||
frame() catch |err| {
|
||||
std.debug.panic("Module {s} frame event error: {!}", .{ mod.name, err });
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.");
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
@@ -13,23 +13,33 @@ const Window = @import("Window.zig");
|
||||
const im = @import("cimgui");
|
||||
pub usingnamespace im;
|
||||
|
||||
pub const Options = struct {};
|
||||
pub const Config = struct {};
|
||||
const config = nu.config.imgui;
|
||||
|
||||
pub const Hooks = struct {
|
||||
pub const Frame = Hook(fn () void);
|
||||
frame: Frame,
|
||||
};
|
||||
pub fn module() nu.Module {
|
||||
return nu.Module{
|
||||
.name = "ImGui",
|
||||
// .dependencies = &.{Render.module()},
|
||||
.setup = setup,
|
||||
.teardown = teardown,
|
||||
.update = update,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn loader_wrapper(procname: [*c]const u8, _: ?*anyopaque) callconv(.C) vk.PfnVoidFunction {
|
||||
return au.glfwGetInstanceProcAddress(au.I.handle, procname);
|
||||
}
|
||||
|
||||
pub var gui: Hook(fn () void) = undefined;
|
||||
var ctx: *im.ImGuiContext = 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 {
|
||||
return error.igCreateContextFailed;
|
||||
};
|
||||
@@ -64,7 +74,7 @@ pub fn init(alloc: std.mem.Allocator) !void {
|
||||
.DescriptorPool = @ptrFromInt(@intFromEnum(descriptor_pool)),
|
||||
.RenderPass = null,
|
||||
.MinImageCount = 2,
|
||||
.ImageCount = @intCast(nu.options.render.frames_in_flight),
|
||||
.ImageCount = @intCast(nu.config.render.frames_in_flight),
|
||||
.PipelineRenderingCreateInfo = @bitCast(vk.PipelineRenderingCreateInfo{
|
||||
.view_mask = 0,
|
||||
.depth_attachment_format = .undefined,
|
||||
@@ -85,38 +95,30 @@ pub fn init(alloc: std.mem.Allocator) !void {
|
||||
if (!im.impl.ImGui_ImplVulkan_CreateFontsTexture()) {
|
||||
return error.igVulkanFontTextureFailed;
|
||||
}
|
||||
|
||||
hooks = .{
|
||||
.frame = Hooks.Frame.init(alloc),
|
||||
};
|
||||
errdefer hooks.frame.deinit();
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
hooks.frame.deinit();
|
||||
pub fn teardown() void {
|
||||
au.D.deviceWaitIdle() catch |err| std.debug.panic("Device wait failed: {!}", .{err});
|
||||
|
||||
im.impl.ImGui_ImplVulkan_Shutdown();
|
||||
au.D.destroyDescriptorPool(descriptor_pool, null);
|
||||
im.impl.ImGui_ImplGlfw_Shutdown();
|
||||
im.igDestroyContext(ctx);
|
||||
gui.deinit();
|
||||
}
|
||||
|
||||
pub fn connect() !void {
|
||||
try nu.hooks.frame.register(nu_frame);
|
||||
try Render.hooks.present.register(nu_render_present);
|
||||
}
|
||||
|
||||
pub fn nu_frame() !void {
|
||||
pub fn update() !void {
|
||||
im.impl.ImGui_ImplGlfw_NewFrame();
|
||||
im.impl.ImGui_ImplVulkan_NewFrame();
|
||||
im.igNewFrame();
|
||||
|
||||
hooks.frame.invoke(.{});
|
||||
gui.invoke(.{});
|
||||
|
||||
im.igEndFrame();
|
||||
im.igRender();
|
||||
}
|
||||
|
||||
pub fn nu_render_present(cmd: au.CommandBufferProxy) void {
|
||||
pub fn present(cmd: au.CommandBufferProxy) void {
|
||||
im.impl.ImGui_ImplVulkan_RenderDrawData(
|
||||
@ptrCast(im.igGetDrawData()),
|
||||
@ptrFromInt(@intFromEnum(cmd.handle)),
|
||||
|
@@ -9,9 +9,7 @@ const vk = @import("vk");
|
||||
const nu = @import("../nu.zig");
|
||||
const au = @import("Render/au.zig");
|
||||
|
||||
const Hook = @import("hooks.zig").Hook;
|
||||
|
||||
pub const Options = struct {
|
||||
pub const Config = struct {
|
||||
app_name: [*:0]const u8 = "nu-au-app",
|
||||
app_version: struct {
|
||||
variant: u3 = 0,
|
||||
@@ -27,20 +25,29 @@ pub const Options = struct {
|
||||
patch: u12 = 0,
|
||||
} = .{},
|
||||
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 const Present = Hook(fn (au.CommandBufferProxy) void);
|
||||
|
||||
present: Present,
|
||||
};
|
||||
|
||||
pub var hooks: Hooks = undefined;
|
||||
pub fn module() nu.Module {
|
||||
return nu.Module{
|
||||
.name = "Render",
|
||||
.setup = setup,
|
||||
.teardown = teardown,
|
||||
.frame = frame,
|
||||
.dependencies = &.{nu.Window.driver().module},
|
||||
};
|
||||
}
|
||||
|
||||
var sc: au.SwapChain = 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.
|
||||
try au.init(alloc);
|
||||
errdefer au.deinit();
|
||||
@@ -48,26 +55,22 @@ pub fn init(alloc: std.mem.Allocator) !void {
|
||||
sc = try au.SwapChain.init(alloc);
|
||||
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();
|
||||
|
||||
hooks = .{ .present = Hooks.Present.init(alloc) };
|
||||
errdefer hooks.present.deinit();
|
||||
present = @TypeOf(present).init(alloc);
|
||||
errdefer present.deinit();
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
hooks.present.deinit();
|
||||
pub fn teardown() void {
|
||||
au.D.deviceWaitIdle() catch |err| std.debug.panic("Device wait failed: {!}", .{err});
|
||||
errdefer present.deinit();
|
||||
flights.deinit();
|
||||
sc.deinit();
|
||||
au.deinit();
|
||||
}
|
||||
|
||||
pub fn connect() !void {
|
||||
try nu.hooks.frame.register(nu_frame);
|
||||
try nu.hooks.close.register(nu_close);
|
||||
}
|
||||
|
||||
pub fn nu_frame() !void {
|
||||
pub fn frame() !void {
|
||||
const flight: au.Flights.Flight = flights.next();
|
||||
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.
|
||||
// will need some comptime -> anytype mapping.
|
||||
hooks.present.invoke(.{cmd});
|
||||
|
||||
present.invoke(.{cmd});
|
||||
|
||||
target.end_rendering(cmd);
|
||||
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});
|
||||
};
|
||||
}
|
||||
|
@@ -8,10 +8,7 @@ pub const SwapChain = @import("au/SwapChain.zig");
|
||||
pub const Flights = @import("au/Flights.zig");
|
||||
pub const VkAllocator = @import("au/VkAllocator.zig");
|
||||
|
||||
pub const use_debug_messenger = switch (builtin.mode) {
|
||||
.Debug, .ReleaseSafe => true,
|
||||
.ReleaseSmall, .ReleaseFast => false,
|
||||
};
|
||||
const config = nu.config.render;
|
||||
|
||||
pub const apis: []const vk.ApiInfo = &.{
|
||||
vk.features.version_1_0,
|
||||
@@ -21,7 +18,7 @@ pub const apis: []const vk.ApiInfo = &.{
|
||||
vk.extensions.khr_surface,
|
||||
vk.extensions.khr_swapchain,
|
||||
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 = &.{
|
||||
@@ -82,7 +79,7 @@ fn init_base() !void {
|
||||
if (glfwVulkanSupported() != nu.Window.c.GLFW_TRUE)
|
||||
return error.glfwNoVulkan;
|
||||
|
||||
if (use_debug_messenger) {
|
||||
if (config.use_debug_messenger) {
|
||||
_bw = try BaseWrapper.load(glfwGetInstanceProcAddress);
|
||||
} else {
|
||||
_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);
|
||||
defer layers.deinit();
|
||||
|
||||
if (use_debug_messenger) {
|
||||
if (config.use_debug_messenger) {
|
||||
try extensions.appendSlice(&.{
|
||||
vk.extensions.ext_debug_utils.name,
|
||||
});
|
||||
@@ -132,19 +129,19 @@ fn init_instance(alloc: std.mem.Allocator) !void {
|
||||
|
||||
_instance = try B.createInstance(&.{
|
||||
.p_application_info = &.{
|
||||
.p_application_name = nu.options.render.app_name,
|
||||
.p_application_name = config.app_name,
|
||||
.application_version = vk.makeApiVersion(
|
||||
nu.options.render.app_version.variant,
|
||||
nu.options.render.app_version.major,
|
||||
nu.options.render.app_version.minor,
|
||||
nu.options.render.app_version.patch,
|
||||
config.app_version.variant,
|
||||
config.app_version.major,
|
||||
config.app_version.minor,
|
||||
config.app_version.patch,
|
||||
),
|
||||
.p_engine_name = nu.options.render.engine_name,
|
||||
.p_engine_name = config.engine_name,
|
||||
.engine_version = vk.makeApiVersion(
|
||||
nu.options.render.engine_version.variant,
|
||||
nu.options.render.engine_version.major,
|
||||
nu.options.render.engine_version.minor,
|
||||
nu.options.render.engine_version.patch,
|
||||
config.engine_version.variant,
|
||||
config.engine_version.major,
|
||||
config.engine_version.minor,
|
||||
config.engine_version.patch,
|
||||
),
|
||||
.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,
|
||||
.enabled_layer_count = @intCast(layers.items.len),
|
||||
.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);
|
||||
|
||||
if (use_debug_messenger) {
|
||||
if (config.use_debug_messenger) {
|
||||
_iw = try InstanceWrapper.load(_instance, _bw.dispatch.vkGetInstanceProcAddr);
|
||||
} else {
|
||||
_iw = InstanceWrapper.loadNoFail(_instance, _bw.dispatch.vkGetInstanceProcAddr);
|
||||
@@ -306,7 +303,7 @@ fn init_device(alloc: std.mem.Allocator) !void {
|
||||
},
|
||||
}, null);
|
||||
|
||||
if (use_debug_messenger) {
|
||||
if (config.use_debug_messenger) {
|
||||
_dw = try DeviceWrapper.load(_device, _iw.dispatch.vkGetDeviceProcAddr);
|
||||
} else {
|
||||
_dw = DeviceWrapper.loadNoFail(_device, _iw.dispatch.vkGetDeviceProcAddr);
|
||||
|
@@ -13,61 +13,62 @@ pub const c = @cImport({
|
||||
|
||||
pub const Bus = @import("Bus.zig");
|
||||
|
||||
pub const Options = struct {
|
||||
pub const Config = struct {
|
||||
title: [*:0]const u8 = "Hello World",
|
||||
width: u32 = 1280,
|
||||
height: u32 = 720,
|
||||
x11_class_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 var handle: *c.GLFWwindow = undefined;
|
||||
var unfocused_rate: f32 = 1.0 / 20.0;
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator) !void {
|
||||
if (c.glfwInit() != c.GLFW_TRUE)
|
||||
return error.glfwInitFailed;
|
||||
errdefer c.glfwTerminate();
|
||||
|
||||
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 driver() nu.Driver {
|
||||
return nu.Driver{
|
||||
.module = .{
|
||||
.name = "Window",
|
||||
.dependencies = &.{}, // todo bus
|
||||
.setup = setup,
|
||||
.teardown = teardown,
|
||||
},
|
||||
.next = next,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
bus.deinit();
|
||||
pub var handle: *c.GLFWwindow = undefined;
|
||||
|
||||
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.glfwTerminate();
|
||||
}
|
||||
|
||||
pub fn next() ?[]Bus.Event {
|
||||
bus.clear();
|
||||
|
||||
pub fn next() bool {
|
||||
if (c.glfwWindowShouldClose(handle) == c.GLFW_TRUE)
|
||||
return null;
|
||||
return false;
|
||||
|
||||
if (c.glfwGetWindowAttrib(handle, c.GLFW_FOCUSED) == c.GLFW_TRUE) {
|
||||
c.glfwPollEvents();
|
||||
} else {
|
||||
c.glfwWaitEventsTimeout(unfocused_rate);
|
||||
c.glfwWaitEventsTimeout(config.unfocused_wait);
|
||||
}
|
||||
|
||||
return bus.events.items;
|
||||
return true;
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ pub fn Hook(ftype: type) type {
|
||||
_ = self.handlers.orderedRemove(f);
|
||||
}
|
||||
|
||||
fn invoke(self: Self, args: anytype) void {
|
||||
pub fn invoke(self: Self, args: anytype) void {
|
||||
for (self.handlers.keys()) |handler| {
|
||||
@call(.auto, handler, args);
|
||||
}
|
||||
@@ -57,7 +57,7 @@ pub fn Hook(ftype: type) type {
|
||||
_ = 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());
|
||||
for (self.handlers.keys(), results) |handler, *result| {
|
||||
result.* = @call(.auto, handler, args);
|
||||
|
Reference in New Issue
Block a user