diff --git a/cimgui/src/root.zig b/cimgui/src/root.zig index bd5d960..f12ad07 100644 --- a/cimgui/src/root.zig +++ b/cimgui/src/root.zig @@ -1,4 +1,9 @@ -pub const c = @cImport({ +pub usingnamespace @cImport({ + @cDefine("CIMGUI_DEFINE_ENUMS_AND_STRUCTS", {}); + @cInclude("cimgui.h"); +}); + +pub const impl = @cImport({ @cDefine("CIMGUI_DEFINE_ENUMS_AND_STRUCTS", {}); @cInclude("cimgui.h"); diff --git a/src/main.zig b/src/main.zig index 9063123..21cff7a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -11,6 +11,14 @@ pub const nu_options: nu.Options = .{ }, }; +pub const nu_driver = nu.Window; + +pub const nu_modules = .{ + App, + nu.ImGui, + nu.Render, +}; + pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.detectLeaks(); @@ -37,9 +45,5 @@ pub fn main() !void { try App.init(alloc); defer App.deinit(); - try nu.run(nu.Window, .{ - App, - nu.ImGui, - nu.Render, - }); + try nu.run(); } diff --git a/src/nu.zig b/src/nu.zig index a977e4e..6ceccb9 100644 --- a/src/nu.zig +++ b/src/nu.zig @@ -12,31 +12,36 @@ pub const Options = struct { }; 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 fn run( - driver: anytype, - modules: anytype, -) !void { +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."); + }, + } + } +} + +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); + } + } +} + +pub fn run() !void { while (driver.next()) |events| { // todo event handler _ = events; - inline for (modules) |module| { - if (@hasDecl(module, "frame")) { - if (@typeInfo(@TypeOf(module.frame)).Fn.return_type) |R| { - switch (@typeInfo(R)) { - .ErrorUnion => try module.frame(), - .Void => module.frame(), - else => { - @compileLog(module.frame, @typeInfo(R)); - @compileError("frame must be void or !void."); - }, - } - } else { - module.frame(); - } - } - } + try invoke_hook("frame", .{}); // todo fixed timestep } diff --git a/src/nu/ImGui.zig b/src/nu/ImGui.zig index e5231bd..ee9bfa0 100644 --- a/src/nu/ImGui.zig +++ b/src/nu/ImGui.zig @@ -5,32 +5,34 @@ const std = @import("std"); const vk = @import("vk"); const nu = @import("../nu.zig"); const au = @import("Render/au.zig"); + const Render = @import("Render.zig"); const Window = @import("Window.zig"); const im = @import("cimgui"); +pub usingnamespace im; pub fn loader_wrapper(procname: [*c]const u8, _: ?*anyopaque) callconv(.C) vk.PfnVoidFunction { return au.glfwGetInstanceProcAddress(au.I.handle, procname); } -var ctx: *im.c.ImGuiContext = undefined; +var ctx: *im.ImGuiContext = undefined; var descriptor_pool: vk.DescriptorPool = undefined; pub fn init() !void { - ctx = im.c.igCreateContext(null) orelse { + ctx = im.igCreateContext(null) orelse { return error.igCreateContextFailed; }; - errdefer im.c.igDestroyContext(ctx); + errdefer im.igDestroyContext(ctx); - if (!im.c.ImGui_ImplVulkan_LoadFunctions(loader_wrapper, null)) { + if (!im.impl.ImGui_ImplVulkan_LoadFunctions(loader_wrapper, null)) { return error.igVulkanLoadFunctionsFailed; } - if (!im.c.ImGui_ImplGlfw_InitForVulkan(@ptrCast(Window.handle), true)) { + if (!im.impl.ImGui_ImplGlfw_InitForVulkan(@ptrCast(Window.handle), true)) { return error.igGlfwInitFailed; } - errdefer im.c.ImGui_ImplGlfw_Shutdown(); + errdefer im.impl.ImGui_ImplGlfw_Shutdown(); descriptor_pool = try au.D.createDescriptorPool(&vk.DescriptorPoolCreateInfo{ .flags = .{ .free_descriptor_set_bit = true }, @@ -43,7 +45,7 @@ pub fn init() !void { }, null); errdefer au.D.destroyDescriptorPool(descriptor_pool, null); - if (im.c.ImGui_ImplVulkan_Init(@constCast(&im.c.ImGui_ImplVulkan_InitInfo{ + if (im.impl.ImGui_ImplVulkan_Init(@constCast(&im.impl.ImGui_ImplVulkan_InitInfo{ .Instance = @ptrFromInt(@intFromEnum(au.I.handle)), .PhysicalDevice = @ptrFromInt(@intFromEnum(au.device_config.pdev)), .Device = @ptrFromInt(@intFromEnum(au.D.handle)), @@ -68,9 +70,9 @@ pub fn init() !void { })) != true) { return error.igVulkanInitFailed; } - errdefer im.c.ImGui_ImplVulkan_Shutdown(); + errdefer im.impl.ImGui_ImplVulkan_Shutdown(); - if (!im.c.ImGui_ImplVulkan_CreateFontsTexture()) { + if (!im.impl.ImGui_ImplVulkan_CreateFontsTexture()) { return error.igVulkanFontTextureFailed; } @@ -79,27 +81,27 @@ pub fn init() !void { } pub fn frame() void { - im.c.ImGui_ImplGlfw_NewFrame(); - im.c.ImGui_ImplVulkan_NewFrame(); - im.c.igNewFrame(); + im.impl.ImGui_ImplGlfw_NewFrame(); + im.impl.ImGui_ImplVulkan_NewFrame(); + im.igNewFrame(); - im.c.igShowDemoWindow(null); + im.igShowDemoWindow(null); - im.c.igEndFrame(); - im.c.igRender(); + im.igEndFrame(); + im.igRender(); } pub fn deinit() void { Render.remove_present_callback(present); - im.c.ImGui_ImplVulkan_Shutdown(); + im.impl.ImGui_ImplVulkan_Shutdown(); au.D.destroyDescriptorPool(descriptor_pool, null); - im.c.ImGui_ImplGlfw_Shutdown(); - im.c.igDestroyContext(ctx); + im.impl.ImGui_ImplGlfw_Shutdown(); + im.igDestroyContext(ctx); } pub fn present(cmd: au.CommandBufferProxy) void { - im.c.ImGui_ImplVulkan_RenderDrawData( - im.c.igGetDrawData(), + im.impl.ImGui_ImplVulkan_RenderDrawData( + @ptrCast(im.igGetDrawData()), @ptrFromInt(@intFromEnum(cmd.handle)), null, ); diff --git a/src/nu/Render/au/ui.zig b/src/nu/Render/au/ui.zig deleted file mode 100644 index 9d4c5f3..0000000 --- a/src/nu/Render/au/ui.zig +++ /dev/null @@ -1,90 +0,0 @@ -const std = @import("std"); -const vk = @import("vk"); -const im = @import("cimgui"); -const au = @import("../au.zig"); -const c = @import("../c.zig"); - -pub usingnamespace im.c; - -pub fn loader_wrapper(procname: [*c]const u8, _: ?*anyopaque) callconv(.C) vk.PfnVoidFunction { - return c.glfwGetInstanceProcAddress(au.I.handle, procname); -} - -var descriptor_pool: vk.DescriptorPool = undefined; - -pub fn init(frames_in_flight: usize) !*im.c.ImGuiContext { - const ctx = im.c.igCreateContext(null) orelse return error.igCreateContextFailed; - errdefer im.c.igDestroyContext(ctx); - - if (im.c.ImGui_ImplVulkan_LoadFunctions(loader_wrapper, null) != true) { - return error.igVulkanLoadFunctionsFailed; - } - - if (im.c.ImGui_ImplGlfw_InitForVulkan(@ptrCast(au.W.handle), true) != true) { - return error.igGlfwInitFailed; - } - errdefer im.c.ImGui_ImplGlfw_Shutdown(); - - descriptor_pool = try au.D.createDescriptorPool(&vk.DescriptorPoolCreateInfo{ - .flags = .{ .free_descriptor_set_bit = true }, - .pool_size_count = 1, - .p_pool_sizes = &.{vk.DescriptorPoolSize{ .descriptor_count = 32, .type = .combined_image_sampler }}, - .max_sets = 32, - }, null); - errdefer au.D.destroyDescriptorPool(descriptor_pool, null); - - if (im.c.ImGui_ImplVulkan_Init(@constCast(&im.c.ImGui_ImplVulkan_InitInfo{ - .Instance = @ptrFromInt(@intFromEnum(au.I.handle)), - .PhysicalDevice = @ptrFromInt(@intFromEnum(au.device_config.pdev)), - .Device = @ptrFromInt(@intFromEnum(au.D.handle)), - .QueueFamily = au.device_config.family, - .Queue = @ptrFromInt(@intFromEnum(au.Q.handle)), - .DescriptorPool = @ptrFromInt(@intFromEnum(descriptor_pool)), - .RenderPass = null, - .MinImageCount = 2, - .ImageCount = @intCast(frames_in_flight), - .PipelineRenderingCreateInfo = @bitCast(vk.PipelineRenderingCreateInfo{ - .view_mask = 0, - .depth_attachment_format = .undefined, - .stencil_attachment_format = .undefined, - .color_attachment_count = 1, - .p_color_attachment_formats = &.{au.device_config.format.format}, - }), - .MSAASamples = 0, - .PipelineCache = null, - .Subpass = 0, - .UseDynamicRendering = true, - .Allocator = null, - })) != true) { - return error.igVulkanInitFailed; - } - errdefer im.c.ImGui_ImplVulkan_Shutdown(); - - if (im.c.ImGui_ImplVulkan_CreateFontsTexture() != true) { - return error.igVulkanFontTextureFailed; - } - - return ctx; -} - -pub fn deinit(ctx: *im.c.ImGuiContext) void { - im.c.ImGui_ImplVulkan_Shutdown(); - au.D.destroyDescriptorPool(descriptor_pool, null); - im.c.ImGui_ImplGlfw_Shutdown(); - im.c.igDestroyContext(ctx); -} - -pub fn NewFrame() void { - im.c.ImGui_ImplGlfw_NewFrame(); - im.c.ImGui_ImplVulkan_NewFrame(); - im.c.igNewFrame(); -} - -pub fn EndFrame() void { - im.c.igEndFrame(); - im.c.igRender(); -} - -pub fn Draw(cmd: au.CommandBufferProxy) void { - im.c.ImGui_ImplVulkan_RenderDrawData(im.c.igGetDrawData(), @ptrFromInt(@intFromEnum(cmd.handle)), null); -}