6#include <brenta/renderer/opengl/gl.hpp>
7#include <brenta/renderer/opengl/texture.hpp>
8#include <brenta/renderer/opengl/framebuffer.hpp>
9#include <brenta/gui.hpp>
10#include <brenta/window.hpp>
11#include <brenta/logger.hpp>
12#include <brenta/asset.hpp>
15#include <imgui_impl_glfw.h>
16#include <imgui_impl_opengl3.h>
17#include <implot/implot.h>
21#ifndef BRENTA_NO_IMGUI
30 ImVector<ImVec2> data;
34 this->max_size = max_size;
36 this->data.reserve(max_size);
39 void add_point(
float x,
float y)
41 if (this->data.size() < this->max_size)
42 this->data.push_back(ImVec2(x,y));
44 this->data[this->offset] = ImVec2(x,y);
45 this->offset = (this->offset + 1) % this->max_size;
51 if (this->data.size() > 0)
61using namespace brenta;
67const std::string Gui::subsystem_name =
"gui";
68bool Gui::initialized =
false;
69ImFont *Gui::font =
nullptr;
71static void setup_style()
73 ImGuiStyle& style = ImGui::GetStyle();
74 ImVec4* colors = style.Colors;
77 const ImVec4 base = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
78 const ImVec4 mantle = ImVec4(0.169f, 0.169f, 0.169f, 1.0f);
79 const ImVec4 surface0 = ImVec4(0.169f, 0.169f, 0.169f, 1.0f);
80 const ImVec4 surface1 = ImVec4(0.100f, 0.100f, 0.100f, 1.0f);
81 const ImVec4 surface2 = ImVec4(0.050f, 0.050f, 0.050f, 1.0f);
82 const ImVec4 overlay0 = ImVec4(0.396f, 0.403f, 0.486f, 1.0f);
83 const ImVec4 overlay2 = ImVec4(0.576f, 0.584f, 0.654f, 1.0f);
84 const ImVec4 text = ImVec4(0.803f, 0.815f, 0.878f, 1.0f);
85 const ImVec4 subtext0 = ImVec4(0.639f, 0.658f, 0.764f, 1.0f);
86 const ImVec4 mauve = ImVec4(0.796f, 0.698f, 0.972f, 1.0f);
87 const ImVec4 peach = ImVec4(0.980f, 0.709f, 0.572f, 1.0f);
88 const ImVec4 yellow = ImVec4(0.980f, 0.913f, 0.596f, 1.0f);
89 const ImVec4 green = ImVec4(0.650f, 0.890f, 0.631f, 1.0f);
90 const ImVec4 teal = ImVec4(0.580f, 0.886f, 0.819f, 1.0f);
91 const ImVec4 sapphire = ImVec4(0.458f, 0.784f, 0.878f, 1.0f);
92 const ImVec4 blue = ImVec4(0.533f, 0.698f, 0.976f, 1.0f);
93 const ImVec4 lavender = ImVec4(0.709f, 0.764f, 0.980f, 1.0f);
96 colors[ImGuiCol_WindowBg] = base;
97 colors[ImGuiCol_ChildBg] = base;
98 colors[ImGuiCol_PopupBg] = surface0;
99 colors[ImGuiCol_Border] = surface1;
100 colors[ImGuiCol_BorderShadow] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
101 colors[ImGuiCol_FrameBg] = surface0;
102 colors[ImGuiCol_FrameBgHovered] = surface1;
103 colors[ImGuiCol_FrameBgActive] = surface2;
104 colors[ImGuiCol_TitleBg] = mantle;
105 colors[ImGuiCol_TitleBgActive] = surface0;
106 colors[ImGuiCol_TitleBgCollapsed] = mantle;
107 colors[ImGuiCol_MenuBarBg] = mantle;
108 colors[ImGuiCol_ScrollbarBg] = surface0;
109 colors[ImGuiCol_ScrollbarGrab] = surface2;
110 colors[ImGuiCol_ScrollbarGrabHovered] = overlay0;
111 colors[ImGuiCol_ScrollbarGrabActive] = overlay2;
112 colors[ImGuiCol_CheckMark] = green;
113 colors[ImGuiCol_SliderGrab] = sapphire;
114 colors[ImGuiCol_SliderGrabActive] = blue;
115 colors[ImGuiCol_Button] = surface0;
116 colors[ImGuiCol_ButtonHovered] = surface1;
117 colors[ImGuiCol_ButtonActive] = surface2;
118 colors[ImGuiCol_Header] = surface0;
119 colors[ImGuiCol_HeaderHovered] = surface1;
120 colors[ImGuiCol_HeaderActive] = surface2;
121 colors[ImGuiCol_Separator] = surface1;
122 colors[ImGuiCol_SeparatorHovered] = mauve;
123 colors[ImGuiCol_SeparatorActive] = mauve;
124 colors[ImGuiCol_ResizeGrip] = surface2;
125 colors[ImGuiCol_ResizeGripHovered] = mauve;
126 colors[ImGuiCol_ResizeGripActive] = mauve;
127 colors[ImGuiCol_Tab] = surface0;
128 colors[ImGuiCol_TabHovered] = surface2;
129 colors[ImGuiCol_TabActive] = surface1;
130 colors[ImGuiCol_TabUnfocused] = surface0;
131 colors[ImGuiCol_TabUnfocusedActive] = surface1;
132 colors[ImGuiCol_DockingPreview] = sapphire;
133 colors[ImGuiCol_DockingEmptyBg] = base;
134 colors[ImGuiCol_PlotLines] = blue;
135 colors[ImGuiCol_PlotLinesHovered] = peach;
136 colors[ImGuiCol_PlotHistogram] = teal;
137 colors[ImGuiCol_PlotHistogramHovered] = green;
138 colors[ImGuiCol_TableHeaderBg] = surface0;
139 colors[ImGuiCol_TableBorderStrong] = surface1;
140 colors[ImGuiCol_TableBorderLight] = surface0;
141 colors[ImGuiCol_TableRowBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
142 colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.0f, 1.0f, 1.0f, 0.06f);
143 colors[ImGuiCol_TextSelectedBg] = surface2;
144 colors[ImGuiCol_DragDropTarget] = yellow;
145 colors[ImGuiCol_NavHighlight] = lavender;
146 colors[ImGuiCol_NavWindowingHighlight]= ImVec4(1.0f, 1.0f, 1.0f, 0.7f);
147 colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.8f, 0.8f, 0.8f, 0.2f);
148 colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.35f);
149 colors[ImGuiCol_Text] = text;
150 colors[ImGuiCol_TextDisabled] = subtext0;
153 style.WindowRounding = 6.0f;
154 style.ChildRounding = 6.0f;
155 style.FrameRounding = 4.0f;
156 style.PopupRounding = 4.0f;
157 style.ScrollbarRounding = 9.0f;
158 style.GrabRounding = 4.0f;
159 style.TabRounding = 4.0f;
162 style.WindowPadding = ImVec2(8.0f, 8.0f);
163 style.FramePadding = ImVec2(5.0f, 3.0f);
164 style.ItemSpacing = ImVec2(8.0f, 4.0f);
165 style.ItemInnerSpacing = ImVec2(4.0f, 4.0f);
166 style.IndentSpacing = 21.0f;
167 style.ScrollbarSize = 14.0f;
168 style.GrabMinSize = 10.0f;
171 style.WindowBorderSize = 1.0f;
172 style.ChildBorderSize = 1.0f;
173 style.PopupBorderSize = 1.0f;
174 style.FrameBorderSize = 0.0f;
175 style.TabBorderSize = 0.0f;
182std::expected<void, Subsystem::Error> Gui::initialize()
184 if (this->is_initialized())
return {};
186 IMGUI_CHECKVERSION();
187 ImGui::CreateContext();
188 ImPlot::CreateContext();
189 ImGuiIO &io = ImGui::GetIO();
192 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
193 io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
194 io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
197 ImGui_ImplGlfw_InitForOpenGL((GLFWwindow*)Window::get_window(),
true);
198 ImGui_ImplOpenGL3_Init();
199 ImGui::SetNextWindowPos(ImVec2(0, 0));
202 Gui::initialized =
true;
203 INFO(
"{} initialized", Gui::subsystem_name);
207std::expected<void, Subsystem::Error> Gui::terminate()
209 if (!this->is_initialized())
return {};
211 ImGui_ImplOpenGL3_Shutdown();
212 ImGui_ImplGlfw_Shutdown();
214 ImPlot::DestroyContext();
215 ImGui::DestroyContext();
217 Gui::initialized =
false;
218 INFO(
"{}: terminated", Gui::subsystem_name);
222std::string Gui::name()
224 return Gui::subsystem_name;
227bool Gui::is_initialized()
229 return Gui::initialized;
242void Gui::load_font(
const std::filesystem::path &path,
float size)
244 ImGuiIO& io = ImGui::GetIO();
245 Gui::font = io.Fonts->AddFontFromFileTTF(path.string().c_str(), size);
248void Gui::push_font(ImFont *f)
258void Gui::new_frame(tenno::shared_ptr<FrameBuffer> fb, std::string name)
260 ImGui_ImplOpenGL3_NewFrame();
261 ImGui_ImplGlfw_NewFrame();
264 ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport());
270 ImGui::SetNextWindowSize(ImVec2(Window::get_width() * 0.8,
271 Window::get_width() * 0.8),
272 ImGuiCond_FirstUseEver);
273 ImGui::Begin(name.c_str());
275 float window_width = ImGui::GetContentRegionAvail().x;
276 float window_height = ImGui::GetContentRegionAvail().y;
278 fb->rescale(window_width, window_height);
280 ImGui::Image((
void *) (intptr_t) fb->texture_id,
281 ImGui::GetContentRegionAvail(), ImVec2(0, 1), ImVec2(1, 0));
290 ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
294static float gui_debug_last_time = 0;
296void Gui::debug_stats()
298 ImGui::Begin(
"Stats");
306 auto time = Window::get_time();
307 const float interval = 0.1f;
309 float fps = time.get_fps();
311 if (time.elapsed > gui_debug_last_time + interval)
313 gui_debug_last_time = time.elapsed;
314 fps_data.add_point(time.elapsed, fps);
317 const ImPlotAxisFlags flags = 0;
318 static float history = 10.0f;
319 ImGui::SliderFloat(
"History", &history, 1, 60,
"%.1f s");
321 if (ImPlot::BeginPlot(
"##FPS", ImVec2(-1,ImGui::GetTextLineHeight()*10)))
323 ImPlot::SetupAxes(
nullptr,
nullptr, flags, flags);
326 ImPlot::SetupAxisLimits(ImAxis_X1, gui_debug_last_time - history,
327 gui_debug_last_time, ImGuiCond_Always);
329 ImPlot::SetupAxisLimits(ImAxis_Y1, 0, 100);
332 spec.Offset = fps_data.offset;
333 spec.Stride = 2 *
sizeof(float);
334 spec.FillAlpha = 0.5f;
335 ImPlot::PlotShaded(
"FPS", &fps_data.data[0].x, &fps_data.data[0].y,
336 fps_data.data.size(), -INFINITY, spec);
346 ImGui::Text(
"Tot GlBuffer Memory: %f MB",
347 Buffer::tot_memory / 1024.0 / 1024.0);
348 ImGui::Text(
"Tot GlFrameByffer Memory: %f MB",
349 FrameBuffer::tot_memory / 1024.0 / 1024.0);
350 ImGui::Text(
"Tot GlTexture Memory: %f MB",
351 Texture::tot_memory / 1024.0 / 1024.0);
359 ImGui::Text(
"Number of assets loaded with AssetManager");
361 ImGui::BulletText(
"Models: %ld", AssetManager::models.size());
362 ImGui::BulletText(
"Textures: %ld", AssetManager::textures.size());
363 ImGui::BulletText(
"Materials: %ld", AssetManager::materials.size());
364 ImGui::BulletText(
"Shaders: %ld", AssetManager::shaders.size());
365 ImGui::BulletText(
"Fonts: %ld", AssetManager::fonts.size());
366 ImGui::BulletText(
"Scenes: %ld", AssetManager::scenes.size());
367 ImGui::BulletText(
"Sound Assets: %ld", AssetManager::sound_assets.size());
378 return Gui::instance();