From eb1c36fdfb2456c310398008f945468cc77c9073 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 25 Apr 2018 22:07:14 +0200 Subject: [PATCH 01/30] Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769) --- CHANGELOG.txt | 2 ++ examples/allegro5_example/main.cpp | 3 ++- examples/directx10_example/main.cpp | 3 ++- examples/directx11_example/main.cpp | 3 ++- examples/directx12_example/main.cpp | 3 ++- examples/directx9_example/main.cpp | 3 ++- examples/marmalade_example/main.cpp | 3 ++- examples/null_example/main.cpp | 1 + examples/opengl2_example/main.cpp | 3 ++- examples/opengl3_example/main.cpp | 3 ++- examples/sdl_opengl2_example/main.cpp | 3 ++- examples/sdl_opengl3_example/main.cpp | 3 ++- examples/vulkan_example/main.cpp | 3 ++- imgui.cpp | 14 ++++++++++++++ imgui.h | 23 ++++++++++++----------- 15 files changed, 51 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 73644a92..8af43b8c 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -57,7 +57,9 @@ Other Changes: - InputText: On Mac OS X, filter out characters when the Cmd modifier is held. (#1747) [@sivu] - InputText: On Mac OS X, support Cmd+Shift+Z for Redo. Cmd+Y is also supported as major apps seems to default to support both. (#1765) [@lfnoise] - Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439) +- Misc: Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769) - Demo: Fixed Overlay: Added a context menu item to enable freely moving the window. +- Examples: Calling IMGUI_CHECKVERSION() in the main.cpp of every example application. - Examples: Allegro 5: Added support for 32-bit indices setup via defining ImDrawIdx, to avoid an unnecessary conversion (Allegro 5 doesn't support 16-bit indices). - Examples: Allegro 5: Renamed bindings from imgui_impl_a5.cpp to imgui_impl_allegro5.cpp. - Various minor fixes, tweaks, refactoring, comments. diff --git a/examples/allegro5_example/main.cpp b/examples/allegro5_example/main.cpp index 5ecd4125..aa54057a 100644 --- a/examples/allegro5_example/main.cpp +++ b/examples/allegro5_example/main.cpp @@ -22,7 +22,8 @@ int main(int, char**) al_register_event_source(queue, al_get_keyboard_event_source()); al_register_event_source(queue, al_get_mouse_event_source()); - // Setup ImGui binding + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index b69919d0..15ed9985 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -111,7 +111,8 @@ int main(int, char**) ShowWindow(hwnd, SW_SHOWDEFAULT); UpdateWindow(hwnd); - // Setup ImGui binding + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index f91a181c..8b358698 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -114,7 +114,8 @@ int main(int, char**) ShowWindow(hwnd, SW_SHOWDEFAULT); UpdateWindow(hwnd); - // Setup ImGui binding + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/examples/directx12_example/main.cpp b/examples/directx12_example/main.cpp index 24bf58cf..1e7c2748 100644 --- a/examples/directx12_example/main.cpp +++ b/examples/directx12_example/main.cpp @@ -285,7 +285,8 @@ int main(int, char**) ShowWindow(hwnd, SW_SHOWDEFAULT); UpdateWindow(hwnd); - // Setup ImGui binding + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index cb75a43f..8b27b5dc 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -74,7 +74,8 @@ int main(int, char**) return 0; } - // Setup ImGui binding + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/examples/marmalade_example/main.cpp b/examples/marmalade_example/main.cpp index cb9113ed..3fcf1526 100644 --- a/examples/marmalade_example/main.cpp +++ b/examples/marmalade_example/main.cpp @@ -16,7 +16,8 @@ int main(int, char**) { IwGxInit(); - // Setup ImGui binding + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/examples/null_example/main.cpp b/examples/null_example/main.cpp index 482d689b..547ed3c1 100644 --- a/examples/null_example/main.cpp +++ b/examples/null_example/main.cpp @@ -4,6 +4,7 @@ int main(int, char**) { + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index 92abfbd1..2dfa129e 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -26,7 +26,8 @@ int main(int, char**) glfwMakeContextCurrent(window); glfwSwapInterval(1); // Enable vsync - // Setup ImGui binding + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 4ca76636..4542c891 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -31,7 +31,8 @@ int main(int, char**) glfwSwapInterval(1); // Enable vsync gl3wInit(); - // Setup ImGui binding + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index 79765037..ac349be3 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -33,7 +33,8 @@ int main(int, char**) SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_SetSwapInterval(1); // Enable vsync - // Setup ImGui binding + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index 1cac6b16..8b1e3f40 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -33,7 +33,8 @@ int main(int, char**) SDL_GL_SetSwapInterval(1); // Enable vsync gl3wInit(); - // Setup ImGui binding + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index cd0b0e49..57cab6ab 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -625,7 +625,8 @@ int main(int, char**) setup_vulkan(window); glfwSetFramebufferSizeCallback(window, glfw_resize_callback); - // Setup ImGui binding + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplGlfwVulkan_Init_Data init_data = {}; diff --git a/imgui.cpp b/imgui.cpp index 127d07d3..13181e92 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2644,6 +2644,20 @@ void ImGui::SetCurrentContext(ImGuiContext* ctx) #endif } +// Helper function to verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit +// If the user has inconsistent compilation settings, imgui configuration #define, packing pragma, etc. you may see different structures from what imgui.cpp sees which is highly problematic. +bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert) +{ + bool error = false; + if (strcmp(version, IMGUI_VERSION)!=0) { error = true; IM_ASSERT(strcmp(version,IMGUI_VERSION)==0 && "Mismatch version string!"); } + if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); } + if (sz_style != sizeof(ImGuiStyle)) { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle) && "Mismatched struct layout!"); } + if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); } + if (sz_vec4 != sizeof(ImVec4)) { error = true; IM_ASSERT(sz_vec4 == sizeof(ImVec4) && "Mismatched struct layout!"); } + if (sz_vert != sizeof(ImDrawVert)) { error = true; IM_ASSERT(sz_vert == sizeof(ImDrawVert) && "Mismatched struct layout!"); } + return !error; +} + void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void(*free_func)(void* ptr, void* user_data), void* user_data) { GImAllocatorAllocFunc = alloc_func; diff --git a/imgui.h b/imgui.h index 6fd1399f..2bdebb99 100644 --- a/imgui.h +++ b/imgui.h @@ -16,25 +16,25 @@ #include "imconfig.h" #endif -#include // FLT_MAX -#include // va_list -#include // ptrdiff_t, NULL -#include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp +#include // FLT_MAX +#include // va_list +#include // ptrdiff_t, NULL +#include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.61 WIP" +// Version +#define IMGUI_VERSION "1.61 WIP" +#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert)) -// Define attributes of all API symbols declarations, e.g. for DLL under Windows. +// Define attributes of all API symbols declarations (e.g. for DLL under Windows) #ifndef IMGUI_API #define IMGUI_API #endif -// Define assertion handler. +// Helpers #ifndef IM_ASSERT #include -#define IM_ASSERT(_EXPR) assert(_EXPR) +#define IM_ASSERT(_EXPR) assert(_EXPR) #endif - -// Helpers #if defined(__clang__) || defined(__GNUC__) #define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) // Apply printf-style warnings to user functions. #define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) @@ -60,7 +60,7 @@ struct ImDrawVert; // A single vertex (20 bytes by default, ove struct ImFont; // Runtime data for a single font within a parent ImFontAtlas struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF/OTF font loader struct ImFontConfig; // Configuration data when adding a font or merging fonts -struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 +struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 (*obsolete* please avoid using) struct ImGuiIO; // Main configuration and I/O between your application and ImGui struct ImGuiOnceUponAFrame; // Simple helper for running a block of code not more than once a frame, used by IMGUI_ONCE_UPON_A_FRAME macro struct ImGuiStorage; // Simple custom key value storage @@ -143,6 +143,7 @@ namespace ImGui IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context IMGUI_API ImGuiContext* GetCurrentContext(); IMGUI_API void SetCurrentContext(ImGuiContext* ctx); + IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert); // Main IMGUI_API ImGuiIO& GetIO(); From 27ac9f4761075457dda1639fb76da4e540aeb2ed Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 25 Apr 2018 22:16:16 +0200 Subject: [PATCH 02/30] Comments (#1695) --- imconfig.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imconfig.h b/imconfig.h index 191807d6..6f839f31 100644 --- a/imconfig.h +++ b/imconfig.h @@ -8,6 +8,7 @@ // If you do so you need to make sure that configuration settings are defined consistently _everywhere_ dear imgui is used, which include // the imgui*.cpp files but also _any_ of your code that uses imgui. This is because some compile-time options have an affect on data structures. // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. +// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. //----------------------------------------------------------------------------- #pragma once From f8c9c33d33835f1e7b2a32131f6802588b521046 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Thu, 26 Apr 2018 14:51:46 +0700 Subject: [PATCH 03/30] Fixed static analyzers warnings with bool literals (#1775) * Use `false` instead of `0` for a bool literal. * Simplify calls to RadioButton to not need bool literals. --- imgui.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 13181e92..033bfe89 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3419,7 +3419,7 @@ void ImGui::NewFrameUpdateHoveredWindowAndCaptureFlags() g.IO.WantCaptureKeyboard = true; // Update io.WantTextInput flag, this is to allow systems without a keyboard (e.g. mobile, hand-held) to show a software keyboard if possible - g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : 0; + g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false; } void ImGui::NewFrame() @@ -11593,15 +11593,15 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags) ImGuiColorEditFlags opts = g.ColorEditOptions; if (allow_opt_inputs) { - if (RadioButton("RGB", (opts & ImGuiColorEditFlags_RGB) ? 1 : 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_RGB; - if (RadioButton("HSV", (opts & ImGuiColorEditFlags_HSV) ? 1 : 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_HSV; - if (RadioButton("HEX", (opts & ImGuiColorEditFlags_HEX) ? 1 : 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_HEX; + if (RadioButton("RGB", (opts & ImGuiColorEditFlags_RGB) != 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_RGB; + if (RadioButton("HSV", (opts & ImGuiColorEditFlags_HSV) != 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_HSV; + if (RadioButton("HEX", (opts & ImGuiColorEditFlags_HEX) != 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_HEX; } if (allow_opt_datatype) { if (allow_opt_inputs) Separator(); - if (RadioButton("0..255", (opts & ImGuiColorEditFlags_Uint8) ? 1 : 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Uint8; - if (RadioButton("0.00..1.00", (opts & ImGuiColorEditFlags_Float) ? 1 : 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Float; + if (RadioButton("0..255", (opts & ImGuiColorEditFlags_Uint8) != 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Uint8; + if (RadioButton("0.00..1.00", (opts & ImGuiColorEditFlags_Float) != 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Float; } if (allow_opt_inputs || allow_opt_datatype) From 28edece04f2b8d2d01666d9a6f631ecac51888a9 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 26 Apr 2018 14:56:46 +0200 Subject: [PATCH 04/30] Comments, minor tweaks --- imgui.h | 28 ++++++++++++++-------------- imgui_draw.cpp | 2 -- misc/fonts/README.txt | 5 +++-- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/imgui.h b/imgui.h index 2bdebb99..679c487b 100644 --- a/imgui.h +++ b/imgui.h @@ -113,27 +113,27 @@ typedef unsigned long long ImU64; // 64-bit unsigned integer struct ImVec2 { - float x, y; - ImVec2() { x = y = 0.0f; } + float x, y; + ImVec2() { x = y = 0.0f; } ImVec2(float _x, float _y) { x = _x; y = _y; } - float operator[] (size_t idx) const { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine. -#ifdef IM_VEC2_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec2. - IM_VEC2_CLASS_EXTRA + float operator[] (size_t i) const { IM_ASSERT(i <= 1); return (&x)[i]; } // We very rarely use this [] operator, the assert overhead is fine. +#ifdef IM_VEC2_CLASS_EXTRA + IM_VEC2_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec2. #endif }; struct ImVec4 { - float x, y, z, w; - ImVec4() { x = y = z = w = 0.0f; } + float x, y, z, w; + ImVec4() { x = y = z = w = 0.0f; } ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } -#ifdef IM_VEC4_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec4. - IM_VEC4_CLASS_EXTRA +#ifdef IM_VEC4_CLASS_EXTRA + IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4. #endif }; // ImGui end-user API -// In a namespace so that user can add extra functions in a separate file (e.g. Value() helpers for your vector or common types) +// In a namespace so that user can add extra functions in your own separate file (please don't modify imgui.cpp/.h) namespace ImGui { // Context creation and access @@ -696,7 +696,7 @@ enum ImGuiDragDropFlags_ ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. }; -// Standard Drag and Drop payload types. You can define you own payload types using 12-characters long strings. Types starting with '_' are defined by Dear ImGui. +// Standard Drag and Drop payload types. You can define you own payload types using short strings. Types starting with '_' are defined by Dear ImGui. #define IMGUI_PAYLOAD_TYPE_COLOR_3F "_COL3F" // float[3]: Standard type for colors, without alpha. User code may use this type. #define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4]: Standard type for colors. User code may use this type. @@ -837,10 +837,10 @@ enum ImGuiCol_ ImGuiCol_PlotHistogram, ImGuiCol_PlotHistogramHovered, ImGuiCol_TextSelectedBg, - ImGuiCol_ModalWindowDarkening, // darken/colorize entire screen behind a modal window, when one is active + ImGuiCol_ModalWindowDarkening, // Darken/colorize entire screen behind a modal window, when one is active ImGuiCol_DragDropTarget, - ImGuiCol_NavHighlight, // gamepad/keyboard: current highlighted item - ImGuiCol_NavWindowingHighlight, // gamepad/keyboard: when holding NavMenu to focus/move/resize windows + ImGuiCol_NavHighlight, // Gamepad/keyboard: current highlighted item + ImGuiCol_NavWindowingHighlight, // Gamepad/keyboard: when holding NavMenu to focus/move/resize windows ImGuiCol_COUNT // Obsolete names (will be removed) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index c76ea79f..ea822146 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -244,8 +244,6 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst) colors[ImGuiCol_Text] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - //colors[ImGuiCol_TextHovered] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - //colors[ImGuiCol_TextActive] = ImVec4(1.00f, 1.00f, 0.00f, 1.00f); colors[ImGuiCol_WindowBg] = ImVec4(0.94f, 0.94f, 0.94f, 1.00f); colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_PopupBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.98f); diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index f7468f02..9ef6811e 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -49,8 +49,9 @@ In this document: io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config, icon_ranges); // Usage, e.g. - ImGui::Text("%s Search", ICON_FA_SEARCH); - + ImGui::Button(ICON_FA_SEARCH " Search"); // C string literals can be concatenated at compilation time, this is the same as "A" "B" becoming "AB" + ImGui::Text("%s among %d items", ICON_FA_SEARCH, count); + See Links below for other icons fonts and related tools. From 101f9b42b73caf3476c622bb48d4a544242121ad Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 27 Apr 2018 17:19:49 +0200 Subject: [PATCH 05/30] InputText: Fixed returning true when edition is cancelled with Esc and the current buffer matches the initial value. --- CHANGELOG.txt | 1 + imgui.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 8af43b8c..896dd372 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -56,6 +56,7 @@ Other Changes: - MenuBar: Made BeginMainMenuBar() honor style.DisplaySafeAreaPadding so the text can be made visible on TV settings that don't display all pixels. (#1439) [@dougbinks] - InputText: On Mac OS X, filter out characters when the Cmd modifier is held. (#1747) [@sivu] - InputText: On Mac OS X, support Cmd+Shift+Z for Redo. Cmd+Y is also supported as major apps seems to default to support both. (#1765) [@lfnoise] +- InputText: Fixed returning true when edition is cancelled with Esc and the current buffer matches the initial value. - Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439) - Misc: Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769) - Demo: Fixed Overlay: Added a context menu item to enable freely moving the window. diff --git a/imgui.cpp b/imgui.cpp index 033bfe89..59faabb3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10245,8 +10245,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 { if (cancel_edit) { - // Restore initial value - if (is_editable) + // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents. + if (is_editable && strncmp(buf, edit_state.InitialText.Data, buf_size) != 0) { ImStrncpy(buf, edit_state.InitialText.Data, buf_size); value_changed = true; From 1d99b5f963a2b80fbf50e7e5ee17ec8d5c37fc11 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 27 Apr 2018 17:32:31 +0200 Subject: [PATCH 06/30] Internals: Reordered parameters of DataTypeFormatString() internal helper functions and shallow tweaks. --- imgui.cpp | 69 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 59faabb3..f190d148 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -746,8 +746,8 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInpu static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end); static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); -static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, const char* display_format, char* buf, int buf_size); -static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size); +static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* display_format); +static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, int decimal_precision); static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2); static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format); @@ -8441,39 +8441,40 @@ void ImGui::BulletText(const char* fmt, ...) va_end(args); } -static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, const char* display_format, char* buf, int buf_size) +static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* display_format) { if (data_type == ImGuiDataType_Int) - ImFormatString(buf, buf_size, display_format, *(int*)data_ptr); - else if (data_type == ImGuiDataType_Float) - ImFormatString(buf, buf_size, display_format, *(float*)data_ptr); - else if (data_type == ImGuiDataType_Double) - ImFormatString(buf, buf_size, display_format, *(double*)data_ptr); + return ImFormatString(buf, buf_size, display_format, *(const int*)data_ptr); + if (data_type == ImGuiDataType_Float) + return ImFormatString(buf, buf_size, display_format, *(const float*)data_ptr); + if (data_type == ImGuiDataType_Double) + return ImFormatString(buf, buf_size, display_format, *(const double*)data_ptr); + IM_ASSERT(0); + return 0; } -static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size) +static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, int decimal_precision) { - if (data_type == ImGuiDataType_Int) + if (decimal_precision < 0) { - if (decimal_precision < 0) - ImFormatString(buf, buf_size, "%d", *(int*)data_ptr); - else - ImFormatString(buf, buf_size, "%.*d", decimal_precision, *(int*)data_ptr); + if (data_type == ImGuiDataType_Int) + return ImFormatString(buf, buf_size, "%d", *(const int*)data_ptr); + if (data_type == ImGuiDataType_Float) + return ImFormatString(buf, buf_size, "%f", *(const float*)data_ptr); // Ideally we'd have a minimum decimal precision of 1 to visually denote that it is a float, while hiding non-significant digits? + if (data_type == ImGuiDataType_Double) + return ImFormatString(buf, buf_size, "%f", *(const double*)data_ptr); } - else if (data_type == ImGuiDataType_Float) + else { - if (decimal_precision < 0) - ImFormatString(buf, buf_size, "%f", *(float*)data_ptr); // Ideally we'd have a minimum decimal precision of 1 to visually denote that it is a float, while hiding non-significant digits? - else - ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(float*)data_ptr); - } - else if (data_type == ImGuiDataType_Double) - { - if (decimal_precision < 0) - ImFormatString(buf, buf_size, "%f", *(double*)data_ptr); - else - ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(double*)data_ptr); + if (data_type == ImGuiDataType_Int) + return ImFormatString(buf, buf_size, "%.*d", decimal_precision, *(const int*)data_ptr); + if (data_type == ImGuiDataType_Float) + return ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(const float*)data_ptr); + if (data_type == ImGuiDataType_Double) + return ImFormatString(buf, buf_size, "%.*g", decimal_precision, *(const double*)data_ptr); } + IM_ASSERT(0); + return 0; } static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg1, const void* arg2) @@ -8481,18 +8482,18 @@ static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* IM_ASSERT(op == '+' || op == '-'); if (data_type == ImGuiDataType_Int) { - if (op == '+') *(int*)output = *(int*)arg1 + *(const int*)arg2; - else if (op == '-') *(int*)output = *(int*)arg1 - *(const int*)arg2; + if (op == '+') *(int*)output = *(const int*)arg1 + *(const int*)arg2; + else if (op == '-') *(int*)output = *(const int*)arg1 - *(const int*)arg2; } else if (data_type == ImGuiDataType_Float) { - if (op == '+') *(float*)output = *(float*)arg1 + *(const float*)arg2; - else if (op == '-') *(float*)output = *(float*)arg1 - *(const float*)arg2; + if (op == '+') *(float*)output = *(const float*)arg1 + *(const float*)arg2; + else if (op == '-') *(float*)output = *(const float*)arg1 - *(const float*)arg2; } else if (data_type == ImGuiDataType_Double) { - if (op == '+') *(double*)output = *(double*)arg1 + *(const double*)arg2; - else if (op == '-') *(double*)output = *(double*)arg1 - *(const double*)arg2; + if (op == '+') *(double*)output = *(const double*)arg1 + *(const double*)arg2; + else if (op == '-') *(double*)output = *(const double*)arg1 - *(const double*)arg2; } } @@ -8593,7 +8594,7 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label FocusableItemUnregister(window); char buf[32]; - DataTypeFormatString(data_type, data_ptr, decimal_precision, buf, IM_ARRAYSIZE(buf)); + DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, decimal_precision); bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), aabb.GetSize(), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll); if (g.ScalarAsInputTextId == 0) // First frame we started displaying the InputText widget { @@ -10557,7 +10558,7 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_sz.x + style.ItemInnerSpacing.x)*2)); char buf[64]; - DataTypeFormatString(data_type, data_ptr, scalar_format, buf, IM_ARRAYSIZE(buf)); + DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, scalar_format); bool value_changed = false; if ((extra_flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0) From a84aff1875e9acf5adb3fe7cb39572fc21eb6cac Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 27 Apr 2018 18:22:10 +0200 Subject: [PATCH 07/30] Internals: DragBehavior: tweaks internals. --- imgui.cpp | 119 +++++++++++++++++++++++++++--------------------------- 1 file changed, 59 insertions(+), 60 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f190d148..dd4c462f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9063,8 +9063,6 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); - bool value_changed = false; - // Process interacting with the drag if (g.ActiveId == id) { @@ -9073,69 +9071,70 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) ClearActiveID(); } - if (g.ActiveId == id) + if (g.ActiveId != id) + return false; + + bool value_changed = false; + if (g.ActiveIdIsJustActivated) { - if (g.ActiveIdIsJustActivated) + // Lock current value on click + g.DragCurrentValue = *v; + g.DragLastMouseDelta = ImVec2(0.f, 0.f); + } + + if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) + v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio; + + float v_cur = g.DragCurrentValue; + const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); + float adjust_delta = 0.0f; + if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid()) + { + adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x; + if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) + adjust_delta *= g.DragSpeedScaleFast; + if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) + adjust_delta *= g.DragSpeedScaleSlow; + g.DragLastMouseDelta.x = mouse_drag_delta.x; + } + if (g.ActiveIdSource == ImGuiInputSource_Nav) + { + adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; + if (v_min < v_max && ((v_cur >= v_max && adjust_delta > 0.0f) || (v_cur <= v_min && adjust_delta < 0.0f))) // This is to avoid applying the saturation when already past the limits + adjust_delta = 0.0f; + v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); + } + adjust_delta *= v_speed; + + if (fabsf(adjust_delta) > 0.0f) + { + if (fabsf(power - 1.0f) > 0.001f) { - // Lock current value on click - g.DragCurrentValue = *v; - g.DragLastMouseDelta = ImVec2(0.f, 0.f); + // Logarithmic curve on both side of 0.0 + float v0_abs = v_cur >= 0.0f ? v_cur : -v_cur; + float v0_sign = v_cur >= 0.0f ? 1.0f : -1.0f; + float v1 = powf(v0_abs, 1.0f / power) + (adjust_delta * v0_sign); + float v1_abs = v1 >= 0.0f ? v1 : -v1; + float v1_sign = v1 >= 0.0f ? 1.0f : -1.0f; // Crossed sign line + v_cur = powf(v1_abs, power) * v0_sign * v1_sign; // Reapply sign + } + else + { + v_cur += adjust_delta; } - if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) - v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio; + // Clamp + if (v_min < v_max) + v_cur = ImClamp(v_cur, v_min, v_max); + g.DragCurrentValue = v_cur; + } - float v_cur = g.DragCurrentValue; - const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); - float adjust_delta = 0.0f; - if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid()) - { - adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x; - if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) - adjust_delta *= g.DragSpeedScaleFast; - if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) - adjust_delta *= g.DragSpeedScaleSlow; - g.DragLastMouseDelta.x = mouse_drag_delta.x; - } - if (g.ActiveIdSource == ImGuiInputSource_Nav) - { - adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; - if (v_min < v_max && ((v_cur >= v_max && adjust_delta > 0.0f) || (v_cur <= v_min && adjust_delta < 0.0f))) // This is to avoid applying the saturation when already past the limits - adjust_delta = 0.0f; - v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); - } - adjust_delta *= v_speed; - - if (fabsf(adjust_delta) > 0.0f) - { - if (fabsf(power - 1.0f) > 0.001f) - { - // Logarithmic curve on both side of 0.0 - float v0_abs = v_cur >= 0.0f ? v_cur : -v_cur; - float v0_sign = v_cur >= 0.0f ? 1.0f : -1.0f; - float v1 = powf(v0_abs, 1.0f / power) + (adjust_delta * v0_sign); - float v1_abs = v1 >= 0.0f ? v1 : -v1; - float v1_sign = v1 >= 0.0f ? 1.0f : -1.0f; // Crossed sign line - v_cur = powf(v1_abs, power) * v0_sign * v1_sign; // Reapply sign - } - else - { - v_cur += adjust_delta; - } - - // Clamp - if (v_min < v_max) - v_cur = ImClamp(v_cur, v_min, v_max); - g.DragCurrentValue = v_cur; - } - - // Round to user desired precision, then apply - v_cur = RoundScalar(v_cur, decimal_precision); - if (*v != v_cur) - { - *v = v_cur; - value_changed = true; - } + // Round to user desired precision, then apply + v_cur = RoundScalar(v_cur, decimal_precision); + if (*v != v_cur) + { + *v = v_cur; + value_changed = true; } return value_changed; From 066550de68c8b708171b6959eeac427a7eb4f184 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 27 Apr 2018 19:15:25 +0200 Subject: [PATCH 08/30] DragFloat, DragInt: Cancel mouse tweak when current value is initially past the min/max boundaries and mouse is pushing in the same direction (keyboard/gamepad version already did this). --- CHANGELOG.txt | 1 + imgui.cpp | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 896dd372..de4e4cf8 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -57,6 +57,7 @@ Other Changes: - InputText: On Mac OS X, filter out characters when the Cmd modifier is held. (#1747) [@sivu] - InputText: On Mac OS X, support Cmd+Shift+Z for Redo. Cmd+Y is also supported as major apps seems to default to support both. (#1765) [@lfnoise] - InputText: Fixed returning true when edition is cancelled with Esc and the current buffer matches the initial value. +- DragFloat, DragInt: Cancel mouse tweak when current value is initially past the min/max boundaries and mouse is pushing in the same direction (keyboard/gamepad version already did this). - Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439) - Misc: Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769) - Demo: Fixed Overlay: Added a context menu item to enable freely moving the window. diff --git a/imgui.cpp b/imgui.cpp index dd4c462f..122552b3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9074,7 +9074,10 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s if (g.ActiveId != id) return false; - bool value_changed = false; + // Default tweak speed + if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) + v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio; + if (g.ActiveIdIsJustActivated) { // Lock current value on click @@ -9082,10 +9085,6 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s g.DragLastMouseDelta = ImVec2(0.f, 0.f); } - if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) - v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio; - - float v_cur = g.DragCurrentValue; const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); float adjust_delta = 0.0f; if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid()) @@ -9100,12 +9099,15 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s if (g.ActiveIdSource == ImGuiInputSource_Nav) { adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; - if (v_min < v_max && ((v_cur >= v_max && adjust_delta > 0.0f) || (v_cur <= v_min && adjust_delta < 0.0f))) // This is to avoid applying the saturation when already past the limits - adjust_delta = 0.0f; v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); } adjust_delta *= v_speed; + // Avoid applying the saturation when we are _already_ past the limits and heading in the same direction, so e.g. if range is 0..255, current value is 300 and we are pushing to the right side, keep the 300 + float v_cur = g.DragCurrentValue; + if (v_min < v_max && ((v_cur >= v_max && adjust_delta > 0.0f) || (v_cur <= v_min && adjust_delta < 0.0f))) + adjust_delta = 0.0f; + if (fabsf(adjust_delta) > 0.0f) { if (fabsf(power - 1.0f) > 0.001f) @@ -9130,6 +9132,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s } // Round to user desired precision, then apply + bool value_changed = false; v_cur = RoundScalar(v_cur, decimal_precision); if (*v != v_cur) { From 8a38271a7cc151e92efed96418817ac0b8e3d3e3 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 27 Apr 2018 23:18:28 +0200 Subject: [PATCH 09/30] SliderFloat, DragFloat: Fix to allow input of scientific notation when Ctrl+Clicking a slider or drag, matching the change done in c19b2781 for InputFloat(). (#648, #1011) --- CHANGELOG.txt | 1 + imgui.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index de4e4cf8..1a0a4aa3 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -58,6 +58,7 @@ Other Changes: - InputText: On Mac OS X, support Cmd+Shift+Z for Redo. Cmd+Y is also supported as major apps seems to default to support both. (#1765) [@lfnoise] - InputText: Fixed returning true when edition is cancelled with Esc and the current buffer matches the initial value. - DragFloat, DragInt: Cancel mouse tweak when current value is initially past the min/max boundaries and mouse is pushing in the same direction (keyboard/gamepad version already did this). +- DragFloat, SliderFloat: Fix to allow input of scientific notation numbers when using CTRL+Click to input the value. (~#648, #1011) - Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439) - Misc: Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769) - Demo: Fixed Overlay: Added a context menu item to enable freely moving the window. diff --git a/imgui.cpp b/imgui.cpp index 122552b3..d4bae197 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8595,7 +8595,8 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label char buf[32]; DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, decimal_precision); - bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), aabb.GetSize(), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll); + ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal); + bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), aabb.GetSize(), flags); if (g.ScalarAsInputTextId == 0) // First frame we started displaying the InputText widget { IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible) From 73445ff248f18e74caa0d077eadbe17d2d93b2d7 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 27 Apr 2018 23:44:27 +0200 Subject: [PATCH 10/30] Renamed all "display_format" arguments to "format" to emphasis that they also affect rounding of values. (#648, #642) --- imgui.cpp | 156 +++++++++++++++++++++++++++--------------------------- imgui.h | 42 +++++++-------- 2 files changed, 99 insertions(+), 99 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d4bae197..f1af4861 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -746,10 +746,10 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInpu static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end); static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); -static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* display_format); +static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format); static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, int decimal_precision); static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2); -static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format); +static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format); namespace ImGui { @@ -8441,14 +8441,14 @@ void ImGui::BulletText(const char* fmt, ...) va_end(args); } -static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* display_format) +static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format) { if (data_type == ImGuiDataType_Int) - return ImFormatString(buf, buf_size, display_format, *(const int*)data_ptr); + return ImFormatString(buf, buf_size, format, *(const int*)data_ptr); if (data_type == ImGuiDataType_Float) - return ImFormatString(buf, buf_size, display_format, *(const float*)data_ptr); + return ImFormatString(buf, buf_size, format, *(const float*)data_ptr); if (data_type == ImGuiDataType_Double) - return ImFormatString(buf, buf_size, display_format, *(const double*)data_ptr); + return ImFormatString(buf, buf_size, format, *(const double*)data_ptr); IM_ASSERT(0); return 0; } @@ -8832,11 +8832,11 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v } // Use power!=1.0 for logarithmic sliders. -// Adjust display_format to decorate the value with a prefix or a suffix. +// Adjust format to decorate the value with a prefix or a suffix. // "%.3f" 1.234 // "%5.2f secs" 01.23 secs // "Gold: %.0f" Gold: 1 -bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format, float power) +bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float power) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -8859,9 +8859,9 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c } const bool hovered = ItemHoverable(frame_bb, id); - if (!display_format) - display_format = "%.3f"; - int decimal_precision = ParseFormatPrecision(display_format, 3); + if (!format) + format = "%.3f"; + int decimal_precision = ParseFormatPrecision(format, 3); // Tabbing or CTRL-clicking on Slider turns it into an input box bool start_text_input = false; @@ -8887,7 +8887,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; - const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); + const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), format, *v); RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f)); if (label_size.x > 0.0f) @@ -8896,7 +8896,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c return value_changed; } -bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* display_format, float power) +bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format, float power) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -8915,9 +8915,9 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float return false; const bool hovered = ItemHoverable(frame_bb, id); - if (!display_format) - display_format = "%.3f"; - int decimal_precision = ParseFormatPrecision(display_format, 3); + if (!format) + format = "%.3f"; + int decimal_precision = ParseFormatPrecision(format, 3); if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id) { @@ -8933,7 +8933,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // For the vertical slider we allow centered text to overlap the frame padding char value_buf[64]; - char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); + char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), format, *v); RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.0f)); if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); @@ -8949,28 +8949,28 @@ bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, fl return value_changed; } -bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format) +bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* format) { - if (!display_format) - display_format = "%.0f"; + if (!format) + format = "%.0f"; float v_f = (float)*v; - bool value_changed = SliderFloat(label, &v_f, (float)v_min, (float)v_max, display_format, 1.0f); + bool value_changed = SliderFloat(label, &v_f, (float)v_min, (float)v_max, format, 1.0f); *v = (int)v_f; return value_changed; } -bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format) +bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format) { - if (!display_format) - display_format = "%.0f"; + if (!format) + format = "%.0f"; float v_f = (float)*v; - bool value_changed = VSliderFloat(label, size, &v_f, (float)v_min, (float)v_max, display_format, 1.0f); + bool value_changed = VSliderFloat(label, size, &v_f, (float)v_min, (float)v_max, format, 1.0f); *v = (int)v_f; return value_changed; } // Add multiple sliders on 1 line for compact edition of multiple components -bool ImGui::SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power) +bool ImGui::SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* format, float power) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -8984,7 +8984,7 @@ bool ImGui::SliderFloatN(const char* label, float* v, int components, float v_mi for (int i = 0; i < components; i++) { PushID(i); - value_changed |= SliderFloat("##v", &v[i], v_min, v_max, display_format, power); + value_changed |= SliderFloat("##v", &v[i], v_min, v_max, format, power); SameLine(0, g.Style.ItemInnerSpacing.x); PopID(); PopItemWidth(); @@ -8997,22 +8997,22 @@ bool ImGui::SliderFloatN(const char* label, float* v, int components, float v_mi return value_changed; } -bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format, float power) +bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power) { - return SliderFloatN(label, v, 2, v_min, v_max, display_format, power); + return SliderFloatN(label, v, 2, v_min, v_max, format, power); } -bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format, float power) +bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, float power) { - return SliderFloatN(label, v, 3, v_min, v_max, display_format, power); + return SliderFloatN(label, v, 3, v_min, v_max, format, power); } -bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* display_format, float power) +bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, float power) { - return SliderFloatN(label, v, 4, v_min, v_max, display_format, power); + return SliderFloatN(label, v, 4, v_min, v_max, format, power); } -bool ImGui::SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format) +bool ImGui::SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* format) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -9026,7 +9026,7 @@ bool ImGui::SliderIntN(const char* label, int* v, int components, int v_min, int for (int i = 0; i < components; i++) { PushID(i); - value_changed |= SliderInt("##v", &v[i], v_min, v_max, display_format); + value_changed |= SliderInt("##v", &v[i], v_min, v_max, format); SameLine(0, g.Style.ItemInnerSpacing.x); PopID(); PopItemWidth(); @@ -9039,19 +9039,19 @@ bool ImGui::SliderIntN(const char* label, int* v, int components, int v_min, int return value_changed; } -bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* display_format) +bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format) { - return SliderIntN(label, v, 2, v_min, v_max, display_format); + return SliderIntN(label, v, 2, v_min, v_max, format); } -bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* display_format) +bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format) { - return SliderIntN(label, v, 3, v_min, v_max, display_format); + return SliderIntN(label, v, 3, v_min, v_max, format); } -bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* display_format) +bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format) { - return SliderIntN(label, v, 4, v_min, v_max, display_format); + return SliderIntN(label, v, 4, v_min, v_max, format); } bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power) @@ -9144,7 +9144,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s return value_changed; } -bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* display_format, float power) +bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, float power) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -9168,9 +9168,9 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f } const bool hovered = ItemHoverable(frame_bb, id); - if (!display_format) - display_format = "%.3f"; - int decimal_precision = ParseFormatPrecision(display_format, 3); + if (!format) + format = "%.3f"; + int decimal_precision = ParseFormatPrecision(format, 3); // Tabbing or CTRL-clicking on Drag turns it into an input box bool start_text_input = false; @@ -9196,7 +9196,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; - const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); + const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), format, *v); RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f)); if (label_size.x > 0.0f) @@ -9205,7 +9205,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f return value_changed; } -bool ImGui::DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power) +bool ImGui::DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* format, float power) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -9219,7 +9219,7 @@ bool ImGui::DragFloatN(const char* label, float* v, int components, float v_spee for (int i = 0; i < components; i++) { PushID(i); - value_changed |= DragFloat("##v", &v[i], v_speed, v_min, v_max, display_format, power); + value_changed |= DragFloat("##v", &v[i], v_speed, v_min, v_max, format, power); SameLine(0, g.Style.ItemInnerSpacing.x); PopID(); PopItemWidth(); @@ -9232,22 +9232,22 @@ bool ImGui::DragFloatN(const char* label, float* v, int components, float v_spee return value_changed; } -bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* display_format, float power) +bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, float power) { - return DragFloatN(label, v, 2, v_speed, v_min, v_max, display_format, power); + return DragFloatN(label, v, 2, v_speed, v_min, v_max, format, power); } -bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* display_format, float power) +bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, float power) { - return DragFloatN(label, v, 3, v_speed, v_min, v_max, display_format, power); + return DragFloatN(label, v, 3, v_speed, v_min, v_max, format, power); } -bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* display_format, float power) +bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, float power) { - return DragFloatN(label, v, 4, v_speed, v_min, v_max, display_format, power); + return DragFloatN(label, v, 4, v_speed, v_min, v_max, format, power); } -bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* display_format, const char* display_format_max, float power) +bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* format, const char* format_max, float power) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -9258,10 +9258,10 @@ bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_cu BeginGroup(); PushMultiItemsWidths(2); - bool value_changed = DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format, power); + bool value_changed = DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format, power); PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= DragFloat("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, display_format_max ? display_format_max : display_format, power); + value_changed |= DragFloat("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, format_max ? format_max : format, power); PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); @@ -9273,17 +9273,17 @@ bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_cu } // NB: v_speed is float to allow adjusting the drag speed with more precision -bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* display_format) +bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* format) { - if (!display_format) - display_format = "%.0f"; + if (!format) + format = "%.0f"; float v_f = (float)*v; - bool value_changed = DragFloat(label, &v_f, v_speed, (float)v_min, (float)v_max, display_format); + bool value_changed = DragFloat(label, &v_f, v_speed, (float)v_min, (float)v_max, format); *v = (int)v_f; return value_changed; } -bool ImGui::DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format) +bool ImGui::DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* format) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -9297,7 +9297,7 @@ bool ImGui::DragIntN(const char* label, int* v, int components, float v_speed, i for (int i = 0; i < components; i++) { PushID(i); - value_changed |= DragInt("##v", &v[i], v_speed, v_min, v_max, display_format); + value_changed |= DragInt("##v", &v[i], v_speed, v_min, v_max, format); SameLine(0, g.Style.ItemInnerSpacing.x); PopID(); PopItemWidth(); @@ -9310,22 +9310,22 @@ bool ImGui::DragIntN(const char* label, int* v, int components, float v_speed, i return value_changed; } -bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* display_format) +bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* format) { - return DragIntN(label, v, 2, v_speed, v_min, v_max, display_format); + return DragIntN(label, v, 2, v_speed, v_min, v_max, format); } -bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* display_format) +bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* format) { - return DragIntN(label, v, 3, v_speed, v_min, v_max, display_format); + return DragIntN(label, v, 3, v_speed, v_min, v_max, format); } -bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* display_format) +bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* format) { - return DragIntN(label, v, 4, v_speed, v_min, v_max, display_format); + return DragIntN(label, v, 4, v_speed, v_min, v_max, format); } -bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* display_format, const char* display_format_max) +bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* format, const char* format_max) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -9336,10 +9336,10 @@ bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_ BeginGroup(); PushMultiItemsWidths(2); - bool value_changed = DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format); + bool value_changed = DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format); PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); - value_changed |= DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? INT_MAX : v_max, display_format_max ? display_format_max : display_format); + value_changed |= DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? INT_MAX : v_max, format_max ? format_max : format); PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); @@ -10543,7 +10543,7 @@ bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, co return InputTextEx(label, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data); } -// NB: scalar_format here must be a simple "%xx" format string with no prefix/suffix (unlike the Drag/Slider functions "display_format" argument) +// NB: scalar_format here must be a simple "%xx" format string with no prefix/suffix (unlike the Drag/Slider functions "format" argument) bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags) { ImGuiWindow* window = GetCurrentWindow(); @@ -10610,16 +10610,16 @@ bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, } else { - char display_format[16]; - ImFormatString(display_format, IM_ARRAYSIZE(display_format), "%%.%df", decimal_precision); - return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), display_format, extra_flags); + char format[16]; + ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); + return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), format, extra_flags); } } -bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* display_format, ImGuiInputTextFlags extra_flags) +bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags extra_flags) { extra_flags |= ImGuiInputTextFlags_CharsScientific; - return InputScalarEx(label, ImGuiDataType_Double, (void*)v, (void*)(step>0.0 ? &step : NULL), (void*)(step_fast>0.0 ? &step_fast : NULL), display_format, extra_flags); + return InputScalarEx(label, ImGuiDataType_Double, (void*)v, (void*)(step>0.0 ? &step : NULL), (void*)(step_fast>0.0 ? &step_fast : NULL), format, extra_flags); } bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags extra_flags) diff --git a/imgui.h b/imgui.h index 679c487b..fed66a7a 100644 --- a/imgui.h +++ b/imgui.h @@ -336,16 +336,16 @@ namespace ImGui // Widgets: Drags (tip: ctrl+click on a drag box to input with keyboard. manually input values aren't clamped, can go off-bounds) // For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, note that a 'float v[X]' function argument is the same as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x // Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For gamepad/keyboard navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision). - IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); // If v_min >= v_max we have no bound - IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", const char* display_format_max = NULL, float power = 1.0f); - IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_min >= v_max we have no bound - IMGUI_API bool DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); - IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); - IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); - IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f", const char* display_format_max = NULL); + IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); // If v_min >= v_max we have no bound + IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", const char* format_max = NULL, float power = 1.0f); + IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%.0f"); // If v_min >= v_max we have no bound + IMGUI_API bool DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%.0f"); + IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%.0f"); + IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%.0f"); + IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%.0f", const char* format_max = NULL); // Widgets: Input with Keyboard IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); @@ -358,20 +358,20 @@ namespace ImGui IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags = 0); IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags = 0); IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0f, double step_fast = 0.0f, const char* display_format = "%.6f", ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0f, double step_fast = 0.0f, const char* format = "%.6f", ImGuiInputTextFlags extra_flags = 0); // Widgets: Sliders (tip: ctrl+click on a slider to input with keyboard. manually input values aren't clamped, can go off-bounds) - IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix for in-slider labels or unit display. Use power!=1.0 for logarithmic sliders - IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); + IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); // adjust format to decorate the value with a prefix or a suffix for in-slider labels or unit display. Use power!=1.0 for logarithmic sliders + IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); IMGUI_API bool SliderAngle(const char* label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f); - IMGUI_API bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format = "%.0f"); - IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* display_format = "%.0f"); - IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* display_format = "%.0f"); - IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* display_format = "%.0f"); - IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); - IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format = "%.0f"); + IMGUI_API bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* format = "%.0f"); + IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format = "%.0f"); + IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format = "%.0f"); + IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format = "%.0f"); + IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); + IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format = "%.0f"); // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little colored preview square that can be left-clicked to open a picker, and right-clicked to open an option menu.) // Note that a 'float v[X]' function argument is the same as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can the pass the address of a first float element out of a contiguous structure, e.g. &myvector.x From f80314754cf64cfcafdf38558442abb750c60adf Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 28 Apr 2018 00:11:40 +0200 Subject: [PATCH 11/30] InputFloat,InputFloat2,InputFloat3,InputFloat4: Added variations taking a more flexible and consistent optional "const char* format" parameter instead of "int decimal_precision". This allow using custom formats to display values in scientific notation, and is generally more consistent with other API. Obsoleted functions using the optional "int decimal_precision" parameter. (#648) --- CHANGELOG.txt | 2 ++ imgui.cpp | 64 ++++++++++++++++++++++++++++++++++-------------- imgui.h | 13 +++++++--- imgui_demo.cpp | 6 +++-- imgui_internal.h | 2 +- 5 files changed, 61 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 1a0a4aa3..57134352 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -57,6 +57,8 @@ Other Changes: - InputText: On Mac OS X, filter out characters when the Cmd modifier is held. (#1747) [@sivu] - InputText: On Mac OS X, support Cmd+Shift+Z for Redo. Cmd+Y is also supported as major apps seems to default to support both. (#1765) [@lfnoise] - InputText: Fixed returning true when edition is cancelled with Esc and the current buffer matches the initial value. +- InputFloat,InputFloat2,InputFloat3,InputFloat4: Added variations taking a more flexible and consistent optional "const char* format" parameter instead of "int decimal_precision". + This allow using custom formats to display values in scientific notation, and is generally more consistent with other API. Obsoleted functions using the optional "int decimal_precision" parameter. (#648) - DragFloat, DragInt: Cancel mouse tweak when current value is initially past the min/max boundaries and mouse is pushing in the same direction (keyboard/gamepad version already did this). - DragFloat, SliderFloat: Fix to allow input of scientific notation numbers when using CTRL+Click to input the value. (~#648, #1011) - Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439) diff --git a/imgui.cpp b/imgui.cpp index f1af4861..c51695da 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -262,6 +262,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2018/04/28 (1.61) - obsoleted InputFloat() functions taking an optional "int decimal_precision" in favor of an equivalent and more flexible "const char* format", consistent with other functions. Kept redirection functions (will obsolete). - 2018/04/09 (1.61) - IM_DELETE() helper function added in 1.60 doesn't clear the input _pointer_ reference, more consistent with expectation and allows passing r-value. - 2018/03/20 (1.60) - Renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, _not_ used by core and only honored by some binding ahead of merging the Nav branch). - 2018/03/12 (1.60) - Removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now. @@ -10600,20 +10601,10 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data return value_changed; } -bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags extra_flags) { extra_flags |= ImGuiInputTextFlags_CharsScientific; - if (decimal_precision < 0) - { - // Ideally we'd have a minimum decimal precision of 1 to visually denote that this is a float, while hiding non-significant digits? %f doesn't have a minimum of 1 - return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), "%f", extra_flags); - } - else - { - char format[16]; - ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); - return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), format, extra_flags); - } + return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), format, extra_flags); } bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags extra_flags) @@ -10625,11 +10616,11 @@ bool ImGui::InputDouble(const char* label, double* v, double step, double step_f bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags extra_flags) { // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes. - const char* scalar_format = (extra_flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; - return InputScalarEx(label, ImGuiDataType_Int, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), scalar_format, extra_flags); + const char* format = (extra_flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; + return InputScalarEx(label, ImGuiDataType_Int, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), format, extra_flags); } -bool ImGui::InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags) +bool ImGui::InputFloatN(const char* label, float* v, int components, const char* format, ImGuiInputTextFlags extra_flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -10643,7 +10634,7 @@ bool ImGui::InputFloatN(const char* label, float* v, int components, int decimal for (int i = 0; i < components; i++) { PushID(i); - value_changed |= InputFloat("##v", &v[i], 0, 0, decimal_precision, extra_flags); + value_changed |= InputFloat("##v", &v[i], 0, 0, format, extra_flags); SameLine(0, g.Style.ItemInnerSpacing.x); PopID(); PopItemWidth(); @@ -10656,20 +10647,55 @@ bool ImGui::InputFloatN(const char* label, float* v, int components, int decimal return value_changed; } +bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags extra_flags) +{ + return InputFloatN(label, v, 2, format, extra_flags); +} + +bool ImGui::InputFloat3(const char* label, float v[3], const char* format, ImGuiInputTextFlags extra_flags) +{ + return InputFloatN(label, v, 3, format, extra_flags); +} + +bool ImGui::InputFloat4(const char* label, float v[4], const char* format, ImGuiInputTextFlags extra_flags) +{ + return InputFloatN(label, v, 4, format, extra_flags); +} + +// Prefer using "const char* format" directly, which is more flexible and consistent with other API. +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags) +{ + char format[16] = "%f"; + if (decimal_precision >= 0) + ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); + return InputFloat(label, v, step, step_fast, format, extra_flags); +} + bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags) { - return InputFloatN(label, v, 2, decimal_precision, extra_flags); + char format[16] = "%f"; + if (decimal_precision >= 0) + ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); + return InputFloatN(label, v, 2, format, extra_flags); } bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags) { - return InputFloatN(label, v, 3, decimal_precision, extra_flags); + char format[16] = "%f"; + if (decimal_precision >= 0) + ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); + return InputFloatN(label, v, 3, format, extra_flags); } bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags) { - return InputFloatN(label, v, 4, decimal_precision, extra_flags); + char format[16] = "%f"; + if (decimal_precision >= 0) + ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision); + return InputFloatN(label, v, 4, format, extra_flags); } +#endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS bool ImGui::InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags) { diff --git a/imgui.h b/imgui.h index fed66a7a..f72668dc 100644 --- a/imgui.h +++ b/imgui.h @@ -350,10 +350,10 @@ namespace ImGui // Widgets: Input with Keyboard IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0,0), ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); - IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision = -1, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat2(const char* label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat3(const char* label, float v[3], const char* format = "%.3f", ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputFloat4(const char* label, float v[4], const char* format = "%.3f", ImGuiInputTextFlags extra_flags = 0); IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags extra_flags = 0); IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags = 0); IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags = 0); @@ -1116,6 +1116,11 @@ struct ImGuiIO #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { + // OBSOLETED in 1.61 (from Apr 2018) + bool InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags = 0); // Use the 'const char* format' version instead of 'decimal_precision'! + bool InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); + bool InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); + bool InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags extra_flags = 0); // OBSOLETED in 1.60 (from Dec 2017) static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 872fdbeb..0e85d7ef 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -336,18 +336,20 @@ void ImGui::ShowDemoWindow(bool* p_open) { static char str0[128] = "Hello, world!"; static int i0 = 123; - static float f0 = 0.001f; ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); ImGui::SameLine(); ShowHelpMarker("Hold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n"); ImGui::InputInt("input int", &i0); ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n"); + static float f0 = 0.001f; ImGui::InputFloat("input float", &f0, 0.01f, 1.0f); - // NB: You can use the %e notation as well. static double d0 = 999999.000001; ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.6f"); + + static float f1 = 1.e10f; + ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e"); ImGui::SameLine(); ShowHelpMarker("You can input value using the scientific notation,\n e.g. \"1e+8\" becomes \"100000000\".\n"); static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; diff --git a/imgui_internal.h b/imgui_internal.h index 36556f08..617527fc 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1105,7 +1105,7 @@ namespace ImGui IMGUI_API bool DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format); IMGUI_API bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags); + IMGUI_API bool InputFloatN(const char* label, float* v, int components, const char* format, ImGuiInputTextFlags extra_flags); IMGUI_API bool InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags); IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags); IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision); From d317951b370ff192c4562104c1350cb3e22a9d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Fri, 27 Apr 2018 16:17:25 -0700 Subject: [PATCH 12/30] Demo: Fixed demo from using obsolete functions. --- imgui_demo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0e85d7ef..c885a30b 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1708,14 +1708,14 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Text("ImGui"); ImGui::Button("Apple"); static float foo = 1.0f; - ImGui::InputFloat("red", &foo, 0.05f, 0, 3); + ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f"); ImGui::Text("An extra line here."); ImGui::NextColumn(); ImGui::Text("Sailor"); ImGui::Button("Corniflower"); static float bar = 1.0f; - ImGui::InputFloat("blue", &bar, 0.05f, 0, 3); + ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f"); ImGui::NextColumn(); if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn(); From f2e9dddeca2f3e59f4a5e11dfa83e161dac82946 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 28 Apr 2018 10:43:15 +0200 Subject: [PATCH 13/30] DragDrop: Removed const qualifier from ImGuiPayload 's void* data, easing casting on user side. --- imgui.cpp | 4 ++-- imgui.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c51695da..86f51c08 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -13029,14 +13029,14 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s // Store in heap g.DragDropPayloadBufHeap.resize((int)data_size); payload.Data = g.DragDropPayloadBufHeap.Data; - memcpy((void*)(intptr_t)payload.Data, data, data_size); + memcpy(payload.Data, data, data_size); } else if (data_size > 0) { // Store locally memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); payload.Data = g.DragDropPayloadBufLocal; - memcpy((void*)(intptr_t)payload.Data, data, data_size); + memcpy(payload.Data, data, data_size); } else { diff --git a/imgui.h b/imgui.h index f72668dc..06eeda71 100644 --- a/imgui.h +++ b/imgui.h @@ -1374,7 +1374,7 @@ struct ImGuiSizeCallbackData struct ImGuiPayload { // Members - const void* Data; // Data (copied and owned by dear imgui) + void* Data; // Data (copied and owned by dear imgui) int DataSize; // Data size // [Internal] From 429f48bb4fa7fdffdb996e4a697d6df48babe3eb Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 29 Apr 2018 12:19:44 +0200 Subject: [PATCH 14/30] Clarified usage of ListBoxHeader() before we rename those functions + fixed demo code that didn't honor it correctly. (#1783) --- imgui.h | 4 ++-- imgui_demo.cpp | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/imgui.h b/imgui.h index 06eeda71..0f135c84 100644 --- a/imgui.h +++ b/imgui.h @@ -407,9 +407,9 @@ namespace ImGui IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1); IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); - IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. make sure to call ListBoxFooter() afterwards. + IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. if the function return true, you can output elements then call ListBoxFooter() afterwards. IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // " - IMGUI_API void ListBoxFooter(); // terminate the scrolling region + IMGUI_API void ListBoxFooter(); // terminate the scrolling region. only call ListBoxFooter() if ListBoxHeader() returned true! // Widgets: Value() Helpers. Output single value in "name: value" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace) IMGUI_API void Value(const char* prefix, bool b); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c885a30b..6717aaaa 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1299,10 +1299,12 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Button("LEVERAGE\nBUZZWORD", size); ImGui::SameLine(); - ImGui::ListBoxHeader("List", size); - ImGui::Selectable("Selected", true); - ImGui::Selectable("Not Selected", false); - ImGui::ListBoxFooter(); + if (ImGui::ListBoxHeader("List", size)) + { + ImGui::Selectable("Selected", true); + ImGui::Selectable("Not Selected", false); + ImGui::ListBoxFooter(); + } ImGui::TreePop(); } From d7e24416dd2d8b0ff82dff433c89f04b961338cc Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Apr 2018 11:08:45 +0200 Subject: [PATCH 15/30] DragFloat/SliderFloat internal InputScalar relies on the user supplied format string to format and parse value. (#648) The trailing text after the format will be displayed in the InputText but not affect back parsing. Ideally we can try to strip it later. --- imgui.cpp | 49 +++++++++++++++++++----------------------------- imgui_internal.h | 15 ++++++++------- 2 files changed, 27 insertions(+), 37 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 86f51c08..78734d7c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -748,7 +748,6 @@ static int InputTextCalcTextLenAndLineCount(const char* text_begin, static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format); -static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, int decimal_precision); static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2); static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format); @@ -8454,30 +8453,6 @@ static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType da return 0; } -static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, int decimal_precision) -{ - if (decimal_precision < 0) - { - if (data_type == ImGuiDataType_Int) - return ImFormatString(buf, buf_size, "%d", *(const int*)data_ptr); - if (data_type == ImGuiDataType_Float) - return ImFormatString(buf, buf_size, "%f", *(const float*)data_ptr); // Ideally we'd have a minimum decimal precision of 1 to visually denote that it is a float, while hiding non-significant digits? - if (data_type == ImGuiDataType_Double) - return ImFormatString(buf, buf_size, "%f", *(const double*)data_ptr); - } - else - { - if (data_type == ImGuiDataType_Int) - return ImFormatString(buf, buf_size, "%.*d", decimal_precision, *(const int*)data_ptr); - if (data_type == ImGuiDataType_Float) - return ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(const float*)data_ptr); - if (data_type == ImGuiDataType_Double) - return ImFormatString(buf, buf_size, "%.*g", decimal_precision, *(const double*)data_ptr); - } - IM_ASSERT(0); - return 0; -} - static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg1, const void* arg2) { IM_ASSERT(op == '+' || op == '-'); @@ -8582,7 +8557,7 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_b // Create text input in place of a slider (when CTRL+Clicking on slider) // FIXME: Logic is messy and confusing. -bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision) +bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -8595,9 +8570,10 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label FocusableItemUnregister(window); char buf[32]; - DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, decimal_precision); + format = ParseFormatSkipLeadingText(format); + DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, format); ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal); - bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), aabb.GetSize(), flags); + bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), bb.GetSize(), flags); if (g.ScalarAsInputTextId == 0) // First frame we started displaying the InputText widget { IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible) @@ -8609,6 +8585,19 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label return false; } +const char* ImGui::ParseFormatSkipLeadingText(const char* fmt) +{ + if (fmt[0] == '%') + return fmt; + while (char c = fmt[0]) + { + if (c == '%' && fmt[1] != '%') + return fmt; + fmt++; + } + return fmt; +} + // Parse display precision back from the display format string int ImGui::ParseFormatPrecision(const char* fmt, int default_precision) { @@ -8880,7 +8869,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c } } if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) - return InputScalarAsWidgetReplacement(frame_bb, label, ImGuiDataType_Float, v, id, decimal_precision); + return InputScalarAsWidgetReplacement(frame_bb, id, label, ImGuiDataType_Float, v, format); // Actual slider behavior + render grab ItemSize(total_bb, style.FramePadding.y); @@ -9189,7 +9178,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f } } if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) - return InputScalarAsWidgetReplacement(frame_bb, label, ImGuiDataType_Float, v, id, decimal_precision); + return InputScalarAsWidgetReplacement(frame_bb, id, label, ImGuiDataType_Float, v, format); // Actual drag behavior ItemSize(total_bb, style.FramePadding.y); diff --git a/imgui_internal.h b/imgui_internal.h index 617527fc..548d7729 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1097,18 +1097,18 @@ namespace ImGui IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius); IMGUI_API bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power); - IMGUI_API bool SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format); + IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* format, float power); + IMGUI_API bool SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* format); IMGUI_API bool DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power); - IMGUI_API bool DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power); - IMGUI_API bool DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format); + IMGUI_API bool DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* format, float power); + IMGUI_API bool DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* format); IMGUI_API bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputFloatN(const char* label, float* v, int components, const char* format, ImGuiInputTextFlags extra_flags); IMGUI_API bool InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags); - IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags); - IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision); + IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* format, ImGuiInputTextFlags extra_flags); + IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format); IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); IMGUI_API void ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags); @@ -1119,7 +1119,8 @@ namespace ImGui IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size); - IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value); + IMGUI_API const char* ParseFormatSkipLeadingText(const char* format); + IMGUI_API int ParseFormatPrecision(const char* format, int default_value); IMGUI_API float RoundScalar(float value, int decimal_precision); // Shade functions (write over already created vertices) From 6881d065b8bb0fc4949c2a65d818f61c1e3c6903 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Apr 2018 15:59:59 +0200 Subject: [PATCH 16/30] DragFloat/SliderFloat internal InputScalar trip trailing decoration off the format string when presenting an edit box to the user. (#648) --- CHANGELOG.txt | 2 +- imgui.cpp | 47 ++++++++++++++++++++++++++++++++--------------- imgui_internal.h | 2 +- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 57134352..a1de9d64 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -60,7 +60,7 @@ Other Changes: - InputFloat,InputFloat2,InputFloat3,InputFloat4: Added variations taking a more flexible and consistent optional "const char* format" parameter instead of "int decimal_precision". This allow using custom formats to display values in scientific notation, and is generally more consistent with other API. Obsoleted functions using the optional "int decimal_precision" parameter. (#648) - DragFloat, DragInt: Cancel mouse tweak when current value is initially past the min/max boundaries and mouse is pushing in the same direction (keyboard/gamepad version already did this). -- DragFloat, SliderFloat: Fix to allow input of scientific notation numbers when using CTRL+Click to input the value. (~#648, #1011) +- DragFloat, SliderFloat: Fixes to allow input of scientific notation numbers when using CTRL+Click to input the value. (~#648, #1011) - Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439) - Misc: Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769) - Demo: Fixed Overlay: Added a context menu item to enable freely moving the window. diff --git a/imgui.cpp b/imgui.cpp index 78734d7c..1efce826 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8569,33 +8569,50 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const c SetHoveredID(0); FocusableItemUnregister(window); - char buf[32]; - format = ParseFormatSkipLeadingText(format); - DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, format); + char fmt_buf[32]; + char data_buf[32]; + format = ParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf)); + DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, data_ptr, format); ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal); - bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), bb.GetSize(), flags); + bool value_changed = InputTextEx(label, data_buf, IM_ARRAYSIZE(data_buf), bb.GetSize(), flags); if (g.ScalarAsInputTextId == 0) // First frame we started displaying the InputText widget { - IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible) + IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID g.ScalarAsInputTextId = g.ActiveId; SetHoveredID(id); } - if (text_value_changed) - return DataTypeApplyOpFromText(buf, GImGui->InputTextState.InitialText.begin(), data_type, data_ptr, NULL); + if (value_changed) + return DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialText.begin(), data_type, data_ptr, NULL); return false; } -const char* ImGui::ParseFormatSkipLeadingText(const char* fmt) +// Extract the format out of a format string with leading or trailing decorations +// fmt = "blah blah" -> return fmt +// fmt = "%.3f" -> return fmt +// fmt = "hello %.3f" -> return fmt + 6 +// fmt = "%.3f hello" -> return buf written with "%.3f" +const char* ImGui::ParseFormatTrimDecorations(const char* fmt, char* buf, int buf_size) { - if (fmt[0] == '%') - return fmt; - while (char c = fmt[0]) + // We don't use strchr() because our strings are usually very short and often start with '%' + const char* fmt_start = fmt; + while (char c = *fmt++) { - if (c == '%' && fmt[1] != '%') - return fmt; - fmt++; + if (c != '%') continue; // Looking for % + if (fmt[0] == '%') { fmt++; continue; } // Ignore "%%" + fmt_start = fmt - 1; + while ((c = *fmt++) != 0) + { + if (c >= 'A' && c <= 'Z' && (c != 'L')) // L is a type modifier, other letters qualify as types aka end of the format + break; + if (c >= 'a' && c <= 'z' && (c != 'h' && c != 'j' && c != 'l' && c != 't' && c != 'w' && c != 'z')) // h/j/l/t/w/z are type modifiers, other letters qualify as types aka end of the format + break; + } + if (fmt[0] == 0) // If we only have leading decoration, we don't need to copy the data. + return fmt_start; + ImStrncpy(buf, fmt_start, ImMin((int)(fmt + 1 - fmt_start), buf_size)); + return buf; } - return fmt; + return fmt_start; } // Parse display precision back from the display format string diff --git a/imgui_internal.h b/imgui_internal.h index 548d7729..8e7f935b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1119,7 +1119,7 @@ namespace ImGui IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size); - IMGUI_API const char* ParseFormatSkipLeadingText(const char* format); + IMGUI_API const char* ParseFormatTrimDecorations(const char* format, char* buf, int buf_size); IMGUI_API int ParseFormatPrecision(const char* format, int default_value); IMGUI_API float RoundScalar(float value, int decimal_precision); From 92f0165f8540b7294db864877c614bc728ff51d7 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Apr 2018 16:44:57 +0200 Subject: [PATCH 17/30] DragFloat, SliderFloat: Rounding scalar using the provided format string instead of parsed precision. (#648) --- CHANGELOG.txt | 1 + imgui.cpp | 83 +++++++++++++++++++++++------------------------- imgui_internal.h | 7 ++-- 3 files changed, 45 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a1de9d64..d3442339 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -61,6 +61,7 @@ Other Changes: This allow using custom formats to display values in scientific notation, and is generally more consistent with other API. Obsoleted functions using the optional "int decimal_precision" parameter. (#648) - DragFloat, DragInt: Cancel mouse tweak when current value is initially past the min/max boundaries and mouse is pushing in the same direction (keyboard/gamepad version already did this). - DragFloat, SliderFloat: Fixes to allow input of scientific notation numbers when using CTRL+Click to input the value. (~#648, #1011) +- DragFloat, SliderFloat: Rounding-on-write uses the provided format string instead of parsing the precision from the string, which allows for finer uses of %e %g etc. (#648, #642) - Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439) - Misc: Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769) - Demo: Fixed Overlay: Added a context menu item to enable freely moving the window. diff --git a/imgui.cpp b/imgui.cpp index 1efce826..44cc0cc3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8586,6 +8586,19 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const c return false; } +const char* ImGui::ParseFormatTrimDecorationsLeading(const char* fmt) +{ + while (char c = fmt[0]) + { + if (c == '%' && fmt[1] != '%') + return fmt; + else if (c == '%') + fmt++; + fmt++; + } + return fmt; +} + // Extract the format out of a format string with leading or trailing decorations // fmt = "blah blah" -> return fmt // fmt = "%.3f" -> return fmt @@ -8594,25 +8607,21 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const c const char* ImGui::ParseFormatTrimDecorations(const char* fmt, char* buf, int buf_size) { // We don't use strchr() because our strings are usually very short and often start with '%' - const char* fmt_start = fmt; + const char* fmt_start = ParseFormatTrimDecorationsLeading(fmt); + if (fmt_start[0] != '%') + return fmt; + fmt = fmt_start; while (char c = *fmt++) { - if (c != '%') continue; // Looking for % - if (fmt[0] == '%') { fmt++; continue; } // Ignore "%%" - fmt_start = fmt - 1; - while ((c = *fmt++) != 0) - { - if (c >= 'A' && c <= 'Z' && (c != 'L')) // L is a type modifier, other letters qualify as types aka end of the format - break; - if (c >= 'a' && c <= 'z' && (c != 'h' && c != 'j' && c != 'l' && c != 't' && c != 'w' && c != 'z')) // h/j/l/t/w/z are type modifiers, other letters qualify as types aka end of the format - break; - } - if (fmt[0] == 0) // If we only have leading decoration, we don't need to copy the data. - return fmt_start; - ImStrncpy(buf, fmt_start, ImMin((int)(fmt + 1 - fmt_start), buf_size)); - return buf; + if (c >= 'A' && c <= 'Z' && (c != 'L')) // L is a type modifier, other letters qualify as types aka end of the format + break; + if (c >= 'a' && c <= 'z' && (c != 'h' && c != 'j' && c != 'l' && c != 't' && c != 'w' && c != 'z')) // h/j/l/t/w/z are type modifiers, other letters qualify as types aka end of the format + break; } - return fmt_start; + if (fmt[0] == 0) // If we only have leading decoration, we don't need to copy the data. + return fmt_start; + ImStrncpy(buf, fmt_start, ImMin((int)(fmt + 1 - fmt_start), buf_size)); + return buf; } // Parse display precision back from the display format string @@ -8644,22 +8653,11 @@ static float GetMinimumStepAtDecimalPrecision(int decimal_precision) return (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : powf(10.0f, (float)-decimal_precision); } -float ImGui::RoundScalar(float value, int decimal_precision) +float ImGui::RoundScalarWithFormat(const char* format, float value) { - // Round past decimal precision - // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 - // FIXME: Investigate better rounding methods - if (decimal_precision < 0) - return value; - const float min_step = GetMinimumStepAtDecimalPrecision(decimal_precision); - bool negative = value < 0.0f; - value = fabsf(value); - float remainder = fmodf(value, min_step); - if (remainder <= min_step*0.5f) - value -= remainder; - else - value += (min_step - remainder); - return negative ? -value : value; + char buf[64]; + ImFormatString(buf, IM_ARRAYSIZE(buf), ParseFormatTrimDecorationsLeading(format), value); + return (float)atof(buf); } static inline float SliderBehaviorCalcRatioFromValue(float v, float v_min, float v_max, float power, float linear_zero_pos) @@ -8687,7 +8685,7 @@ static inline float SliderBehaviorCalcRatioFromValue(float v, float v_min, float return (v_clamped - v_min) / (v_max - v_min); } -bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags) +bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, const char* format, float power, ImGuiSliderFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -8700,11 +8698,12 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v const bool is_non_linear = (power < 1.0f-0.00001f) || (power > 1.0f+0.00001f); const bool is_horizontal = (flags & ImGuiSliderFlags_Vertical) == 0; + const bool is_decimal = ParseFormatPrecision(format, 3) > 0; const float grab_padding = 2.0f; const float slider_sz = is_horizontal ? (frame_bb.GetWidth() - grab_padding * 2.0f) : (frame_bb.GetHeight() - grab_padding * 2.0f); float grab_sz; - if (decimal_precision != 0) + if (is_decimal) grab_sz = ImMin(style.GrabMinSize, slider_sz); else grab_sz = ImMin(ImMax(1.0f * (slider_sz / ((v_min < v_max ? v_max - v_min : v_min - v_max) + 1.0f)), style.GrabMinSize), slider_sz); // Integer sliders, if possible have the grab size represent 1 unit @@ -8759,7 +8758,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v else if (delta != 0.0f) { clicked_t = SliderBehaviorCalcRatioFromValue(*v, v_min, v_max, power, linear_zero_pos); - if (decimal_precision == 0 && !is_non_linear) + if (!is_decimal && !is_non_linear) { if (fabsf(v_max - v_min) <= 100.0f || IsNavInputDown(ImGuiNavInput_TweakSlow)) delta = ((delta < 0.0f) ? -1.0f : +1.0f) / (v_max - v_min); // Gamepad/keyboard tweak speeds in integer steps @@ -8814,7 +8813,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v } // Round past decimal precision - new_value = RoundScalar(new_value, decimal_precision); + new_value = RoundScalarWithFormat(format, new_value); if (*v != new_value) { *v = new_value; @@ -8868,7 +8867,6 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c if (!format) format = "%.3f"; - int decimal_precision = ParseFormatPrecision(format, 3); // Tabbing or CTRL-clicking on Slider turns it into an input box bool start_text_input = false; @@ -8890,7 +8888,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c // Actual slider behavior + render grab ItemSize(total_bb, style.FramePadding.y); - const bool value_changed = SliderBehavior(frame_bb, id, v, v_min, v_max, power, decimal_precision); + const bool value_changed = SliderBehavior(frame_bb, id, v, v_min, v_max, format, power); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; @@ -8924,7 +8922,6 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float if (!format) format = "%.3f"; - int decimal_precision = ParseFormatPrecision(format, 3); if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id) { @@ -8935,7 +8932,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float } // Actual slider behavior + render grab - bool value_changed = SliderBehavior(frame_bb, id, v, v_min, v_max, power, decimal_precision, ImGuiSliderFlags_Vertical); + bool value_changed = SliderBehavior(frame_bb, id, v, v_min, v_max, format, power, ImGuiSliderFlags_Vertical); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // For the vertical slider we allow centered text to overlap the frame padding @@ -9061,7 +9058,7 @@ bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const return SliderIntN(label, v, 4, v_min, v_max, format); } -bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power) +bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, const char* format, float power) { ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; @@ -9106,6 +9103,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s } if (g.ActiveIdSource == ImGuiInputSource_Nav) { + int decimal_precision = ParseFormatPrecision(format, 3); adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); } @@ -9141,7 +9139,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s // Round to user desired precision, then apply bool value_changed = false; - v_cur = RoundScalar(v_cur, decimal_precision); + v_cur = RoundScalarWithFormat(format, v_cur); if (*v != v_cur) { *v = v_cur; @@ -9177,7 +9175,6 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f if (!format) format = "%.3f"; - int decimal_precision = ParseFormatPrecision(format, 3); // Tabbing or CTRL-clicking on Drag turns it into an input box bool start_text_input = false; @@ -9199,7 +9196,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f // Actual drag behavior ItemSize(total_bb, style.FramePadding.y); - const bool value_changed = DragBehavior(frame_bb, id, v, v_speed, v_min, v_max, decimal_precision, power); + const bool value_changed = DragBehavior(frame_bb, id, v, v_speed, v_min, v_max, format, power); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; diff --git a/imgui_internal.h b/imgui_internal.h index 8e7f935b..6da76e01 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1096,11 +1096,11 @@ namespace ImGui IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0); IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius); - IMGUI_API bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags = 0); + IMGUI_API bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, const char* format, float power, ImGuiSliderFlags flags = 0); IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* format, float power); IMGUI_API bool SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* format); - IMGUI_API bool DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power); + IMGUI_API bool DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, const char* format, float power); IMGUI_API bool DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* format, float power); IMGUI_API bool DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* format); @@ -1119,9 +1119,10 @@ namespace ImGui IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size); + IMGUI_API const char* ParseFormatTrimDecorationsLeading(const char* format); IMGUI_API const char* ParseFormatTrimDecorations(const char* format, char* buf, int buf_size); IMGUI_API int ParseFormatPrecision(const char* format, int default_value); - IMGUI_API float RoundScalar(float value, int decimal_precision); + IMGUI_API float RoundScalarWithFormat(const char* format, float value); // Shade functions (write over already created vertices) IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1); From a1da7f9860b3f45c2251a37053e3cec4fb099b98 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Apr 2018 16:52:16 +0200 Subject: [PATCH 18/30] Internals: Tweaked ParseFormatPrecision(), clarified its more limited purpose, allowing 2-digits precisions since it makes (some) sense for doubles. (#648) --- imgui.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 44cc0cc3..2db40258 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8625,26 +8625,27 @@ const char* ImGui::ParseFormatTrimDecorations(const char* fmt, char* buf, int bu } // Parse display precision back from the display format string +// FIXME: This is still used by some navigation code path to infer a minimum tweak step, but we should aim to rework widgets so it isn't needed. int ImGui::ParseFormatPrecision(const char* fmt, int default_precision) { - int precision = default_precision; - while ((fmt = strchr(fmt, '%')) != NULL) - { + fmt = ParseFormatTrimDecorationsLeading(fmt); + if (fmt[0] != '%') + return default_precision; + fmt++; + while (*fmt >= '0' && *fmt <= '9') fmt++; - if (fmt[0] == '%') { fmt++; continue; } // Ignore "%%" - while (*fmt >= '0' && *fmt <= '9') - fmt++; - if (*fmt == '.') - { - fmt = ImAtoi(fmt + 1, &precision); - if (precision < 0 || precision > 10) - precision = default_precision; - } - if (*fmt == 'e' || *fmt == 'E') // Maximum precision with scientific notation - precision = -1; - break; + int precision = INT_MAX; + if (*fmt == '.') + { + fmt = ImAtoi(fmt + 1, &precision); + if (precision < 0 || precision > 99) + precision = default_precision; } - return precision; + if (*fmt == 'e' || *fmt == 'E') // Maximum precision with scientific notation + precision = -1; + if ((*fmt == 'g' || *fmt == 'G') && precision == INT_MAX) + precision = -1; + return (precision == INT_MAX) ? default_precision : precision; } static float GetMinimumStepAtDecimalPrecision(int decimal_precision) From 7df985bc5c0b5b7ed1759f18f79d05025b1e613a Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Apr 2018 19:40:25 +0200 Subject: [PATCH 19/30] Nav: Fixed hovering a Selectable() with the mouse so that it update the navigation cursor. Fixed c8b9b2c6 which was incorrect (#787) --- CHANGELOG.txt | 3 ++- imgui.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d3442339..4554d69d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -60,8 +60,9 @@ Other Changes: - InputFloat,InputFloat2,InputFloat3,InputFloat4: Added variations taking a more flexible and consistent optional "const char* format" parameter instead of "int decimal_precision". This allow using custom formats to display values in scientific notation, and is generally more consistent with other API. Obsoleted functions using the optional "int decimal_precision" parameter. (#648) - DragFloat, DragInt: Cancel mouse tweak when current value is initially past the min/max boundaries and mouse is pushing in the same direction (keyboard/gamepad version already did this). -- DragFloat, SliderFloat: Fixes to allow input of scientific notation numbers when using CTRL+Click to input the value. (~#648, #1011) +- DragFloat, SliderFloat: Fixes to allow input of scientific notation numbers when using CTRL+Click to input the value. (~#648, #1011) - DragFloat, SliderFloat: Rounding-on-write uses the provided format string instead of parsing the precision from the string, which allows for finer uses of %e %g etc. (#648, #642) +- Nav: Fixed hovering a Selectable() with the mouse so that it update the navigation cursor (as it happened in the pre 1.60 navigation branch). (#787) - Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439) - Misc: Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769) - Demo: Fixed Overlay: Added a context menu item to enable freely moving the window. diff --git a/imgui.cpp b/imgui.cpp index 2db40258..d44c7b5d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11013,8 +11013,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl selected = false; // Hovering selectable with mouse updates NavId accordingly so navigation can be resumed with gamepad/keyboard (this doesn't happen on most widgets) - if (pressed || hovered)// && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) - if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerActiveMask) + if (pressed || hovered) + if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) { g.NavDisableHighlight = true; SetNavID(id, window->DC.NavLayerCurrent); From ed756d474e55cf3ed6d4cd66bd8cfa532a519f8c Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Apr 2018 20:02:33 +0200 Subject: [PATCH 20/30] Internals: Added ImGuiDataType_Uint32 data type which is usable with InputScalarEx(). --- imgui.cpp | 55 +++++++++++++++++++++++++++++++++--------------- imgui_internal.h | 5 +++-- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d44c7b5d..7be4e381 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8443,7 +8443,7 @@ void ImGui::BulletText(const char* fmt, ...) static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format) { - if (data_type == ImGuiDataType_Int) + if (data_type == ImGuiDataType_Int32 || data_type == ImGuiDataType_Uint32) return ImFormatString(buf, buf_size, format, *(const int*)data_ptr); if (data_type == ImGuiDataType_Float) return ImFormatString(buf, buf_size, format, *(const float*)data_ptr); @@ -8456,11 +8456,16 @@ static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType da static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg1, const void* arg2) { IM_ASSERT(op == '+' || op == '-'); - if (data_type == ImGuiDataType_Int) + if (data_type == ImGuiDataType_Int32) { if (op == '+') *(int*)output = *(const int*)arg1 + *(const int*)arg2; else if (op == '-') *(int*)output = *(const int*)arg1 - *(const int*)arg2; } + else if (data_type == ImGuiDataType_Uint32) + { + if (op == '+') *(unsigned int*)output = *(const unsigned int*)arg1 + *(const unsigned int*)arg2; + else if (op == '-') *(unsigned int*)output = *(const unsigned int*)arg1 - *(const unsigned int*)arg2; + } else if (data_type == ImGuiDataType_Float) { if (op == '+') *(float*)output = *(const float*)arg1 + *(const float*)arg2; @@ -8476,12 +8481,13 @@ static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* static size_t GDataTypeSize[ImGuiDataType_COUNT] = { sizeof(int), + sizeof(unsigned int), sizeof(float), sizeof(double) }; // User can input math operators (e.g. +100) to edit a numerical values. -// NB: This is _not_ a full expression evaluator. We should probably add one though.. +// NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess.. static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format) { while (ImCharIsSpace((unsigned int)*buf)) @@ -8508,7 +8514,9 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_b IM_ASSERT(GDataTypeSize[data_type] <= sizeof(data_backup)); memcpy(data_backup, data_ptr, GDataTypeSize[data_type]); - if (data_type == ImGuiDataType_Int) + int arg1i = 0; + float arg1f = 0.0f; + if (data_type == ImGuiDataType_Int32) { if (!scalar_format) scalar_format = "%d"; @@ -8517,18 +8525,31 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_b if (op && sscanf(initial_value_buf, scalar_format, &arg0i) < 1) return false; // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision - float arg1f = 0.0f; - if (op == '+') { if (sscanf(buf, "%f", &arg1f) == 1) *v = (int)(arg0i + arg1f); } // Add (use "+-" to subtract) - else if (op == '*') { if (sscanf(buf, "%f", &arg1f) == 1) *v = (int)(arg0i * arg1f); } // Multiply - else if (op == '/') { if (sscanf(buf, "%f", &arg1f) == 1 && arg1f != 0.0f) *v = (int)(arg0i / arg1f); }// Divide - else { if (sscanf(buf, scalar_format, &arg0i) == 1) *v = arg0i; } // Assign integer constant + if (op == '+') { if (sscanf(buf, "%d", &arg1i)) *v = (int)(arg0i + arg1i); } // Add (use "+-" to subtract) + else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (int)(arg0i * arg1f); } // Multiply + else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (int)(arg0i / arg1f); } // Divide + else { if (sscanf(buf, scalar_format, &arg0i) == 1) *v = arg0i; } // Assign integer constant + } + else if (data_type == ImGuiDataType_Uint32) + { + if (!scalar_format) + scalar_format = "%u"; + ImU32* v = (unsigned int*)data_ptr; + ImU32 arg0i = *v; + if (op && sscanf(initial_value_buf, scalar_format, &arg0i) < 1) + return false; + // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision + if (op == '+') { if (sscanf(buf, "%d", &arg1i)) *v = (ImU32)(arg0i + arg1f); } // Add (use "+-" to subtract) + else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (ImU32)(arg0i * arg1f); } // Multiply + else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (ImU32)(arg0i / arg1f); }// Divide + else { if (sscanf(buf, scalar_format, &arg0i) == 1) *v = arg0i; } // Assign integer constant } else if (data_type == ImGuiDataType_Float) { // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in scalar_format = "%f"; float* v = (float*)data_ptr; - float arg0f = *v, arg1f = 0.0f; + float arg0f = *v; if (op && sscanf(initial_value_buf, scalar_format, &arg0f) < 1) return false; if (sscanf(buf, scalar_format, &arg1f) < 1) @@ -8540,9 +8561,9 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_b } else if (data_type == ImGuiDataType_Double) { - scalar_format = "%lf"; + scalar_format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis double* v = (double*)data_ptr; - double arg0f = *v, arg1f = 0.0f; + double arg0f = *v; if (op && sscanf(initial_value_buf, scalar_format, &arg0f) < 1) return false; if (sscanf(buf, scalar_format, &arg1f) < 1) @@ -10558,12 +10579,12 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImVec2 label_size = CalcTextSize(label, NULL, true); + const ImVec2 button_size = ImVec2(GetFrameHeight(), GetFrameHeight()); BeginGroup(); PushID(label); - const ImVec2 button_sz = ImVec2(GetFrameHeight(), GetFrameHeight()); if (step_ptr) - PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_sz.x + style.ItemInnerSpacing.x)*2)); + PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size.x + style.ItemInnerSpacing.x)*2)); char buf[64]; DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, scalar_format); @@ -10580,13 +10601,13 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data { PopItemWidth(); SameLine(0, style.ItemInnerSpacing.x); - if (ButtonEx("-", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) + if (ButtonEx("-", button_size, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) { DataTypeApplyOp(data_type, '-', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr); value_changed = true; } SameLine(0, style.ItemInnerSpacing.x); - if (ButtonEx("+", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) + if (ButtonEx("+", button_size, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) { DataTypeApplyOp(data_type, '+', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr); value_changed = true; @@ -10621,7 +10642,7 @@ bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiIn { // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes. const char* format = (extra_flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; - return InputScalarEx(label, ImGuiDataType_Int, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), format, extra_flags); + return InputScalarEx(label, ImGuiDataType_Int32, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), format, extra_flags); } bool ImGui::InputFloatN(const char* label, float* v, int components, const char* format, ImGuiInputTextFlags extra_flags) diff --git a/imgui_internal.h b/imgui_internal.h index 6da76e01..411db886 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -246,7 +246,8 @@ enum ImGuiPlotType enum ImGuiDataType { - ImGuiDataType_Int, + ImGuiDataType_Int32, + ImGuiDataType_Uint32, ImGuiDataType_Float, ImGuiDataType_Double, ImGuiDataType_COUNT @@ -1107,7 +1108,7 @@ namespace ImGui IMGUI_API bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputFloatN(const char* label, float* v, int components, const char* format, ImGuiInputTextFlags extra_flags); IMGUI_API bool InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags); - IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* format, ImGuiInputTextFlags extra_flags); + IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* format, ImGuiInputTextFlags extra_flags = 0); IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format); IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); From ef05141a06d8a4cf8921d453690f6775044adf34 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Apr 2018 20:12:14 +0200 Subject: [PATCH 21/30] Internals: InputScalarEx: Tweak internals so there is a fast path for the simple case. (in particular because it makes it clear what the extra code is for, so people tempted to create their own InputText data transform/handler understand how little is actually needed) --- imgui.cpp | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7be4e381..8f727b04 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10578,13 +10578,6 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImVec2 button_size = ImVec2(GetFrameHeight(), GetFrameHeight()); - - BeginGroup(); - PushID(label); - if (step_ptr) - PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size.x + style.ItemInnerSpacing.x)*2)); char buf[64]; DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, scalar_format); @@ -10593,35 +10586,42 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data if ((extra_flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0) extra_flags |= ImGuiInputTextFlags_CharsDecimal; extra_flags |= ImGuiInputTextFlags_AutoSelectAll; - if (InputText("", buf, IM_ARRAYSIZE(buf), extra_flags)) // PushId(label) + "" gives us the expected ID from outside point of view - value_changed = DataTypeApplyOpFromText(buf, GImGui->InputTextState.InitialText.begin(), data_type, data_ptr, scalar_format); - // Step buttons if (step_ptr) { + const float button_size = GetFrameHeight(); + + BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive() + PushID(label); + PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2)); + if (InputText("", buf, IM_ARRAYSIZE(buf), extra_flags)) // PushId(label) + "" gives us the expected ID from outside point of view + value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialText.Data, data_type, data_ptr, scalar_format); PopItemWidth(); + + // Step buttons SameLine(0, style.ItemInnerSpacing.x); - if (ButtonEx("-", button_size, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) + if (ButtonEx("-", ImVec2(button_size, button_size), ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) { DataTypeApplyOp(data_type, '-', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr); value_changed = true; } SameLine(0, style.ItemInnerSpacing.x); - if (ButtonEx("+", button_size, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) + if (ButtonEx("+", ImVec2(button_size, button_size), ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) { DataTypeApplyOp(data_type, '+', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr); value_changed = true; } - } - PopID(); - - if (label_size.x > 0) - { SameLine(0, style.ItemInnerSpacing.x); - RenderText(ImVec2(window->DC.CursorPos.x, window->DC.CursorPos.y + style.FramePadding.y), label); - ItemSize(label_size, style.FramePadding.y); + TextUnformatted(label, FindRenderedTextEnd(label)); + + PopID(); + EndGroup(); + } + else + { + if (InputText(label, buf, IM_ARRAYSIZE(buf), extra_flags)) + value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialText.Data, data_type, data_ptr, scalar_format); } - EndGroup(); return value_changed; } From dbe16b6a70c782324e8a9bbc943ac01cfed047b7 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 4 May 2018 14:55:38 +0200 Subject: [PATCH 22/30] Made IMGUI_DISABLE_OBSOLETE_FUNCTIONS exceptionally not affect the layout of ImGuiIO. (#1695) --- imgui.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index 0f135c84..02b75219 100644 --- a/imgui.h +++ b/imgui.h @@ -1043,9 +1043,12 @@ struct ImGuiIO void* ImeWindowHandle; // (Windows) Set this to your HWND to get automatic IME cursor positioning. #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - // [OBSOLETE] Rendering function, will be automatically called in Render(). Please call your rendering function yourself now! You can obtain the ImDrawData* by calling ImGui::GetDrawData() after Render(). - // See example applications if you are unsure of how to implement this. + // [OBSOLETE] Rendering function, will be automatically called in Render(). Please call your rendering function yourself now! + // You can obtain the ImDrawData* by calling ImGui::GetDrawData() after Render(). See example applications if you are unsure of how to implement this. void (*RenderDrawListsFn)(ImDrawData* data); +#else + // This is only here to keep ImGuiIO the same size, so that IMGUI_DISABLE_OBSOLETE_FUNCTIONS can exceptionally be used outside of imconfig.h. + void* RenderDrawListsFnDummy; #endif //------------------------------------------------------------------ From d0051ce5cb302f36708461749d4be026cdce7bf6 Mon Sep 17 00:00:00 2001 From: SR_team Date: Thu, 3 May 2018 12:01:41 +0300 Subject: [PATCH 23/30] add renderstate D3DRS_SHADEMODE for Dx9 impl add backuping transform for Dx9 impl (#1790, #1687) --- examples/directx9_example/imgui_impl_dx9.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index e0f0ac5a..0bbcaff6 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -76,6 +76,12 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0) return; + // Backup the DX9 transform + D3DMATRIX last_world, last_view, last_projection; + g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world); + g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view); + g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection); + // Copy and convert all vertices into a single contiguous buffer CUSTOMVERTEX* vtx_dst; ImDrawIdx* idx_dst; @@ -116,7 +122,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) vp.MaxZ = 1.0f; g_pd3dDevice->SetViewport(&vp); - // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing + // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient) g_pd3dDevice->SetPixelShader(NULL); g_pd3dDevice->SetVertexShader(NULL); g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); @@ -128,6 +134,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, true); + g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); @@ -179,6 +186,11 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) vtx_offset += cmd_list->VtxBuffer.Size; } + // Restore the DX9 transform + g_pd3dDevice->SetTransform(D3DTS_WORLD, &last_world); + g_pd3dDevice->SetTransform(D3DTS_VIEW, &last_view); + g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection); + // Restore the DX9 state d3d9_state_block->Apply(); d3d9_state_block->Release(); From 4310bad32a7ba44ce11e3cb7282eb022884f3cbc Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 7 May 2018 11:52:11 +0200 Subject: [PATCH 24/30] Examples: DirectX9: Comments, updated changelog, notes about usage of imconfig.h (#1790, #1687) --- CHANGELOG.txt | 1 + examples/directx9_example/imgui_impl_dx9.cpp | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 4554d69d..0bac79ad 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -69,6 +69,7 @@ Other Changes: - Examples: Calling IMGUI_CHECKVERSION() in the main.cpp of every example application. - Examples: Allegro 5: Added support for 32-bit indices setup via defining ImDrawIdx, to avoid an unnecessary conversion (Allegro 5 doesn't support 16-bit indices). - Examples: Allegro 5: Renamed bindings from imgui_impl_a5.cpp to imgui_impl_allegro5.cpp. +- Examples: DirectX 9 : Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud. (#1790, #1687) [@sr-tream] - Various minor fixes, tweaks, refactoring, comments. ----------------------------------------------------------------------- diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 0bbcaff6..da0b37b0 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-05-07: Render: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud. // 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself. @@ -76,13 +77,16 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0) return; - // Backup the DX9 transform + // Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to) D3DMATRIX last_world, last_view, last_projection; g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world); g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view); g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection); - // Copy and convert all vertices into a single contiguous buffer + // Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format. + // FIXME-OPT: This is a waste of resource, the ideal is to use imconfig.h and + // 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR + // 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; } CUSTOMVERTEX* vtx_dst; ImDrawIdx* idx_dst; if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0) @@ -98,7 +102,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) vtx_dst->pos[0] = vtx_src->pos.x; vtx_dst->pos[1] = vtx_src->pos.y; vtx_dst->pos[2] = 0.0f; - vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000)>>16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9 + vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000) >> 16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9 vtx_dst->uv[0] = vtx_src->uv.x; vtx_dst->uv[1] = vtx_src->uv.y; vtx_dst++; From 807c4f0ea4337a672d27532b3526b7b1d64d8d98 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 3 May 2018 21:11:53 +0200 Subject: [PATCH 25/30] Ran a spell checker for sanity. --- CHANGELOG.txt | 128 +++++++++++++++++++++++++------------------------- README.md | 12 ++--- 2 files changed, 70 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 0bac79ad..949a5667 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -49,20 +49,20 @@ Other Changes: - Settings: Fixed saving an empty .ini file if CreateContext/DestroyContext are called without a single call to NewFrame(). (#1741) - Window: Fixed default proportional item width lagging by one frame on resize. -- Window: Fixed popups/tooltips/menus not honoring style.DisplaySafeAreaPadding as well as it should have (part of menus displayed outside the safe area, etc.). +- Window: Fixed pop-ups/tooltips/menus not honoring style.DisplaySafeAreaPadding as well as it should have (part of menus displayed outside the safe area, etc.). - Window: Fixed windows using the ImGuiWindowFlags_NoSavedSettings flag from not using the same default position as other windows. (#1760) - Window: Relaxed the internal stack size checker to allow Push/Begin/Pop/.../End patterns to be used with PushStyleColor, PushStyleVar, PushFont without causing a false positive assert. (#1767) - Columns: Fixed a bug introduced in 1.51 where columns would affect the contents size of their container, often creating feedback loops when ImGuiWindowFlags_AlwaysAutoResize was used. (#1760) - MenuBar: Made BeginMainMenuBar() honor style.DisplaySafeAreaPadding so the text can be made visible on TV settings that don't display all pixels. (#1439) [@dougbinks] -- InputText: On Mac OS X, filter out characters when the Cmd modifier is held. (#1747) [@sivu] -- InputText: On Mac OS X, support Cmd+Shift+Z for Redo. Cmd+Y is also supported as major apps seems to default to support both. (#1765) [@lfnoise] -- InputText: Fixed returning true when edition is cancelled with Esc and the current buffer matches the initial value. +- InputText: On Mac OS X, filter out characters when the CMD modifier is held. (#1747) [@sivu] +- InputText: On Mac OS X, support CMD+SHIFT+Z for Redo. CMD+Y is also supported as major apps seems to default to support both. (#1765) [@lfnoise] +- InputText: Fixed returning true when edition is canceled with ESC and the current buffer matches the initial value. - InputFloat,InputFloat2,InputFloat3,InputFloat4: Added variations taking a more flexible and consistent optional "const char* format" parameter instead of "int decimal_precision". This allow using custom formats to display values in scientific notation, and is generally more consistent with other API. Obsoleted functions using the optional "int decimal_precision" parameter. (#648) - DragFloat, DragInt: Cancel mouse tweak when current value is initially past the min/max boundaries and mouse is pushing in the same direction (keyboard/gamepad version already did this). - DragFloat, SliderFloat: Fixes to allow input of scientific notation numbers when using CTRL+Click to input the value. (~#648, #1011) - DragFloat, SliderFloat: Rounding-on-write uses the provided format string instead of parsing the precision from the string, which allows for finer uses of %e %g etc. (#648, #642) -- Nav: Fixed hovering a Selectable() with the mouse so that it update the navigation cursor (as it happened in the pre 1.60 navigation branch). (#787) +- Nav: Fixed hovering a Selectable() with the mouse so that it update the navigation cursor (as it happened in the pre-1.60 navigation branch). (#787) - Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439) - Misc: Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769) - Demo: Fixed Overlay: Added a context menu item to enable freely moving the window. @@ -79,15 +79,15 @@ Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.60 The gamepad/keyboard navigation branch (which has been in the work since July 2016) has been merged. Gamepad/keyboard navigation is still marked as Beta and has to be enabled explicitly. -Various internal refactors have also been done, as part of the navigation work and as part of the upcoming viewport/docking work. +Various internal refactoring have also been done, as part of the navigation work and as part of the upcoming viewport/docking work. Breaking Changes: - Obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). - e.g. with example back-ends, call ImDrawData* draw_data = ImGui::GetDrawData(); ImGui_ImplXXXX_RenderDrawData(draw_data). + e.g. with example backends, call ImDrawData* draw_data = ImGui::GetDrawData(); ImGui_ImplXXXX_RenderDrawData(draw_data). - Reorganized context handling to be more explicit: (#1599) - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. - - removed Shutdown() function, as DestroyContext() serve this purpose. If you are using an old back-end from the examples/ folder, remove the line that calls Shutdown(). + - removed Shutdown() function, as DestroyContext() serve this purpose. If you are using an old backend from the examples/ folder, remove the line that calls Shutdown(). - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwise CreateContext() will create its own font atlas instance. - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts. - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts. @@ -129,23 +129,23 @@ Other Changes: - Context: Added SetAllocatorFunctions() to rewire memory allocators (as a replacement to previous parameters to CreateContext()). Allocators are shared by all contexts and imgui helpers. (#1565, #586, #992, #1007, #1558) - Context: You may pass a ImFontAtlas to CreateContext() to specify a font atlas to share. Shared font atlas are not owned by the context and not destroyed along with it. (#1599) - Context: Added IMGUI_DISABLE_DEFAULT_ALLOCATORS to disable linking with malloc/free. (#1565, #586, #992, #1007, #1558) -- IO: Added io.ConfigFlags for user application to store settings for imgui and for the back-end: +- IO: Added io.ConfigFlags for user application to store settings for imgui and for the backend: - ImGuiConfigFlags_NavEnableKeyboard: Enable keyboard navigation. - - ImGuiConfigFlags_NavEnableGamepad: Enable gamepad navigation (provided ImGuiBackendFlags_HasGamepad is also set by back-end). + - ImGuiConfigFlags_NavEnableGamepad: Enable gamepad navigation (provided ImGuiBackendFlags_HasGamepad is also set by backend). - ImGuiConfigFlags_NavEnableSetMousePos: Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. - - ImGuiConfigFlags_NoMouseCursorChange: Instruct back-end to not alter mouse cursor shape and visibility (by default the example back-end use mouse cursor API of the platform when available) - - ImGuiConfigFlags_NoMouse: Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information passed by the back-end. + - ImGuiConfigFlags_NoMouseCursorChange: Instruct backend to not alter mouse cursor shape and visibility (by default the example backend use mouse cursor API of the platform when available) + - ImGuiConfigFlags_NoMouse: Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information passed by the backend. - ImGuiConfigFlags_IsSRGB, ImGuiConfigFlags_IsTouchScreen: Flags for general application use. -- IO: Added io.BackendFlags for back-end to store its capabilities (currently: _HasGamepad, _HasMouseCursors, _HasSetMousePos). This will be used more in the next version. +- IO: Added io.BackendFlags for backend to store its capabilities (currently: _HasGamepad, _HasMouseCursors, _HasSetMousePos). This will be used more in the next version. - IO: Added ImGuiKey_Insert, ImGuiKey_Space keys. Setup in all example bindings. (#1541) - IO: Added Horizontal Mouse Wheel support for horizontal scrolling. (#1463) [@tseeker] - IO: Added IsAnyMouseDown() helper which is helpful for bindings to handle mouse capturing. - Window: Clicking on a window with the ImGuiWIndowFlags_NoMove flags takes an ActiveId so we can't hover something else when dragging afterwards. (#1381, #1337) - Window: IsWindowHovered(): Added ImGuiHoveredFlags_AnyWindow, ImGuiFocusedFlags_AnyWindow flags (See Breaking Changes). Added to demo. (#1382) -- Window: Added SetNextWindowBgAlpha() helper. Particularly helpul since the legacy 5-parameters version of Begin() has been marked as obsolete in 1.53. (#1567) +- Window: Added SetNextWindowBgAlpha() helper. Particularly helpful since the legacy 5-parameters version of Begin() has been marked as obsolete in 1.53. (#1567) - Window: Fixed SetNextWindowContentSize() with 0.0f on Y axis (or SetNextWindowContentWidth()) overwriting the contents size. Got broken on Dec 10 (1.53). (#1363) - ArrowButton: Added ArrowButton() given a cardinal direction (e.g. ImGuiDir_Left). -- InputText: Added alternative clipboard shortcuts: Shift+Delete (cut), Ctrl+Insert (copy), Shift+Insert (paste). (#1541) +- InputText: Added alternative clipboard shortcuts: Shift+Delete (cut), CTRL+Insert (copy), Shift+Insert (paste). (#1541) - InputText: Fixed losing Cursor X position when clicking outside on an item that's submitted after the InputText(). It was only noticeable when restoring focus programmatically. (#1418, #1554) - InputText: Added ImGuiInputTextFlags_CharsScientific flag to also allow 'e'/'E' for input of values using scientific notation. Automatically used by InputFloat. - Style: Default style is now StyleColorsDark(), instead of the old StyleColorsClassic(). (#707) @@ -153,7 +153,7 @@ Other Changes: - Style: Exposed ImGuiStyleVar_WindowTitleAlign, ImGuiStyleVar_ScrollbarSize, ImGuiStyleVar_ScrollbarRounding, ImGuiStyleVar_GrabRounding + added an assert to reduce accidental breakage. (#1181) - Style: Added style.MouseCursorScale help when using the software mouse cursor facility. (#939). - Style: Close button nows display a cross before hovering. Fixed cross positioning being a little off. Uses button colors for highlight when hovering. (#707) -- Popup: OpenPopup() Always reopen existing popup. (Removed imgui_internal.h's OpenPopupEx() which was used for this.) (#1497, #1533). +- Popup: OpenPopup() Always reopen existing pop-ups. (Removed imgui_internal.h's OpenPopupEx() which was used for this.) (#1497, #1533). - Popup: BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick() all react on mouse release instead of mouse press. (~#439) - Popup: Better handling of user mistakenly calling OpenPopup() every frame (with reopen_existing option). The error will now be more visible and easier to understand. (#1497) - Popup: BeginPopup(): Exposed extra_flags parameter that are passed through to Begin(). (#1533) @@ -187,7 +187,7 @@ Other Changes: - ImFontAtlas: Moved mouse cursor data out of ImGuiContext, fix drawing them with multiple contexts. Also remove the last remaining undesirable dependency on ImGui in imgui_draw.cpp. (#939) - ImFontAtlas: Added ImFontAtlasFlags_NoPowerOfTwoHeight flag to disable padding font height to nearest power of two. (#1613) - ImFontAtlas: Added ImFontAtlasFlags_NoMouseCursors flag to disable baking software mouse cursors, mostly to save texture memory on very low end hardware. (#1613) -- ImDrawList: Fixed AddRect() with antialiasing disabled (lower-right corner pixel was often missing, rounding looks a little better.) (#1646) +- ImDrawList: Fixed AddRect() with anti-aliasing disabled (lower-right corner pixel was often missing, rounding looks a little better.) (#1646) - ImDrawList: Added CloneOutput() helper to facilitate the cloning of ImDrawData or ImDrawList for multi-threaded rendering. - Misc: Functions passed to libc qsort are explicitly marked cdecl to support compiling with vectorcall as the default calling convention. (#1230, #1611) [@RandyGaul] - Misc: ImVec2: added [] operator. This is becoming desirable for some code working of either axes independently. Better adding it sooner than later. @@ -199,7 +199,7 @@ Other Changes: - Misc: Added IMGUI_USER_CONFIG to define a custom configuration filename. (#255, #1573, #1144, #41) - Misc: Added IMGUI_STB_TRUETYPE_FILENAME and IMGUI_STB_RECT_PACK_FILENAME compile time directives to use another version of the stb_ files. - Misc: Updated stb_rect_pack from 0.10 to 0.11 (minor changes). - (Those flags are not used by ImGui itself, they only exists to make it easy for the engine/back-end to pass information to the application in a standard manner.) + (Those flags are not used by ImGui itself, they only exists to make it easy for the engine/backend to pass information to the application in a standard manner.) - Metrics: Added display of Columns state. - Demo: Improved Selectable() examples. (#1528) - Demo: Tweaked the Child demos, added a menu bar to the second child to test some navigation functions. @@ -209,7 +209,7 @@ Other Changes: - Examples: Using Dark theme by default. (#707). Tweaked demo code. - Examples: Added support for horizontal mouse wheel for API that allows it. (#1463) [@tseeker] - Examples: All examples now setup the io.BackendFlags to signify they can honor mouse cursors, gamepad, etc. -- Examples: DirectX10: Fixed erroneous call to io.Fonts->ClearInputData() + ClearTexData() that was left in DX10 example but removed in 1.47 (Nov 2015) in every other back-ends. (#1733) +- Examples: DirectX10: Fixed erroneous call to io.Fonts->ClearInputData() + ClearTexData() that was left in DX10 example but removed in 1.47 (Nov 2015) in every other backends. (#1733) - Examples: DirectX12: Added DirectX 12 example. (#301) [@jdm3] - Examples: OpenGL3+GLFW,SDL: Changed GLSL shader version from 330 to 150. (#1466, #1504) - Examples: OpenGL3+GLFW,SDL: Added a way to override the GLSL version string in the Init function. (#1466, #1504). @@ -224,9 +224,9 @@ Other Changes: - Examples: GLFW: Don't attempt to change the mouse cursor input mode if it is set to GLFW_CURSOR_DISABLED by the application. (#1202) [@PhilCK] - Examples: SDL: Added support for mouse cursor shapes. (#1626) [@olls] - Examples: SDL: Using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging (SDL 2.0.4+ only, otherwise using SDL_WINDOW_INPUT_FOCUS instead of previously SDL_WINDOW_MOUSE_FOCUS). (#1559) -- Examples: SDL: Enabled vsync by default so people don't come at us with demoes running at 2000 FPS burning a cpu core. -- Examples: SDL: Using SDL_GetPerformanceCounter() / SDL_GetPerformanceFrequency() to handle framerate over 1000 FPS properly. (#996) -- Examples: SDL: Using scancode exclusively instead of a confusing mixture of scancodes and keycodes. +- Examples: SDL: Enabled vsync by default so people don't come at us when the examples are running at 2000 FPS and burning a CPU core. +- Examples: SDL: Using SDL_GetPerformanceCounter() / SDL_GetPerformanceFrequency() to handle frame-rate over 1000 FPS properly. (#996) +- Examples: SDL: Using scan-code exclusively instead of a confusing mixture of scan-codes and key-codes. - Examples: SDL: Visual Studio: Added .vcxproj file. Using %SDL2_DIR% in the default .vcxproj and build files instead of %SDL_DIR%, the earlier being more standard. - Examples: Vulkan: Visual Studio: Added .vcxproj file. - Examples: Apple: Fixed filenames in OSX xcode project. Various other Mac friendly fixes. [@gerryhernandez etc.] @@ -254,7 +254,7 @@ Breaking Changes: Use `ImGui::ShowStyleEditor()` to look them up. Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time. It is recommended that you use the `StyleColorsClassic()`, `StyleColorsDark()`, `StyleColorsLight()` functions. Also see `ShowStyleSelector()`. -- Style: Removed `ImGuiCol_ComboBg` in favor of combo boxes using `ImGuiCol_PopupBg` for consistency. Combo are normal popups. +- Style: Removed `ImGuiCol_ComboBg` in favor of combo boxes using `ImGuiCol_PopupBg` for consistency. Combo are normal pop-ups. - Style: Renamed `ImGuiCol_ChildWindowBg` to `ImGuiCol_ChildBg`. - Style: Renamed `style.ChildWindowRounding` to `style.ChildRounding`, `ImGuiStyleVar_ChildWindowRounding` to `ImGuiStyleVar_ChildRounding`. - Removed obsolete redirection functions: SetScrollPosHere() - marked obsolete in v1.42, July 2015. @@ -285,11 +285,11 @@ Other Changes: - Style: Made the ScaleAllSizes() helper rounds down every values so they are aligned on integers. - Focus: Added SetItemDefaultFocus(), which in the current (master) branch behave the same as doing `if (IsWindowAppearing()) SetScrollHere()`. In the navigation branch this will also set the default focus. Prefer using this when creating combo boxes with `BeginCombo()` so your code will be forward-compatible with gamepad/keyboard navigation features. (#787) -- Combo: Popup grows horizontally to accomodate for contents that is larger then the parent combo button. +- Combo: Pop-up grows horizontally to accommodate for contents that is larger then the parent combo button. - Combo: Added BeginCombo()/EndCombo() API which allows use to submit content of any form and manage your selection state without relying on indices. -- Combo: Added ImGuiComboFlags_PopupAlignLeft flag to BeginCombo() to prioritize keeping the popup on the left side (for small-button-looking combos). -- Combo: Added ImGuiComboFlags_HeightSmall, ImGuiComboFlags_HeightLarge, ImGuiComboFlags_HeightLargest to easily provide desired popup height. -- Combo: You can use SetNextWindowSizeConstraints() before BeginCombo() to specify specific popup width/height constraints. +- Combo: Added ImGuiComboFlags_PopupAlignLeft flag to BeginCombo() to prioritize keeping the pop-up on the left side (for small-button-looking combos). +- Combo: Added ImGuiComboFlags_HeightSmall, ImGuiComboFlags_HeightLarge, ImGuiComboFlags_HeightLargest to easily provide desired pop-up height. +- Combo: You can use SetNextWindowSizeConstraints() before BeginCombo() to specify specific pop-up width/height constraints. - Combo: Offset popup position by border size so that a double border isn't so visible. (#707) - Combo: Recycling windows by using a stack number instead of a unique id, wasting less memory (like menus do). - InputText: Added ImGuiInputTextFlags_NoUndoRedo flag. (#1506, #1508) [@ibachar] @@ -300,11 +300,11 @@ Other Changes: - Window: Made it possible to use SetNextWindowPos() on a child window. - Window: Fixed a one frame glitch. When an appearing window claimed the focus themselves, the title bar wouldn't use the focused color for one frame. - Window: Added ImGuiWindowFlags_ResizeFromAnySide flag to resize from any borders or from the lower-left corner of a window. This requires your backend to honor GetMouseCursor() requests for full usability. (#822) -- Window: Sizing fixes when useing SetNextWindowSize() on individual axises. +- Window: Sizing fixes when using SetNextWindowSize() on individual axises. - Window: Hide new window for one frame until they calculate their size. Also fixes SetNextWindowPos() given a non-zero pivot. (#1694) -- Window: Made mouse wheel scrolling accomodate better to windows that are smaller than the scroll step. +- Window: Made mouse wheel scrolling accommodate better to windows that are smaller than the scroll step. - Window: SetNextWindowContentSize() adjust for the size of decorations (title bar/menu bar), but _not_ for borders are we consistently make borders not affect layout. - If you need a non-child window of an exact size with border enabled but zero window padding, you'll need to accodomate for the border size yourself. + If you need a non-child window of an exact size with border enabled but zero window padding, you'll need to accommodate for the border size yourself. - Window: Using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. (#1380, #1502) - Window: Active Modal window always set the WantCaptureKeyboard flag. (#744) - Window: Moving window doesn't use accumulating MouseDelta so straying out of imgui boundaries keeps moved imgui window at the same cursor-relative position. @@ -317,7 +317,7 @@ Other Changes: - IsWindowHovered(): Always return true when current window is being moved. (#1382) - Scrollbar: Fixed issues with vertical scrollbar flickering/appearing, typically when manually resizing and using a pattern of filling available height (e.g. full sized BeginChild). - Scrollbar: Minor graphical fix for when scrollbar don't have enough visible space to display the full grab. -- Scrolling: Fixed padding and scrolling asymetry where lower/right sides of a window wouldn't use WindowPadding properly + causing minor scrolling glitches. +- Scrolling: Fixed padding and scrolling asymmetry where lower/right sides of a window wouldn't use WindowPadding properly + causing minor scrolling glitches. - Tree: TreePush with zero arguments was ambiguous. Resolved by making it call TreePush(const void*). [@JasonWilkins] - Tree: Renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. (#600, #1330) - MenuBar: Fixed minor rendering issues on the right size when resizing a window very small and using rounded window corners. @@ -328,19 +328,19 @@ Other Changes: - Columns: Columns width is no longer lost when dragging a column to the right side of the window, until releasing the mouse button you have a chance to save them. (#1499, #125). [@ggtucker] - Columns: Fixed dragging when using a same of columns multiple times in the frame. (#125) - Indent(), Unindent(): Allow passing negative values. -- ColorEdit4(): Made IsItemActive() return true when picker popup is active. (#1489) +- ColorEdit4(): Made IsItemActive() return true when picker pop-up is active. (#1489) - ColorEdit4(): Tweaked tooltip so that the color button aligns more correctly with text. - ColorEdit4(): Support drag and drop. Color buttons can be used as drag sources, and ColorEdit widgets as drag targets. (#143) -- ColorPicker4(): Fixed continously returning true when holding mouse button on the sat/value/alpha locations. We only return true on value change. (#1489) +- ColorPicker4(): Fixed continuously returning true when holding mouse button on the sat/value/alpha locations. We only return true on value change. (#1489) - NewFrame(): using literal strings in the most-frequently firing IM_ASSERT expressions to increase the odd of programmers seeing them (especially those who don't use a debugger). - NewFrame() now asserts if neither Render or EndFrame have been called. Exposed EndFrame(). Made it legal to call EndFrame() more than one. (#1423) -- ImGuiStorage: Added BuildSortByKey() helper to rebuild storage from stratch. +- ImGuiStorage: Added BuildSortByKey() helper to rebuild storage from scratch. - ImFont: Added GetDebugName() helper. - ImFontAtlas: Added missing Thai punctuation in the GetGlyphRangesThai() ranges. (#1396) [@nProtect] - ImDrawList: Removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Anti-aliasing is controlled via the regular style.AntiAliased flags. - ImDrawList: Added ImDrawList::AddImageRounded() helper. (#845) [@thedmd] -- ImDrawList: Refactored to make ImDrawList independant of ImGui. Removed static variable in PathArcToFast() which caused linking issues to some. -- ImDrawList: Exposed ImDrawCornerFlags, replaced occurences of ~0 with an explicit ImDrawCornerFlags_All. NB: Inversed BotLeft (prev 1<<3, now 1<<2) and BotRight (prev 1<<2, now 1<<3). +- ImDrawList: Refactored to make ImDrawList independent of ImGui. Removed static variable in PathArcToFast() which caused linking issues to some. +- ImDrawList: Exposed ImDrawCornerFlags, replaced occurrences of ~0 with an explicit ImDrawCornerFlags_All. NB: Inversed BotLeft (prev 1<<3, now 1<<2) and BotRight (prev 1<<2, now 1<<3). - ImVector: Added ImVector::push_front() helper. - ImVector: Added ImVector::contains() helper. - ImVector: insert() uses grow_capacity() instead of using grow policy inconsistent with push_back(). @@ -354,9 +354,9 @@ Other Changes: - Demo: Added ShowFontSelector() showing loaded fonts. - Demo: Added ShowStyleSelector() to select among default styles. (#707) - Demo: Renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). -- Demo: Style Editor: Added a "Simplified settings" sections with checkboxes for border size and frame rounding. (#707, #1019) +- Demo: Style Editor: Added a "Simplified settings" sections with check-boxes for border size and frame rounding. (#707, #1019) - Demo: Style Editor: Added combo box to select stock styles and select current font when multiple are loaded. (#707) -- Demo: Style Editor: Using local storage so Save/Revert button makes more sense without code passing its storage. Aadded horizontal scroll bar. Fixed Save/Revert button to be always accessible. (#1211) +- Demo: Style Editor: Using local storage so Save/Revert button makes more sense without code passing its storage. Added horizontal scroll bar. Fixed Save/Revert button to be always accessible. (#1211) - Demo: Console: Fixed context menu issue. (#1404) - Demo: Console: Fixed incorrect positioning which was hidden by a minor scroll issue (this would affect people who copied the Console code as is). - Demo: Constrained Resize: Added more test cases. (#1417) @@ -393,7 +393,7 @@ Other Changes: - Combo, InputFloat, InputInt: Made the small button on the right side align properly with the equivalent colored button of ColorEdit4(). - IO: Tweaked logic for `io.WantCaptureMouse` so it now outputs false when e.g. hovering over void while an InputText() is active. (#621) [@pdoane] - IO: Fixed `io.WantTextInput` from mistakenly outputting true when an activated Drag or Slider was previously turned into an InputText(). (#1317) -- Misc: Added flags to `IsItemHovered()`, `IsWindowHovered()` to access advanced hovering-test behavior. Generally useful for popups and drag'n drop behaviors: (relates to ~#439, #1013, #143, #925) +- Misc: Added flags to `IsItemHovered()`, `IsWindowHovered()` to access advanced hovering-test behavior. Generally useful for pop-ups and drag and drop behaviors: (relates to ~#439, #1013, #143, #925) - `ImGuiHoveredFlags_AllowWhenBlockedByPopup` - `ImGuiHoveredFlags_AllowWhenBlockedByActiveItem` - `ImGuiHoveredFlags_AllowWhenOverlapped` @@ -401,10 +401,10 @@ Other Changes: - Input: Added `IsMousePosValid()` helper. - Input: Added `GetKeyPressedAmount()` to easily measure press count when the repeat rate is faster than the frame rate. - Input/Focus: Disabled TAB and Shift+TAB when CTRL key is held. -- Checkbox: Now rendering a tick mark instead of a full square. +- CheckBox: Now rendering a tick mark instead of a full square. - ColorEdit4: Added "Copy as..." option in context menu. (#346) - ColorPicker: Improved ColorPicker hue wheel color interpolation. (#1313) [@thevaber] -- ColorButton: Reduced bordering artefact that would be particularly visible with an opaque Col_FrameBg and FrameRounding enabled. +- ColorButton: Reduced bordering artifact that would be particularly visible with an opaque Col_FrameBg and FrameRounding enabled. - ColorButton: Fixed rendering color button with a checkerboard if the transparency comes from the global style.Alpha and not from the actual source color. - TreeNode: Added `ImGuiTreeNodeFlags_FramePadding` flag to conveniently create a tree node with full padding at the beginning of a line, without having to call `AlignTextToFramePadding()`. - Trees: Fixed calling `SetNextTreeNodeOpen()` on a collapsed window leaking to the first tree node item of the next frame. @@ -417,7 +417,7 @@ Other Changes: - Windows: Fixed calling `Begin()` more than once per frame setting `window_just_activated_by_user` which in turn would set enable the Appearing condition for that frame. - Windows: The implicit "Debug" window now uses a "Debug##Default" identifier instead of "Debug" to allow user creating a window called "Debug" without losing their custom flags. - Windows: Made the `ImGuiWindowFlags_NoMove` flag properly inherited from parent to child. In a setup with ParentWindow (no flag) -> Child (NoMove) -> SubChild (no flag), the user won't be able to move the parent window by clicking on SubChild. (#1381) -- Popups: Popups can be closed with a right-click anywhere, without altering focus under the popup. (~#439) +- Popups: Pop-ups can be closed with a right-click anywhere, without altering focus under the pop-up. (~#439) - Popups: `BeginPopupContextItem()`, `BeginPopupContextWindow()` are now setup to allow reopening a context menu by right-clicking again. (~#439) - Popups: `BeginPopupContextItem()` now supports a NULL string identifier and uses the last item ID if available. - Popups: Added `OpenPopupOnItemClick()` helper which mimic `BeginPopupContextItem()` but doesn't do the BeginPopup(). @@ -460,7 +460,7 @@ Beta Navigation Branch: - Nav: MainMenuBar now releases focus when user gets out of the menu layer. (#787) - Nav: When applying focus to a window with only menus, the menu layer is automatically activated. (#787) - Nav: Added `ImGuiNavInput_KeyMenu` (~Alt key) aside from ImGuiNavInput_PadMenu input as it is one differentiator of pad vs keyboard that was detrimental to the keyboard experience. Although isn't officially supported, it makes the current experience better. (#787) -- Nav: Move requests now wrap vertically inside Menus and Popups. (#787) +- Nav: Move requests now wrap vertically inside Menus and Pop-ups. (#787) - Nav: Allow to collapse tree nodes with NavLeft and open them with NavRight. (#787, #1079). - Nav: It's now possible to navigate sibling of a menu-bar while navigating inside one of their child. If a Left<>Right navigation request fails to find a match we forward the request to the root menu. (#787, #126) - Nav: Fixed `SetItemDefaultFocus` from stealing default focus when we are initializing default focus for a menu bar layer. (#787) @@ -487,7 +487,7 @@ Work on dear imgui has been gradually resuming. It means that fixes and new feat - Renamed `ImGuiCol_Columns***` enums to `ImGuiCol_Separator***`. Kept redirection enums (will obsolete). - Renamed `ImGuiSetCond***` types and enums to `ImGuiCond***`. Kept redirection enums (will obsolete). - Renamed `GetStyleColName()` to `GetStyleColorName()` for consistency. Unlikely to be used by end-user! -- Added `PushStyleColor(ImGuiCol idx, ImU32 col)` overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix. +- Added `PushStyleColor(ImGuiCol idx, ImU32 col)` overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicitly to fix. - Marked the weird `IMGUI_ONCE_UPON_A_FRAME` helper macro as obsolete. Prefer using the more explicit `ImGuiOnceUponAFrame`. - Changed `ColorEdit4(const char* label, float col[4], bool show_alpha = true)` signature to `ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)`, where flags 0x01 is a safe no-op (hello dodgy backward compatibility!). The new `ColorEdit4`/`ColorPicker4` functions have lots of available flags! Check and run the demo window, under "Color/Picker Widgets", to understand the various new options. - Changed signature of `ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)` to `ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0))`. This function was rarely used and was very dodgy (no explicit ID!). @@ -518,15 +518,15 @@ Other Changes: - Columns: Dragging a column preserve its width by default. (#913) [@ggtucker] - Columns: Fixed first column appearing wider than others. (#1266) - Columns: Fixed allocating space on the right-most side with the assumption of a vertical scrollbar. The space is only allocated when needed. (#125, #913, #893, #1138) -- Columns: Fixed the right-most column from registering its content width to the parent window, which led to various issues when using auto-resizing window or e.g. horizonal scrolling. (#519, #125, #913) +- Columns: Fixed the right-most column from registering its content width to the parent window, which led to various issues when using auto-resizing window or e.g. horizontal scrolling. (#519, #125, #913) - Columns: Refactored some of the columns code internally toward a better API (not yet exposed) + minor optimizations. (#913) [@ggtucker, @ocornut] -- Popups: Most popups windows can be moved by the user after appearing (if they don't have explicit positions provided by caller, or e.g. sub-menu popup). The previous restriction was totally arbitrary. (#1252) +- Popups: Most pop-ups windows can be moved by the user after appearing (if they don't have explicit positions provided by caller, or e.g. sub-menu pop-up). The previous restriction was totally arbitrary. (#1252) - Tooltip: `SetTooltip()` is expanded immediately into a window, honoring current font / styling setting. Add internal mechanism to override tooltips. (#862) - PlotHistogram: bars are drawn based on zero-line, so negative values are going under. (#828) - Scrolling: Fixed return values of `GetScrollMaxX()`, `GetScrollMaxY()` when both scrollbars were enabled. Tweak demo to display more data. (#1271) [@degracode] - Scrolling: Fixes for Vertical Scrollbar not automatically getting enabled if enabled Horizontal Scrollbar straddle the vertical limit. (#1271, #246) - Scrolling: `SetScrollHere()`, `SetScrollFromPosY()`: Fixed Y scroll aiming when Horizontal Scrollbar is enabled. (#665). -- [Windows] Clipboard: Fixed not closing win32 clipboard on early open failure path. (#1264) +- [Windows] Clipboard: Fixed not closing Win32 clipboard on early open failure path. (#1264) - Removed an unnecessary dependency on int64_t which failed on some older compilers. - Demo: Rearranged everything under Widgets in a more consistent way. - Demo: Columns: Added Horizontal Scrolling demo. Tweaked another Columns demo. (#519, #125, #913) @@ -555,7 +555,7 @@ Other Changes: - InputText(): Got rid of individual OSX-specific options in ImGuiIO, added a single io.OSXBehaviors flag. (#473, #650) - InputText(): Fixed pressing home key on last character when it isn't a trailing \n (#588, #815) - InputText(): Fixed state corruption/crash bug in stb_textedit.h redo logic when exhausting undo/redo char buffer. (#715. #681) -- InputTextMultiline(): Fixed Ctrl+DownArrow moving scrolling out of bounds. +- InputTextMultiline(): Fixed CTRL+DownArrow moving scrolling out of bounds. - InputTextMultiline(): Scrollbar fix for when input and latched internal buffers differs in a way that affects vertical scrollbar existence. (#725) - ImFormatString(): Fixed an overflow handling bug with implementation of vsnprintf() that do not return -1. (#793) - BeginChild(const char*) now applies stack id to provided label, consistent with other widgets. (#894, #713) @@ -582,7 +582,7 @@ Other Changes: - Word-wrapping: Fixed a bug where we never wrapped after a 1 character word. [@sronsse] - Word-wrapping: Fixed TextWrapped() overriding wrap position if one is already set. (#690) - Word-wrapping: Fixed incorrect testing for negative wrap coordinates, they are perfectly legal. (#706) -- ImGuiListClipper: fixed automatic-height calc path dumbly having user display element 0 twice. (#661, #716) +- ImGuiListClipper: Fixed automatic-height calc path dumbly having user display element 0 twice. (#661, #716) - ImGuiListClipper: Fix to behave within column. (#661, #662, #716) - ImDrawList: Renamed ImDrawList::PathFill() to ImDrawList::PathFillConvex() for clarity. (BREAKING API) - Columns: End() avoid calling Columns(1) if no columns set is open, not sure why it wasn't the case already (pros: faster, cons: exercise less code). @@ -638,7 +638,7 @@ Breaking Changes: - Renamed `SetNextTreeNodeOpened()` to `SetNextTreeNodeOpen()` for consistency, no redirection. - Removed confusing set of `GetInternalState()`, `GetInternalStateSize()`, `SetInternalState()` functions. Now using `CreateContext()`, `DestroyContext()`, `GetCurrentContext()`, `SetCurrentContext()`. If you were using multiple contexts the change should be obvious and trivial. - Obsoleted old signature of `CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false)`, as extra parameters were badly designed and rarely used. Most uses were using 1 parameter and shouldn't affect you. You can replace the "default_open = true" flag in new API with `CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen)`. -- Changed `ImDrawList::PushClipRect(ImVec4 rect)` to `ImDraw::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false)`. Note that higher-level `ImGui::PushClipRect()` is preferable because it will clip at logic/widget level, whereas `ImDrawList::PushClipRect()` only affect your renderer. +- Changed `ImDrawList::PushClipRect(ImVec4 rect)` to `ImDraw::PushClipRect(ImVec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false)`. Note that higher-level `ImGui::PushClipRect()` is preferable because it will clip at logic/widget level, whereas `ImDrawList::PushClipRect()` only affect your renderer. - Title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore (see #655). If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color. (Or If this is confusing, just pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color.) @@ -656,7 +656,7 @@ Other changes: - Added PushClipRect()/PopClipRect() (previously part of imgui_internal.h). Changed ImDrawList::PushClipRect() prototype. (#610) - Added IsRootWindowOrAnyChildHovered() helper. (#615) - Added TreeNodeEx() functions. (#581, #600, #190) -- Added ImGuiTreeNodeFlags_Selected flag to display treenode as "selected". (#581, #190) +- Added ImGuiTreeNodeFlags_Selected flag to display TreeNode as "selected". (#581, #190) - Added ImGuiTreeNodeFlags_AllowOverlapMode flag. (#600) - Added ImGuiTreeNodeFlags_NoTreePushOnOpen flag (#590). - Added ImGuiTreeNodeFlags_NoAutoOpenOnLog flag (previously private). @@ -673,9 +673,9 @@ Other changes: - Fixed MenuBar missing lower border when borders are enabled. - InputText(): Fixed clipping of cursor rendering in case it gets out of the box (which can be forced w/ ImGuiInputTextFlags_NoHorizontalScroll. (#601) - Style: Changed default IndentSpacing from 22 to 21. (#581, #324) -- Style: Fixed TitleBg/TitleBgActive color being rendered above WindowBg color, which was inconsistent and causing visual artefact. (#655) +- Style: Fixed TitleBg/TitleBgActive color being rendered above WindowBg color, which was inconsistent and causing visual artifact. (#655) This broke the meaning of TitleBg and TitleBgActive. Only affect values where Alpha<1.0f. Fixed default theme. Read comments in "API BREAKING CHANGES" section to convert. -- Relative rendering of order of Child windows creation is preserved, to allow more control with overlapping childs. (#595) +- Relative rendering of order of Child windows creation is preserved, to allow more control with overlapping children. (#595) - Fixed GetWindowContentRegionMax() being off by ScrollbarSize amount when explicit SizeContents is set. - Indent(), Unindent(): optional non-default indenting width. (#324, #581) - Bullet(), BulletText(): Slightly bigger. Less polygons. @@ -684,8 +684,8 @@ Other changes: - BeginGroup(): fixed using within Columns set. (#630) - Fixed a lag in reading the currently hovered window when dragging a window. (#635) - Obsoleted 4 parameters version of CollapsingHeader(). Refactored code into TreeNodeBehavior. (#600, #579) -- Scrollbar: minor fix for top-right rounding of scrollbar background when window has menubar but no title bar. -- MenuItem(): checkmark render in disabled color when menu item is disabled. +- Scrollbar: minor fix for top-right rounding of scrollbar background when window has menu bar but no title bar. +- MenuItem(): the check mark renders in disabled color when menu item is disabled. - Fixed clipping rectangle floating point representation to ensure renderer-side float point operations yield correct results in typical DirectX/GL settings. (#582, 597) - Fixed GetFrontMostModalRootWindow(), fixing missing fade-out when a combo pop was used stacked over a modal window. (#604) - ImDrawList: Added AddQuad(), AddQuadFilled() helpers. @@ -694,7 +694,7 @@ Other changes: - ImFont: Added AddRemapChar() helper. (#609) - ImFontConfig: Clarified persistence requirement of GlyphRanges array. (#651) - ImGuiStorage: Added bool helper functions for completeness. -- AddFontFromMemoryCompressedTTF(): Fix font config propagation. (#587) +- AddFontFromMemoryCompressedTTF(): Fix ImFontConfig propagation. (#587) - Renamed majority of use of the word "opened" to "open" for clarity. Renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(). (#625, #579) - Examples: OpenGL3: Saving/restoring glActiveTexture() state. (#602) - Examples: DirectX9: save/restore all device state. @@ -702,7 +702,7 @@ Other changes: - Examples: DirectX10/X11: Apply depth-stencil state (no use of depth buffer). (#640, #636) - Examples: DirectX11/X11: Added comments on removing dependency on D3DCompiler. (#638) - Examples: SDL: Initialize video+timer subsystem only. -- Examples: Apple/iOS: lowered xcode project deployment target from 10.7 to 10.11. (#598, #575) +- Examples: Apple/iOS: lowered XCode project deployment target from 10.7 to 10.11. (#598, #575) ----------------------------------------------------------------------- @@ -712,7 +712,7 @@ Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.48 Breaking Changes: - Consistently honoring exact width passed to PushItemWidth() (when positive), previously it would add extra FramePadding.x*2 over that width. Some hand-tuned layout may be affected slightly. (#346) -- Style: removed `style.WindowFillAlphaDefault` which was confusing and redundant, baked alpha into `ImGuiCol_WindowBg` color. If you had a custom WindowBg color but didn't change WindowFillAlphaDefault, multiply WindowBg alpha component by 0.7. Renamed `ImGuiCol_TooltipBg` to `ImGuiCol_PopupBG`, applies to other types of popups. `bg_alpha` parameter of 5-parameters version of Begin() is an override. (#337) +- Style: removed `style.WindowFillAlphaDefault` which was confusing and redundant, baked alpha into `ImGuiCol_WindowBg` color. If you had a custom WindowBg color but didn't change WindowFillAlphaDefault, multiply WindowBg alpha component by 0.7. Renamed `ImGuiCol_TooltipBg` to `ImGuiCol_PopupBG`, applies to other types of pop-ups. `bg_alpha` parameter of 5-parameters version of Begin() is an override. (#337) - InputText(): Added BufTextLen field in ImGuiTextEditCallbackData. Requesting user to update it if the buffer is modified in the callback. Added a temporary length-check assert to minimize panic for the 3 people using the callback. (#541) - Renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). (#340) @@ -721,7 +721,7 @@ Other Changes: - Consistently honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. Some hand-tuned layout may be affected slightly. (#346) - Fixed clipping of child windows within parent not taking account of child outer clipping boundaries (including scrollbar, etc.). (#506) - TextUnformatted(): Fixed rare crash bug with large blurb of text (2k+) not finished with a '\n' and fully above the clipping Y line. (#535) -- IO: Added 'KeySuper' field to hold Cmd keyboard modifiers for OS X. Updated all examples accordingly. (#473) +- IO: Added 'KeySuper' field to hold CMD keyboard modifiers for OS X. Updated all examples accordingly. (#473) - Added ImGuiWindowFlags_ForceVerticalScrollbar, ImGuiWindowFlags_ForceHorizontalScrollbar flags. (#476) - Added IM_COL32 macros to generate a U32 packed color, convenient for direct use of ImDrawList api. (#346) - Added GetFontTexUvWhitePixel() helper, convenient for direct use of ImDrawList api. @@ -732,11 +732,11 @@ Other Changes: - Fixed InputTextMultiLine(), ListBox(), BeginChildFrame(), ProgressBar(): outer frame not honoring bordering. (#462, #503) - Fixed Image(), ImageButtion() rendering a rectangle 1 px too large on each axis. (#457) - SetItemAllowOverlap(): Promoted from imgui_internal.h to public imgui.h api. (#517) -- Combo(): Right-most button stays highlighted when popup is open. -- Combo(): Display popup above if there's isn't enough space below / or select largest side. (#505) +- Combo(): Right-most button stays highlighted when pop-up is open. +- Combo(): Display pop-up above if there's isn't enough space below / or select largest side. (#505) - DragFloat(), SliderFloat(), InputFloat(): fixed cases of erroneously returning true repeatedly after a text input modification (e.g. "0.0" --> "0.000" would keep returning true). (#564) - DragFloat(): Always apply value when mouse is held/widget active, so that an always-reseting variable (e.g. non saved local) can be passed. -- InputText(): OS X friendly behaviors: Word movement uses Alt key; Shortcuts uses Cmd key; Double-clicking text select a single word; Jumping to next word sets cursor to end of current word instead of beginning of current word. (@zhiayang), (#473) +- InputText(): OS X friendly behaviors: Word movement uses ALT key; Shortcuts uses CMD key; Double-clicking text select a single word; Jumping to next word sets cursor to end of current word instead of beginning of current word. (@zhiayang), (#473) - InputText(): Added BufTextLen in ImGuiTextEditCallbackData. Requesting user to maintain it if buffer is modified. Zero-ing structure properly before use. (#541) - CheckboxFlags(): Added support for testing/setting multiple flags at the same time. (@DMartinek) (#555) - TreeNode(), CollapsingHeader() fixed not being able to use "##" sequence in a formatted label. @@ -755,7 +755,7 @@ Other Changes: - ImDrawList: Allow AddText(ImFont\* font, float font_size, ...) variant to take NULL/0.0f as default. - ImFontAtlas: heuristic increase default texture width up for large number of glyphs. (#491) - ImTextBuffer: Fixed empty() helper which was utterly broken. -- Metrics: allow to inspect individual triangles in drawcalls. +- Metrics: allow to inspect individual triangles in draw calls. - Demo: added more draw primitives in the Custom Rendering example. (#457) - Demo: extra comments and example for PushItemWidth(-1) patterns. - Demo: InputText password demo filters out blanks. (#515) @@ -770,7 +770,7 @@ Other Changes: - Examples: SDL2+OpenGL3: Fix context creation options. Made ImGui_ImplSdlGL3_NewFrame() signature match GL2 one. (#468, #463) - Examples: SDL2+OpenGL2/3: Fix for high-dpi displays. (@nickgravelyn) - Various extra comments and clarification in the code. -- Various other fixes and optimisations. +- Various other fixes and optimizations. ----------------------------------------------------------------------- diff --git a/README.md b/README.md index ee163691..76ca6dff 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Dear ImGui is a bloat-free graphical user interface library for C++. It outputs Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries. -Dear ImGui is particularly suited to integration in games engine (for tooling), realtime 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard. +Dear ImGui is particularly suited to integration in games engine (for tooling), real-time 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard. Dear ImGui is self-contained within a few files that you can easily copy and compile into your application/engine: - imgui.cpp @@ -98,7 +98,7 @@ Demo Binaries You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: - [imgui-demo-binaries-20180407.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20180407.zip) (Windows binaries, Dear ImGui 1.60 built 2018/04/07, 5 executables) -The demo applications are unfortunately not yet DPI aware so expect some blurryness on a 4K screen. For DPI awareness you can load/reload your font at different scale, and scale your Style with `style.ScaleAllSizes()`. +The demo applications are unfortunately not yet DPI aware so expect some blurriness on a 4K screen. For DPI awareness you can load/reload your font at different scale, and scale your Style with `style.ScaleAllSizes()`. Bindings -------- @@ -204,7 +204,7 @@ The Immediate Mode GUI paradigm may at first appear unusual to some users. This - [A presentation by Rickard Gustafsson and Johannes Algelind](http://www.cse.chalmers.se/edu/year/2011/course/TDA361/Advanced%20Computer%20Graphics/IMGUI.pdf). - [Jari Komppa's tutorial on building an ImGui library](http://iki.fi/sol/imgui/). - [Casey Muratori's original video that popularized the concept](https://mollyrocket.com/861). -- [Nicolas Guillemot's CppCon'16 flashtalk about Dear ImGui](https://www.youtube.com/watch?v=LSRJ1jZq90k). +- [Nicolas Guillemot's CppCon'16 flash-talk about Dear ImGui](https://www.youtube.com/watch?v=LSRJ1jZq90k). - [Thierry Excoffier's Zero Memory Widget](http://perso.univ-lyon1.fr/thierry.excoffier/ZMW/). See the [Links page](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to different languages and frameworks. @@ -249,9 +249,9 @@ See the FAQ in imgui.cpp for answers. You can control Dear ImGui with a gamepad, see the explanation in imgui.cpp about how to use the navigation feature (short version: map your gamepad inputs into the `io.NavInputs[]` array and set `io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad`). -You can share your computer mouse seamlessy with your console/tablet/phone using [Synergy](http://synergy-project.org). This is the prefered solution for developer productivity. In particular, their [micro-synergy-client](https://github.com/symless/micro-synergy-client) repo there is _uSynergy.c_ sources for a small embeddable that you can use on any platform to connect to your host PC using Synergy 1.x. You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui). +You can share your computer mouse seamlessly with your console/tablet/phone using [Synergy](http://synergy-project.org). This is the preferred solution for developer productivity. In particular, their [micro-synergy-client](https://github.com/symless/micro-synergy-client) repo there is _uSynergy.c_ sources for a small embeddable that you can use on any platform to connect to your host PC using Synergy 1.x. You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui). -For touch inputs, you can increase the hit box of widgets (via the _style.TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimising for screen real-estate and precision. +For touch inputs, you can increase the hit box of widgets (via the _style.TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing for screen real-estate and precision. Can you create elaborate/serious tools with Dear ImGui? @@ -261,7 +261,7 @@ Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might Can you reskin the look of Dear ImGui? -You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimised to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Below is a screenshot from [LumixEngine](https://github.com/nem0/LumixEngine) with custom colors + a docking/tabs extension (both of which you can find in the Issues section and will eventually be merged): +You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimized to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Below is a screenshot from [LumixEngine](https://github.com/nem0/LumixEngine) with custom colors + a docking/tabs extension (both of which you can find in the Issues section and will eventually be merged): ![LumixEngine](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v151/lumix-201710-rearranged.png) From 787a47565039418a927a7281622081927401f333 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 7 May 2018 17:59:23 +0200 Subject: [PATCH 26/30] Skip missing font glyphs to 1) avoid using space for missing glyphs and 2) allow merging fonts with overlapping ranges. Demo: Fixed displaying ? instead of greyed out empty box. (#1671, #1703) --- CHANGELOG.txt | 2 ++ imgui_demo.cpp | 3 ++- stb_textedit.h | 2 +- stb_truetype.h | 23 +++++++++++++++-------- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 949a5667..ff464619 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -64,6 +64,8 @@ Other Changes: - DragFloat, SliderFloat: Rounding-on-write uses the provided format string instead of parsing the precision from the string, which allows for finer uses of %e %g etc. (#648, #642) - Nav: Fixed hovering a Selectable() with the mouse so that it update the navigation cursor (as it happened in the pre-1.60 navigation branch). (#787) - Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439) +- Fonts: When building font atlas, glyphs that are missing in the fonts are not using the glyph slot to render a dummy/default glyph. Saves space and allow merging fonts with + overlapping font ranges such as FontAwesome5 which split out the Brands separately from the Solid fonts. (#1703, #1671) - Misc: Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769) - Demo: Fixed Overlay: Added a context menu item to enable freely moving the window. - Examples: Calling IMGUI_CHECKVERSION() in the main.cpp of every example application. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 6717aaaa..2960d371 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2288,7 +2288,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size); const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base+n)); draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50)); - font->RenderChar(draw_list, cell_size, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string. + if (glyph) + font->RenderChar(draw_list, cell_size, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string. if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2)) { ImGui::BeginTooltip(); diff --git a/stb_textedit.h b/stb_textedit.h index 7324fb6b..270153c1 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -1,4 +1,4 @@ -// [ImGui] this is a slightly modified version of stb_truetype.h 1.9. Those changes would need to be pushed into nothings/sb +// [ImGui] this is a slightly modified version of stb_textedit.h 1.9. Those changes would need to be pushed into nothings/stb // [ImGui] - fixed linestart handler when over last character of multi-line buffer + simplified existing code (#588, #815) // [ImGui] - fixed a state corruption/crash bug in stb_text_redo and stb_textedit_discard_redo (#715) // [ImGui] - fixed a crash bug in stb_textedit_discard_redo (#681) diff --git a/stb_truetype.h b/stb_truetype.h index f65deb50..13627d4f 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,3 +1,6 @@ +// [ImGui] this is a slightly modified version of stb_truetype.h 1.19. Those changes would need to be pushed into nothings/stb +// [ImGui] - skip missing glyphs instead of allocating and rendering a default glyph (stb #607, imgui #1703, imgui #1671) + // stb_truetype.h - v1.19 - public domain // authored from 2009-2016 by Sean Barrett / RAD Game Tools // @@ -3968,13 +3971,17 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb int x0,y0,x1,y1; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; int glyph = stbtt_FindGlyphIndex(info, codepoint); - stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - &x0,&y0,&x1,&y1); - rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); - rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph != 0) { + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + } else { + rects[k].w = rects[k].h = 0; + } ++k; } } @@ -4027,7 +4034,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const sub_y = stbtt__oversample_shift(spc->v_oversample); for (j=0; j < ranges[i].num_chars; ++j) { stbrp_rect *r = &rects[k]; - if (r->was_packed) { + if (r->was_packed && r->w != 0 && r->h != 0) { stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; int advance, lsb, x0,y0,x1,y1; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; From 6eda9ed3fbeb776f408b074c9719e2392642de67 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 7 May 2018 19:57:53 +0200 Subject: [PATCH 27/30] Skip missing font glyphs V2 revert changes to stb_truetype.h ( --- imgui_draw.cpp | 17 ++++++++++++++++- stb_truetype.h | 23 ++++++++--------------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index ea822146..efcdacd7 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1774,19 +1774,34 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) buf_packedchars_n += range.num_chars; } - // Pack + // Gather the sizes of all rectangle we need tmp.Rects = buf_rects + buf_rects_n; tmp.RectsCount = font_glyphs_count; buf_rects_n += font_glyphs_count; stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV); int n = stbtt_PackFontRangesGatherRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects); IM_ASSERT(n == font_glyphs_count); + + // Detect missing glyphs and replace them with a zero-sized box instead of relying on the default glyphs + // This allows us merging overlapping icon fonts more easily. + int rect_i = 0; + for (int range_i = 0; range_i < tmp.RangesCount; range_i++) + for (int char_i = 0; char_i < tmp.Ranges[range_i].num_chars; char_i++, rect_i++) + if (stbtt_FindGlyphIndex(&tmp.FontInfo, tmp.Ranges[range_i].first_unicode_codepoint_in_range + char_i) == 0) + tmp.Rects[rect_i].w = tmp.Rects[rect_i].h = 0; + + // Pack stbrp_pack_rects((stbrp_context*)spc.pack_info, tmp.Rects, n); // Extend texture height + // Also mark missing glyphs as non-packed so we don't attempt to render into them for (int i = 0; i < n; i++) + { + if (tmp.Rects[i].w == 0 && tmp.Rects[i].h == 0) + tmp.Rects[i].was_packed = 0; if (tmp.Rects[i].was_packed) atlas->TexHeight = ImMax(atlas->TexHeight, tmp.Rects[i].y + tmp.Rects[i].h); + } } IM_ASSERT(buf_rects_n == total_glyphs_count); IM_ASSERT(buf_packedchars_n == total_glyphs_count); diff --git a/stb_truetype.h b/stb_truetype.h index 13627d4f..f65deb50 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,6 +1,3 @@ -// [ImGui] this is a slightly modified version of stb_truetype.h 1.19. Those changes would need to be pushed into nothings/stb -// [ImGui] - skip missing glyphs instead of allocating and rendering a default glyph (stb #607, imgui #1703, imgui #1671) - // stb_truetype.h - v1.19 - public domain // authored from 2009-2016 by Sean Barrett / RAD Game Tools // @@ -3971,17 +3968,13 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb int x0,y0,x1,y1; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; int glyph = stbtt_FindGlyphIndex(info, codepoint); - if (glyph != 0) { - stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - &x0,&y0,&x1,&y1); - rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); - rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); - } else { - rects[k].w = rects[k].h = 0; - } + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); ++k; } } @@ -4034,7 +4027,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const sub_y = stbtt__oversample_shift(spc->v_oversample); for (j=0; j < ranges[i].num_chars; ++j) { stbrp_rect *r = &rects[k]; - if (r->was_packed && r->w != 0 && r->h != 0) { + if (r->was_packed) { stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; int advance, lsb, x0,y0,x1,y1; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; From 35e74c72abe3d9799a9c0f1a70afd07ae992a5bc Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 7 May 2018 20:32:17 +0200 Subject: [PATCH 28/30] imgui_freetype: skip missing glyphs as well to match our stb loader (#1671, #1703) --- misc/freetype/imgui_freetype.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 8235ac5f..f7233bc3 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -182,6 +182,8 @@ namespace bool FreeTypeFont::CalcGlyphInfo(uint32_t codepoint, GlyphInfo &glyph_info, FT_Glyph& ft_glyph, FT_BitmapGlyph& ft_bitmap) { uint32_t glyph_index = FT_Get_Char_Index(FreetypeFace, codepoint); + if (glyph_index == 0) + return false; FT_Error error = FT_Load_Glyph(FreetypeFace, glyph_index, FreetypeLoadFlags); if (error) return false; From 023cc25c7caf959bd28a205611a30224f9293485 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 7 May 2018 22:15:25 +0200 Subject: [PATCH 29/30] Internals: Removed unnecessary allocation indirection for g.LogClipboard (this only made sense when there was a global context instance) --- imgui.cpp | 13 +++++-------- imgui_internal.h | 3 +-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8f727b04..318ea616 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3669,7 +3669,6 @@ void ImGui::Initialize(ImGuiContext* context) { ImGuiContext& g = *context; IM_ASSERT(!g.Initialized && !g.SettingsLoaded); - g.LogClipboard = IM_NEW(ImGuiTextBuffer)(); // Add .ini handle for ImGuiWindow type ImGuiSettingsHandler ini_handler; @@ -3736,9 +3735,7 @@ void ImGui::Shutdown(ImGuiContext* context) fclose(g.LogFile); g.LogFile = NULL; } - if (g.LogClipboard) - IM_DELETE(g.LogClipboard); - g.LogClipboard = NULL; + g.LogClipboard.clear(); g.Initialized = false; } @@ -4179,7 +4176,7 @@ void ImGui::LogText(const char* fmt, ...) if (g.LogFile) vfprintf(g.LogFile, fmt, args); else - g.LogClipboard->appendfv(fmt, args); + g.LogClipboard.appendfv(fmt, args); va_end(args); } @@ -7973,10 +7970,10 @@ void ImGui::LogFinish() fclose(g.LogFile); g.LogFile = NULL; } - if (g.LogClipboard->size() > 1) + if (g.LogClipboard.size() > 1) { - SetClipboardText(g.LogClipboard->begin()); - g.LogClipboard->clear(); + SetClipboardText(g.LogClipboard.begin()); + g.LogClipboard.clear(); } g.LogEnabled = false; } diff --git a/imgui_internal.h b/imgui_internal.h index 411db886..9c6f504e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -683,7 +683,7 @@ struct ImGuiContext // Logging bool LogEnabled; FILE* LogFile; // If != NULL log to stdout/ file - ImGuiTextBuffer* LogClipboard; // Else log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators. + ImGuiTextBuffer LogClipboard; // Accumulation buffer when log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators. int LogStartDepth; int LogAutoExpandMaxDepth; @@ -783,7 +783,6 @@ struct ImGuiContext LogEnabled = false; LogFile = NULL; - LogClipboard = NULL; LogStartDepth = 0; LogAutoExpandMaxDepth = 2; From 0bf43b3a1b8ce9a9f8f6ced6c8a310a7bf8fb4c2 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 7 May 2018 22:18:45 +0200 Subject: [PATCH 30/30] Settings: Added LoadIniSettingsFromDisk(), LoadIniSettingsFromMemory(), SaveIniSettingsToDisk(), SaveIniSettingsToMemory(), io.WantSaveIniSettings. (#923, #993) --- CHANGELOG.txt | 2 ++ TODO.txt | 1 - imgui.cpp | 91 ++++++++++++++++++++++++++---------------------- imgui.h | 14 ++++++-- imgui_draw.cpp | 4 +-- imgui_internal.h | 8 +++-- 6 files changed, 69 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index ff464619..848cf5ab 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -53,6 +53,8 @@ Other Changes: - Window: Fixed windows using the ImGuiWindowFlags_NoSavedSettings flag from not using the same default position as other windows. (#1760) - Window: Relaxed the internal stack size checker to allow Push/Begin/Pop/.../End patterns to be used with PushStyleColor, PushStyleVar, PushFont without causing a false positive assert. (#1767) - Columns: Fixed a bug introduced in 1.51 where columns would affect the contents size of their container, often creating feedback loops when ImGuiWindowFlags_AlwaysAutoResize was used. (#1760) +- Settings: Added LoadIniSettingsFromDisk(), LoadIniSettingsFromMemory(), SaveIniSettingsToDisk(), SaveIniSettingsToMemory() to manually load/save .ini settings. (#923, #993) +- Settings: Added io.WantSaveIniSettings flag, which is set to notify the application that e.g. SaveIniSettingsToMemory() should be called. (#923, #993) - MenuBar: Made BeginMainMenuBar() honor style.DisplaySafeAreaPadding so the text can be made visible on TV settings that don't display all pixels. (#1439) [@dougbinks] - InputText: On Mac OS X, filter out characters when the CMD modifier is held. (#1747) [@sivu] - InputText: On Mac OS X, support CMD+SHIFT+Z for Redo. CMD+Y is also supported as major apps seems to default to support both. (#1765) [@lfnoise] diff --git a/TODO.txt b/TODO.txt index 2ddd1cf9..1a79c4ee 100644 --- a/TODO.txt +++ b/TODO.txt @@ -183,7 +183,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - tree node: tweak color scheme to distinguish headers from selected tree node (#581) - tree node: leaf/non-leaf highlight mismatch. -!- settings: expose enough to save/load .ini from RAM instead of fopen - settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes? - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file (#437) - stb: add defines to disable stb implementations diff --git a/imgui.cpp b/imgui.cpp index 318ea616..c5b16151 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -733,12 +733,6 @@ static void AddWindowToSortedBuffer(ImVector* out_sort static ImGuiWindowSettings* AddWindowSettings(const char* name); -static void LoadIniSettingsFromDisk(const char* ini_filename); -static void LoadIniSettingsFromMemory(const char* buf); -static void SaveIniSettingsToDisk(const char* ini_filename); -static void SaveIniSettingsToMemory(ImVector& out_buf); -static void MarkIniSettingsDirty(ImGuiWindow* window); - static ImRect GetViewportRect(); static void ClosePopupToLevel(int remaining); @@ -1455,7 +1449,7 @@ FILE* ImFileOpen(const char* filename, const char* mode) // Load file content into memory // Memory allocated with ImGui::MemAlloc(), must be freed by user using ImGui::MemFree() -void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size, int padding_bytes) +void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_t* out_file_size, int padding_bytes) { IM_ASSERT(filename && file_open_mode); if (out_file_size) @@ -1472,14 +1466,14 @@ void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* return NULL; } - int file_size = (int)file_size_signed; - void* file_data = ImGui::MemAlloc((size_t)(file_size + padding_bytes)); + size_t file_size = (size_t)file_size_signed; + void* file_data = ImGui::MemAlloc(file_size + padding_bytes); if (file_data == NULL) { fclose(f); return NULL; } - if (fread(file_data, 1, (size_t)file_size, f) != (size_t)file_size) + if (fread(file_data, 1, file_size, f) != file_size) { fclose(f); ImGui::MemFree(file_data); @@ -3444,20 +3438,27 @@ void ImGui::NewFrame() if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); - // Load settings on first frame + // Load settings on first frame (if not explicitly loaded manually before) if (!g.SettingsLoaded) { IM_ASSERT(g.SettingsWindows.empty()); - LoadIniSettingsFromDisk(g.IO.IniFilename); + if (g.IO.IniFilename) + LoadIniSettingsFromDisk(g.IO.IniFilename); g.SettingsLoaded = true; } - // Save settings (with a delay so we don't spam disk too much) + // Save settings (with a delay after the last modification, so we don't spam disk too much) if (g.SettingsDirtyTimer > 0.0f) { g.SettingsDirtyTimer -= g.IO.DeltaTime; if (g.SettingsDirtyTimer <= 0.0f) - SaveIniSettingsToDisk(g.IO.IniFilename); + { + if (g.IO.IniFilename != NULL) + SaveIniSettingsToDisk(g.IO.IniFilename); + else + g.IO.WantSaveIniSettings = true; // Let user know they can call SaveIniSettingsToMemory(). user will need to clear io.WantSaveIniSettings themselves. + g.SettingsDirtyTimer = 0.0f; + } } g.Time += g.IO.DeltaTime; @@ -3685,19 +3686,18 @@ void ImGui::Initialize(ImGuiContext* context) // This function is merely here to free heap allocations. void ImGui::Shutdown(ImGuiContext* context) { - ImGuiContext& g = *context; - // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame) + ImGuiContext& g = *context; if (g.IO.Fonts && g.FontAtlasOwnedByContext) IM_DELETE(g.IO.Fonts); g.IO.Fonts = NULL; - // Cleanup of other data are conditional on actually having initialize ImGui. + // Cleanup of other data are conditional on actually having initialized ImGui. if (!g.Initialized) return; // Save settings (unless we haven't attempted to load them: CreateContext/DestroyContext without a call to NewFrame shouldn't save an empty file) - if (g.SettingsLoaded) + if (g.SettingsLoaded && g.IO.IniFilename != NULL) SaveIniSettingsToDisk(g.IO.IniFilename); // Clear everything else @@ -3759,14 +3759,13 @@ static ImGuiWindowSettings* AddWindowSettings(const char* name) return settings; } -static void LoadIniSettingsFromDisk(const char* ini_filename) +void ImGui::LoadIniSettingsFromDisk(const char* ini_filename) { - if (!ini_filename) - return; - char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", NULL, +1); + size_t file_data_size = 0; + char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_data_size); if (!file_data) return; - LoadIniSettingsFromMemory(file_data); + LoadIniSettingsFromMemory(file_data, (size_t)file_data_size); ImGui::MemFree(file_data); } @@ -3781,13 +3780,21 @@ ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name) } // Zero-tolerance, no error reporting, cheap .ini parsing -static void LoadIniSettingsFromMemory(const char* buf_readonly) +void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size) { - // For convenience and to make the code simpler, we'll write zero terminators inside the buffer. So let's create a writable copy. - char* buf = ImStrdup(buf_readonly); - char* buf_end = buf + strlen(buf); - ImGuiContext& g = *GImGui; + IM_ASSERT(g.Initialized); + IM_ASSERT(g.SettingsLoaded == false && g.FrameCount == 0); + + // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter). + // For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy.. + if (ini_size == 0) + ini_size = strlen(ini_data); + char* buf = (char*)ImGui::MemAlloc(ini_size + 1); + char* buf_end = buf + ini_size; + memcpy(buf, ini_data, ini_size); + buf[ini_size] = 0; + void* entry_data = NULL; ImGuiSettingsHandler* entry_handler = NULL; @@ -3820,7 +3827,7 @@ static void LoadIniSettingsFromMemory(const char* buf_readonly) *type_end = 0; // Overwrite first ']' name_start++; // Skip second '[' } - entry_handler = ImGui::FindSettingsHandler(type_start); + entry_handler = FindSettingsHandler(type_start); entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL; } else if (entry_handler != NULL && entry_data != NULL) @@ -3833,37 +3840,37 @@ static void LoadIniSettingsFromMemory(const char* buf_readonly) g.SettingsLoaded = true; } -static void SaveIniSettingsToDisk(const char* ini_filename) +void ImGui::SaveIniSettingsToDisk(const char* ini_filename) { ImGuiContext& g = *GImGui; g.SettingsDirtyTimer = 0.0f; if (!ini_filename) return; - ImVector buf; - SaveIniSettingsToMemory(buf); - + size_t ini_data_size = 0; + const char* ini_data = SaveIniSettingsToMemory(&ini_data_size); FILE* f = ImFileOpen(ini_filename, "wt"); if (!f) return; - fwrite(buf.Data, sizeof(char), (size_t)buf.Size, f); + fwrite(ini_data, sizeof(char), ini_data_size, f); fclose(f); } -static void SaveIniSettingsToMemory(ImVector& out_buf) +// Call registered handlers (e.g. SettingsHandlerWindow_WriteAll() + custom handlers) to write their stuff into a text buffer +const char* ImGui::SaveIniSettingsToMemory(size_t* out_size) { ImGuiContext& g = *GImGui; g.SettingsDirtyTimer = 0.0f; - - ImGuiTextBuffer buf; + g.SettingsIniData.Buf.resize(0); + g.SettingsIniData.Buf.push_back(0); for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) { ImGuiSettingsHandler* handler = &g.SettingsHandlers[handler_n]; - handler->WriteAllFn(&g, handler, &buf); + handler->WriteAllFn(&g, handler, &g.SettingsIniData); } - - buf.Buf.pop_back(); // Remove extra zero-terminator used by ImGuiTextBuffer - out_buf.swap(buf.Buf); + if (out_size) + *out_size = (size_t)g.SettingsIniData.size(); + return g.SettingsIniData.c_str(); } void ImGui::MarkIniSettingsDirty() @@ -3873,7 +3880,7 @@ void ImGui::MarkIniSettingsDirty() g.SettingsDirtyTimer = g.IO.IniSavingRate; } -static void MarkIniSettingsDirty(ImGuiWindow* window) +void ImGui::MarkIniSettingsDirty(ImGuiWindow* window) { ImGuiContext& g = *GImGui; if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings)) diff --git a/imgui.h b/imgui.h index 02b75219..8a5604ee 100644 --- a/imgui.h +++ b/imgui.h @@ -542,6 +542,13 @@ namespace ImGui IMGUI_API const char* GetClipboardText(); IMGUI_API void SetClipboardText(const char* text); + // Settings/.Ini Utilities + // The disk functions are automatically called if io.IniFilename != NULL (default is "imgui.ini"). Set io.IniFilename to NULL to load/save manually. + IMGUI_API void LoadIniSettingsFromDisk(const char* ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename). + IMGUI_API void LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size=0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source. + IMGUI_API void SaveIniSettingsToDisk(const char* ini_filename); + IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. + // Memory Utilities // All those functions are not reliant on the current context. // If you reload the contents of imgui.cpp at runtime, you may need to call SetCurrentContext() + SetAllocatorFunctions() again. @@ -1001,11 +1008,11 @@ struct ImGuiIO //------------------------------------------------------------------ ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc. - ImGuiBackendFlags BackendFlags; // = 0 // Set ImGuiBackendFlags_ enum. Set by imgui_impl_xxx files or custom back-end. + ImGuiBackendFlags BackendFlags; // = 0 // Set ImGuiBackendFlags_ enum. Set by imgui_impl_xxx files or custom back-end to communicate features supported by the back-end. ImVec2 DisplaySize; // // Display size, in pixels. For clamping windows positions. float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. - float IniSavingRate; // = 5.0f // Maximum time between saving positions/sizes to .ini file, in seconds. - const char* IniFilename; // = "imgui.ini" // Path to .ini file. NULL to disable .ini saving. + float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds. + const char* IniFilename; // = "imgui.ini" // Path to .ini file. Set NULL to disable automatic .ini loading/saving, if e.g. you want to manually load/save from memory. const char* LogFilename; // = "imgui_log.txt" // Path to .log file (default parameter to ImGui::LogToFile when no file is specified). float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds. float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels. @@ -1081,6 +1088,7 @@ struct ImGuiIO bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, imgui will use the keyboard inputs, do not dispatch them to your main game/application (in both cases, always pass keyboard inputs to imgui). (e.g. InputText active, or an imgui window is focused and navigation is enabled, etc.). bool WantTextInput; // Mobile/console: when io.WantTextInput is true, you may display an on-screen keyboard. This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). bool WantSetMousePos; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when ImGuiConfigFlags_NavEnableSetMousePos flag is enabled. + bool WantSaveIniSettings; // If io.IniFilename == NULL, this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. IMPORTANT: You need to clear io.WantSaveIniSettings yourself. bool NavActive; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. bool NavVisible; // Directional navigation is visible and allowed (will handle ImGuiKey_NavXXX events). float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames diff --git a/imgui_draw.cpp b/imgui_draw.cpp index efcdacd7..e67d5519 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1541,7 +1541,7 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template) ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) { - int data_size = 0; + size_t data_size = 0; void* data = ImFileLoadToMemory(filename, "rb", &data_size, 0); if (!data) { @@ -1556,7 +1556,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {} ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels); } - return AddFontFromMemoryTTF(data, data_size, size_pixels, &font_cfg, glyph_ranges); + return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges); } // NB: Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build(). diff --git a/imgui_internal.h b/imgui_internal.h index 9c6f504e..031ff82c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -96,7 +96,7 @@ IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, cons // Helpers: Misc IMGUI_API ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings -IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size = NULL, int padding_bytes = 0); +IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_t* out_file_size = NULL, int padding_bytes = 0); IMGUI_API FILE* ImFileOpen(const char* filename, const char* file_open_mode); static inline bool ImCharIsSpace(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; } @@ -676,9 +676,10 @@ struct ImGuiContext // Settings bool SettingsLoaded; - float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero - ImVector SettingsWindows; // .ini settings for ImGuiWindow + float SettingsDirtyTimer; // Save .ini Settings to memory when time reaches zero + ImGuiTextBuffer SettingsIniData; // In memory .ini settings ImVector SettingsHandlers; // List of .ini settings handlers + ImVector SettingsWindows; // ImGuiWindow .ini settings entries (parsed from the last loaded .ini file and maintained on saving) // Logging bool LogEnabled; @@ -1022,6 +1023,7 @@ namespace ImGui IMGUI_API void NewFrameUpdateHoveredWindowAndCaptureFlags(); IMGUI_API void MarkIniSettingsDirty(); + IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window); IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id);