From acb8ef200610e0e3618182c8407681090eaa75ec Mon Sep 17 00:00:00 2001 From: Bill Six Date: Wed, 21 Oct 2020 03:13:54 -0400 Subject: [PATCH 01/11] Examples: Vulkan: Fixed CMake include path. (#3550) The backends directory was not included, so the build was failing. --- examples/example_glfw_vulkan/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_glfw_vulkan/CMakeLists.txt b/examples/example_glfw_vulkan/CMakeLists.txt index 22e17a20..801aee4d 100644 --- a/examples/example_glfw_vulkan/CMakeLists.txt +++ b/examples/example_glfw_vulkan/CMakeLists.txt @@ -25,7 +25,7 @@ include_directories(${GLFW_DIR}/include) # Dear ImGui set(IMGUI_DIR ../../) -include_directories(${IMGUI_DIR} ..) +include_directories(${IMGUI_DIR} ${IMGUI_DIR}/backends ..) # Libraries find_package(Vulkan REQUIRED) From ffe8f0177fb8ca371e5f3195d8399cadf1596483 Mon Sep 17 00:00:00 2001 From: Louis Schnellbach Date: Tue, 20 Oct 2020 10:00:26 +0200 Subject: [PATCH 02/11] Backends: OpenGL3: Backup/restore GL_PRIMITIVE_RESTART state (#3544) --- backends/imgui_impl_opengl3.cpp | 18 ++++++++++++++++++ docs/CHANGELOG.txt | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index aa0e9e55..a26538d7 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2020-10-23: OpenGL: Save and restore current GL_PRIMITIVE_RESTART state. // 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x) // 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader. // 2020-07-10: OpenGL: Added support for glad2 OpenGL loader. @@ -134,6 +135,11 @@ using namespace gl; #define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER #endif +// Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state +#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1) +#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART +#endif + // OpenGL Data static GLuint g_GlVersion = 0; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2) static char g_GlslVersionString[32] = ""; // Specified by user or detected based on compile time GL settings. @@ -244,6 +250,10 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART + if (g_GlVersion >= 310) + glDisable(GL_PRIMITIVE_RESTART); +#endif #ifdef GL_POLYGON_MODE glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif @@ -334,6 +344,9 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART + GLboolean last_enable_primitive_restart = g_GlVersion >= 310 ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE; +#endif // Setup desired GL state // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts) @@ -419,6 +432,11 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART + if (g_GlVersion >= 310) + if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); +#endif + #ifdef GL_POLYGON_MODE glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); #endif diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 68e30508..bd709286 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,8 +59,9 @@ Other Changes: - Tab Bar: Do not display a tooltip if the name already fits over a given tab. (#3521) - Drag and Drop: Fix drag and drop to tie same-size drop targets by choosen the later one. Fixes dragging into a full-window-sized dockspace inside a zero-padded window. (#3519, #2717) [@Black-Cat] -- Backends: OpenGL: use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) +- Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] +- Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon] - Docs: Split examples/README.txt into docs/BACKENDS.md and docs/EXAMPLES.md improved them. - Docs: Consistently renamed all occurences of "binding" and "back-end" to "backend" in comments and docs. From 5292320110b9ee3a303d055cd39fc6963b66150f Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 23 Oct 2020 11:25:26 +0200 Subject: [PATCH 03/11] Amend ffe8f0177fb8ca371e5f3195d8399cadf1596483 (#3544) + readme fixes --- backends/imgui_impl_opengl3.cpp | 5 ++--- docs/README.md | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index a26538d7..c70cfd6c 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -345,7 +345,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART - GLboolean last_enable_primitive_restart = g_GlVersion >= 310 ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE; + GLboolean last_enable_primitive_restart = (g_GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE; #endif // Setup desired GL state @@ -433,8 +433,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART - if (g_GlVersion >= 310) - if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); + if (g_GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } #endif #ifdef GL_POLYGON_MODE diff --git a/docs/README.md b/docs/README.md index a946315f..35b08f9c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -110,7 +110,7 @@ The demo applications are not DPI aware so expect some blurriness on a 4K screen ### Integration -On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/examples) files without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more of the imgui_impl_xxxx files instead of rewriting them: this will be less work for you and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom backend using your custom engine functions if you wish so. +On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/backends) backends without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more of the imgui_impl_xxxx files instead of rewriting them: this will be less work for you and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom backend using your custom engine functions if you wish so. Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the [FAQ](https://www.dearimgui.org/faq), comments, and some of the examples/ application!** @@ -129,10 +129,10 @@ Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. ### Upcoming Changes Some of the goals for 2020 are: -- Work on docking. (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch) -- Work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback) -- Work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787)) - Work on new Tables API (to replace Columns). (see [#2957](https://github.com/ocornut/imgui/issues/2957), in public [tables](https://github.com/ocornut/imgui/tree/tables) branch looking for feedback) +- Work on Docking (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch) +- Work on Multi-Viewport / Multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback) +- Work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787)) - Work on automation and testing system, both to test the library and end-user apps. (see [#435](https://github.com/ocornut/imgui/issues/435)) - Make the examples look better, improve styles, improve font support, make the examples hi-DPI and multi-DPI aware. From bca4749346bd250127a8324bf7f5342ba0d6afcc Mon Sep 17 00:00:00 2001 From: Warren Moore Date: Sun, 18 Oct 2020 13:24:35 -0700 Subject: [PATCH 04/11] Examples: Apple: Consolidated example_apple_metal to reduce class and file count (#1873, #3543) --- docs/CHANGELOG.txt | 1 + .../example_apple_metal/Shared/AppDelegate.h | 18 - .../example_apple_metal/Shared/AppDelegate.m | 11 - .../example_apple_metal/Shared/Renderer.h | 8 - .../example_apple_metal/Shared/Renderer.mm | 154 ------- .../Shared/ViewController.h | 19 - .../Shared/ViewController.mm | 153 ------- examples/example_apple_metal/Shared/main.m | 22 - .../project.pbxproj | 155 +++---- .../iOS/Base.lproj/Main.storyboard | 28 -- .../iOS/Default-568h@2x.png | Bin 1673 -> 0 bytes .../example_apple_metal/iOS/Info-iOS.plist | 4 +- ...een.storyboard => LaunchScreen.storyboard} | 12 +- .../macOS/Info-macOS.plist | 4 +- .../Main.storyboard => MainMenu.storyboard} | 43 +- examples/example_apple_metal/main.mm | 378 ++++++++++++++++++ 16 files changed, 444 insertions(+), 566 deletions(-) delete mode 100644 examples/example_apple_metal/Shared/AppDelegate.h delete mode 100644 examples/example_apple_metal/Shared/AppDelegate.m delete mode 100644 examples/example_apple_metal/Shared/Renderer.h delete mode 100644 examples/example_apple_metal/Shared/Renderer.mm delete mode 100644 examples/example_apple_metal/Shared/ViewController.h delete mode 100644 examples/example_apple_metal/Shared/ViewController.mm delete mode 100644 examples/example_apple_metal/Shared/main.m delete mode 100644 examples/example_apple_metal/iOS/Base.lproj/Main.storyboard delete mode 100644 examples/example_apple_metal/iOS/Default-568h@2x.png rename examples/example_apple_metal/iOS/{Launch Screen.storyboard => LaunchScreen.storyboard} (69%) rename examples/example_apple_metal/macOS/{Base.lproj/Main.storyboard => MainMenu.storyboard} (68%) create mode 100644 examples/example_apple_metal/main.mm diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bd709286..7c3f32c8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -62,6 +62,7 @@ Other Changes: - Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] - Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon] +- Examples: Apple+Metal: Consolidated/simplified to get closer to other examples. (#3543) [@warrenm] - Docs: Split examples/README.txt into docs/BACKENDS.md and docs/EXAMPLES.md improved them. - Docs: Consistently renamed all occurences of "binding" and "back-end" to "backend" in comments and docs. diff --git a/examples/example_apple_metal/Shared/AppDelegate.h b/examples/example_apple_metal/Shared/AppDelegate.h deleted file mode 100644 index 94878d94..00000000 --- a/examples/example_apple_metal/Shared/AppDelegate.h +++ /dev/null @@ -1,18 +0,0 @@ -#import - -#if TARGET_OS_IPHONE - -#import - -@interface AppDelegate : UIResponder -@property (strong, nonatomic) UIWindow *window; -@end - -#else - -#import - -@interface AppDelegate : NSObject -@end - -#endif diff --git a/examples/example_apple_metal/Shared/AppDelegate.m b/examples/example_apple_metal/Shared/AppDelegate.m deleted file mode 100644 index 6947eb23..00000000 --- a/examples/example_apple_metal/Shared/AppDelegate.m +++ /dev/null @@ -1,11 +0,0 @@ -#import "AppDelegate.h" - -@implementation AppDelegate - -#if TARGET_OS_OSX -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { - return YES; -} -#endif - -@end diff --git a/examples/example_apple_metal/Shared/Renderer.h b/examples/example_apple_metal/Shared/Renderer.h deleted file mode 100644 index 81fc6f54..00000000 --- a/examples/example_apple_metal/Shared/Renderer.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface Renderer : NSObject - --(nonnull instancetype)initWithView:(nonnull MTKView *)view; - -@end - diff --git a/examples/example_apple_metal/Shared/Renderer.mm b/examples/example_apple_metal/Shared/Renderer.mm deleted file mode 100644 index c121f692..00000000 --- a/examples/example_apple_metal/Shared/Renderer.mm +++ /dev/null @@ -1,154 +0,0 @@ -#import "Renderer.h" -#import - -#include "imgui.h" -#include "imgui_impl_metal.h" - -#if TARGET_OS_OSX -#include "imgui_impl_osx.h" -#endif - -@interface Renderer () -@property (nonatomic, strong) id device; -@property (nonatomic, strong) id commandQueue; -@end - -@implementation Renderer - --(nonnull instancetype)initWithView:(nonnull MTKView*)view; -{ - self = [super init]; - if(self) - { - _device = view.device; - _commandQueue = [_device newCommandQueue]; - - // Setup Dear ImGui context - // FIXME: This example doesn't have proper cleanup... - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); (void)io; - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls - - // Setup Dear ImGui style - ImGui::StyleColorsDark(); - //ImGui::StyleColorsClassic(); - - // Setup Renderer backend - ImGui_ImplMetal_Init(_device); - - // Load Fonts - // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. - // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. - // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). - // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Read 'docs/FONTS.txt' for more instructions and details. - // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); - //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); - //IM_ASSERT(font != NULL); - } - - return self; -} - -- (void)drawInMTKView:(MTKView*)view -{ - ImGuiIO &io = ImGui::GetIO(); - io.DisplaySize.x = view.bounds.size.width; - io.DisplaySize.y = view.bounds.size.height; - -#if TARGET_OS_OSX - CGFloat framebufferScale = view.window.screen.backingScaleFactor ?: NSScreen.mainScreen.backingScaleFactor; -#else - CGFloat framebufferScale = view.window.screen.scale ?: UIScreen.mainScreen.scale; -#endif - io.DisplayFramebufferScale = ImVec2(framebufferScale, framebufferScale); - - io.DeltaTime = 1 / float(view.preferredFramesPerSecond ?: 60); - - id commandBuffer = [self.commandQueue commandBuffer]; - - // Our state (make them static = more or less global) as a convenience to keep the example terse. - static bool show_demo_window = true; - static bool show_another_window = false; - static float clear_color[4] = { 0.28f, 0.36f, 0.5f, 1.0f }; - - MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor; - if (renderPassDescriptor != nil) - { - renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0], clear_color[1], clear_color[2], clear_color[3]); - - // Here, you could do additional rendering work, including other passes as necessary. - - id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; - [renderEncoder pushDebugGroup:@"ImGui demo"]; - - // Start the Dear ImGui frame - ImGui_ImplMetal_NewFrame(renderPassDescriptor); -#if TARGET_OS_OSX - ImGui_ImplOSX_NewFrame(view); -#endif - ImGui::NewFrame(); - - // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). - if (show_demo_window) - ImGui::ShowDemoWindow(&show_demo_window); - - // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window. - { - static float f = 0.0f; - static int counter = 0; - - ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. - - ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) - ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state - ImGui::Checkbox("Another Window", &show_another_window); - - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color - - if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) - counter++; - ImGui::SameLine(); - ImGui::Text("counter = %d", counter); - - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); - ImGui::End(); - } - - // 3. Show another simple window. - if (show_another_window) - { - ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) - ImGui::Text("Hello from another window!"); - if (ImGui::Button("Close Me")) - show_another_window = false; - ImGui::End(); - } - - // Rendering - ImGui::Render(); - ImDrawData* drawData = ImGui::GetDrawData(); - ImGui_ImplMetal_RenderDrawData(drawData, commandBuffer, renderEncoder); - - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; - - [commandBuffer presentDrawable:view.currentDrawable]; - } - - [commandBuffer commit]; -} - -- (void)mtkView:(MTKView*)view drawableSizeWillChange:(CGSize)size -{ -} - -@end diff --git a/examples/example_apple_metal/Shared/ViewController.h b/examples/example_apple_metal/Shared/ViewController.h deleted file mode 100644 index 137f93e1..00000000 --- a/examples/example_apple_metal/Shared/ViewController.h +++ /dev/null @@ -1,19 +0,0 @@ -#import -#import -#import "Renderer.h" - -#if TARGET_OS_IPHONE - -#import - -@interface ViewController : UIViewController -@end - -#else - -#import - -@interface ViewController : NSViewController -@end - -#endif diff --git a/examples/example_apple_metal/Shared/ViewController.mm b/examples/example_apple_metal/Shared/ViewController.mm deleted file mode 100644 index 3c79cc1c..00000000 --- a/examples/example_apple_metal/Shared/ViewController.mm +++ /dev/null @@ -1,153 +0,0 @@ -#import "ViewController.h" -#import "Renderer.h" -#include "imgui.h" - -#if TARGET_OS_OSX -#include "imgui_impl_osx.h" -#endif - -@interface ViewController () -@property (nonatomic, readonly) MTKView *mtkView; -@property (nonatomic, strong) Renderer *renderer; -@end - -@implementation ViewController - -- (MTKView *)mtkView { - return (MTKView *)self.view; -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.mtkView.device = MTLCreateSystemDefaultDevice(); - - if (!self.mtkView.device) { - NSLog(@"Metal is not supported"); - abort(); - } - - self.renderer = [[Renderer alloc] initWithView:self.mtkView]; - - [self.renderer mtkView:self.mtkView drawableSizeWillChange:self.mtkView.bounds.size]; - - self.mtkView.delegate = self.renderer; - -#if TARGET_OS_OSX - // Add a tracking area in order to receive mouse events whenever the mouse is within the bounds of our view - NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect - options:NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways - owner:self - userInfo:nil]; - [self.view addTrackingArea:trackingArea]; - - // If we want to receive key events, we either need to be in the responder chain of the key view, - // or else we can install a local monitor. The consequence of this heavy-handed approach is that - // we receive events for all controls, not just Dear ImGui widgets. If we had native controls in our - // window, we'd want to be much more careful than just ingesting the complete event stream, though we - // do make an effort to be good citizens by passing along events when Dear ImGui doesn't want to capture. - NSEventMask eventMask = NSEventMaskKeyDown | NSEventMaskKeyUp | NSEventMaskFlagsChanged | NSEventTypeScrollWheel; - [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _Nullable(NSEvent *event) { - BOOL wantsCapture = ImGui_ImplOSX_HandleEvent(event, self.view); - if (event.type == NSEventTypeKeyDown && wantsCapture) { - return nil; - } else { - return event; - } - - }]; - - ImGui_ImplOSX_Init(); -#endif -} - -#if TARGET_OS_OSX - -- (void)mouseMoved:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)mouseDown:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)rightMouseDown:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)otherMouseDown:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)mouseUp:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)rightMouseUp:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)otherMouseUp:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)mouseDragged:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)rightMouseDragged:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)otherMouseDragged:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -- (void)scrollWheel:(NSEvent *)event { - ImGui_ImplOSX_HandleEvent(event, self.view); -} - -#elif TARGET_OS_IOS - -// This touch mapping is super cheesy/hacky. We treat any touch on the screen -// as if it were a depressed left mouse button, and we don't bother handling -// multitouch correctly at all. This causes the "cursor" to behave very erratically -// when there are multiple active touches. But for demo purposes, single-touch -// interaction actually works surprisingly well. -- (void)updateIOWithTouchEvent:(UIEvent *)event { - UITouch *anyTouch = event.allTouches.anyObject; - CGPoint touchLocation = [anyTouch locationInView:self.view]; - ImGuiIO &io = ImGui::GetIO(); - io.MousePos = ImVec2(touchLocation.x, touchLocation.y); - - BOOL hasActiveTouch = NO; - for (UITouch *touch in event.allTouches) { - if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled) { - hasActiveTouch = YES; - break; - } - } - io.MouseDown[0] = hasActiveTouch; -} - -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - [self updateIOWithTouchEvent:event]; -} - -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - [self updateIOWithTouchEvent:event]; -} - -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - [self updateIOWithTouchEvent:event]; -} - -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - [self updateIOWithTouchEvent:event]; -} - -#endif - -@end - diff --git a/examples/example_apple_metal/Shared/main.m b/examples/example_apple_metal/Shared/main.m deleted file mode 100644 index 15938a90..00000000 --- a/examples/example_apple_metal/Shared/main.m +++ /dev/null @@ -1,22 +0,0 @@ -#import - -#if TARGET_OS_IPHONE - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} - -#else - -#import - -int main(int argc, const char * argv[]) { - return NSApplicationMain(argc, argv); -} - -#endif diff --git a/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj b/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj index 38c45cfd..f382520f 100644 --- a/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj +++ b/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj @@ -9,27 +9,19 @@ /* Begin PBXBuildFile section */ 07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; }; 07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; }; - 8307E7CC20E9F9C900473790 /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7CB20E9F9C900473790 /* ViewController.mm */; }; - 8307E7CF20E9F9C900473790 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8307E7CD20E9F9C900473790 /* Main.storyboard */; }; - 8307E7DE20E9F9C900473790 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7DD20E9F9C900473790 /* AppDelegate.m */; }; - 8307E7E420E9F9C900473790 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8307E7E220E9F9C900473790 /* Main.storyboard */; }; - 8307E7E720E9F9C900473790 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7E620E9F9C900473790 /* main.m */; }; - 8307E7E820E9F9C900473790 /* Renderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7BC20E9F9C700473790 /* Renderer.mm */; }; - 8307E7E920E9F9C900473790 /* Renderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7BC20E9F9C700473790 /* Renderer.mm */; }; - 836D2A2E20EE208E0098E909 /* imgui_impl_osx.mm in Sources */ = {isa = PBXBuildFile; fileRef = 836D2A2D20EE208E0098E909 /* imgui_impl_osx.mm */; }; - 836D2A3020EE4A180098E909 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 836D2A2F20EE4A180098E909 /* Default-568h@2x.png */; }; - 836D2A3220EE4A900098E909 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 836D2A3120EE4A900098E909 /* Launch Screen.storyboard */; }; - 83BBE9DE20EB3FFC00295997 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7E620E9F9C900473790 /* main.m */; }; - 83BBE9DF20EB40AE00295997 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7DD20E9F9C900473790 /* AppDelegate.m */; }; - 83BBE9E020EB42D000295997 /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8307E7CB20E9F9C900473790 /* ViewController.mm */; }; + 8309BD8F253CCAAA0045E2A1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */; }; + 8309BDA5253CCC070045E2A1 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDA0253CCBC10045E2A1 /* main.mm */; }; + 8309BDA8253CCC080045E2A1 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDA0253CCBC10045E2A1 /* main.mm */; }; + 8309BDBB253CCCAD0045E2A1 /* imgui_impl_metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */; }; + 8309BDBE253CCCB60045E2A1 /* imgui_impl_metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */; }; + 8309BDBF253CCCB60045E2A1 /* imgui_impl_osx.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDB6253CCC9D0045E2A1 /* imgui_impl_osx.mm */; }; + 8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8309BDC5253CCCFE0045E2A1 /* AppKit.framework */; }; + 8309BDFC253CDAB30045E2A1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */; }; + 8309BE04253CDAB60045E2A1 /* MainMenu.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */; }; 83BBE9E520EB46B900295997 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9E420EB46B900295997 /* Metal.framework */; }; 83BBE9E720EB46BD00295997 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9E620EB46BD00295997 /* MetalKit.framework */; }; - 83BBE9E920EB46C100295997 /* ModelIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9E820EB46C100295997 /* ModelIO.framework */; }; 83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9EA20EB471700295997 /* MetalKit.framework */; }; 83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9EB20EB471700295997 /* Metal.framework */; }; - 83BBE9EF20EB471C00295997 /* ModelIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9EE20EB471C00295997 /* ModelIO.framework */; }; - 83BBE9FE20EB54D800295997 /* imgui_impl_metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83BBE9FD20EB54D800295997 /* imgui_impl_metal.mm */; }; - 83BBE9FF20EB54D800295997 /* imgui_impl_metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83BBE9FD20EB54D800295997 /* imgui_impl_metal.mm */; }; 83BBEA0520EB54E700295997 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0120EB54E700295997 /* imgui_draw.cpp */; }; 83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0120EB54E700295997 /* imgui_draw.cpp */; }; 83BBEA0720EB54E700295997 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0220EB54E700295997 /* imgui_demo.cpp */; }; @@ -41,31 +33,23 @@ /* Begin PBXFileReference section */ 07A82ED62139413C0078D120 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../imgui_internal.h; sourceTree = ""; }; 07A82ED72139413C0078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = ""; }; - 8307E7BB20E9F9C700473790 /* Renderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Renderer.h; sourceTree = ""; }; - 8307E7BC20E9F9C700473790 /* Renderer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Renderer.mm; sourceTree = ""; }; 8307E7C420E9F9C900473790 /* example_apple_metal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example_apple_metal.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 8307E7CA20E9F9C900473790 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; - 8307E7CB20E9F9C900473790 /* ViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = ""; }; - 8307E7CE20E9F9C900473790 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 8307E7D320E9F9C900473790 /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; }; 8307E7DA20E9F9C900473790 /* example_apple_metal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example_apple_metal.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 8307E7DC20E9F9C900473790 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 8307E7DD20E9F9C900473790 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 8307E7E320E9F9C900473790 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 8307E7E520E9F9C900473790 /* Info-macOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-macOS.plist"; sourceTree = ""; }; - 8307E7E620E9F9C900473790 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 836D2A2C20EE208D0098E909 /* imgui_impl_osx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_osx.h; path = ../../../backends/imgui_impl_osx.h; sourceTree = ""; }; - 836D2A2D20EE208E0098E909 /* imgui_impl_osx.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_osx.mm; path = ../../../backends/imgui_impl_osx.mm; sourceTree = ""; }; - 836D2A2F20EE4A180098E909 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; - 836D2A3120EE4A900098E909 /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; + 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 8309BDA0253CCBC10045E2A1 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; + 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_metal.mm; path = ../../backends/imgui_impl_metal.mm; sourceTree = ""; }; + 8309BDB6253CCC9D0045E2A1 /* imgui_impl_osx.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_osx.mm; path = ../../backends/imgui_impl_osx.mm; sourceTree = ""; }; + 8309BDC5253CCCFE0045E2A1 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; + 8309BDF8253CDAAE0045E2A1 /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; }; + 8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = MainMenu.storyboard; sourceTree = ""; }; + 8309BDFB253CDAAE0045E2A1 /* Info-macOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-macOS.plist"; sourceTree = ""; }; 83BBE9E420EB46B900295997 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/Metal.framework; sourceTree = DEVELOPER_DIR; }; 83BBE9E620EB46BD00295997 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/MetalKit.framework; sourceTree = DEVELOPER_DIR; }; 83BBE9E820EB46C100295997 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/ModelIO.framework; sourceTree = DEVELOPER_DIR; }; 83BBE9EA20EB471700295997 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; 83BBE9EB20EB471700295997 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 83BBE9EE20EB471C00295997 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = System/Library/Frameworks/ModelIO.framework; sourceTree = SDKROOT; }; - 83BBE9FC20EB54D800295997 /* imgui_impl_metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_metal.h; path = ../../../backends/imgui_impl_metal.h; sourceTree = ""; }; - 83BBE9FD20EB54D800295997 /* imgui_impl_metal.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_metal.mm; path = ../../../backends/imgui_impl_metal.mm; sourceTree = ""; }; 83BBEA0020EB54E700295997 /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; 83BBEA0120EB54E700295997 /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; 83BBEA0220EB54E700295997 /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../imgui_demo.cpp; sourceTree = ""; }; @@ -78,7 +62,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 83BBE9E920EB46C100295997 /* ModelIO.framework in Frameworks */, + 8309BD8F253CCAAA0045E2A1 /* UIKit.framework in Frameworks */, 83BBE9E720EB46BD00295997 /* MetalKit.framework in Frameworks */, 83BBE9E520EB46B900295997 /* Metal.framework in Frameworks */, ); @@ -88,7 +72,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 83BBE9EF20EB471C00295997 /* ModelIO.framework in Frameworks */, + 8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */, 83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */, 83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */, ); @@ -101,32 +85,12 @@ isa = PBXGroup; children = ( 83BBE9F020EB544400295997 /* imgui */, - 8307E7BA20E9F9C700473790 /* Shared */, - 8307E7C620E9F9C900473790 /* iOS */, - 8307E7DB20E9F9C900473790 /* macOS */, + 8309BD9E253CCBA70045E2A1 /* example */, 8307E7C520E9F9C900473790 /* Products */, 83BBE9E320EB46B800295997 /* Frameworks */, ); sourceTree = ""; }; - 8307E7BA20E9F9C700473790 /* Shared */ = { - isa = PBXGroup; - children = ( - 83BBE9FC20EB54D800295997 /* imgui_impl_metal.h */, - 83BBE9FD20EB54D800295997 /* imgui_impl_metal.mm */, - 836D2A2C20EE208D0098E909 /* imgui_impl_osx.h */, - 836D2A2D20EE208E0098E909 /* imgui_impl_osx.mm */, - 8307E7DC20E9F9C900473790 /* AppDelegate.h */, - 8307E7DD20E9F9C900473790 /* AppDelegate.m */, - 8307E7BB20E9F9C700473790 /* Renderer.h */, - 8307E7BC20E9F9C700473790 /* Renderer.mm */, - 8307E7CA20E9F9C900473790 /* ViewController.h */, - 8307E7CB20E9F9C900473790 /* ViewController.mm */, - 8307E7E620E9F9C900473790 /* main.m */, - ); - path = Shared; - sourceTree = ""; - }; 8307E7C520E9F9C900473790 /* Products */ = { isa = PBXGroup; children = ( @@ -136,22 +100,30 @@ name = Products; sourceTree = ""; }; - 8307E7C620E9F9C900473790 /* iOS */ = { + 8309BD9E253CCBA70045E2A1 /* example */ = { isa = PBXGroup; children = ( - 836D2A2F20EE4A180098E909 /* Default-568h@2x.png */, - 8307E7CD20E9F9C900473790 /* Main.storyboard */, - 8307E7D320E9F9C900473790 /* Info-iOS.plist */, - 836D2A3120EE4A900098E909 /* Launch Screen.storyboard */, + 8309BDF6253CDAAE0045E2A1 /* iOS */, + 8309BDF9253CDAAE0045E2A1 /* macOS */, + 8309BDA0253CCBC10045E2A1 /* main.mm */, + ); + name = example; + sourceTree = ""; + }; + 8309BDF6253CDAAE0045E2A1 /* iOS */ = { + isa = PBXGroup; + children = ( + 8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */, + 8309BDF8253CDAAE0045E2A1 /* Info-iOS.plist */, ); path = iOS; sourceTree = ""; }; - 8307E7DB20E9F9C900473790 /* macOS */ = { + 8309BDF9253CDAAE0045E2A1 /* macOS */ = { isa = PBXGroup; children = ( - 8307E7E220E9F9C900473790 /* Main.storyboard */, - 8307E7E520E9F9C900473790 /* Info-macOS.plist */, + 8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */, + 8309BDFB253CDAAE0045E2A1 /* Info-macOS.plist */, ); path = macOS; sourceTree = ""; @@ -159,6 +131,8 @@ 83BBE9E320EB46B800295997 /* Frameworks */ = { isa = PBXGroup; children = ( + 8309BDC5253CCCFE0045E2A1 /* AppKit.framework */, + 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */, 83BBE9EE20EB471C00295997 /* ModelIO.framework */, 83BBE9EB20EB471700295997 /* Metal.framework */, 83BBE9EA20EB471700295997 /* MetalKit.framework */, @@ -172,6 +146,8 @@ 83BBE9F020EB544400295997 /* imgui */ = { isa = PBXGroup; children = ( + 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */, + 8309BDB6253CCC9D0045E2A1 /* imgui_impl_osx.mm */, 83BBEA0420EB54E700295997 /* imconfig.h */, 83BBEA0320EB54E700295997 /* imgui.cpp */, 83BBEA0020EB54E700295997 /* imgui.h */, @@ -226,7 +202,7 @@ 8307E7B620E9F9C700473790 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0940; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = "Warren Moore"; TargetAttributes = { 8307E7C320E9F9C900473790 = { @@ -263,9 +239,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 836D2A3220EE4A900098E909 /* Launch Screen.storyboard in Resources */, - 8307E7CF20E9F9C900473790 /* Main.storyboard in Resources */, - 836D2A3020EE4A180098E909 /* Default-568h@2x.png in Resources */, + 8309BDFC253CDAB30045E2A1 /* LaunchScreen.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -273,7 +247,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8307E7E420E9F9C900473790 /* Main.storyboard in Resources */, + 8309BE04253CDAB60045E2A1 /* MainMenu.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -284,15 +258,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8307E7E820E9F9C900473790 /* Renderer.mm in Sources */, - 8307E7CC20E9F9C900473790 /* ViewController.mm in Sources */, + 8309BDBB253CCCAD0045E2A1 /* imgui_impl_metal.mm in Sources */, 83BBEA0520EB54E700295997 /* imgui_draw.cpp in Sources */, - 83BBE9DF20EB40AE00295997 /* AppDelegate.m in Sources */, 83BBEA0920EB54E700295997 /* imgui.cpp in Sources */, 83BBEA0720EB54E700295997 /* imgui_demo.cpp in Sources */, - 83BBE9FE20EB54D800295997 /* imgui_impl_metal.mm in Sources */, 07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */, - 83BBE9DE20EB3FFC00295997 /* main.m in Sources */, + 8309BDA5253CCC070045E2A1 /* main.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -300,40 +271,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 83BBE9E020EB42D000295997 /* ViewController.mm in Sources */, - 8307E7E920E9F9C900473790 /* Renderer.mm in Sources */, + 8309BDBE253CCCB60045E2A1 /* imgui_impl_metal.mm in Sources */, + 8309BDBF253CCCB60045E2A1 /* imgui_impl_osx.mm in Sources */, 83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */, 07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */, - 8307E7E720E9F9C900473790 /* main.m in Sources */, 83BBEA0A20EB54E700295997 /* imgui.cpp in Sources */, 83BBEA0820EB54E700295997 /* imgui_demo.cpp in Sources */, - 83BBE9FF20EB54D800295997 /* imgui_impl_metal.mm in Sources */, - 836D2A2E20EE208E0098E909 /* imgui_impl_osx.mm in Sources */, - 8307E7DE20E9F9C900473790 /* AppDelegate.m in Sources */, + 8309BDA8253CCC080045E2A1 /* main.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXVariantGroup section */ - 8307E7CD20E9F9C900473790 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 8307E7CE20E9F9C900473790 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 8307E7E220E9F9C900473790 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 8307E7E320E9F9C900473790 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin XCBuildConfiguration section */ 8307E7EE20E9F9C900473790 /* Debug */ = { isa = XCBuildConfiguration; @@ -361,6 +310,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -416,6 +366,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -451,6 +402,7 @@ PRODUCT_NAME = example_apple_metal; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**"; }; name = Debug; }; @@ -467,6 +419,7 @@ PRODUCT_NAME = example_apple_metal; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**"; VALIDATE_PRODUCT = YES; }; name = Release; @@ -484,6 +437,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-macos"; PRODUCT_NAME = example_apple_metal; SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**"; }; name = Debug; }; @@ -500,6 +454,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-macos"; PRODUCT_NAME = example_apple_metal; SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**"; }; name = Release; }; diff --git a/examples/example_apple_metal/iOS/Base.lproj/Main.storyboard b/examples/example_apple_metal/iOS/Base.lproj/Main.storyboard deleted file mode 100644 index 24a4009e..00000000 --- a/examples/example_apple_metal/iOS/Base.lproj/Main.storyboard +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/example_apple_metal/iOS/Default-568h@2x.png b/examples/example_apple_metal/iOS/Default-568h@2x.png deleted file mode 100644 index e3ce940a36b6bebefdc8944e931dac246a1ec425..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1673 zcmeHGJ7^R^7@j;(2?=PCLaT98iQdl4CimDSYfNtMyoGEyFAE;nxVJk=mSi8l0%a#sB~l zdQEEpFuVi6Xn1CXdyE^C62H!~N|P-IE39or6wEt8i$dMAR%wG;PP+M?&H^wp>6%T} zG!_**@I))ah=~_+HUP78Nod*Yl))BVb$wO%`f68zuA>S!^9DA;GF@|P+Yw#fUNY_N zbz63XxvOwCQMiCdnFSMX!;h6j6*{^Ke`jtazz&41tHM!IO`{IWK}2C*EaYr5gJDq? zNdeE~$rUJJQbah9a3P0@f=h}-VD|_-TI8%K4XxUZ#Vu7>V=Pn8D%9PCZg`mu zB@v7H4#Y4N-H(~&+f>(7fs;hnbre$2uq0Qfi^YX1A(c|8f~Cqd(MkneDCeuV$JGLR z%cDN)ah+rC%s_57eJ|vZH5$2hs8fvs4|b|l+`+k!fqGr8GdLG%AQ$muP&UgyX4`Y| zg~^`%P31;^*Qw7JJmQ=D?os-X|AJHXMYF>1G)*trpNssX9qQV=nH+rCe>(y2`0$J8 zzxLfHpU&M{-0>fbn?DanYx1?Zy~}&2vrlw#PCD>kc3^Yp!;jG#dGlI7I~2X#eF{dv Wx9{NM<9i1mvwHN(lJ;!j_TAqnTQ0Z& diff --git a/examples/example_apple_metal/iOS/Info-iOS.plist b/examples/example_apple_metal/iOS/Info-iOS.plist index 8d919d1e..93ef078d 100644 --- a/examples/example_apple_metal/iOS/Info-iOS.plist +++ b/examples/example_apple_metal/iOS/Info-iOS.plist @@ -21,9 +21,7 @@ LSRequiresIPhoneOS UILaunchStoryboardName - Launch Screen - UIMainStoryboardFile - Main + LaunchScreen UIRequiredDeviceCapabilities armv7 diff --git a/examples/example_apple_metal/iOS/Launch Screen.storyboard b/examples/example_apple_metal/iOS/LaunchScreen.storyboard similarity index 69% rename from examples/example_apple_metal/iOS/Launch Screen.storyboard rename to examples/example_apple_metal/iOS/LaunchScreen.storyboard index 96047e1f..12c52cfb 100644 --- a/examples/example_apple_metal/iOS/Launch Screen.storyboard +++ b/examples/example_apple_metal/iOS/LaunchScreen.storyboard @@ -1,11 +1,9 @@ - - - - + + - + @@ -15,10 +13,10 @@ - + - + diff --git a/examples/example_apple_metal/macOS/Info-macOS.plist b/examples/example_apple_metal/macOS/Info-macOS.plist index 52d99204..6f4a2b23 100644 --- a/examples/example_apple_metal/macOS/Info-macOS.plist +++ b/examples/example_apple_metal/macOS/Info-macOS.plist @@ -22,10 +22,8 @@ 1 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2018 Warren Moore. All rights reserved. NSMainStoryboardFile - Main + MainMenu NSPrincipalClass NSApplication diff --git a/examples/example_apple_metal/macOS/Base.lproj/Main.storyboard b/examples/example_apple_metal/macOS/MainMenu.storyboard similarity index 68% rename from examples/example_apple_metal/macOS/Base.lproj/Main.storyboard rename to examples/example_apple_metal/macOS/MainMenu.storyboard index cf414617..38ad432b 100644 --- a/examples/example_apple_metal/macOS/Base.lproj/Main.storyboard +++ b/examples/example_apple_metal/macOS/MainMenu.storyboard @@ -1,9 +1,8 @@ - + - - + @@ -16,8 +15,6 @@ - - @@ -90,41 +87,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/examples/example_apple_metal/main.mm b/examples/example_apple_metal/main.mm new file mode 100644 index 00000000..ec6482ee --- /dev/null +++ b/examples/example_apple_metal/main.mm @@ -0,0 +1,378 @@ + +#import + +#if TARGET_OS_OSX +#import +#else +#import +#endif + +#import +#import + +#include "imgui.h" +#include "imgui_impl_metal.h" + +#if TARGET_OS_OSX +#include "imgui_impl_osx.h" + +@interface ViewController : NSViewController +@end +#else +@interface ViewController : UIViewController +@end +#endif + +@interface ViewController () +@property (nonatomic, readonly) MTKView *mtkView; +@property (nonatomic, strong) id device; +@property (nonatomic, strong) id commandQueue; +@end + +@implementation ViewController + +- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil { + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + + _device = MTLCreateSystemDefaultDevice(); + _commandQueue = [_device newCommandQueue]; + + if (!self.device) { + NSLog(@"Metal is not supported"); + abort(); + } + + // Setup Dear ImGui context + // FIXME: This example doesn't have proper cleanup... + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); + + // Setup Renderer backend + ImGui_ImplMetal_Init(_device); + + // Load Fonts + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'docs/FONTS.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); + + return self; +} + +- (MTKView *)mtkView { + return (MTKView *)self.view; +} + +- (void)loadView { + self.view = [[MTKView alloc] initWithFrame:CGRectMake(0, 0, 1200, 720)]; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.mtkView.device = self.device; + self.mtkView.delegate = self; + +#if TARGET_OS_OSX + // Add a tracking area in order to receive mouse events whenever the mouse is within the bounds of our view + NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect + options:NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways + owner:self + userInfo:nil]; + [self.view addTrackingArea:trackingArea]; + + // If we want to receive key events, we either need to be in the responder chain of the key view, + // or else we can install a local monitor. The consequence of this heavy-handed approach is that + // we receive events for all controls, not just Dear ImGui widgets. If we had native controls in our + // window, we'd want to be much more careful than just ingesting the complete event stream, though we + // do make an effort to be good citizens by passing along events when Dear ImGui doesn't want to capture. + NSEventMask eventMask = NSEventMaskKeyDown | NSEventMaskKeyUp | NSEventMaskFlagsChanged | NSEventTypeScrollWheel; + [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _Nullable(NSEvent *event) { + BOOL wantsCapture = ImGui_ImplOSX_HandleEvent(event, self.view); + if (event.type == NSEventTypeKeyDown && wantsCapture) { + return nil; + } else { + return event; + } + + }]; + + ImGui_ImplOSX_Init(); + +#endif +} + +#pragma mark - Interaction + +#if TARGET_OS_OSX + +- (void)mouseMoved:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)mouseDown:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)rightMouseDown:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)otherMouseDown:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)mouseUp:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)rightMouseUp:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)otherMouseUp:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)mouseDragged:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)rightMouseDragged:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)otherMouseDragged:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +- (void)scrollWheel:(NSEvent *)event { + ImGui_ImplOSX_HandleEvent(event, self.view); +} + +#else + +// This touch mapping is super cheesy/hacky. We treat any touch on the screen +// as if it were a depressed left mouse button, and we don't bother handling +// multitouch correctly at all. This causes the "cursor" to behave very erratically +// when there are multiple active touches. But for demo purposes, single-touch +// interaction actually works surprisingly well. +- (void)updateIOWithTouchEvent:(UIEvent *)event { + UITouch *anyTouch = event.allTouches.anyObject; + CGPoint touchLocation = [anyTouch locationInView:self.view]; + ImGuiIO &io = ImGui::GetIO(); + io.MousePos = ImVec2(touchLocation.x, touchLocation.y); + + BOOL hasActiveTouch = NO; + for (UITouch *touch in event.allTouches) { + if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled) { + hasActiveTouch = YES; + break; + } + } + io.MouseDown[0] = hasActiveTouch; +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + [self updateIOWithTouchEvent:event]; +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + [self updateIOWithTouchEvent:event]; +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + [self updateIOWithTouchEvent:event]; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + [self updateIOWithTouchEvent:event]; +} + +#endif + +#pragma mark - MTKViewDelegate + +- (void)drawInMTKView:(MTKView*)view +{ + ImGuiIO &io = ImGui::GetIO(); + io.DisplaySize.x = view.bounds.size.width; + io.DisplaySize.y = view.bounds.size.height; + +#if TARGET_OS_OSX + CGFloat framebufferScale = view.window.screen.backingScaleFactor ?: NSScreen.mainScreen.backingScaleFactor; +#else + CGFloat framebufferScale = view.window.screen.scale ?: UIScreen.mainScreen.scale; +#endif + io.DisplayFramebufferScale = ImVec2(framebufferScale, framebufferScale); + + io.DeltaTime = 1 / float(view.preferredFramesPerSecond ?: 60); + + id commandBuffer = [self.commandQueue commandBuffer]; + + // Our state (make them static = more or less global) as a convenience to keep the example terse. + static bool show_demo_window = true; + static bool show_another_window = false; + static float clear_color[4] = { 0.28f, 0.36f, 0.5f, 1.0f }; + + MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor; + if (renderPassDescriptor != nil) + { + renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0], clear_color[1], clear_color[2], clear_color[3]); + + // Here, you could do additional rendering work, including other passes as necessary. + + id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; + [renderEncoder pushDebugGroup:@"ImGui demo"]; + + // Start the Dear ImGui frame + ImGui_ImplMetal_NewFrame(renderPassDescriptor); +#if TARGET_OS_OSX + ImGui_ImplOSX_NewFrame(view); +#endif + ImGui::NewFrame(); + + // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window. + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + ImGui::End(); + } + + // 3. Show another simple window. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // Rendering + ImGui::Render(); + ImDrawData* drawData = ImGui::GetDrawData(); + ImGui_ImplMetal_RenderDrawData(drawData, commandBuffer, renderEncoder); + + [renderEncoder popDebugGroup]; + [renderEncoder endEncoding]; + + [commandBuffer presentDrawable:view.currentDrawable]; + } + + [commandBuffer commit]; +} + +- (void)mtkView:(MTKView*)view drawableSizeWillChange:(CGSize)size +{ +} + +@end + +#pragma mark - Application Delegate + +#if TARGET_OS_OSX + +@interface AppDelegate : NSObject +@property (nonatomic, strong) NSWindow *window; +@end + +@implementation AppDelegate + +- (instancetype)init { + if (self = [super init]) { + NSViewController *rootViewController = [[ViewController alloc] initWithNibName:nil bundle:nil]; + self.window = [[NSWindow alloc] initWithContentRect:NSZeroRect + styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable + backing:NSBackingStoreBuffered + defer:NO]; + self.window.contentViewController = rootViewController; + [self.window orderFront:self]; + [self.window center]; + [self.window becomeKeyWindow]; + } + return self; +} + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { + return YES; +} + +@end + +#else + +@interface AppDelegate : UIResponder +@property (strong, nonatomic) UIWindow *window; +@end + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + UIViewController *rootViewController = [[ViewController alloc] init]; + self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; + self.window.rootViewController = rootViewController; + [self.window makeKeyAndVisible]; + return YES; +} + +@end + +#endif + +#pragma mark - main() + +#if TARGET_OS_OSX + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} + +#else + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} + +#endif From b3576dd35409a3a3ad742bb74122e14fcda2d886 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Wed, 23 Sep 2020 14:35:46 +0300 Subject: [PATCH 05/11] Replace UTF-8 decoder with branchless version by Christopher Wellons. Decoding performance increase ranges from 30-40%. Changes: * Errors handling near the end of string changed. If input does not contain enough bytes, decoder returns `IM_UNICODE_CODEPOINT_INVALID`, consuming all remaining bytes while old decoder consumed only one byte. Guarantees: * At least one byte is consumed, if input had at least one byte available. * Number of consumed bytes will never seek past end of string. Requirements: * `in_text` is a valid pointer. * String pointed by `in_text` must be zero-terminated, or `in_text_end` is not NULL. --- docs/CHANGELOG.txt | 3 ++ imgui.cpp | 107 +++++++++++++++++++++------------------------ 2 files changed, 53 insertions(+), 57 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7c3f32c8..33e84373 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,6 +59,9 @@ Other Changes: - Tab Bar: Do not display a tooltip if the name already fits over a given tab. (#3521) - Drag and Drop: Fix drag and drop to tie same-size drop targets by choosen the later one. Fixes dragging into a full-window-sized dockspace inside a zero-padded window. (#3519, #2717) [@Black-Cat] +- Misc: Replaced UTF-8 decoder by branchless one by Christopher Wellons (30~40% faster). [@rokups] + Super minor fix handling incomplete UTF-8 contents: if input does not contain enough bytes, decoder + returns IM_UNICODE_CODEPOINT_INVALID and consume remaining bytes (vs old decoded consumed only 1 byte). - Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] - Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon] diff --git a/imgui.cpp b/imgui.cpp index 0bb82d23..d8b7d5ed 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1553,66 +1553,59 @@ void* ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_f //----------------------------------------------------------------------------- // Convert UTF-8 to 32-bit character, process single character input. -// Based on stb_from_utf8() from github.com/nothings/stb/ +// Based on work of Christopher Wellons (https://github.com/skeeto/branchless-utf8) // We handle UTF-8 decoding error by skipping forward. int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end) { - unsigned int c = (unsigned int)-1; - const unsigned char* str = (const unsigned char*)in_text; - if (!(*str & 0x80)) - { - c = (unsigned int)(*str++); - *out_char = c; - return 1; - } - if ((*str & 0xe0) == 0xc0) - { - *out_char = IM_UNICODE_CODEPOINT_INVALID; // will be invalid but not end of string - if (in_text_end && in_text_end - (const char*)str < 2) return 1; - if (*str < 0xc2) return 2; - c = (unsigned int)((*str++ & 0x1f) << 6); - if ((*str & 0xc0) != 0x80) return 2; - c += (*str++ & 0x3f); - *out_char = c; - return 2; - } - if ((*str & 0xf0) == 0xe0) - { - *out_char = IM_UNICODE_CODEPOINT_INVALID; // will be invalid but not end of string - if (in_text_end && in_text_end - (const char*)str < 3) return 1; - if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3; - if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below - c = (unsigned int)((*str++ & 0x0f) << 12); - if ((*str & 0xc0) != 0x80) return 3; - c += (unsigned int)((*str++ & 0x3f) << 6); - if ((*str & 0xc0) != 0x80) return 3; - c += (*str++ & 0x3f); - *out_char = c; - return 3; - } - if ((*str & 0xf8) == 0xf0) - { - *out_char = IM_UNICODE_CODEPOINT_INVALID; // will be invalid but not end of string - if (in_text_end && in_text_end - (const char*)str < 4) return 1; - if (*str > 0xf4) return 4; - if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4; - if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below - c = (unsigned int)((*str++ & 0x07) << 18); - if ((*str & 0xc0) != 0x80) return 4; - c += (unsigned int)((*str++ & 0x3f) << 12); - if ((*str & 0xc0) != 0x80) return 4; - c += (unsigned int)((*str++ & 0x3f) << 6); - if ((*str & 0xc0) != 0x80) return 4; - c += (*str++ & 0x3f); - // utf-8 encodings of values used in surrogate pairs are invalid - if ((c & 0xFFFFF800) == 0xD800) return 4; - // If codepoint does not fit in ImWchar, use replacement character U+FFFD instead - if (c > IM_UNICODE_CODEPOINT_MAX) c = IM_UNICODE_CODEPOINT_INVALID; - *out_char = c; - return 4; - } - *out_char = 0; - return 0; + static const char lengths[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0 }; + static const int masks[] = { 0x00, 0x7f, 0x1f, 0x0f, 0x07 }; + static const uint32_t mins[] = { 4194304, 0, 128, 2048, 65536 }; + static const int shiftc[] = { 0, 18, 12, 6, 0 }; + static const int shifte[] = { 0, 6, 4, 2, 0 }; + unsigned char s[4]; + int len = lengths[*(const unsigned char*)in_text >> 3]; + + if (in_text_end == NULL) + in_text_end = in_text + len + !len; // Max length, nulls will be taken into account. + + // Copy at most 'len' bytes, stop copying at 0 or past in_text_end. + s[0] = in_text + 0 < in_text_end ? in_text[0] : 0; + s[1] = s[0] && in_text + 1 < in_text_end ? in_text[1] : 0; + s[2] = s[1] && in_text + 2 < in_text_end ? in_text[2] : 0; + s[3] = s[2] && in_text + 3 < in_text_end ? in_text[3] : 0; + + // Compute the pointer to the next character early so that the next + // iteration can start working on the next character. Neither Clang + // nor GCC figure out this reordering on their own. + //const unsigned char *next = s + len + !len; + + // No bytes are consumed when *in_text == 0 || in_text == in_text_end. + // One byte is consumed in case of invalid first byte of in_text. + // All available bytes (at most `len` bytes) are consumed on incomplete/invalid second to last bytes. + int consumed = !!s[0] + !!s[1] + !!s[2] + !!s[3]; + + // Assume a four-byte character and load four bytes. Unused bits are shifted out. + *out_char = (uint32_t)(s[0] & masks[len]) << 18; + *out_char |= (uint32_t)(s[1] & 0x3f) << 12; + *out_char |= (uint32_t)(s[2] & 0x3f) << 6; + *out_char |= (uint32_t)(s[3] & 0x3f) << 0; + *out_char >>= shiftc[len]; + + // Accumulate the various error conditions. + int e = 0; + e = (*out_char < mins[len]) << 6; // non-canonical encoding + e |= ((*out_char >> 11) == 0x1b) << 7; // surrogate half? + e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8; // out of range? + e |= (s[1] & 0xc0) >> 2; + e |= (s[2] & 0xc0) >> 4; + e |= (s[3] ) >> 6; + e ^= 0x2a; // top two bits of each tail byte correct? + e >>= shifte[len]; + + if (e) + *out_char = IM_UNICODE_CODEPOINT_INVALID; + + return consumed; } int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining) From b7530e5d04fcd9d5859c089244f562be82b4c531 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 25 Oct 2020 16:27:32 +0100 Subject: [PATCH 06/11] Revert "Replace UTF-8 decoder with branchless version by Christopher Wellons." (#3558) This reverts commit b3576dd35409a3a3ad742bb74122e14fcda2d886. --- docs/CHANGELOG.txt | 3 -- imgui.cpp | 107 ++++++++++++++++++++++++--------------------- 2 files changed, 57 insertions(+), 53 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 33e84373..7c3f32c8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,9 +59,6 @@ Other Changes: - Tab Bar: Do not display a tooltip if the name already fits over a given tab. (#3521) - Drag and Drop: Fix drag and drop to tie same-size drop targets by choosen the later one. Fixes dragging into a full-window-sized dockspace inside a zero-padded window. (#3519, #2717) [@Black-Cat] -- Misc: Replaced UTF-8 decoder by branchless one by Christopher Wellons (30~40% faster). [@rokups] - Super minor fix handling incomplete UTF-8 contents: if input does not contain enough bytes, decoder - returns IM_UNICODE_CODEPOINT_INVALID and consume remaining bytes (vs old decoded consumed only 1 byte). - Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] - Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon] diff --git a/imgui.cpp b/imgui.cpp index d8b7d5ed..0bb82d23 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1553,59 +1553,66 @@ void* ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_f //----------------------------------------------------------------------------- // Convert UTF-8 to 32-bit character, process single character input. -// Based on work of Christopher Wellons (https://github.com/skeeto/branchless-utf8) +// Based on stb_from_utf8() from github.com/nothings/stb/ // We handle UTF-8 decoding error by skipping forward. int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end) { - static const char lengths[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0 }; - static const int masks[] = { 0x00, 0x7f, 0x1f, 0x0f, 0x07 }; - static const uint32_t mins[] = { 4194304, 0, 128, 2048, 65536 }; - static const int shiftc[] = { 0, 18, 12, 6, 0 }; - static const int shifte[] = { 0, 6, 4, 2, 0 }; - unsigned char s[4]; - int len = lengths[*(const unsigned char*)in_text >> 3]; - - if (in_text_end == NULL) - in_text_end = in_text + len + !len; // Max length, nulls will be taken into account. - - // Copy at most 'len' bytes, stop copying at 0 or past in_text_end. - s[0] = in_text + 0 < in_text_end ? in_text[0] : 0; - s[1] = s[0] && in_text + 1 < in_text_end ? in_text[1] : 0; - s[2] = s[1] && in_text + 2 < in_text_end ? in_text[2] : 0; - s[3] = s[2] && in_text + 3 < in_text_end ? in_text[3] : 0; - - // Compute the pointer to the next character early so that the next - // iteration can start working on the next character. Neither Clang - // nor GCC figure out this reordering on their own. - //const unsigned char *next = s + len + !len; - - // No bytes are consumed when *in_text == 0 || in_text == in_text_end. - // One byte is consumed in case of invalid first byte of in_text. - // All available bytes (at most `len` bytes) are consumed on incomplete/invalid second to last bytes. - int consumed = !!s[0] + !!s[1] + !!s[2] + !!s[3]; - - // Assume a four-byte character and load four bytes. Unused bits are shifted out. - *out_char = (uint32_t)(s[0] & masks[len]) << 18; - *out_char |= (uint32_t)(s[1] & 0x3f) << 12; - *out_char |= (uint32_t)(s[2] & 0x3f) << 6; - *out_char |= (uint32_t)(s[3] & 0x3f) << 0; - *out_char >>= shiftc[len]; - - // Accumulate the various error conditions. - int e = 0; - e = (*out_char < mins[len]) << 6; // non-canonical encoding - e |= ((*out_char >> 11) == 0x1b) << 7; // surrogate half? - e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8; // out of range? - e |= (s[1] & 0xc0) >> 2; - e |= (s[2] & 0xc0) >> 4; - e |= (s[3] ) >> 6; - e ^= 0x2a; // top two bits of each tail byte correct? - e >>= shifte[len]; - - if (e) - *out_char = IM_UNICODE_CODEPOINT_INVALID; - - return consumed; + unsigned int c = (unsigned int)-1; + const unsigned char* str = (const unsigned char*)in_text; + if (!(*str & 0x80)) + { + c = (unsigned int)(*str++); + *out_char = c; + return 1; + } + if ((*str & 0xe0) == 0xc0) + { + *out_char = IM_UNICODE_CODEPOINT_INVALID; // will be invalid but not end of string + if (in_text_end && in_text_end - (const char*)str < 2) return 1; + if (*str < 0xc2) return 2; + c = (unsigned int)((*str++ & 0x1f) << 6); + if ((*str & 0xc0) != 0x80) return 2; + c += (*str++ & 0x3f); + *out_char = c; + return 2; + } + if ((*str & 0xf0) == 0xe0) + { + *out_char = IM_UNICODE_CODEPOINT_INVALID; // will be invalid but not end of string + if (in_text_end && in_text_end - (const char*)str < 3) return 1; + if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3; + if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below + c = (unsigned int)((*str++ & 0x0f) << 12); + if ((*str & 0xc0) != 0x80) return 3; + c += (unsigned int)((*str++ & 0x3f) << 6); + if ((*str & 0xc0) != 0x80) return 3; + c += (*str++ & 0x3f); + *out_char = c; + return 3; + } + if ((*str & 0xf8) == 0xf0) + { + *out_char = IM_UNICODE_CODEPOINT_INVALID; // will be invalid but not end of string + if (in_text_end && in_text_end - (const char*)str < 4) return 1; + if (*str > 0xf4) return 4; + if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4; + if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below + c = (unsigned int)((*str++ & 0x07) << 18); + if ((*str & 0xc0) != 0x80) return 4; + c += (unsigned int)((*str++ & 0x3f) << 12); + if ((*str & 0xc0) != 0x80) return 4; + c += (unsigned int)((*str++ & 0x3f) << 6); + if ((*str & 0xc0) != 0x80) return 4; + c += (*str++ & 0x3f); + // utf-8 encodings of values used in surrogate pairs are invalid + if ((c & 0xFFFFF800) == 0xD800) return 4; + // If codepoint does not fit in ImWchar, use replacement character U+FFFD instead + if (c > IM_UNICODE_CODEPOINT_MAX) c = IM_UNICODE_CODEPOINT_INVALID; + *out_char = c; + return 4; + } + *out_char = 0; + return 0; } int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining) From df351573977af584d61a0a4437bcaef8db71bf6e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 26 Oct 2020 14:40:44 +0100 Subject: [PATCH 07/11] Drag and Drop: Fix losing drop source ActiveID (and often source tooltip) when opening a TreeNode() or CollapsingHeader() while dragging. (#1738) Amend 7b3d379, 8241cd62 etc. --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7c3f32c8..a18eb357 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,8 @@ Other Changes: - Tab Bar: Made it possible to append to an existing tab bar by calling BeginTabBar()/EndTabBar() again. - Tab Bar: Fixed using more than 128 tabs in a tab bar (scrolling policy recommended). - Tab Bar: Do not display a tooltip if the name already fits over a given tab. (#3521) +- Drag and Drop: Fix losing drop source ActiveID (and often source tooltip) when opening a TreeNode() + or CollapsingHeader() while dragging. (#1738) - Drag and Drop: Fix drag and drop to tie same-size drop targets by choosen the later one. Fixes dragging into a full-window-sized dockspace inside a zero-padded window. (#3519, #2717) [@Black-Cat] - Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) diff --git a/imgui.cpp b/imgui.cpp index 0bb82d23..af632a8e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9425,6 +9425,8 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) g.DragDropActive = true; g.DragDropSourceFlags = flags; g.DragDropMouseButton = mouse_button; + if (payload.SourceId == g.ActiveId) + g.ActiveIdNoClearOnFocusLoss = true; } g.DragDropSourceFrameCount = g.FrameCount; g.DragDropWithinSource = true; From 6f57d58e825e7c5c740b82acb636f17e49f76c7f Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Wed, 28 Oct 2020 11:35:27 +0200 Subject: [PATCH 08/11] Backends: OSX: Fix KeyPadEnter on MacOS. (#3554) --- backends/imgui_impl_osx.mm | 3 ++- docs/CHANGELOG.txt | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index bf643e29..fc347a40 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -18,6 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2020-10-28: Inputs: Added a fix for handling keypad-enter key. // 2020-05-25: Inputs: Added a fix for missing trackpad clicks when done with "soft tap". // 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor. // 2019-10-11: Inputs: Fix using Backspace key. @@ -72,7 +73,7 @@ bool ImGui_ImplOSX_Init() io.KeyMap[ImGuiKey_Space] = 32; io.KeyMap[ImGuiKey_Enter] = 13; io.KeyMap[ImGuiKey_Escape] = 27; - io.KeyMap[ImGuiKey_KeyPadEnter] = 13; + io.KeyMap[ImGuiKey_KeyPadEnter] = 3; io.KeyMap[ImGuiKey_A] = 'A'; io.KeyMap[ImGuiKey_C] = 'C'; io.KeyMap[ImGuiKey_V] = 'V'; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a18eb357..ce65396a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -61,9 +61,10 @@ Other Changes: or CollapsingHeader() while dragging. (#1738) - Drag and Drop: Fix drag and drop to tie same-size drop targets by choosen the later one. Fixes dragging into a full-window-sized dockspace inside a zero-padded window. (#3519, #2717) [@Black-Cat] -- Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) +- Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] - Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon] +- Backends: OSX: Fix keypad-enter key not working on MacOS. (#3554) [@rokups, @lfnoise] - Examples: Apple+Metal: Consolidated/simplified to get closer to other examples. (#3543) [@warrenm] - Docs: Split examples/README.txt into docs/BACKENDS.md and docs/EXAMPLES.md improved them. - Docs: Consistently renamed all occurences of "binding" and "back-end" to "backend" in comments and docs. @@ -98,7 +99,7 @@ Other Changes: - Window: Fixed using non-zero pivot in SetNextWindowPos() when the window is collapsed. (#3433) - Nav: Fixed navigation resuming on first visible item when using gamepad. [@rokups] - Nav: Fixed using Alt to toggle the Menu layer when inside a Modal window. (#787) -- Scrolling: Fixed SetScrollHere(0) functions edge snapping when called during a frame where +- Scrolling: Fixed SetScrollHere(0) functions edge snapping when called during a frame where ContentSize is changing (issue introduced in 1.78). (#3452). - InputText: Added support for Page Up/Down in InputTextMultiline(). (#3430) [@Xipiryon] - InputText: Added selection helpers in ImGuiInputTextCallbackData(). From a129621292a98454d8d636c2daca063f0fb3e3f3 Mon Sep 17 00:00:00 2001 From: "M. Frink ~ Lemur" Date: Thu, 29 Oct 2020 12:21:06 -0500 Subject: [PATCH 09/11] Doc: mention IMGUI_USE_WCHAR32 in fonts documentation (#3562) --- docs/FONTS.md | 1 + imconfig.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/FONTS.md b/docs/FONTS.md index 87e6ee04..96573402 100644 --- a/docs/FONTS.md +++ b/docs/FONTS.md @@ -157,6 +157,7 @@ Some solutions: 3. Set `io.Fonts.TexDesiredWidth` to specify a texture width to minimize texture height (see comment in `ImFontAtlas::Build()` function). 4. Set `io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;` to disable rounding the texture height to the next power of two. 5. Read about oversampling [here](https://github.com/nothings/stb/blob/master/tests/oversample). +6. To support the extended range of unicode beyond 0xFFFF (e.g. emoticons, dingbats, symbols, shapes, ancient languages, etc...) add `#define IMGUI_USE_WCHAR32`in your `imconfig.h` ##### [Return to Index](#index) diff --git a/imconfig.h b/imconfig.h index 280d1436..015540f3 100644 --- a/imconfig.h +++ b/imconfig.h @@ -49,7 +49,7 @@ //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) //#define IMGUI_USE_BGRA_PACKED_COLOR -//---- Use 32-bit for ImWchar (default is 16-bit) to support full unicode code points. +//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) //#define IMGUI_USE_WCHAR32 //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version From 044ed22379a068498482c7f0d76f9952908d5cc5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 30 Oct 2020 22:40:44 +0100 Subject: [PATCH 10/11] Metrics: Fixed mishandling of ImDrawCmd::VtxOffset in wireframe mesh renderer + omitting trailing empty ImDrawCmd in count + relying on IdxOffset value. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 49 +++++++++++++++++++++++----------------------- imgui_widgets.cpp | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ce65396a..5118fece 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -61,6 +61,7 @@ Other Changes: or CollapsingHeader() while dragging. (#1738) - Drag and Drop: Fix drag and drop to tie same-size drop targets by choosen the later one. Fixes dragging into a full-window-sized dockspace inside a zero-padded window. (#3519, #2717) [@Black-Cat] +- Metrics: Fixed mishandling of ImDrawCmd::VtxOffset in wireframe mesh renderer. - Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] - Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon] diff --git a/imgui.cpp b/imgui.cpp index af632a8e..a8599afb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -76,7 +76,7 @@ CODE // [SECTION] LOGGING/CAPTURING // [SECTION] SETTINGS // [SECTION] PLATFORM DEPENDENT HELPERS -// [SECTION] METRICS/DEBUG WINDOW +// [SECTION] METRICS/DEBUGGER WINDOW */ @@ -10328,10 +10328,11 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {} #endif //----------------------------------------------------------------------------- -// [SECTION] METRICS/DEBUG WINDOW +// [SECTION] METRICS/DEBUGGER WINDOW //----------------------------------------------------------------------------- #ifndef IMGUI_DISABLE_METRICS_WINDOW + // Avoid naming collision with imgui_demo.cpp's HelpMarker() for unity builds. static void MetricsHelpMarker(const char* desc) { @@ -10401,26 +10402,23 @@ void ImGui::ShowMetricsWindow(bool* p_open) return ImRect(); } - static void NodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow* window, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, int elem_offset, bool show_mesh, bool show_aabb) + static void NodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow* window, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb) { IM_ASSERT(show_mesh || show_aabb); ImDrawList* fg_draw_list = GetForegroundDrawList(window); // Render additional visuals into the top-most draw list ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; + ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset; // Draw wire-frame version of all triangles ImRect clip_rect = draw_cmd->ClipRect; ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); ImDrawListFlags backup_flags = fg_draw_list->Flags; fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles. - for (unsigned int base_idx = elem_offset; base_idx < (elem_offset + draw_cmd->ElemCount); base_idx += 3) + for (unsigned int idx_n = draw_cmd->IdxOffset; idx_n < draw_cmd->IdxOffset + draw_cmd->ElemCount; ) { ImVec2 triangle[3]; - for (int n = 0; n < 3; n++) - { - ImVec2 p = draw_list->VtxBuffer[idx_buffer ? idx_buffer[base_idx + n] : (base_idx + n)].pos; - triangle[n] = p; - vtxs_rect.Add(p); - } + for (int n = 0; n < 3; n++, idx_n++) + vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos)); if (show_mesh) fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), true, 1.0f); // In yellow: mesh triangles } @@ -10435,7 +10433,10 @@ void ImGui::ShowMetricsWindow(bool* p_open) static void NodeDrawList(ImGuiWindow* window, ImDrawList* draw_list, const char* label) { - bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size); + int cmd_count = draw_list->CmdBuffer.Size; + if (cmd_count > 0 && draw_list->CmdBuffer.back().ElemCount == 0 && draw_list->CmdBuffer.back().UserCallback == NULL) + cmd_count--; + bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, cmd_count); if (draw_list == ImGui::GetWindowDrawList()) { ImGui::SameLine(); @@ -10453,36 +10454,34 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (window && !window->WasActive) ImGui::TextDisabled("Warning: owning Window is inactive. This DrawList is not being rendered!"); - unsigned int elem_offset = 0; - for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++) + for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.Data; pcmd < draw_list->CmdBuffer.Data + cmd_count; pcmd++) { - if (pcmd->UserCallback == NULL && pcmd->ElemCount == 0) - continue; if (pcmd->UserCallback) { ImGui::BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData); continue; } - ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; char buf[300]; - ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d triangles, Tex 0x%p, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", + ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d tris, Tex 0x%p, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", pcmd->ElemCount / 3, (void*)(intptr_t)pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf); if (ImGui::IsItemHovered() && (show_drawcmd_mesh || show_drawcmd_aabb) && fg_draw_list) - NodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, elem_offset, show_drawcmd_mesh, show_drawcmd_aabb); + NodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, show_drawcmd_mesh, show_drawcmd_aabb); if (!pcmd_node_open) continue; // Calculate approximate coverage area (touched pixel count) // This will be in pixels squared as long there's no post-scaling happening to the renderer output. + const ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; + const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + pcmd->VtxOffset; float total_area = 0.0f; - for (unsigned int base_idx = elem_offset; base_idx < (elem_offset + pcmd->ElemCount); base_idx += 3) + for (unsigned int idx_n = pcmd->IdxOffset; idx_n < pcmd->IdxOffset + pcmd->ElemCount; ) { ImVec2 triangle[3]; - for (int n = 0; n < 3; n++) - triangle[n] = draw_list->VtxBuffer[idx_buffer ? idx_buffer[base_idx + n] : (base_idx + n)].pos; + for (int n = 0; n < 3; n++, idx_n++) + triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos; total_area += ImTriangleArea(triangle[0], triangle[1], triangle[2]); } @@ -10490,19 +10489,19 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImFormatString(buf, IM_ARRAYSIZE(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area); ImGui::Selectable(buf); if (ImGui::IsItemHovered() && fg_draw_list) - NodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, elem_offset, true, false); + NodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, true, false); // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. ImGuiListClipper clipper; clipper.Begin(pcmd->ElemCount / 3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. while (clipper.Step()) - for (int prim = clipper.DisplayStart, idx_i = elem_offset + clipper.DisplayStart * 3; prim < clipper.DisplayEnd; prim++) + for (int prim = clipper.DisplayStart, idx_i = pcmd->IdxOffset + clipper.DisplayStart * 3; prim < clipper.DisplayEnd; prim++) { char* buf_p = buf, *buf_end = buf + IM_ARRAYSIZE(buf); ImVec2 triangle[3]; for (int n = 0; n < 3; n++, idx_i++) { - ImDrawVert& v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[idx_i] : idx_i]; + const ImDrawVert& v = vtx_buffer[idx_buffer ? idx_buffer[idx_i] : idx_i]; triangle[n] = v.pos; buf_p += ImFormatString(buf_p, buf_end - buf_p, "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n", (n == 0) ? "Vert:" : " ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); @@ -10774,7 +10773,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (ImGui::TreeNode("SettingsIniData", "Settings unpacked data (.ini): %d bytes", g.SettingsIniData.size())) { - ImGui::InputTextMultiline("##Ini", (char*)(void*)g.SettingsIniData.c_str(), g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, 0.0f), ImGuiInputTextFlags_ReadOnly); + ImGui::InputTextMultiline("##Ini", (char*)(void*)g.SettingsIniData.c_str(), g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 20), ImGuiInputTextFlags_ReadOnly); ImGui::TreePop(); } ImGui::TreePop(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index fe892451..9b440878 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6539,7 +6539,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) // If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin(). // We are relying on a O(N) search - so O(N log N) over the frame - which seems like the most efficient for the expected small amount of BeginMenu() calls per frame. - // If somehow this is ever becoming a problem we can switch to use e.g. a ImGuiStorager mapping key to last frame used. + // If somehow this is ever becoming a problem we can switch to use e.g. ImGuiStorage mapping key to last frame used. if (g.MenusIdSubmittedThisFrame.contains(id)) { if (menu_is_open) From 047d4c4500fc08b64d800eceae9951fc01c0a78b Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 30 Oct 2020 23:02:54 +0100 Subject: [PATCH 11/11] Metrics: Extracted most functions. + avoid using full namesapce prefix --- imgui.cpp | 747 ++++++++++++++++++++++++----------------------- imgui_internal.h | 33 +++ 2 files changed, 415 insertions(+), 365 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a8599afb..0effb3b4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10330,6 +10330,17 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {} //----------------------------------------------------------------------------- // [SECTION] METRICS/DEBUGGER WINDOW //----------------------------------------------------------------------------- +// - MetricsHelpMarker() [Internal] +// - ShowMetricsWindow() +// - DebugNodeColumns() [Internal] +// - DebugNodeDrawList() [Internal] +// - DebugNodeDrawCmdShowMeshAndBoundingBox() [Internal] +// - DebugNodeStorage() [Internal] +// - DebugNodeTabBar() [Internal] +// - DebugNodeWindow() [Internal] +// - DebugNodeWindowSettings() [Internal] +// - DebugNodeWindowsList() [Internal] +//----------------------------------------------------------------------------- #ifndef IMGUI_DISABLE_METRICS_WINDOW @@ -10349,30 +10360,17 @@ static void MetricsHelpMarker(const char* desc) void ImGui::ShowMetricsWindow(bool* p_open) { - if (!ImGui::Begin("Dear ImGui Metrics", p_open)) + if (!Begin("Dear ImGui Metrics", p_open)) { - ImGui::End(); + End(); return; } - // Debugging enums - enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentRegionRect, WRT_Count }; // Windows Rect Type - const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Content", "ContentRegionRect" }; - enum { TRT_OuterRect, TRT_WorkRect, TRT_HostClipRect, TRT_InnerClipRect, TRT_BackgroundClipRect, TRT_ColumnsRect, TRT_ColumnsClipRect, TRT_ColumnsContentHeadersUsed, TRT_ColumnsContentHeadersIdeal, TRT_ColumnsContentRowsFrozen, TRT_ColumnsContentRowsUnfrozen, TRT_Count }; // Tables Rect Type - const char* trt_rects_names[TRT_Count] = { "OuterRect", "WorkRect", "HostClipRect", "InnerClipRect", "BackgroundClipRect", "ColumnsRect", "ColumnsClipRect", "ColumnsContentHeadersUsed", "ColumnsContentHeadersIdeal", "ColumnsContentRowsFrozen", "ColumnsContentRowsUnfrozen" }; - - // State - static bool show_windows_rects = false; - static int show_windows_rect_type = WRT_WorkRect; - static bool show_windows_begin_order = false; - static bool show_tables_rects = false; - static int show_tables_rect_type = TRT_WorkRect; - static bool show_drawcmd_mesh = true; - static bool show_drawcmd_aabb = true; + ImGuiContext& g = *GImGui; + ImGuiIO& io = g.IO; + ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig; // Basic info - ImGuiContext& g = *GImGui; - ImGuiIO& io = ImGui::GetIO(); ImGui::Text("Dear ImGui %s", ImGui::GetVersion()); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); ImGui::Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3); @@ -10380,13 +10378,16 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("%d active allocations", io.MetricsActiveAllocations); ImGui::Separator(); - // Helper functions to display common structures: - // - NodeDrawList() - // - NodeColumns() - // - NodeWindow() - // - NodeWindows() - // - NodeTabBar() - // - NodeStorage() + // Debugging enums + enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentRegionRect, WRT_Count }; // Windows Rect Type + const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Content", "ContentRegionRect" }; + enum { TRT_OuterRect, TRT_WorkRect, TRT_HostClipRect, TRT_InnerClipRect, TRT_BackgroundClipRect, TRT_ColumnsRect, TRT_ColumnsClipRect, TRT_ColumnsContentHeadersUsed, TRT_ColumnsContentHeadersIdeal, TRT_ColumnsContentRowsFrozen, TRT_ColumnsContentRowsUnfrozen, TRT_Count }; // Tables Rect Type + const char* trt_rects_names[TRT_Count] = { "OuterRect", "WorkRect", "HostClipRect", "InnerClipRect", "BackgroundClipRect", "ColumnsRect", "ColumnsClipRect", "ColumnsContentHeadersUsed", "ColumnsContentHeadersIdeal", "ColumnsContentRowsFrozen", "ColumnsContentRowsUnfrozen" }; + if (cfg->ShowWindowsRectsType < 0) + cfg->ShowWindowsRectsType = WRT_WorkRect; + if (cfg->ShowTablesRectsType < 0) + cfg->ShowWindowsRectsType = TRT_WorkRect; + struct Funcs { static ImRect GetWindowRect(ImGuiWindow* window, int rect_type) @@ -10401,422 +10402,174 @@ void ImGui::ShowMetricsWindow(bool* p_open) IM_ASSERT(0); return ImRect(); } - - static void NodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow* window, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb) - { - IM_ASSERT(show_mesh || show_aabb); - ImDrawList* fg_draw_list = GetForegroundDrawList(window); // Render additional visuals into the top-most draw list - ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; - ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset; - - // Draw wire-frame version of all triangles - ImRect clip_rect = draw_cmd->ClipRect; - ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); - ImDrawListFlags backup_flags = fg_draw_list->Flags; - fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles. - for (unsigned int idx_n = draw_cmd->IdxOffset; idx_n < draw_cmd->IdxOffset + draw_cmd->ElemCount; ) - { - ImVec2 triangle[3]; - for (int n = 0; n < 3; n++, idx_n++) - vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos)); - if (show_mesh) - fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), true, 1.0f); // In yellow: mesh triangles - } - // Draw bounding boxes - if (show_aabb) - { - fg_draw_list->AddRect(ImFloor(clip_rect.Min), ImFloor(clip_rect.Max), IM_COL32(255, 0, 255, 255)); // In pink: clipping rectangle submitted to GPU - fg_draw_list->AddRect(ImFloor(vtxs_rect.Min), ImFloor(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)); // In cyan: bounding box of triangles - } - fg_draw_list->Flags = backup_flags; - } - - static void NodeDrawList(ImGuiWindow* window, ImDrawList* draw_list, const char* label) - { - int cmd_count = draw_list->CmdBuffer.Size; - if (cmd_count > 0 && draw_list->CmdBuffer.back().ElemCount == 0 && draw_list->CmdBuffer.back().UserCallback == NULL) - cmd_count--; - bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, cmd_count); - if (draw_list == ImGui::GetWindowDrawList()) - { - ImGui::SameLine(); - ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered) - if (node_open) ImGui::TreePop(); - return; - } - - ImDrawList* fg_draw_list = GetForegroundDrawList(window); // Render additional visuals into the top-most draw list - if (window && IsItemHovered()) - fg_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); - if (!node_open) - return; - - if (window && !window->WasActive) - ImGui::TextDisabled("Warning: owning Window is inactive. This DrawList is not being rendered!"); - - for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.Data; pcmd < draw_list->CmdBuffer.Data + cmd_count; pcmd++) - { - if (pcmd->UserCallback) - { - ImGui::BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData); - continue; - } - - char buf[300]; - ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d tris, Tex 0x%p, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", - pcmd->ElemCount / 3, (void*)(intptr_t)pcmd->TextureId, - pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); - bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf); - if (ImGui::IsItemHovered() && (show_drawcmd_mesh || show_drawcmd_aabb) && fg_draw_list) - NodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, show_drawcmd_mesh, show_drawcmd_aabb); - if (!pcmd_node_open) - continue; - - // Calculate approximate coverage area (touched pixel count) - // This will be in pixels squared as long there's no post-scaling happening to the renderer output. - const ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; - const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + pcmd->VtxOffset; - float total_area = 0.0f; - for (unsigned int idx_n = pcmd->IdxOffset; idx_n < pcmd->IdxOffset + pcmd->ElemCount; ) - { - ImVec2 triangle[3]; - for (int n = 0; n < 3; n++, idx_n++) - triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos; - total_area += ImTriangleArea(triangle[0], triangle[1], triangle[2]); - } - - // Display vertex information summary. Hover to get all triangles drawn in wire-frame - ImFormatString(buf, IM_ARRAYSIZE(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area); - ImGui::Selectable(buf); - if (ImGui::IsItemHovered() && fg_draw_list) - NodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, true, false); - - // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. - ImGuiListClipper clipper; - clipper.Begin(pcmd->ElemCount / 3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. - while (clipper.Step()) - for (int prim = clipper.DisplayStart, idx_i = pcmd->IdxOffset + clipper.DisplayStart * 3; prim < clipper.DisplayEnd; prim++) - { - char* buf_p = buf, *buf_end = buf + IM_ARRAYSIZE(buf); - ImVec2 triangle[3]; - for (int n = 0; n < 3; n++, idx_i++) - { - const ImDrawVert& v = vtx_buffer[idx_buffer ? idx_buffer[idx_i] : idx_i]; - triangle[n] = v.pos; - buf_p += ImFormatString(buf_p, buf_end - buf_p, "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n", - (n == 0) ? "Vert:" : " ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); - } - - ImGui::Selectable(buf, false); - if (fg_draw_list && ImGui::IsItemHovered()) - { - ImDrawListFlags backup_flags = fg_draw_list->Flags; - fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles. - fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255,255,0,255), true, 1.0f); - fg_draw_list->Flags = backup_flags; - } - } - ImGui::TreePop(); - } - ImGui::TreePop(); - } - - static void NodeColumns(const ImGuiColumns* columns) - { - if (!ImGui::TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags)) - return; - ImGui::BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX, columns->OffMaxX); - for (int column_n = 0; column_n < columns->Columns.Size; column_n++) - ImGui::BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, GetColumnOffsetFromNorm(columns, columns->Columns[column_n].OffsetNorm)); - ImGui::TreePop(); - } - - static void NodeWindows(ImVector& windows, const char* label) - { - if (!ImGui::TreeNode(label, "%s (%d)", label, windows.Size)) - return; - ImGui::Text("(In front-to-back order:)"); - for (int i = windows.Size - 1; i >= 0; i--) // Iterate front to back - { - ImGui::PushID(windows[i]); - Funcs::NodeWindow(windows[i], "Window"); - ImGui::PopID(); - } - ImGui::TreePop(); - } - - static void NodeWindow(ImGuiWindow* window, const char* label) - { - if (window == NULL) - { - ImGui::BulletText("%s: NULL", label); - return; - } - - ImGuiContext& g = *GImGui; - const bool is_active = window->WasActive; - ImGuiTreeNodeFlags tree_node_flags = (window == g.NavWindow) ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None; - if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } - const bool open = ImGui::TreeNodeEx(label, tree_node_flags, "%s '%s'%s", label, window->Name, is_active ? "" : " *Inactive*"); - if (!is_active) { PopStyleColor(); } - if (ImGui::IsItemHovered() && is_active) - ImGui::GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); - if (!open) - return; - - if (window->MemoryCompacted) - ImGui::TextDisabled("Note: some memory buffers have been compacted/freed."); - - ImGuiWindowFlags flags = window->Flags; - NodeDrawList(window, window->DrawList, "DrawList"); - ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), ContentSize (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->ContentSize.x, window->ContentSize.y); - ImGui::BulletText("Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags, - (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "", - (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "", - (flags & ImGuiWindowFlags_NoMouseInputs)? "NoMouseInputs":"", (flags & ImGuiWindowFlags_NoNavInputs) ? "NoNavInputs" : "", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : ""); - ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f) Scrollbar:%s%s", window->Scroll.x, window->ScrollMax.x, window->Scroll.y, window->ScrollMax.y, window->ScrollbarX ? "X" : "", window->ScrollbarY ? "Y" : ""); - ImGui::BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1); - ImGui::BulletText("Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems); - ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); - ImGui::BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL"); - if (!window->NavRectRel[0].IsInverted()) - ImGui::BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y); - else - ImGui::BulletText("NavRectRel[0]: "); - if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); - if (window->ParentWindow != NULL) NodeWindow(window->ParentWindow, "ParentWindow"); - if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); - if (window->ColumnsStorage.Size > 0 && ImGui::TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size)) - { - for (int n = 0; n < window->ColumnsStorage.Size; n++) - NodeColumns(&window->ColumnsStorage[n]); - ImGui::TreePop(); - } - NodeStorage(&window->StateStorage, "Storage"); - ImGui::TreePop(); - } - - static void NodeWindowSettings(ImGuiWindowSettings* settings) - { - ImGui::Text("0x%08X \"%s\" Pos (%d,%d) Size (%d,%d) Collapsed=%d", - settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed); - } - - static void NodeTabBar(ImGuiTabBar* tab_bar) - { - // Standalone tab bars (not associated to docking/windows functionality) currently hold no discernible strings. - char buf[256]; - char* p = buf; - const char* buf_end = buf + IM_ARRAYSIZE(buf); - const bool is_active = (tab_bar->PrevFrameVisible >= ImGui::GetFrameCount() - 2); - p += ImFormatString(p, buf_end - p, "Tab Bar 0x%08X (%d tabs)%s", tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*"); - IM_UNUSED(p); - if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } - bool open = ImGui::TreeNode(tab_bar, "%s", buf); - if (!is_active) { PopStyleColor(); } - if (is_active && ImGui::IsItemHovered()) - { - ImDrawList* draw_list = ImGui::GetForegroundDrawList(); - draw_list->AddRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, IM_COL32(255, 255, 0, 255)); - draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255)); - draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255)); - } - if (open) - { - for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) - { - const ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; - ImGui::PushID(tab); - if (ImGui::SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } ImGui::SameLine(0, 2); - if (ImGui::SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } ImGui::SameLine(); - ImGui::Text("%02d%c Tab 0x%08X '%s' Offset: %.1f, Width: %.1f/%.1f", tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "", tab->Offset, tab->Width, tab->ContentWidth); - ImGui::PopID(); - } - ImGui::TreePop(); - } - } - - static void NodeStorage(ImGuiStorage* storage, const char* label) - { - if (!ImGui::TreeNode(label, "%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes())) - return; - for (int n = 0; n < storage->Data.Size; n++) - { - const ImGuiStorage::ImGuiStoragePair& p = storage->Data[n]; - ImGui::BulletText("Key 0x%08X Value { i: %d }", p.key, p.val_i); // Important: we currently don't store a type, real value may not be integer. - } - ImGui::TreePop(); - } }; // Tools - if (ImGui::TreeNode("Tools")) + if (TreeNode("Tools")) { // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. - if (ImGui::Button("Item Picker..")) - ImGui::DebugStartItemPicker(); - ImGui::SameLine(); + if (Button("Item Picker..")) + DebugStartItemPicker(); + SameLine(); MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash."); - ImGui::Checkbox("Show windows begin order", &show_windows_begin_order); - ImGui::Checkbox("Show windows rectangles", &show_windows_rects); - ImGui::SameLine(); - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12); - show_windows_rects |= ImGui::Combo("##show_windows_rect_type", &show_windows_rect_type, wrt_rects_names, WRT_Count, WRT_Count); - if (show_windows_rects && g.NavWindow) + Checkbox("Show windows begin order", &cfg->ShowWindowsBeginOrder); + ImGui::Checkbox("Show windows rectangles", &cfg->ShowWindowsRects); + SameLine(); + SetNextItemWidth(GetFontSize() * 12); + cfg->ShowWindowsRects |= Combo("##show_windows_rect_type", &cfg->ShowWindowsRectsType, wrt_rects_names, WRT_Count, WRT_Count); + if (cfg->ShowWindowsRects && g.NavWindow != NULL) { - ImGui::BulletText("'%s':", g.NavWindow->Name); - ImGui::Indent(); + BulletText("'%s':", g.NavWindow->Name); + Indent(); for (int rect_n = 0; rect_n < WRT_Count; rect_n++) { ImRect r = Funcs::GetWindowRect(g.NavWindow, rect_n); - ImGui::Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), wrt_rects_names[rect_n]); + Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), wrt_rects_names[rect_n]); } - ImGui::Unindent(); + Unindent(); } - ImGui::Checkbox("Show mesh when hovering ImDrawCmd", &show_drawcmd_mesh); - ImGui::Checkbox("Show bounding boxes when hovering ImDrawCmd", &show_drawcmd_aabb); - ImGui::TreePop(); + Checkbox("Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh); + Checkbox("Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes); + TreePop(); } // Contents - Funcs::NodeWindows(g.Windows, "Windows"); - //Funcs::NodeWindows(g.WindowsFocusOrder, "WindowsFocusOrder"); - if (ImGui::TreeNode("DrawLists", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size)) + DebugNodeWindowsList(&g.Windows, "Windows"); + //DebugNodeWindowList(&g.WindowsFocusOrder, "WindowsFocusOrder"); + if (TreeNode("DrawLists", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size)) { for (int i = 0; i < g.DrawDataBuilder.Layers[0].Size; i++) - Funcs::NodeDrawList(NULL, g.DrawDataBuilder.Layers[0][i], "DrawList"); - ImGui::TreePop(); + DebugNodeDrawList(NULL, g.DrawDataBuilder.Layers[0][i], "DrawList"); + TreePop(); } // Details for Popups - if (ImGui::TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size)) + if (TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size)) { for (int i = 0; i < g.OpenPopupStack.Size; i++) { ImGuiWindow* window = g.OpenPopupStack[i].Window; - ImGui::BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : ""); + BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : ""); } - ImGui::TreePop(); + TreePop(); } // Details for TabBars - if (ImGui::TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.GetSize())) + if (TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.GetSize())) { for (int n = 0; n < g.TabBars.GetSize(); n++) - Funcs::NodeTabBar(g.TabBars.GetByIndex(n)); - ImGui::TreePop(); + DebugNodeTabBar(g.TabBars.GetByIndex(n), "TabBar"); + TreePop(); } // Details for Tables IM_UNUSED(trt_rects_names); - IM_UNUSED(show_tables_rects); - IM_UNUSED(show_tables_rect_type); #ifdef IMGUI_HAS_TABLE - if (ImGui::TreeNode("Tables", "Tables (%d)", g.Tables.GetSize())) + if (TreeNode("Tables", "Tables (%d)", g.Tables.GetSize())) { for (int n = 0; n < g.Tables.GetSize(); n++) - Funcs::NodeTable(g.Tables.GetByIndex(n)); - ImGui::TreePop(); + DebugNodeTable(g.Tables.GetByIndex(n)); + TreePop(); } #endif // #ifdef IMGUI_HAS_TABLE // Details for Docking #ifdef IMGUI_HAS_DOCK - if (ImGui::TreeNode("Dock nodes")) + if (TreeNode("Docking")) { - ImGui::TreePop(); + TreePop(); } #endif // #ifdef IMGUI_HAS_DOCK // Settings - if (ImGui::TreeNode("Settings")) + if (TreeNode("Settings")) { - if (ImGui::SmallButton("Clear")) - ImGui::ClearIniSettings(); - ImGui::SameLine(); - if (ImGui::SmallButton("Save to memory")) - ImGui::SaveIniSettingsToMemory(); - ImGui::SameLine(); - if (ImGui::SmallButton("Save to disk")) - ImGui::SaveIniSettingsToDisk(g.IO.IniFilename); - ImGui::SameLine(); + if (SmallButton("Clear")) + ClearIniSettings(); + SameLine(); + if (SmallButton("Save to memory")) + SaveIniSettingsToMemory(); + SameLine(); + if (SmallButton("Save to disk")) + SaveIniSettingsToDisk(g.IO.IniFilename); + SameLine(); if (g.IO.IniFilename) - ImGui::Text("\"%s\"", g.IO.IniFilename); + Text("\"%s\"", g.IO.IniFilename); else - ImGui::TextUnformatted(""); - ImGui::Text("SettingsDirtyTimer %.2f", g.SettingsDirtyTimer); - if (ImGui::TreeNode("SettingsHandlers", "Settings handlers: (%d)", g.SettingsHandlers.Size)) + TextUnformatted(""); + Text("SettingsDirtyTimer %.2f", g.SettingsDirtyTimer); + if (TreeNode("SettingsHandlers", "Settings handlers: (%d)", g.SettingsHandlers.Size)) { for (int n = 0; n < g.SettingsHandlers.Size; n++) - ImGui::BulletText("%s", g.SettingsHandlers[n].TypeName); - ImGui::TreePop(); + BulletText("%s", g.SettingsHandlers[n].TypeName); + TreePop(); } - if (ImGui::TreeNode("SettingsWindows", "Settings packed data: Windows: %d bytes", g.SettingsWindows.size())) + if (TreeNode("SettingsWindows", "Settings packed data: Windows: %d bytes", g.SettingsWindows.size())) { for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) - Funcs::NodeWindowSettings(settings); - ImGui::TreePop(); + DebugNodeWindowSettings(settings); + TreePop(); } #ifdef IMGUI_HAS_TABLE - if (ImGui::TreeNode("SettingsTables", "Settings packed data: Tables: %d bytes", g.SettingsTables.size())) + if (TreeNode("SettingsTables", "Settings packed data: Tables: %d bytes", g.SettingsTables.size())) { for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) - Funcs::NodeTableSettings(settings); - ImGui::TreePop(); + DebugNodeTableSettings(settings); + TreePop(); } #endif // #ifdef IMGUI_HAS_TABLE #ifdef IMGUI_HAS_DOCK #endif // #ifdef IMGUI_HAS_DOCK - if (ImGui::TreeNode("SettingsIniData", "Settings unpacked data (.ini): %d bytes", g.SettingsIniData.size())) + if (TreeNode("SettingsIniData", "Settings unpacked data (.ini): %d bytes", g.SettingsIniData.size())) { - ImGui::InputTextMultiline("##Ini", (char*)(void*)g.SettingsIniData.c_str(), g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 20), ImGuiInputTextFlags_ReadOnly); - ImGui::TreePop(); + InputTextMultiline("##Ini", (char*)(void*)g.SettingsIniData.c_str(), g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, GetTextLineHeight() * 20), ImGuiInputTextFlags_ReadOnly); + TreePop(); } - ImGui::TreePop(); + TreePop(); } // Misc Details - if (ImGui::TreeNode("Internal state")) + if (TreeNode("Internal state")) { const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); - ImGui::Text("WINDOWING"); - ImGui::Indent(); - ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); - ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); - ImGui::Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name : "NULL"); - ImGui::Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL"); - ImGui::Unindent(); + Text("WINDOWING"); + Indent(); + Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); + Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); + Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name : "NULL"); + Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL"); + Unindent(); - ImGui::Text("ITEMS"); - ImGui::Indent(); - ImGui::Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]); - ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); - ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not - ImGui::Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); - ImGui::Unindent(); + Text("ITEMS"); + Indent(); + Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]); + Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); + Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not + Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); + Unindent(); - ImGui::Text("NAV,FOCUS"); - ImGui::Indent(); - ImGui::Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); - ImGui::Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer); - ImGui::Text("NavInputSource: %s", input_source_names[g.NavInputSource]); - ImGui::Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); - ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId); - ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); - ImGui::Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId); - ImGui::Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name : "NULL"); - ImGui::Unindent(); + Text("NAV,FOCUS"); + Indent(); + Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); + Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer); + Text("NavInputSource: %s", input_source_names[g.NavInputSource]); + Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); + Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId); + Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); + Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId); + Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name : "NULL"); + Unindent(); - ImGui::TreePop(); + TreePop(); } // Overlay: Display windows Rectangles and Begin Order - if (show_windows_rects || show_windows_begin_order) + if (cfg->ShowWindowsRects || cfg->ShowWindowsBeginOrder) { for (int n = 0; n < g.Windows.Size; n++) { @@ -10824,16 +10577,16 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (!window->WasActive) continue; ImDrawList* draw_list = GetForegroundDrawList(window); - if (show_windows_rects) + if (cfg->ShowWindowsRects) { - ImRect r = Funcs::GetWindowRect(window, show_windows_rect_type); + ImRect r = Funcs::GetWindowRect(window, cfg->ShowWindowsRectsType); draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255)); } - if (show_windows_begin_order && !(window->Flags & ImGuiWindowFlags_ChildWindow)) + if (cfg->ShowWindowsBeginOrder && !(window->Flags & ImGuiWindowFlags_ChildWindow)) { char buf[32]; ImFormatString(buf, IM_ARRAYSIZE(buf), "%d", window->BeginOrderWithinContext); - float font_size = ImGui::GetFontSize(); + float font_size = GetFontSize(); draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255)); draw_list->AddText(window->Pos, IM_COL32(255, 255, 255, 255), buf); } @@ -10861,9 +10614,273 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::End(); } +// [DEBUG] Display contents of Columns +void ImGui::DebugNodeColumns(ImGuiColumns* columns) +{ + if (!TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags)) + return; + BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX, columns->OffMaxX); + for (int column_n = 0; column_n < columns->Columns.Size; column_n++) + BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, GetColumnOffsetFromNorm(columns, columns->Columns[column_n].OffsetNorm)); + TreePop(); +} + +// [DEBUG] Display contents of ImDrawList +void ImGui::DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label) +{ + ImGuiContext& g = *GImGui; + ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig; + int cmd_count = draw_list->CmdBuffer.Size; + if (cmd_count > 0 && draw_list->CmdBuffer.back().ElemCount == 0 && draw_list->CmdBuffer.back().UserCallback == NULL) + cmd_count--; + bool node_open = TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, cmd_count); + if (draw_list == GetWindowDrawList()) + { + SameLine(); + TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered) + if (node_open) + TreePop(); + return; + } + + ImDrawList* fg_draw_list = GetForegroundDrawList(window); // Render additional visuals into the top-most draw list + if (window && IsItemHovered()) + fg_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); + if (!node_open) + return; + + if (window && !window->WasActive) + TextDisabled("Warning: owning Window is inactive. This DrawList is not being rendered!"); + + for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.Data; pcmd < draw_list->CmdBuffer.Data + cmd_count; pcmd++) + { + if (pcmd->UserCallback) + { + BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData); + continue; + } + + char buf[300]; + ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d tris, Tex 0x%p, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", + pcmd->ElemCount / 3, (void*)(intptr_t)pcmd->TextureId, + pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); + bool pcmd_node_open = TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf); + if (IsItemHovered() && (cfg->ShowDrawCmdMesh || cfg->ShowDrawCmdBoundingBoxes) && fg_draw_list) + DebugNodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, cfg->ShowDrawCmdMesh, cfg->ShowDrawCmdBoundingBoxes); + if (!pcmd_node_open) + continue; + + // Calculate approximate coverage area (touched pixel count) + // This will be in pixels squared as long there's no post-scaling happening to the renderer output. + const ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; + const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + pcmd->VtxOffset; + float total_area = 0.0f; + for (unsigned int idx_n = pcmd->IdxOffset; idx_n < pcmd->IdxOffset + pcmd->ElemCount; ) + { + ImVec2 triangle[3]; + for (int n = 0; n < 3; n++, idx_n++) + triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos; + total_area += ImTriangleArea(triangle[0], triangle[1], triangle[2]); + } + + // Display vertex information summary. Hover to get all triangles drawn in wire-frame + ImFormatString(buf, IM_ARRAYSIZE(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area); + Selectable(buf); + if (IsItemHovered() && fg_draw_list) + DebugNodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, true, false); + + // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. + ImGuiListClipper clipper; + clipper.Begin(pcmd->ElemCount / 3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. + while (clipper.Step()) + for (int prim = clipper.DisplayStart, idx_i = pcmd->IdxOffset + clipper.DisplayStart * 3; prim < clipper.DisplayEnd; prim++) + { + char* buf_p = buf, * buf_end = buf + IM_ARRAYSIZE(buf); + ImVec2 triangle[3]; + for (int n = 0; n < 3; n++, idx_i++) + { + const ImDrawVert& v = vtx_buffer[idx_buffer ? idx_buffer[idx_i] : idx_i]; + triangle[n] = v.pos; + buf_p += ImFormatString(buf_p, buf_end - buf_p, "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n", + (n == 0) ? "Vert:" : " ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); + } + + Selectable(buf, false); + if (fg_draw_list && IsItemHovered()) + { + ImDrawListFlags backup_flags = fg_draw_list->Flags; + fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles. + fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), true, 1.0f); + fg_draw_list->Flags = backup_flags; + } + } + TreePop(); + } + TreePop(); +} + +// [DEBUG] Display mesh/aabb of a ImDrawCmd +void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow* window, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb) +{ + IM_ASSERT(show_mesh || show_aabb); + ImDrawList* fg_draw_list = GetForegroundDrawList(window); // Render additional visuals into the top-most draw list + ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; + ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset; + + // Draw wire-frame version of all triangles + ImRect clip_rect = draw_cmd->ClipRect; + ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); + ImDrawListFlags backup_flags = fg_draw_list->Flags; + fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles. + for (unsigned int idx_n = draw_cmd->IdxOffset; idx_n < draw_cmd->IdxOffset + draw_cmd->ElemCount; ) + { + ImVec2 triangle[3]; + for (int n = 0; n < 3; n++, idx_n++) + vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos)); + if (show_mesh) + fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), true, 1.0f); // In yellow: mesh triangles + } + // Draw bounding boxes + if (show_aabb) + { + fg_draw_list->AddRect(ImFloor(clip_rect.Min), ImFloor(clip_rect.Max), IM_COL32(255, 0, 255, 255)); // In pink: clipping rectangle submitted to GPU + fg_draw_list->AddRect(ImFloor(vtxs_rect.Min), ImFloor(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)); // In cyan: bounding box of triangles + } + fg_draw_list->Flags = backup_flags; +} + +// [DEBUG] Display contents of ImGuiStorage +void ImGui::DebugNodeStorage(ImGuiStorage* storage, const char* label) +{ + if (!TreeNode(label, "%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes())) + return; + for (int n = 0; n < storage->Data.Size; n++) + { + const ImGuiStorage::ImGuiStoragePair& p = storage->Data[n]; + BulletText("Key 0x%08X Value { i: %d }", p.key, p.val_i); // Important: we currently don't store a type, real value may not be integer. + } + TreePop(); +} + +// [DEBUG] Display contents of ImGuiTabBar +void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label) +{ + // Standalone tab bars (not associated to docking/windows functionality) currently hold no discernible strings. + char buf[256]; + char* p = buf; + const char* buf_end = buf + IM_ARRAYSIZE(buf); + const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2); + p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*"); + IM_UNUSED(p); + if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } + bool open = TreeNode(tab_bar, "%s", buf); + if (!is_active) { PopStyleColor(); } + if (is_active && IsItemHovered()) + { + ImDrawList* draw_list = GetForegroundDrawList(); + draw_list->AddRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, IM_COL32(255, 255, 0, 255)); + draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255)); + draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255)); + } + if (open) + { + for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) + { + const ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; + PushID(tab); + if (SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2); + if (SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine(); + Text("%02d%c Tab 0x%08X '%s' Offset: %.1f, Width: %.1f/%.1f", + tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "", tab->Offset, tab->Width, tab->ContentWidth); + PopID(); + } + TreePop(); + } +} + +void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label) +{ + if (window == NULL) + { + BulletText("%s: NULL", label); + return; + } + + ImGuiContext& g = *GImGui; + const bool is_active = window->WasActive; + ImGuiTreeNodeFlags tree_node_flags = (window == g.NavWindow) ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None; + if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } + const bool open = TreeNodeEx(label, tree_node_flags, "%s '%s'%s", label, window->Name, is_active ? "" : " *Inactive*"); + if (!is_active) { PopStyleColor(); } + if (IsItemHovered() && is_active) + GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); + if (!open) + return; + + if (window->MemoryCompacted) + TextDisabled("Note: some memory buffers have been compacted/freed."); + + ImGuiWindowFlags flags = window->Flags; + DebugNodeDrawList(window, window->DrawList, "DrawList"); + BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), ContentSize (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->ContentSize.x, window->ContentSize.y); + BulletText("Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags, + (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "", + (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "", + (flags & ImGuiWindowFlags_NoMouseInputs)? "NoMouseInputs":"", (flags & ImGuiWindowFlags_NoNavInputs) ? "NoNavInputs" : "", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : ""); + BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f) Scrollbar:%s%s", window->Scroll.x, window->ScrollMax.x, window->Scroll.y, window->ScrollMax.y, window->ScrollbarX ? "X" : "", window->ScrollbarY ? "Y" : ""); + BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1); + BulletText("Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems); + BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); + BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL"); + if (!window->NavRectRel[0].IsInverted()) + BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y); + else + BulletText("NavRectRel[0]: "); + if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); } + if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); } + if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); } + if (window->ColumnsStorage.Size > 0 && TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size)) + { + for (int n = 0; n < window->ColumnsStorage.Size; n++) + DebugNodeColumns(&window->ColumnsStorage[n]); + TreePop(); + } + DebugNodeStorage(&window->StateStorage, "Storage"); + TreePop(); +} + +void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings* settings) +{ + Text("0x%08X \"%s\" Pos (%d,%d) Size (%d,%d) Collapsed=%d", + settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed); +} + + +void ImGui::DebugNodeWindowsList(ImVector* windows, const char* label) +{ + if (!TreeNode(label, "%s (%d)", label, windows->Size)) + return; + Text("(In front-to-back order:)"); + for (int i = windows->Size - 1; i >= 0; i--) // Iterate front to back + { + PushID((*windows)[i]); + DebugNodeWindow((*windows)[i], "Window"); + PopID(); + } + TreePop(); +} + #else -void ImGui::ShowMetricsWindow(bool*) { } +void ImGui::ShowMetricsWindow(bool*) {} +void ImGui::DebugNodeColumns(ImGuiColumns*) {} +void ImGui::DebugNodeDrawList(ImGuiWindow*, ImDrawList*, const char*) {} +void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow*, const ImDrawList*, const ImDrawCmd*, bool, bool) {} +void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {} +void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {} +void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {} +void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings*) {} +void ImGui::DebugNodeWindowsList(ImVector*, const char*) {} #endif diff --git a/imgui_internal.h b/imgui_internal.h index 215f414e..11740019 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -101,6 +101,7 @@ struct ImGuiInputTextState; // Internal state of the currently focused/e struct ImGuiLastItemDataBackup; // Backup and restore IsItemHovered() internal data struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only struct ImGuiNavMoveResult; // Result of a gamepad/keyboard directional navigation move query result +struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions struct ImGuiNextWindowData; // Storage for SetNextWindow** functions struct ImGuiNextItemData; // Storage for SetNextItem** functions struct ImGuiPopupData; // Storage for current popup stack @@ -1101,6 +1102,28 @@ struct ImGuiSettingsHandler ImGuiSettingsHandler() { memset(this, 0, sizeof(*this)); } }; +struct ImGuiMetricsConfig +{ + bool ShowWindowsRects; + bool ShowWindowsBeginOrder; + bool ShowTablesRects; + bool ShowDrawCmdMesh; + bool ShowDrawCmdBoundingBoxes; + int ShowWindowsRectsType; + int ShowTablesRectsType; + + ImGuiMetricsConfig() + { + ShowWindowsRects = false; + ShowWindowsBeginOrder = false; + ShowTablesRects = false; + ShowDrawCmdMesh = true; + ShowDrawCmdBoundingBoxes = true; + ShowWindowsRectsType = -1; + ShowTablesRectsType = -1; + } +}; + //----------------------------------------------------------------------------- // [SECTION] Generic context hooks //----------------------------------------------------------------------------- @@ -1336,6 +1359,7 @@ struct ImGuiContext // Debug Tools bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker()) ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this id + ImGuiMetricsConfig DebugMetricsConfig; // Misc float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds. @@ -2070,6 +2094,15 @@ namespace ImGui inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max, col); } inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } + IMGUI_API void DebugNodeColumns(ImGuiColumns* columns); + IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label); + IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow* window, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb); + IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label); + IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label); + IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label); + IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings); + IMGUI_API void DebugNodeWindowsList(ImVector* windows, const char* label); + } // namespace ImGui // ImFontAtlas internals