git.s-ol.nu zig-imgui / 407a006
more glfw s-ol 2 years ago
2 changed file(s) with 127 addition(s) and 18 deletion(s). Raw diff Collapse all Expand all
00 const c = @import("c.zig");
11 const builtin = @import("builtin");
2 const debug = @import("std").debug;
3 const math = @import("std").math;
4
25 pub const ClientApi = enum {
36 Unknown,
47 OpenGL,
811 // Data
912 var g_Window: ?*c.GLFWwindow = null;
1013 var g_ClientApi: ClientApi = .Unknown;
11 var g_Time: f32 = 0.0;
14 var g_Time: f64 = 0.0;
1215 var g_MouseJustPressed = [_]bool{ false } ** 5;
1316 var g_MouseCursors = [_]?*c.GLFWcursor{ null } ** @enumToInt(c.ImGuiMouseCursor_COUNT);
1417 var g_WantUpdateMonitors = true;
1518
1619 // Chain GLFW callbacks for main viewport:
1720 // our callbacks will call the user's previously installed callbacks, if any.
18 var g_PrevUserCallbackMousebutton: ?c.GLFWmousebuttonfun = null;
19 var g_PrevUserCallbackScroll: ?c.GLFWscrollfun = null;
20 var g_PrevUserCallbackKey: ?c.GLFWkeyfun = null;
21 var g_PrevUserCallbackChar: ?c.GLFWcharfun = null;
21 var g_PrevUserCallbackMousebutton: c.GLFWmousebuttonfun = null;
22 var g_PrevUserCallbackScroll: c.GLFWscrollfun = null;
23 var g_PrevUserCallbackKey: c.GLFWkeyfun = null;
24 var g_PrevUserCallbackChar: c.GLFWcharfun = null;
2225
2326 pub fn Init(window: *c.GLFWwindow, install_callbacks: bool, client_api: ClientApi) void {
2427 g_Window = window;
2831 const io = c.igGetIO();
2932 io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_HasMouseCursors); // We can honor GetMouseCursor() values (optional)
3033 io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_HasSetMousePos); // We can honor io.WantSetMousePos requests (optional, rarely used)
31 io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_PlatformHasViewports); // We can create multi-viewports on the Platform side (optional)
32 if (@hasField(c, "GLFW_HAS_GLFW_HOVERED") and builtin.os == builtin.Os.windows) {
34 if (false) io.*.BackendFlags |= @enumToInt(c.ImGuiBackendFlags_PlatformHasViewports); // We can create multi-viewports on the Platform side (optional)
35 if (false and @hasField(c, "GLFW_HAS_GLFW_HOVERED") and builtin.os == builtin.Os.windows) {
3336 io.*.BackendFlags |= @enumToInt(ImGuiBackendFlags_HasMouseHoveredViewport); // We can set io.MouseHoveredViewport correctly (optional, not easy)
3437 }
3538 io.*.BackendPlatformName = c"imgui_impl_glfw.zig";
6164 // @TODO: Clipboard
6265 // io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
6366 // io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
64 // io.ClipboardUserData = g_Window;
67 io.*.ClipboardUserData = g_Window;
6568
6669 g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_Arrow)] = c.glfwCreateStandardCursor(c.GLFW_ARROW_CURSOR);
6770 g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_TextInput)] = c.glfwCreateStandardCursor(c.GLFW_IBEAM_CURSOR);
8790 // Our mouse update function expect PlatformHandle to be filled for the main viewport
8891 const main_viewport = c.igGetMainViewport();
8992 main_viewport.*.PlatformHandle = g_Window;
90 if (builtin.os == builtin.Os.windows) {
93 if (builtin.os == builtin.Os.windows)
9194 main_viewport.*.PlatformHandleRaw = c.glfwGetWin32Window(g_Window);
92 }
9395
9496 // @TODO: Platform Interface (Viewport)
95 // if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable != 0)
96 // ImGui_ImplGlfw_InitPlatformInterface();
97 if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0)
98 unreachable;
99 // ImGui_ImplGlfw_InitPlatformInterface();
97100
98101 g_ClientApi = client_api;
99102 }
111114
112115 pub fn NewFrame() void {
113116 const io = c.igGetIO();
114 // @TODO: assert font atlas
117 debug.assert(c.ImFontAtlas_IsBuilt(io.*.Fonts));
115118
116119 var w : c_int = undefined;
117120 var h : c_int = undefined;
120123 c.glfwGetWindowSize(g_Window, &w, &h);
121124 c.glfwGetFramebufferSize(g_Window, &display_w, &display_h);
122125 io.*.DisplaySize = c.ImVec2{ .x = @intToFloat(f32, w), .y = @intToFloat(f32, h) };
126
127 if (w > 0 and h > 0)
128 io.*.DisplayFramebufferScale = c.ImVec2{
129 .x = @intToFloat(f32, display_w) / @intToFloat(f32, w),
130 .y = @intToFloat(f32, display_h) / @intToFloat(f32, h),
131 };
132 if (g_WantUpdateMonitors)
133 UpdateMonitors();
134
135 // Setup time step
136 const current_time = c.glfwGetTime();
137 io.*.DeltaTime = if (g_Time > 0.0) @floatCast(f32, current_time - g_Time) else 1.0 / 60.0;
138 g_Time = current_time;
139
140 UpdateMousePosAndButtons();
141 UpdateMouseCursor();
142
143 UpdateGamepads();
144 }
145
146 fn UpdateMonitors() void {
147 // @TODO
148 }
149
150 fn UpdateMousePosAndButtons() void {
151 // Update buttons
152 const io = c.igGetIO();
153 for (io.*.MouseDown) |*isDown, i| {
154 // 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.
155 isDown.* = g_MouseJustPressed[i] or c.glfwGetMouseButton(g_Window, @intCast(c_int, i)) != 0;
156 g_MouseJustPressed[i] = false;
157 }
158
159 // Update mouse position
160 const mouse_pos_backup = io.*.MousePos;
161 io.*.MousePos = c.ImVec2{ .x = math.f32_min, .y = math.f32_min };
162 io.*.MouseHoveredViewport = 0;
163 const platform_io = c.igGetPlatformIO();
164 var n : usize = 0;
165 while (n < @intCast(usize, platform_io.*.Viewports.Size)) : (n += 1) {
166 const viewport = platform_io.*.Viewports.Data[n];
167 const window = @ptrCast(*c.GLFWwindow, viewport.*.PlatformHandle);
168 const focused = c.glfwGetWindowAttrib(window, c.GLFW_FOCUSED) != 0;
169 if (focused) {
170 if (io.*.WantSetMousePos) {
171 c.glfwSetCursorPos(window, mouse_pos_backup.x - viewport.*.Pos.x, mouse_pos_backup.y - viewport.*.Pos.y);
172 } else {
173 var mouse_x : f64 = undefined;
174 var mouse_y : f64 = undefined;
175 c.glfwGetCursorPos(window, &mouse_x, &mouse_y);
176 if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0) {
177 // 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)
178 var window_x : c_int = undefined;
179 var window_y : c_int = undefined;
180 c.glfwGetWindowPos(window, &window_x, &window_y);
181 io.*.MousePos = c.ImVec2{
182 .x = @floatCast(f32, mouse_x) + @intToFloat(f32, window_x),
183 .y = @floatCast(f32, mouse_y) + @intToFloat(f32, window_y),
184 };
185 } else {
186 // 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)
187 io.*.MousePos = c.ImVec2{ .x = @floatCast(f32, mouse_x), .y = @floatCast(f32, mouse_y) };
188 }
189 }
190
191 for (io.*.MouseDown) |*isDown, i|
192 isDown.* = isDown.* or c.glfwGetMouseButton(window, @intCast(c_int, i)) != 0;
193 }
194 }
195 }
196
197 fn UpdateMouseCursor() void {
198 const io = c.igGetIO();
199 if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_NoMouseCursorChange) != 0
200 or c.glfwGetInputMode(g_Window, c.GLFW_CURSOR) == c.GLFW_CURSOR_DISABLED)
201 return;
202
203 const imgui_cursor = c.igGetMouseCursor();
204 const platform_io = c.igGetPlatformIO();
205 var n : usize = 0;
206 while (n < @intCast(usize, platform_io.*.Viewports.Size)) : (n += 1) {
207 const window = @ptrCast(*c.GLFWwindow, platform_io.*.Viewports.Data[n].*.PlatformHandle);
208 if (imgui_cursor == @enumToInt(c.ImGuiMouseCursor_None) or io.*.MouseDrawCursor) {
209 // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
210 c.glfwSetInputMode(window, c.GLFW_CURSOR, c.GLFW_CURSOR_HIDDEN);
211 } else {
212 // Show OS mouse cursor
213 // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
214 c.glfwSetCursor(window,
215 if (g_MouseCursors[@intCast(usize, imgui_cursor)]) |cursor| cursor
216 else g_MouseCursors[@enumToInt(c.ImGuiMouseCursor_Arrow)]);
217 c.glfwSetInputMode(window, c.GLFW_CURSOR, c.GLFW_CURSOR_NORMAL);
218 }
219 }
220 }
221
222 fn UpdateGamepads() void {
223 // @TODO
123224 }
124225
125226 // GLFW Callbacks
126227 extern fn Callback_MouseButton(window: ?*c.GLFWwindow, button: c_int, action: c_int, mods: c_int) void {
127 // @TODO: delegate up
228 if (g_PrevUserCallbackMousebutton) |prev| {
229 prev(window, button, action, mods);
230 }
128231
129232 if (button < 0)
130233 return;
135238 }
136239
137240 extern fn Callback_Scroll(window: ?*c.GLFWwindow, dx: f64, dy: f64) void {
138 // @TODO: delegate up
241 if (g_PrevUserCallbackScroll) |prev| {
242 prev(window, dx, dy);
243 }
139244
140245 const io = c.igGetIO();
141246 io.*.MouseWheelH += @floatCast(f32, dx);
143248 }
144249
145250 extern fn Callback_Key(window: ?*c.GLFWwindow, key: c_int, scancode: c_int, action: c_int, modifiers: c_int) void {
146 // @TODO: delegate up
251 if (g_PrevUserCallbackKey) |prev| {
252 prev(window, key, scancode, action, modifiers);
253 }
147254
148255 if (key < 0)
149256 unreachable;
164271 }
165272
166273 extern fn Callback_Char(window: ?*c.GLFWwindow, char: c_uint) void {
167 // @TODO: delegate up
274 if (g_PrevUserCallbackChar) |prev| {
275 prev(window, char);
276 }
168277
169278 const io = c.igGetIO();
170279 c.ImGuiIO_AddInputCharacter(io, char);
4848 const style = c.igGetStyle();
4949 c.igStyleColorsDark(style);
5050
51 if (io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0) {
51 if (false and io.*.ConfigFlags & @enumToInt(c.ImGuiConfigFlags_ViewportsEnable) != 0) {
5252 style.*.WindowRounding = 0.0;
5353 style.*.Colors[@enumToInt(c.ImGuiCol_WindowBg)].w = 1.0;
5454 }