#include "app_base.h" #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" #include "implot.h" #include #include #ifdef TRACY_ENABLE #include "tracy/Tracy.hpp" #endif static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "GLFW Error %d: %s\n", error, description); } namespace fn { int run_app(AppConfig config, std::function render_fn) { glfwSetErrorCallback(glfw_error_callback); if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW\n"); return 1; } // OpenGL 3.3 core glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif GLFWwindow* window = glfwCreateWindow(config.width, config.height, config.title, nullptr, nullptr); if (!window) { fprintf(stderr, "Failed to create GLFW window\n"); glfwTerminate(); return 1; } glfwMakeContextCurrent(window); glfwSwapInterval(config.vsync ? 1 : 0); // Setup ImGui IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImPlot::CreateContext(); ImGuiIO& io = ImGui::GetIO(); io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; if (config.viewports) { io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; } ImGui::StyleColorsDark(); // When viewports are enabled, tweak WindowRounding/WindowBg so // platform windows look consistent with the main window if (config.viewports) { ImGuiStyle& style = ImGui::GetStyle(); style.WindowRounding = 0.0f; style.Colors[ImGuiCol_WindowBg].w = 1.0f; } ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init("#version 330"); // Main loop while (!glfwWindowShouldClose(window)) { glfwPollEvents(); if (glfwGetWindowAttrib(window, GLFW_ICONIFIED)) { glfwWaitEvents(); continue; } ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); render_fn(); ImGui::Render(); int display_w, display_h; glfwGetFramebufferSize(window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); glClearColor(config.bg_r, config.bg_g, config.bg_b, 1.0f); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); // Multi-viewport: update and render platform windows if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { GLFWwindow* backup_ctx = glfwGetCurrentContext(); ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); glfwMakeContextCurrent(backup_ctx); } glfwSwapBuffers(window); #ifdef TRACY_ENABLE FrameMark; #endif } // Cleanup ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImPlot::DestroyContext(); ImGui::DestroyContext(); glfwDestroyWindow(window); glfwTerminate(); return 0; } int run_app(std::function render_fn) { return run_app(AppConfig{}, render_fn); } } // namespace fn