galaxy 1.0.0
Real-Time C++23 Game Programming Framework. Built on data-driven design principles and agile software engineering.
Loading...
Searching...
No Matches
ImGuiHelpers.cpp
Go to the documentation of this file.
1
7
8#include <glad/glad.h>
9
10#include <entt/locator/locator.hpp>
11#include <imgui/backends/imgui_impl_opengl3.h>
12#include <imgui/backends/imgui_impl_sdl3.h>
13#include <imgui/misc/freetype/imgui_freetype.h>
14#include <imgui/extensions/notify/material_design_icons.h>
15#include <imgui/extensions/notify/material_design_icons_ttf.h>
16#include <mimalloc.h>
17
21
22#include "ImGuiHelpers.hpp"
23
24// #ifdef GALAXY_WIN_PLATFORM
25// #pragma warning(push)
26// #pragma warning(disable : 4312)
27// #endif
28
29namespace galaxy
30{
31 void* mem_alloc(size_t sz, void* user_data)
32 {
33 return mi_malloc(sz);
34 }
35
36 void mem_free(void* ptr, void* user_data)
37 {
38 mi_free(ptr);
39 }
40
41 void load_backend() noexcept
42 {
43 auto& window = entt::locator<Window>::value();
44 ImGui_ImplSDL3_InitForOpenGL(window.handle(), window.context());
45 ImGui_ImplOpenGL3_Init("#version 460 core");
46 }
47
48 void load_theme() noexcept
49 {
50 // Hazy Dark style by kaitabuchi314 from ImThemes.
51 ImGuiStyle& style = ImGui::GetStyle();
52
53 style.Alpha = 1.0f;
54 style.DisabledAlpha = 0.6f;
55 style.WindowPadding = ImVec2(5.5f, 8.3f);
56 style.WindowRounding = 4.5f;
57 style.WindowBorderSize = 1.0f;
58 style.WindowMinSize = ImVec2(32.0f, 32.0f);
59 style.WindowTitleAlign = ImVec2(0.0f, 0.5f);
60 style.WindowMenuButtonPosition = ImGuiDir_Left;
61 style.ChildRounding = 3.2f;
62 style.ChildBorderSize = 1.0f;
63 style.PopupRounding = 2.7f;
64 style.PopupBorderSize = 1.0f;
65 style.FramePadding = ImVec2(4.0f, 3.0f);
66 style.FrameRounding = 2.4f;
67 style.FrameBorderSize = 0.0f;
68 style.ItemSpacing = ImVec2(8.0f, 4.0f);
69 style.ItemInnerSpacing = ImVec2(4.0f, 4.0f);
70 style.CellPadding = ImVec2(4.0f, 2.0f);
71 style.IndentSpacing = 21.0f;
72 style.ColumnsMinSpacing = 6.0f;
73 style.ScrollbarSize = 14.0f;
74 style.ScrollbarRounding = 9.0f;
75 style.GrabMinSize = 10.0f;
76 style.GrabRounding = 3.2f;
77 style.TabRounding = 3.5f;
78 style.TabBorderSize = 1.0f;
79 style.TabCloseButtonMinWidthUnselected = 0.0f;
80 style.ColorButtonPosition = ImGuiDir_Right;
81 style.ButtonTextAlign = ImVec2(0.5f, 0.5f);
82 style.SelectableTextAlign = ImVec2(0.0f, 0.0f);
83
84 style.Colors[ImGuiCol_Text] = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
85 style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.49803922f, 0.49803922f, 0.49803922f, 1.0f);
86 style.Colors[ImGuiCol_WindowBg] = ImVec4(0.05882353f, 0.05882353f, 0.05882353f, 0.94f);
87 style.Colors[ImGuiCol_ChildBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
88 style.Colors[ImGuiCol_PopupBg] = ImVec4(0.078431375f, 0.078431375f, 0.078431375f, 0.94f);
89 style.Colors[ImGuiCol_Border] = ImVec4(0.42745098f, 0.42745098f, 0.49803922f, 0.5f);
90 style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
91 style.Colors[ImGuiCol_FrameBg] = ImVec4(0.13725491f, 0.17254902f, 0.22745098f, 0.54f);
92 style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.21176471f, 0.25490198f, 0.3019608f, 0.4f);
93 style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.043137256f, 0.047058824f, 0.047058824f, 0.67f);
94 style.Colors[ImGuiCol_TitleBg] = ImVec4(0.039215688f, 0.039215688f, 0.039215688f, 1.0f);
95 style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.078431375f, 0.08235294f, 0.09019608f, 1.0f);
96 style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.0f, 0.0f, 0.0f, 0.51f);
97 style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.13725491f, 0.13725491f, 0.13725491f, 1.0f);
98 style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.019607844f, 0.019607844f, 0.019607844f, 0.53f);
99 style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.30980393f, 0.30980393f, 0.30980393f, 1.0f);
100 style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40784314f, 0.40784314f, 0.40784314f, 1.0f);
101 style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.50980395f, 0.50980395f, 0.50980395f, 1.0f);
102 style.Colors[ImGuiCol_CheckMark] = ImVec4(0.7176471f, 0.78431374f, 0.84313726f, 1.0f);
103 style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.47843137f, 0.5254902f, 0.57254905f, 1.0f);
104 style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.2901961f, 0.31764707f, 0.3529412f, 1.0f);
105 style.Colors[ImGuiCol_Button] = ImVec4(0.14901961f, 0.16078432f, 0.1764706f, 0.4f);
106 style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.13725491f, 0.14509805f, 0.15686275f, 1.0f);
107 style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.078431375f, 0.08627451f, 0.09019608f, 1.0f);
108 style.Colors[ImGuiCol_Header] = ImVec4(0.19607843f, 0.21568628f, 0.23921569f, 0.31f);
109 style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.16470589f, 0.1764706f, 0.19215687f, 0.8f);
110 style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.07450981f, 0.08235294f, 0.09019608f, 1.0f);
111 style.Colors[ImGuiCol_Separator] = ImVec4(0.42745098f, 0.42745098f, 0.49803922f, 0.5f);
112 style.Colors[ImGuiCol_SeparatorHovered] = ImVec4(0.23921569f, 0.3254902f, 0.42352942f, 0.78f);
113 style.Colors[ImGuiCol_SeparatorActive] = ImVec4(0.27450982f, 0.38039216f, 0.49803922f, 1.0f);
114 style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.2901961f, 0.32941177f, 0.3764706f, 0.2f);
115 style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.23921569f, 0.29803923f, 0.36862746f, 0.67f);
116 style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(0.16470589f, 0.1764706f, 0.1882353f, 0.95f);
117 style.Colors[ImGuiCol_Tab] = ImVec4(0.11764706f, 0.1254902f, 0.13333334f, 0.862f);
118 style.Colors[ImGuiCol_TabHovered] = ImVec4(0.32941177f, 0.40784314f, 0.5019608f, 0.8f);
119 style.Colors[ImGuiCol_TabSelected] = ImVec4(0.24313726f, 0.24705882f, 0.25490198f, 1.0f);
120 style.Colors[ImGuiCol_TabDimmed] = ImVec4(0.06666667f, 0.101960786f, 0.14509805f, 0.9724f);
121 style.Colors[ImGuiCol_TabDimmedSelected] = ImVec4(0.13333334f, 0.25882354f, 0.42352942f, 1.0f);
122 style.Colors[ImGuiCol_PlotLines] = ImVec4(0.60784316f, 0.60784316f, 0.60784316f, 1.0f);
123 style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.0f, 0.42745098f, 0.34901962f, 1.0f);
124 style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.8980392f, 0.69803923f, 0.0f, 1.0f);
125 style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.0f, 0.6f, 0.0f, 1.0f);
126 style.Colors[ImGuiCol_TableHeaderBg] = ImVec4(0.1882353f, 0.1882353f, 0.2f, 1.0f);
127 style.Colors[ImGuiCol_TableBorderStrong] = ImVec4(0.30980393f, 0.30980393f, 0.34901962f, 1.0f);
128 style.Colors[ImGuiCol_TableBorderLight] = ImVec4(0.22745098f, 0.22745098f, 0.24705882f, 1.0f);
129 style.Colors[ImGuiCol_TableRowBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
130 style.Colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.0f, 1.0f, 1.0f, 0.06f);
131 style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.25882354f, 0.5882353f, 0.9764706f, 0.35f);
132 style.Colors[ImGuiCol_DragDropTarget] = ImVec4(1.0f, 1.0f, 0.0f, 0.9f);
133 style.Colors[ImGuiCol_NavCursor] = ImVec4(0.25882354f, 0.5882353f, 0.9764706f, 1.0f);
134 style.Colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.0f, 1.0f, 1.0f, 0.7f);
135 style.Colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.8f, 0.8f, 0.8f, 0.2f);
136 style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.8f, 0.8f, 0.8f, 0.35f);
137 }
138
139 void load_font() noexcept
140 {
141 auto& io = ImGui::GetIO();
142 auto& window = entt::locator<Window>::value();
143
144 const auto font_size = window.get_display_scale() * 16.0f;
145
146 ImFontConfig font_cfg = {};
147 font_cfg.FontDataOwnedByAtlas = false;
148 font_cfg.RasterizerMultiply = 1.5f;
149 font_cfg.OversampleH = 1;
150 font_cfg.OversampleV = 1;
151 font_cfg.FontLoaderFlags |= ImGuiFreeTypeLoaderFlags_LoadColor;
152 io.FontDefault = io.Fonts->AddFontFromMemoryTTF(&resource::roboto_light, resource::roboto_light_len, font_size, &font_cfg);
153
154 static const ImWchar icons_ranges[] = {ICON_MIN_MDI, ICON_MAX_MDI, 0};
155 ImFontConfig md_icons_cfg;
156 md_icons_cfg.FontDataOwnedByAtlas = false;
157 md_icons_cfg.MergeMode = true;
158 md_icons_cfg.PixelSnapH = true;
159 io.Fonts->AddFontFromMemoryTTF(&materialdesignicons_ttf, sizeof(materialdesignicons_ttf), font_size, &md_icons_cfg, icons_ranges);
160 }
161
162 namespace ui
163 {
164 void imgui_init(const char* ini)
165 {
166 // clang-format off
167 IMGUI_CHECKVERSION();
168 ImGui::SetAllocatorFunctions(mem_alloc, mem_free, nullptr);
169 ImGuiFreeType::SetAllocatorFunctions(mem_alloc, mem_free, nullptr);
170 ImGui::CreateContext();
171 ImGuiIO& io = ImGui::GetIO(); (void)io;
172 // clang-format on
173
174 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
175 io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
176 io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
177
178 io.ConfigInputTextCursorBlink = true;
179 io.ConfigDockingWithShift = true;
180 // io.ConfigDockingAlwaysTabBar = true;
181 io.ConfigWindowsMoveFromTitleBarOnly = true;
182 io.ConfigWindowsResizeFromEdges = true;
183 io.MouseDrawCursor = false;
184 io.ConfigDpiScaleFonts = true;
185 io.ConfigDpiScaleViewports = true;
186 io.IniFilename = ini;
187
188 ImGui::SetColorEditOptions(
189 ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar | ImGuiColorEditFlags_AlphaBar
190 );
191
192 load_backend();
193 load_theme();
194 load_font();
195
197 }
198
200 {
201 ImGui_ImplOpenGL3_NewFrame();
202 ImGui_ImplSDL3_NewFrame();
203 ImGui::NewFrame();
204 }
205
207 {
208 ImGui::Render();
209
210 auto& w = entt::locator<Window>::value();
211 glBindFramebuffer(GL_FRAMEBUFFER, 0);
212 glActiveTexture(GL_TEXTURE0);
213 glViewport(0, 0, w.get_pixel_size().x, w.get_pixel_size().y);
214 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
215 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
216
217 ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
218 }
219
221 {
222 ImGui_ImplOpenGL3_Shutdown();
223 ImGui_ImplSDL3_Shutdown();
224 ImGui::DestroyContext();
225 }
226
228 {
229 auto& style = ImGui::GetStyle();
230
231 const auto& io = ImGui::GetIO();
232 const auto& window = entt::locator<Window>::value();
233 style.ScaleAllSizes(window.get_display_scale());
234 style.FontScaleDpi = window.get_display_scale();
235 }
236 } // namespace ui
237} // namespace galaxy
238
239// #ifdef GALAXY_WIN_PLATFORM
240// #pragma warning(pop)
241// #endif
242
243/*
244 void imgui_center_next_window()
245 {
246 const auto center = ImGui::GetMainViewport()->GetCenter();
247 ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, {0.5f, 0.5f});
248 }
249
250 bool imgui_loaded()
251 {
252 return ImGui::GetCurrentContext() != nullptr;
253 }
254
255 void imgui_popup(const char* id, bool& open, std::move_only_function<void(void)>&& func)
256 {
257 if (open)
258 {
259 ImGui::OpenPopup(id);
260 open = false;
261 }
262
263 imgui_center_next_window();
264 if (ImGui::BeginPopup(id))
265 {
266 func();
267 ImGui::EndPopup();
268 }
269 }
270
271 void imgui_confirm(const char* msg, std::move_only_function<void(void)>&& yes, std::move_only_function<void(void)>&& no)
272 {
273 ImGui::Text(msg);
274
275 ImGui::Separator();
276 ImGui::Spacing();
277
278 if (ImGui::Button("Yes"))
279 {
280 if (yes)
281 {
282 yes();
283 }
284
285 ImGui::CloseCurrentPopup();
286 }
287
288 ImGui::SameLine();
289
290 if (ImGui::Button("No"))
291 {
292 if (no)
293 {
294 no();
295 }
296
297 ImGui::CloseCurrentPopup();
298 }
299 }
300
301 bool imgui_imagebutton(const graphics::Texture2D& texture, const ImVec2& size, const ImVec4& bg_col, const ImVec4& tint_col)
302 {
303 const auto id = std::to_string(texture.id()) + std::to_string(texture.width()) + std::to_string(texture.height());
304 const auto upcast = static_cast<std::uint64_t>(texture.id());
305
306 return ImGui::ImageButton(id.c_str(), reinterpret_cast<void*>(upcast), size, {0, 1}, {1, 0}, bg_col, tint_col);
307 }
308
309 void imgui_image(const graphics::Texture2D& texture, const ImVec2& size)
310 {
311 const auto upcast = static_cast<std::uint64_t>(texture.id());
312 ImGui::Image(reinterpret_cast<void*>(upcast), size, {0, 1}, {1, 0});
313 }
314
315 void imgui_image(const graphics::RenderTexture& texture, const ImVec2& size)
316 {
317 const auto upcast = static_cast<std::uint64_t>(texture.texture());
318 ImGui::Image(reinterpret_cast<void*>(upcast), size, {0, 1}, {1, 0});
319 }
320
321 void imgui_notify_success(const char* msg)
322 {
323 ImGui::InsertNotification({ImGuiToastType::Warning, 2000, msg});
324 }
325
326 void imgui_notify_info(const char* msg)
327 {
328 ImGui::InsertNotification({ImGuiToastType::Info, 2000, msg});
329 }
330
331 void imgui_notify_warning(const char* msg)
332 {
333 ImGui::InsertNotification({ImGuiToastType::Warning, 2000, msg});
334 }
335
336 void imgui_notify_error(const char* msg)
337 {
338 ImGui::InsertNotification({ImGuiToastType::Error, 2000, msg});
339 }
340
341 bool imgui_glm_vec2(const char* label, glm::vec2& vec)
342 {
343 auto clicked = false;
344
345 ImGui::PushID(label);
346
347 ImGui::TextUnformatted(label);
348
349 ImGui::SameLine();
350
351 ImGui::SetNextItemWidth(150);
352 clicked |= ImGui::InputFloat("X", &vec.x, 1.0f, 10.0f, "%.1f");
353
354 ImGui::SameLine();
355
356 ImGui::SetNextItemWidth(150);
357 clicked |= ImGui::InputFloat("Y", &vec.y, 1.0f, 10.0f, "%.1f");
358
359 ImGui::PopID();
360 return clicked;
361 }
362
363 bool imgui_glm_vec3(const char* label, glm::vec3& vec)
364 {
365 auto clicked = false;
366
367 ImGui::PushID(label);
368
369 ImGui::TextUnformatted(label);
370
371 ImGui::SameLine();
372
373 ImGui::SetNextItemWidth(100);
374 clicked |= ImGui::InputFloat("X", &vec.x, 1.0f, 10.0f, "%.1f");
375
376 ImGui::SameLine();
377
378 ImGui::SetNextItemWidth(100);
379 clicked |= ImGui::InputFloat("Y", &vec.y, 1.0f, 10.0f, "%.1f");
380
381 ImGui::SameLine();
382
383 ImGui::SetNextItemWidth(100);
384 clicked |= ImGui::InputFloat("Z", &vec.z, 1.0f, 10.0f, "%.1f");
385
386 ImGui::PopID();
387 return clicked;
388 }
389
390 bool imgui_glm_vec4(const char* label, glm::vec4& vec)
391 {
392 auto clicked = false;
393
394 ImGui::PushID(label);
395
396 ImGui::TextUnformatted(label);
397
398 ImGui::SameLine();
399
400 ImGui::SetNextItemWidth(75);
401 clicked |= ImGui::InputFloat("X", &vec.x, 1.0f, 10.0f, "%.1f");
402
403 ImGui::SameLine();
404
405 ImGui::SetNextItemWidth(75);
406 clicked |= ImGui::InputFloat("Y", &vec.y, 1.0f, 10.0f, "%.1f");
407
408 ImGui::SameLine();
409
410 ImGui::SetNextItemWidth(75);
411 clicked |= ImGui::InputFloat("Z", &vec.z, 1.0f, 10.0f, "%.1f");
412
413 ImGui::SameLine();
414
415 ImGui::SetNextItemWidth(75);
416 clicked |= ImGui::InputFloat("W", &vec.w, 1.0f, 10.0f, "%.1f");
417
418 ImGui::PopID();
419 return clicked;
420 }
421
422 bool imgui_frect(const char* label, math::fRect& rect)
423 {
424 auto clicked = false;
425
426 ImGui::PushID(label);
427
428 ImGui::TextUnformatted(label);
429
430 ImGui::SameLine();
431
432 ImGui::SetNextItemWidth(75);
433 clicked |= ImGui::InputFloat("X", &rect.x, 1.0f, 10.0f, "%.1f");
434
435 ImGui::SameLine();
436
437 ImGui::SetNextItemWidth(75);
438 clicked |= ImGui::InputFloat("Y", &rect.y, 1.0f, 10.0f, "%.1f");
439
440 ImGui::SameLine();
441
442 ImGui::SetNextItemWidth(75);
443 clicked |= ImGui::InputFloat("W", &rect.width, 1.0f, 10.0f, "%.1f");
444
445 ImGui::SameLine();
446
447 ImGui::SetNextItemWidth(75);
448 clicked |= ImGui::InputFloat("H", &rect.height, 1.0f, 10.0f, "%.1f");
449
450 ImGui::PopID();
451 return clicked;
452 }
453*/
static unsigned char roboto_light[]
static constexpr const unsigned int roboto_light_len
void imgui_rescale()
Bake a fixed style scale.
void imgui_new_frame()
Begin setting up ImGui pass.
void imgui_exit()
Destroy imgui context.
void imgui_init(const char *ini)
Initialize ImGui context with galaxy.
void imgui_render()
Render imgui.
Application.hpp galaxy.
void load_theme() noexcept
void load_font() noexcept
void mem_free(void *ptr, void *user_data)
void load_backend() noexcept
void * mem_alloc(size_t sz, void *user_data)