// Dear ImGui: standalone example application for GLFW + Metal, using programmable pipeline // (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.) // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq // - Getting Started https://dearimgui.com/getting-started // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). // - Introduction, links and more at the top of imgui.cpp #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_metal.h" #include #include #include "imgui_main.h" #define GLFW_INCLUDE_NONE #define GLFW_EXPOSE_NATIVE_COCOA #include #include #import #import static GLFWwindow* g_main_window = nullptr; static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "Glfw Error %d: %s\n", error, description); } int init_imgui() { // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); configure_imgui(io); // Setup window glfwSetErrorCallback(glfw_error_callback); if (!glfwInit()) return 1; // Create window with graphics context glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); g_main_window = glfwCreateWindow(1280, 720, get_window_title().c_str(), nullptr, nullptr); if (g_main_window == nullptr) return 1; return 0; } bool imgui_new_frame() { return true; } void render_imgui() { } void shutdown_imgui() { // Cleanup ImGui_ImplMetal_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwDestroyWindow(g_main_window); glfwTerminate(); } void run_imgui() { init_imgui(); id device = MTLCreateSystemDefaultDevice(); id commandQueue = [device newCommandQueue]; // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOther(g_main_window, true); ImGui_ImplMetal_Init(device); NSWindow* nswin = glfwGetCocoaWindow(g_main_window); CAMetalLayer* layer = [CAMetalLayer layer]; layer.device = device; layer.pixelFormat = MTLPixelFormatBGRA8Unorm; nswin.contentView.layer = layer; nswin.contentView.wantsLayer = YES; float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f}; MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor new]; while (!glfwWindowShouldClose(g_main_window)) { @autoreleasepool { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); std::this_thread::sleep_for(std::chrono::milliseconds(5)); int width, height; glfwGetFramebufferSize(g_main_window, &width, &height); layer.drawableSize = CGSizeMake(width, height); id drawable = [layer nextDrawable]; id commandBuffer = [commandQueue commandBuffer]; renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0] * clear_color[3], clear_color[1] * clear_color[3], clear_color[2] * clear_color[3], clear_color[3]); renderPassDescriptor.colorAttachments[0].texture = drawable.texture; renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; [renderEncoder pushDebugGroup:@"ImGui demo"]; // Start the Dear ImGui frame ImGui_ImplMetal_NewFrame(renderPassDescriptor); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); ImGuiIO& io = ImGui::GetIO(); tick_imgui(io.DeltaTime); draw_imgui(io.DeltaTime); // Rendering ImGui::Render(); ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), commandBuffer, renderEncoder); // Update and Render additional Platform Windows if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); } [renderEncoder popDebugGroup]; [renderEncoder endEncoding]; [commandBuffer presentDrawable:drawable]; [commandBuffer commit]; } } shutdown_imgui(); }