git.s-ol.nu zig-imgui / 407a006
more glfw s-ol 30 days ago
2 changed file(s) with 127 addition(s) and 18 deletion(s). Raw diff Collapse all Expand all
11 const c = @import("c.zig");
22 const builtin = @import("builtin");
3 const debug = @import("std").debug;
4 const math = @import("std").math;
5
36 pub const ClientApi = enum {
47 Unknown,
58 OpenGL,
912 // Data
1013 var g_Window: ?*c.GLFWwindow = null;
1114 var g_ClientApi: ClientApi = .Unknown;
12 var g_Time: f32 = 0.0;
15 var g_Time: f64 = 0.0;
1316 var g_MouseJustPressed = [_]bool{ false } ** 5;
1417 var g_MouseCursors = [_]?*c.GLFWcursor{ null } ** @enumToInt(c.ImGuiMouseCursor_COUNT);
1518 var g_WantUpdateMonitors = true;
1619
1720 // Chain GLFW callbacks for main viewport:
1821 // our callbacks will call the user's previously installed callbacks, if any.
19 var g_PrevUserCallbackMousebutton: ?c.GLFWmousebuttonfun = null;
20 var g_PrevUserCallbackScroll: ?c.GLFWscrollfun = null;
21 var g_PrevUserCallbackKey: ?c.GLFWkeyfun = null;
22 var g_PrevUserCallbackChar: ?c.GLFWcharfun = null;
22 var g_PrevUserCallbackMousebutton: c.GLFWmousebuttonfun = null;
23 var g_PrevUserCallbackScroll: c.GLFWscrollfun = null;
24 var g_PrevUserCallbackKey: c.GLFWkeyfun = null;
25 var g_PrevUserCallbackChar: c.GLFWcharfun = null;
2326
2427 pub fn Init(window: *c.GLFWwindow, install_callbacks: bool, client_api: ClientApi) void {
2528 g_Window = window;
2932 const io = c.igGetIO();
3033 io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_HasMouseCursors); // We can honor GetMouseCursor() values (optional)
3134 io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_HasSetMousePos); // We can honor io.WantSetMousePos requests (optional, rarely used)
32 io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_PlatformHasViewports); // We can create multi-viewports on the Platform side (optional)
33 if (@hasField(c, "GLFW_HAS_GLFW_HOVERED") and builtin.os == builtin.Os.windows) {
35 if (false) io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_PlatformHasViewports); // We can create multi-viewports on the Platform side (optional)
36 if (false and @hasField(c, "GLFW_HAS_GLFW_HOVERED") and builtin.os == builtin.Os.windows) {
3437 io.*.BackendFlags |= @enumToInt(ImGuiBackendFlags_HasMouseHoveredViewport); // We can set io.MouseHoveredViewport correctly (optional, not easy)
3538 }
3639 io.*.BackendPlatformName = c"imgui_impl_glfw.zig";
6265 // @TODO: Clipboard
6366 // io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
6467 // io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
65 // io.ClipboardUserData = g_Window;
68 io.*.ClipboardUserData = g_Window;
6669
6770 g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_Arrow)] = c.glfwCreateStandardCursor(c.GLFW_ARROW_CURSOR);
6871 g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_TextInput)] = c.glfwCreateStandardCursor(c.GLFW_IBEAM_CURSOR);
8891 // Our mouse update function expect PlatformHandle to be filled for the main viewport
8992 const main_viewport = c.igGetMainViewport();
9093 main_viewport.*.PlatformHandle = g_Window;
91 if (builtin.os == builtin.Os.windows) {
94 if (builtin.os == builtin.Os.windows)
9295 main_viewport.*.PlatformHandleRaw = c.glfwGetWin32Window(g_Window);
93 }
9496
9597 // @TODO: Platform Interface (Viewport)
96 // if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable != 0)
97 // ImGui_ImplGlfw_InitPlatformInterface();
98 if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0)
99 unreachable;
100 // ImGui_ImplGlfw_InitPlatformInterface();
98101
99102 g_ClientApi = client_api;
100103 }
112115
113116 pub fn NewFrame() void {
114117 const io = c.igGetIO();
115 // @TODO: assert font atlas
118 debug.assert(c.ImFontAtlas_IsBuilt(io.*.Fonts));
116119
117120 var w : c_int = undefined;
118121 var h : c_int = undefined;
121124 c.glfwGetWindowSize(g_Window, &w, &h);
122125 c.glfwGetFramebufferSize(g_Window, &display_w, &display_h);
123126 io.*.DisplaySize = c.ImVec2{ .x = @intToFloat(f32, w), .y = @intToFloat(f32, h) };
127
128 if (w > 0 and h > 0)
129 io.*.DisplayFramebufferScale = c.ImVec2{
130 .x = @intToFloat(f32, display_w) / @intToFloat(f32, w),
131 .y = @intToFloat(f32, display_h) / @intToFloat(f32, h),
132 };
133 if (g_WantUpdateMonitors)
134 UpdateMonitors();
135
136 // Setup time step
137 const current_time = c.glfwGetTime();
138 io.*.DeltaTime = if (g_Time > 0.0) @floatCast(f32, current_time - g_Time) else 1.0 / 60.0;
139 g_Time = current_time;
140
141 UpdateMousePosAndButtons();
142 UpdateMouseCursor();
143
144 UpdateGamepads();
145 }
146
147 fn UpdateMonitors() void {
148 // @TODO
149 }
150
151 fn UpdateMousePosAndButtons() void {
152 // Update buttons
153 const io = c.igGetIO();
154 for (io.*.MouseDown) |*isDown, i| {
155 // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
156 isDown.* = g_MouseJustPressed[i] or c.glfwGetMouseButton(g_Window, @intCast(c_int, i)) != 0;
157 g_MouseJustPressed[i] = false;
158 }
159
160 // Update mouse position
161 const mouse_pos_backup = io.*.MousePos;
162 io.*.MousePos = c.ImVec2{ .x = math.f32_min, .y = math.f32_min };
163 io.*.MouseHoveredViewport = 0;
164 const platform_io = c.igGetPlatformIO();
165 var n : usize = 0;
166 while (n < @intCast(usize, platform_io.*.Viewports.Size)) : (n += 1) {
167 const viewport = platform_io.*.Viewports.Data[n];
168 const window = @ptrCast(*c.GLFWwindow, viewport.*.PlatformHandle);
169 const focused = c.glfwGetWindowAttrib(window, c.GLFW_FOCUSED) != 0;
170 if (focused) {
171 if (io.*.WantSetMousePos) {
172 c.glfwSetCursorPos(window, mouse_pos_backup.x - viewport.*.Pos.x, mouse_pos_backup.y - viewport.*.Pos.y);
173 } else {
174 var mouse_x : f64 = undefined;
175 var mouse_y : f64 = undefined;
176 c.glfwGetCursorPos(window, &mouse_x, &mouse_y);
177 if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0) {
178 // Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor)
179 var window_x : c_int = undefined;
180 var window_y : c_int = undefined;
181 c.glfwGetWindowPos(window, &window_x, &window_y);
182 io.*.MousePos = c.ImVec2{
183 .x = @floatCast(f32, mouse_x) + @intToFloat(f32, window_x),
184 .y = @floatCast(f32, mouse_y) + @intToFloat(f32, window_y),
185 };
186 } else {
187 // Single viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
188 io.*.MousePos = c.ImVec2{ .x = @floatCast(f32, mouse_x), .y = @floatCast(f32, mouse_y) };
189 }
190 }
191
192 for (io.*.MouseDown) |*isDown, i|
193 isDown.* = isDown.* or c.glfwGetMouseButton(window, @intCast(c_int, i)) != 0;
194 }
195 }
196 }
197
198 fn UpdateMouseCursor() void {
199 const io = c.igGetIO();
200 if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_NoMouseCursorChange) != 0
201 or c.glfwGetInputMode(g_Window, c.GLFW_CURSOR) == c.GLFW_CURSOR_DISABLED)
202 return;
203
204 const imgui_cursor = c.igGetMouseCursor();
205 const platform_io = c.igGetPlatformIO();
206 var n : usize = 0;
207 while (n < @intCast(usize, platform_io.*.Viewports.Size)) : (n += 1) {
208 const window = @ptrCast(*c.GLFWwindow, platform_io.*.Viewports.Data[n].*.PlatformHandle);
209 if (imgui_cursor == @enumToInt(c.ImGuiMouseCursor_None) or io.*.MouseDrawCursor) {
210 // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
211 c.glfwSetInputMode(window, c.GLFW_CURSOR, c.GLFW_CURSOR_HIDDEN);
212 } else {
213 // Show OS mouse cursor
214 // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
215 c.glfwSetCursor(window,
216 if (g_MouseCursors[@intCast(usize, imgui_cursor)]) |cursor| cursor
217 else g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_Arrow)]);
218 c.glfwSetInputMode(window, c.GLFW_CURSOR, c.GLFW_CURSOR_NORMAL);
219 }
220 }
221 }
222
223 fn UpdateGamepads() void {
224 // @TODO
124225 }
125226
126227 // GLFW Callbacks
127228 extern fn Callback_MouseButton(window: ?*c.GLFWwindow, button: c_int, action: c_int, mods: c_int) void {
128 // @TODO: delegate up
229 if (g_PrevUserCallbackMousebutton) |prev| {
230 prev(window, button, action, mods);
231 }
129232
130233 if (button < 0)
131234 return;
136239 }
137240
138241 extern fn Callback_Scroll(window: ?*c.GLFWwindow, dx: f64, dy: f64) void {
139 // @TODO: delegate up
242 if (g_PrevUserCallbackScroll) |prev| {
243 prev(window, dx, dy);
244 }
140245
141246 const io = c.igGetIO();
142247 io.*.MouseWheelH += @floatCast(f32, dx);
144249 }
145250
146251 extern fn Callback_Key(window: ?*c.GLFWwindow, key: c_int, scancode: c_int, action: c_int, modifiers: c_int) void {
147 // @TODO: delegate up
252 if (g_PrevUserCallbackKey) |prev| {
253 prev(window, key, scancode, action, modifiers);
254 }
148255
149256 if (key < 0)
150257 unreachable;
165272 }
166273
167274 extern fn Callback_Char(window: ?*c.GLFWwindow, char: c_uint) void {
168 // @TODO: delegate up
275 if (g_PrevUserCallbackChar) |prev| {
276 prev(window, char);
277 }
169278
170279 const io = c.igGetIO();
171280 c.ImGuiIO_AddInputCharacter(io, char);
4949 const style = c.igGetStyle();
5050 c.igStyleColorsDark(style);
5151
52 if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0) {
52 if (false and io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0) {
5353 style.*.WindowRounding = 0.0;
5454 style.*.Colors[@enumToInt(c.ImGuiCol_WindowBg)].w = 1.0;
5555 }