diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 84098d74..05c68ea6 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,8 +1,8 @@ - Please read https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md - When adding a feature, please describe the usage context (how you intend to use it, why you need it, etc.). -- When fixing a warning or compilation problem, please post the compiler log and specify the version and OS you are using. -- Try to attach screenshots to clarify the context and demonstrate the feature at a glance. -- Make sure your code follows the coding style already used in imgui (4 spaces instead of tabs, "type* name", "local_variable", "FunctionName", "MemberName", etc.). We don't use modern C++ idioms and can compile without C++11. +- When adding a feature, try to attach screenshots/gifs to clarify the context and demonstrate the feature at a glance. +- When fixing a warning or compilation problem, post the compiler log and specify the version and OS you are using. +- Make sure your code follows the coding style already used in the codebase (4 spaces identation, no tabs, `type* name`, `local_variable`, `FunctionName()`, `MemberName`, `// Text Comment`, `//CodeComment()`, etc.). We don't use modern C++ idioms, we don't use C++ style cast, we don't use C++ headers, and we can compile without a C++11 compatible compiler. - Make sure you create a branch for the pull request. In Git, 1 PR is associated to 1 branch. If you keep pushing to the same branch after you submitted the PR, your new commits will appear in the PR. (Clear this form before submitting your PR) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e1f5e30c..96e2ed15 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -63,6 +63,7 @@ HOW TO UPDATE? Breaking Changes: - Renamed SetScrollHere() to SetScrollHereY(). Kept redirection function (will obsolete). +- Renamed misc/stl/imgui_stl.* to misc/cpp/imgui_stdlib.* in prevision for other C++ helper files. (#2035, #2096) Other Changes: @@ -83,11 +84,17 @@ Other Changes: - BeginChild(): Fixed BeginChild(const char*, ...) variation erroneously not applying the ID stack to the provided string to uniquely identify the child window. This was undoing an intentional change introduced in 1.50 and broken in 1.60. (#1698, #894, #713). +- TextUnformatted(): Fixed a case where large-text path would read bytes past the text_end marker depending + on the position of new lines in the buffer (it wasn't affecting the output but still not the right thing to do!) +- InputTextMultiline(), RenderText(): Some optimization for very large text buffers, useful for non-optimized builds. - BeginMenu(): Fixed menu popup horizontal offset being off the item in the menu bar when WindowPadding=0.0f. - ArrowButton(): Fixed arrow shape being horizontally misaligned by (FramePadding.y-FramePadding.x) if they are different. - Drag and Drop: Added GetDragDropPayload() to peek directly into the payload (if any) from anywhere. (#143) +- ImGuiTextBuffer: Avoid heap allocation when empty. - ImDrawList: Fixed AddConvexPolyFilled() undefined behavior when passing points_count smaller than 3, in particular, points_count==0 could lead to a memory stomp if the draw list was previously empty. +- Examples: DirectX10, DirectX11: Removed seemingly unnecessary calls to invalidate and recreate device objects + in the WM_SIZE handler. (#2088) [@ice1000] ----------------------------------------------------------------------- @@ -111,7 +118,7 @@ Other Changes: Although it is not perfect and will keep being improved, it is fairly functional and used by many. (#787) - Fixed a build issue with non-Cygwin GCC under Windows. - Demo: Added a "Configuration" block to make io.ConfigFlags/io.BackendFlags more prominent. -- Examples: OpenGL3: Fixed error condition when using the GLAD loader. (#2059, #2002). [@jiri] +- Examples: OpenGL3: Fixed error condition when using the GLAD loader. (#2059, #2002) [@jiri] ----------------------------------------------------------------------- @@ -184,6 +191,7 @@ Other Changes: - Selectable: Added ImGuiSelectableFlags_Disabled flag in the public API. (#211) - ColorEdit4: Fixed a bug when text input or drag and drop leading to unsaturated HSV values would erroneously alter the resulting color. (#2050) - Misc: Added optional misc/stl/imgui_stl.h wrapper to use with STL types (e.g. InputText with std::string). (#2006, #1443, #1008) + [*EDIT* renamed to misc/std/imgui_stdlib.h in 1.66] - Misc: Added IMGUI_VERSION_NUM for easy compile-time testing. (#2025) - Misc: Added ImGuiMouseCursor_Hand cursor enum + corresponding software cursor. (#1913, 1914) [@aiekick, @ocornut] - Misc: Tweaked software mouse cursor offset to match the offset of the corresponding Windows 10 cursors. @@ -255,7 +263,7 @@ Other Changes: - Some frameworks (such as the Allegro, Marmalade) handle both the "platform" and "rendering" part, and your custom engine may as well. - Read examples/README.txt for details. - Added IsItemDeactivated() to query if the last item was active previously and isn't anymore. Useful for Undo/Redo patterns. (#820, #956, #1875) -- Added IsItemDeactivatedAfterChange() [*EDIT* renamed to IsItemDeactivatedAfterEdit() in 1.63) if the last item was active previously, +- Added IsItemDeactivatedAfterChange() [*EDIT* renamed to IsItemDeactivatedAfterEdit() in 1.63] if the last item was active previously, is not anymore, and during its active state modified a value. Note that you may still get false positive (e.g. drag value and while holding return on the same value). (#820, #956, #1875) - Nav: Added support for PageUp/PageDown (explorer-style: first aim at bottom/top most item, when scroll a page worth of contents). (#787) diff --git a/docs/README.md b/docs/README.md index a0f14451..84bc6448 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,7 +3,7 @@ dear imgui, [![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/imgui) [![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720) -_(This library is free but needs your support to sustain its development. There are many desirable features and maintenance ahead. If you are an individual using dear imgui, please consider donating via Patreon or PayPal. If your company is using dear imgui, please consider financial support (e.g. sponsoring a few weeks/months of development. I can invoice for technical support, custom development etc. Email: omarcornut at gmail)._ +_(This library is free but needs your support to sustain its development. There are many desirable features and maintenance ahead. If you are an individual using dear imgui, please consider donating via Patreon or PayPal. If your company is using dear imgui, please consider financial support (e.g. sponsoring a few weeks/months of development). I can invoice for technical support, custom development etc. Email: omarcornut at gmail)._ Monthly donations via Patreon:
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui) @@ -97,7 +97,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-20180512.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20180512.zip) (Windows binaries, Dear ImGui 1.61 WIP built 2018/05/12, 5 executables) +- [imgui-demo-binaries-20181008.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20181008.zip) (Windows binaries, Dear ImGui 1.66 WIP built 2018/10/08, master branch, 5 executables) 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()`. @@ -109,7 +109,7 @@ Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/ _NB: those third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ Languages: (third-party bindings) -- C: [cimgui](https://github.com/Extrawurst/cimgui) or [sonoro1234's cimgui](https://github.com/sonoro1234/cimgui) (more recent update), also see [#1879](https://github.com/ocornut/imgui/issues/1879) +- C: [cimgui](https://github.com/cimgui/cimgui) (new 2018 auto-generated version!) - C#/.Net: [ImGui.NET](https://github.com/mellinoe/ImGui.NET) - ChaiScript: [imgui-chaiscript](https://github.com/JuJuBoSc/imgui-chaiscript) - D: [DerelictImgui](https://github.com/Extrawurst/DerelictImgui) @@ -133,7 +133,7 @@ Frameworks: - Unmerged PR: Android: [#421](https://github.com/ocornut/imgui/pull/421) - Unmerged PR: ORX: [#1843](https://github.com/ocornut/imgui/pull/1843) - Cinder: [Cinder-ImGui](https://github.com/simongeilfus/Cinder-ImGui) -- Cocos2d-x: [imguix](https://github.com/c0i/imguix), [issue #551](https://github.com/ocornut/imgui/issues/551) +- Cocos2d-x: [imguix](https://github.com/c0i/imguix), [#551](https://github.com/ocornut/imgui/issues/551) - Flexium: [FlexGUI](https://github.com/DXsmiley/FlexGUI) - GML/GameMakerStudio2: [ImGuiGML](https://marketplace.yoyogames.com/assets/6221/imguigml) - Irrlicht: [IrrIMGUI](https://github.com/ZahlGraf/IrrIMGUI) @@ -152,10 +152,10 @@ For other bindings: see [Bindings](https://github.com/ocornut/imgui/wiki/Binding Roadmap ------- -Some of the goals for 2018 are: +Some of the goals for 2018-2019 are: - Finish work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787)) +- Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109)) - Finish work on viewports and multiple OS windows management. (see [#1542](https://github.com/ocornut/imgui/issues/1542)) -- Finish work on docking, tabs. (see [#351](https://github.com/ocornut/imgui/issues/351#issuecomment-346865709)) - Make Columns better. (they are currently pretty terrible!) - Make the examples look better, improve styles, improve font support, make the examples hi-DPI aware. @@ -210,7 +210,7 @@ The Immediate Mode GUI paradigm may at first appear unusual to some users. This - [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 [Wiki](https://github.com/ocornut/imgui/wiki) and [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for third-party bindings to different languages and frameworks. +See the [Wiki](https://github.com/ocornut/imgui/wiki) for more references and [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for third-party bindings to different languages and frameworks. Support Forums -------------- @@ -228,11 +228,14 @@ Frequently Asked Question (FAQ) - Example code is in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. It covers most features of ImGui so you can read the code and call the function itself to see its output. - Standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder. - We obviously needs better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort. +- Your programming IDE is your friend, find the type or function declaration to find comments associated to it. **Which version should I get?** I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported. +You may also peak at the [Multi-Viewport](https://github.com/ocornut/imgui/issues/1542) and [Docking](https://github.com/ocornut/imgui/issues/2109) branches. Even though they are marked beta, several projects are using them and they are kept in sync with master regularly. + **Who uses Dear ImGui?** See the [Software using dear imgui page](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) for an (incomplete) list of games/software which are publicly known to use dear imgui. Please add yours if you can! @@ -280,7 +283,7 @@ You can alter the look of the interface to some degree: changing colors, sizes, Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost-insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience. -There is a [c-api for ImGui (cimgui)](https://github.com/Extrawurst/cimgui) by Stephan Dilly + a newer, [auto-generated cimgui](https://github.com/sonoro1234/cimgui) by sonoro1234. Both are designed for binding other languages. I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for third-party bindings to other languages. +There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/cimgui/cimgui) by Sonoro1234 and Stephan Dilly. This is designed for binding other languages. If possible, I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for third-party bindings to other languages. Support dear imgui ------------------ @@ -302,13 +305,13 @@ If your company uses dear imgui, please consider financial support (e.g. sponsor - Blizzard Entertainment. **Double-chocolate sponsors** -- Media Molecule, Mobigame, Insomniac Games, Aras Pranckevičius, Lizardcube, Greggman, DotEmu, Nadeo, Supercell, Runner, Artometa, Friendly Shade. +- Media Molecule, Mobigame, Insomniac Games, Aras Pranckevičius, Lizardcube, Greggman, DotEmu, Nadeo, Supercell, Runner, Friendly Shade. **Salty caramel supporters** - Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko, Mercury Labs, Singularity Demo Group, Mischa Alff, Sebastien Ronsse, Lionel Landwerlin, Nikolay Ivanov, Ron Gilbert, Brandon Townsend, Nikhil Deshpande, Cort Stratton, drudru, Harfang 3D, Jeff Roberts. **Caramel supporters** -- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Kit framework, Josh Faust, Martin Donlon, Quinton, Felix, Andrew Belt, Codecat, Cort Stratton, Claudio Canepa, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Roger Clark, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Miloš Tošić, Jonas Bernemann, Johan Andersson, Nathan Hartman, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Felipe Alfonso, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Edsel Malasig, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Astrofra, Jonas Lehmann, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan. +- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Kit framework, Josh Faust, Martin Donlon, Quinton, Felix, Andrew Belt, Codecat, Cort Stratton, Claudio Canepa, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Roger Clark, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Miloš Tošić, Jonas Bernemann, Johan Andersson, Nathan Hartman, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Felipe Alfonso, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Edsel Malasig, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Astrofra, Jonas Lehmann, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa. And all other supporters; THANK YOU! (Please contact me if you would like to be added or removed from this list) diff --git a/examples/example_win32_directx10/main.cpp b/examples/example_win32_directx10/main.cpp index 3c218f0e..6dc2e050 100644 --- a/examples/example_win32_directx10/main.cpp +++ b/examples/example_win32_directx10/main.cpp @@ -75,11 +75,9 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_SIZE: if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED) { - ImGui_ImplDX10_InvalidateDeviceObjects(); CleanupRenderTarget(); g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0); CreateRenderTarget(); - ImGui_ImplDX10_CreateDeviceObjects(); } return 0; case WM_SYSCOMMAND: diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index 56531340..ee6a0b04 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -82,11 +82,9 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_SIZE: if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED) { - ImGui_ImplDX11_InvalidateDeviceObjects(); CleanupRenderTarget(); g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0); CreateRenderTarget(); - ImGui_ImplDX11_CreateDeviceObjects(); } return 0; case WM_SYSCOMMAND: diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index 7aceea25..1d1e0095 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -326,7 +326,7 @@ static bool CheckShader(GLuint handle, const char* desc) GLint status = 0, log_length = 0; glGetShaderiv(handle, GL_COMPILE_STATUS, &status); glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length); - if (status == GL_FALSE) + if ((GLboolean)status == GL_FALSE) fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc); if (log_length > 0) { @@ -335,7 +335,7 @@ static bool CheckShader(GLuint handle, const char* desc) glGetShaderInfoLog(handle, log_length, NULL, (GLchar*)buf.begin()); fprintf(stderr, "%s\n", buf.begin()); } - return status == GL_TRUE; + return (GLboolean)status == GL_TRUE; } // If you get an error please report on github. You may try different GL context version or GLSL version. @@ -344,7 +344,7 @@ static bool CheckProgram(GLuint handle, const char* desc) GLint status = 0, log_length = 0; glGetProgramiv(handle, GL_LINK_STATUS, &status); glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length); - if (status == GL_FALSE) + if ((GLboolean)status == GL_FALSE) fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s!\n", desc); if (log_length > 0) { @@ -353,7 +353,7 @@ static bool CheckProgram(GLuint handle, const char* desc) glGetProgramInfoLog(handle, log_length, NULL, (GLchar*)buf.begin()); fprintf(stderr, "%s\n", buf.begin()); } - return status == GL_TRUE; + return (GLboolean)status == GL_TRUE; } bool ImGui_ImplOpenGL3_CreateDeviceObjects() diff --git a/examples/imgui_impl_sdl.cpp b/examples/imgui_impl_sdl.cpp index 4c17ce0d..f1da2476 100644 --- a/examples/imgui_impl_sdl.cpp +++ b/examples/imgui_impl_sdl.cpp @@ -138,7 +138,7 @@ bool ImGui_ImplSDL2_ProcessEvent(SDL_Event* event) return false; } -static bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context) +static bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context) { g_Window = window; diff --git a/imgui.cpp b/imgui.cpp index e32c2396..bc69a3cf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -355,6 +355,7 @@ CODE - 2018/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api. - 2018/XX/XX (1.XX) - removed io.DisplayVisibleMin, io.DisplayVisibleMax settings (it was used to clip within the DisplayMin..DisplayMax range, I don't know of anyone using it) + - 2018/10/12 (1.66) - Renamed misc/stl/imgui_stl.* to misc/cpp/imgui_stdlib.* in prevision for other C++ helper files. - 2018/09/28 (1.66) - renamed SetScrollHere() to SetScrollHereY(). Kept redirection function (will obsolete). - 2018/09/06 (1.65) - renamed stb_truetype.h to imstb_truetype.h, stb_textedit.h to imstb_textedit.h, and stb_rect_pack.h to imstb_rectpack.h. If you were conveniently using the imgui copy of those STB headers in your project you will have to update your include paths. @@ -862,6 +863,7 @@ CODE #include // toupper, isprint #include // vsnprintf, sscanf, printf +#include // wcslen #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier #include // intptr_t #else @@ -1227,17 +1229,20 @@ char* ImStrdup(const char *str) const char* ImStrchrRange(const char* str, const char* str_end, char c) { - for ( ; str < str_end; str++) - if (*str == c) - return str; - return NULL; + const char* p = (const char*)memchr(str, (int)c, str_end - str); + return p; } int ImStrlenW(const ImWchar* str) { - int n = 0; - while (*str++) n++; - return n; + return (int)wcslen((const wchar_t*)str); +} + +// Find end-of-line. Return pointer will point to either first \n, either str_end. +const char* ImStreolRange(const char* str, const char* str_end) +{ + const char* p = (const char*)memchr(str, '\n', str_end - str); + return p ? p : str_end; } const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line @@ -1987,6 +1992,8 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const #endif #endif +char ImGuiTextBuffer::EmptyString[1] = { 0 }; + // Helper: Text buffer for logging/accumulating text void ImGuiTextBuffer::appendfv(const char* fmt, va_list args) { @@ -2000,7 +2007,8 @@ void ImGuiTextBuffer::appendfv(const char* fmt, va_list args) return; } - const int write_off = Buf.Size; + // Add zero-terminator the first time + const int write_off = (Buf.Size != 0) ? Buf.Size : 1; const int needed_sz = write_off + len; if (write_off + len >= Buf.Capacity) { @@ -2746,19 +2754,19 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop { ImGuiContext& g = *GImGui; - const bool allow_keyboard_focus = (window->DC.ItemFlags & (ImGuiItemFlags_AllowKeyboardFocus | ImGuiItemFlags_Disabled)) == ImGuiItemFlags_AllowKeyboardFocus; + const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0; window->FocusIdxAllCounter++; - if (allow_keyboard_focus) + if (is_tab_stop) window->FocusIdxTabCounter++; // Process keyboard input at this point: TAB/Shift-TAB to tab out of the currently focused item. // Note that we can always TAB out of a widget that doesn't allow tabbing in. if (tab_stop && (g.ActiveId == id) && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab)) - window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items. + window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items. if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent) return true; - if (allow_keyboard_focus && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent) + if (is_tab_stop && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent) { g.NavJustTabbedId = id; return true; @@ -3465,7 +3473,10 @@ void ImGui::Shutdown(ImGuiContext* 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) + { + g.IO.Fonts->Locked = false; IM_DELETE(g.IO.Fonts); + } g.IO.Fonts = NULL; // Cleanup of other data are conditional on actually having initialized ImGui. @@ -4643,12 +4654,12 @@ ImVec2 ImGui::CalcWindowExpectedSize(ImGuiWindow* window) return CalcSizeAfterConstraint(window, CalcSizeAutoFit(window, size_contents)); } -static float GetScrollMaxX(ImGuiWindow* window) +float ImGui::GetWindowScrollMaxX(ImGuiWindow* window) { return ImMax(0.0f, window->SizeContents.x - (window->SizeFull.x - window->ScrollbarSizes.x)); } -static float GetScrollMaxY(ImGuiWindow* window) +float ImGui::GetWindowScrollMaxY(ImGuiWindow* window) { return ImMax(0.0f, window->SizeContents.y - (window->SizeFull.y - window->ScrollbarSizes.y)); } @@ -4676,8 +4687,8 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool s scroll = ImMax(scroll, ImVec2(0.0f, 0.0f)); if (!window->Collapsed && !window->SkipItems) { - scroll.x = ImMin(scroll.x, GetScrollMaxX(window)); - scroll.y = ImMin(scroll.y, GetScrollMaxY(window)); + scroll.x = ImMin(scroll.x, ImGui::GetWindowScrollMaxX(window)); + scroll.y = ImMin(scroll.y, ImGui::GetWindowScrollMaxY(window)); } return scroll; } @@ -5860,9 +5871,10 @@ void ImGui::PopItemFlag() window->DC.ItemFlags = window->DC.ItemFlagsStack.empty() ? ImGuiItemFlags_Default_ : window->DC.ItemFlagsStack.back(); } +// FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system. void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus) { - PushItemFlag(ImGuiItemFlags_AllowKeyboardFocus, allow_keyboard_focus); + PushItemFlag(ImGuiItemFlags_NoTabStop, !allow_keyboard_focus); } void ImGui::PopAllowKeyboardFocus() @@ -6598,12 +6610,12 @@ float ImGui::GetScrollY() float ImGui::GetScrollMaxX() { - return GetScrollMaxX(GImGui->CurrentWindow); + return GetWindowScrollMaxX(GImGui->CurrentWindow); } float ImGui::GetScrollMaxY() { - return GetScrollMaxY(GImGui->CurrentWindow); + return GetWindowScrollMaxY(GImGui->CurrentWindow); } void ImGui::SetScrollX(float scroll_x) @@ -12415,29 +12427,17 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* for (;;) { // Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry. - const char* line_end = text_remaining; - while (line_end < text_end) - if (*line_end == '\n') - break; - else - line_end++; - if (line_end >= text_end) - line_end = NULL; - - const bool is_first_line = (text == text_remaining); - bool is_last_line = false; - if (line_end == NULL) + const char* line_start = text_remaining; + const char* line_end = ImStreolRange(line_start, text_end); + const bool is_first_line = (line_start == text); + const bool is_last_line = (line_end == text_end); + if (!is_last_line || (line_start != line_end)) { - is_last_line = true; - line_end = text_end; - } - if (line_end != NULL && !(is_last_line && (line_end - text_remaining)==0)) - { - const int char_count = (int)(line_end - text_remaining); + const int char_count = (int)(line_end - line_start); if (log_new_line || !is_first_line) - LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, text_remaining); + LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, line_start); else - LogText(" %.*s", char_count, text_remaining); + LogText(" %.*s", char_count, line_start); } if (is_last_line) @@ -13064,7 +13064,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "", (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "", (flags & ImGuiWindowFlags_NoInputs) ? "NoInputs":"", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : ""); - ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetScrollMaxX(window), window->Scroll.y, GetScrollMaxY(window)); + ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetWindowScrollMaxX(window), window->Scroll.y, GetWindowScrollMaxY(window)); ImGui::BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1); ImGui::BulletText("Appearing: %d, Hidden: %d (Reg %d Resize %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesRegular, window->HiddenFramesForResize, window->SkipItems); ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); diff --git a/imgui.h b/imgui.h index aa262738..55a8f309 100644 --- a/imgui.h +++ b/imgui.h @@ -407,7 +407,7 @@ namespace ImGui IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f); // Widgets: Input with Keyboard - // If you want to use InputText() with a dynamic string type such as std::string or your own, see misc/stl/imgui_stl.h + // If you want to use InputText() with a dynamic string type such as std::string or your own, see misc/cpp/imgui_stdlib.h IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback 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, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); 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); @@ -560,7 +560,7 @@ namespace ImGui IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window. IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. - // Utilities + // Item/Widgets Utilities // See Demo Window under "Widgets->Querying Status" for an interactive visualization of many of those functions. IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered? (and usable, aka not blocked by a popup, etc.). See ImGuiHoveredFlags for more options. IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited. This will continuously return true while holding mouse button on an item. Items that don't interact will always return false) @@ -577,6 +577,8 @@ namespace ImGui IMGUI_API ImVec2 GetItemRectMax(); // " IMGUI_API ImVec2 GetItemRectSize(); // get size of last item, in screen space IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. + + // Miscellaneous Utilities IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. IMGUI_API double GetTime(); @@ -588,16 +590,16 @@ namespace ImGui IMGUI_API ImGuiStorage* GetStateStorage(); IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. - IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame IMGUI_API void EndChildFrame(); // always call EndChildFrame() regardless of BeginChildFrame() return values (which indicates a collapsed/clipped window) + // Color Utilities IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in); IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v); IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b); - // Inputs + // Inputs Utilities IMGUI_API int GetKeyIndex(ImGuiKey imgui_key); // map ImGuiKey_* values into user's key index. == io.KeyMap[key] IMGUI_API bool IsKeyDown(int user_key_index); // is key being held. == io.KeysDown[user_key_index]. note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your backend/engine stored them into io.KeysDown[]! IMGUI_API bool IsKeyPressed(int user_key_index, bool repeat = true); // was key pressed (went from !Down to Down). if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate @@ -700,10 +702,10 @@ enum ImGuiInputTextFlags_ ImGuiInputTextFlags_CharsNoBlank = 1 << 3, // Filter out spaces, tabs ImGuiInputTextFlags_AutoSelectAll = 1 << 4, // Select entire text when first taking mouse focus ImGuiInputTextFlags_EnterReturnsTrue = 1 << 5, // Return 'true' when Enter is pressed (as opposed to when the value was modified) - ImGuiInputTextFlags_CallbackCompletion = 1 << 6, // Call user function on pressing TAB (for completion handling) - ImGuiInputTextFlags_CallbackHistory = 1 << 7, // Call user function on pressing Up/Down arrows (for history handling) - ImGuiInputTextFlags_CallbackAlways = 1 << 8, // Call user function every time. User code may query cursor position, modify text buffer. - ImGuiInputTextFlags_CallbackCharFilter = 1 << 9, // Call user function to filter character. Modify data->EventChar to replace/filter input, or return 1 in callback to discard character. + ImGuiInputTextFlags_CallbackCompletion = 1 << 6, // Callback on pressing TAB (for completion handling) + ImGuiInputTextFlags_CallbackHistory = 1 << 7, // Callback on pressing Up/Down arrows (for history handling) + ImGuiInputTextFlags_CallbackAlways = 1 << 8, // Callback on each iteration. User code may query cursor position, modify text buffer. + ImGuiInputTextFlags_CallbackCharFilter = 1 << 9, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard. ImGuiInputTextFlags_AllowTabInput = 1 << 10, // Pressing TAB input a '\t' character into the text field ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, unfocus with Enter, add new line with Ctrl+Enter (default is opposite: unfocus with Ctrl+Enter, add line with Enter). ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally @@ -712,7 +714,7 @@ enum ImGuiInputTextFlags_ ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*' ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID(). ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input) - ImGuiInputTextFlags_CallbackResize = 1 << 18, // Allow buffer capacity resize + notify when the string wants to be resized (for string types which hold a cache of their Size) (see misc/stl/imgui_stl.h for an example of using this) + ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this) // [Internal] ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline() }; @@ -1468,25 +1470,27 @@ struct ImGuiTextFilter int CountGrep; }; -// Helper: Text buffer for logging/accumulating text +// Helper: Growable text buffer for logging/accumulating text +// (this could be called 'ImGuiTextBuilder' / 'ImGuiStringBuilder') struct ImGuiTextBuffer { ImVector Buf; + static char EmptyString[1]; - ImGuiTextBuffer() { Buf.push_back(0); } - inline char operator[](int i) { return Buf.Data[i]; } - const char* begin() const { return &Buf.front(); } - const char* end() const { return &Buf.back(); } // Buf is zero-terminated, so end() will point on the zero-terminator - int size() const { return Buf.Size - 1; } - bool empty() { return Buf.Size <= 1; } - void clear() { Buf.clear(); Buf.push_back(0); } - void reserve(int capacity) { Buf.reserve(capacity); } - const char* c_str() const { return Buf.Data; } + ImGuiTextBuffer() { } + inline char operator[](int i) { IM_ASSERT(Buf.Data != NULL); return Buf.Data[i]; } + const char* begin() const { return Buf.Data ? &Buf.front() : EmptyString; } + const char* end() const { return Buf.Data ? &Buf.back() : EmptyString; } // Buf is zero-terminated, so end() will point on the zero-terminator + int size() const { return Buf.Data ? Buf.Size - 1 : 0; } + bool empty() { return Buf.Size <= 1; } + void clear() { Buf.clear(); } + void reserve(int capacity) { Buf.reserve(capacity); } + const char* c_str() const { return Buf.Data ? Buf.Data : EmptyString; } IMGUI_API void appendf(const char* fmt, ...) IM_FMTARGS(2); IMGUI_API void appendfv(const char* fmt, va_list args) IM_FMTLIST(2); }; -// Helper: key->value storage +// Helper: Key->Value storage // Typically you don't have to worry about this since a storage is held within each Window. // We use it to e.g. store collapse state for a tree (Int 0/1) // This is optimized for efficient lookup (dichotomy into a contiguous buffer) and rare insertion (typically tied to user interactions aka max once a frame) @@ -1537,9 +1541,12 @@ struct ImGuiStorage // Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used. // The callback function should return 0 by default. -// Special processing: -// - ImGuiInputTextFlags_CallbackCharFilter: return 1 if the character is not allowed. You may also set 'EventChar=0' as any character replacement are allowed. -// - ImGuiInputTextFlags_CallbackResize: notified by InputText() when the string is resized. BufTextLen is set to the new desired string length so you can update the string size on your side of the fence. You can also replace Buf pointer if your underlying data is reallocated. No need to initialize new characters or zero-terminator as InputText will do it right after the resize callback. +// Callbacks (follow a flag name and see comments in ImGuiInputTextFlags_ declarations for more details) +// - ImGuiInputTextFlags_CallbackCompletion: Callback on pressing TAB +// - ImGuiInputTextFlags_CallbackHistory: Callback on pressing Up/Down arrows +// - ImGuiInputTextFlags_CallbackAlways: Callback on each iteration +// - ImGuiInputTextFlags_CallbackCharFilter: Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard. +// - ImGuiInputTextFlags_CallbackResize: Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. struct ImGuiInputTextCallbackData { ImGuiInputTextFlags EventFlag; // One ImGuiInputTextFlags_Callback* // Read-only @@ -1549,12 +1556,12 @@ struct ImGuiInputTextCallbackData // Arguments for the different callback events // - To modify the text buffer in a callback, prefer using the InsertChars() / DeleteChars() function. InsertChars() will take care of calling the resize callback if necessary. // - If you know your edits are not going to resize the underlying buffer allocation, you may modify the contents of 'Buf[]' directly. You need to update 'BufTextLen' accordingly (0 <= BufTextLen < BufSize) and set 'BufDirty'' to true so InputText can update its internal state. - ImWchar EventChar; // Character input // Read-write // [CharFilter] Replace character or set to zero. return 1 is equivalent to setting EventChar=0; + ImWchar EventChar; // Character input // Read-write // [CharFilter] Replace character with another one, or set to zero to drop. return 1 is equivalent to setting EventChar=0; ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only // [Completion,History] char* Buf; // Text buffer // Read-write // [Resize] Can replace pointer / [Completion,History,Always] Only write to pointed data, don't replace the actual pointer! - int BufTextLen; // Text length in bytes // Read-write // [Resize,Completion,History,Always] Exclude zero-terminator storage. In C land: == strlen(some_text), in C++ land: string.length() - int BufSize; // Buffer capacity in bytes // Read-only // [Resize,Completion,History,Always] Include zero-terminator storage. In C land == ARRAYSIZE(my_char_array), in C++ land: string.capacity()+1 - bool BufDirty; // Set if you modify Buf/BufTextLen!! // Write // [Completion,History,Always] + int BufTextLen; // Text length (in bytes) // Read-write // [Resize,Completion,History,Always] Exclude zero-terminator storage. In C land: == strlen(some_text), in C++ land: string.length() + int BufSize; // Buffer size (in bytes) = capacity+1 // Read-only // [Resize,Completion,History,Always] Include zero-terminator storage. In C land == ARRAYSIZE(my_char_array), in C++ land: string.capacity()+1 + bool BufDirty; // Set if you modify Buf/BufTextLen! // Write // [Completion,History,Always] int CursorPos; // // Read-write // [Completion,History,Always] int SelectionStart; // // Read-write // [Completion,History,Always] == to SelectionEnd when no selection) int SelectionEnd; // // Read-write // [Completion,History,Always] diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3bc639bb..e3cf6211 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -490,7 +490,7 @@ void ImGui::ShowDemoWindow(bool* p_open) static char str0[128] = "Hello, world!"; static int i0 = 123; ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); - ImGui::SameLine(); ShowHelpMarker("USER:\nHold 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\nPROGRAMMER:\nYou can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() to a dynamic string type. See misc/stl/imgui_stl.h for an example (this is not demonstrated in imgui_demo.cpp)."); + ImGui::SameLine(); ShowHelpMarker("USER:\nHold 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\nPROGRAMMER:\nYou can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated in imgui_demo.cpp)."); 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"); @@ -937,7 +937,7 @@ void ImGui::ShowDemoWindow(bool* p_open) "label:\n" "\tlock cmpxchg8b eax\n"; - ShowHelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/stl/imgui_stl.h for an example. (This is not demonstrated in imgui_demo.cpp)"); + ShowHelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp)"); ImGui::Checkbox("Read-only", &read_only); ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0); ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), flags); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 8a48bd4f..4ecb2258 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2667,11 +2667,11 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col // Fast-forward to first visible line const char* s = text_begin; if (y + line_height < clip_rect.y && !word_wrap_enabled) - while (y + line_height < clip_rect.y) + while (y + line_height < clip_rect.y && s < text_end) { - while (s < text_end) - if (*s++ == '\n') - break; + s = (const char*)memchr(s, '\n', text_end - s) + 1; + if (s == NULL) + s = text_end; y += line_height; } @@ -2681,15 +2681,15 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col { const char* s_end = s; float y_end = y; - while (y_end < clip_rect.w) + while (y_end < clip_rect.w && s_end < text_end) { - while (s_end < text_end) - if (*s_end++ == '\n') - break; + s_end = (const char*)memchr(s_end, '\n', text_end - s_end) + 1; y_end += line_height; } text_end = s_end; } + if (s == text_end) + return; // Reserve vertices for remaining worse case (over-reserving is useful and easily amortized) const int vtx_count_max = (int)(text_end - s) * 4; diff --git a/imgui_internal.h b/imgui_internal.h index c4639de4..03579a27 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -151,7 +151,8 @@ IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); IMGUI_API char* ImStrdup(const char* str); IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c); IMGUI_API int ImStrlenW(const ImWchar* str); -IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line +IMGUI_API const char* ImStreolRange(const char* str, const char* str_end); // End end-of-line +IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); IMGUI_API void ImStrTrimBlanks(char* str); IMGUI_API const char* ImStrSkipBlank(const char* str); @@ -305,13 +306,13 @@ enum ImGuiSeparatorFlags_ // This is going to be exposed in imgui.h when stabilized enough. enum ImGuiItemFlags_ { - ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // true + ImGuiItemFlags_NoTabStop = 1 << 0, // false ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. ImGuiItemFlags_Disabled = 1 << 2, // false // [BETA] Disable interactions but doesn't affect visuals yet. See github.com/ocornut/imgui/issues/211 ImGuiItemFlags_NoNav = 1 << 3, // false ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window - ImGuiItemFlags_Default_ = ImGuiItemFlags_AllowKeyboardFocus + ImGuiItemFlags_Default_ = 0 }; // Storage for LastItem data @@ -1381,6 +1382,8 @@ namespace ImGui IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); IMGUI_API void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x); IMGUI_API void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y); + IMGUI_API float GetWindowScrollMaxX(ImGuiWindow* window); + IMGUI_API float GetWindowScrollMaxY(ImGuiWindow* window); IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow* window); IMGUI_API void SetCurrentFont(ImFont* font); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c2e9014b..9ba1fd0c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -38,6 +38,7 @@ Index of this file: #include "imgui_internal.h" #include // toupper, isprint +#include // wmemchr #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier #include // intptr_t #else @@ -135,8 +136,9 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) { // Long text! // Perform manual coarse clipping to optimize for long multi-line text - // From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled. - // We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line. + // - From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled. + // - We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line. + // - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster than a casually written loop. const char* line = text; const float line_height = GetTextLineHeight(); const ImRect clip_rect = window->ClipRect; @@ -155,7 +157,7 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) int lines_skipped = 0; while (line < text_end && lines_skipped < lines_skippable) { - const char* line_end = strchr(line, '\n'); + const char* line_end = (const char*)memchr(line, '\n', text_end - line); if (!line_end) line_end = text_end; line = line_end + 1; @@ -171,15 +173,15 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height)); while (line < text_end) { - const char* line_end = strchr(line, '\n'); if (IsClippedEx(line_rect, 0, false)) break; + const char* line_end = (const char*)memchr(line, '\n', text_end - line); + if (!line_end) + line_end = text_end; const ImVec2 line_size = CalcTextSize(line, line_end, false); text_size.x = ImMax(text_size.x, line_size.x); RenderText(pos, line, line_end, false); - if (!line_end) - line_end = text_end; line = line_end + 1; line_rect.Min.y += line_height; line_rect.Max.y += line_height; @@ -190,7 +192,7 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) int lines_skipped = 0; while (line < text_end) { - const char* line_end = strchr(line, '\n'); + const char* line_end = (const char*)memchr(line, '\n', text_end - line); if (!line_end) line_end = text_end; line = line_end + 1; @@ -2928,7 +2930,7 @@ static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n) obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n); obj->CurLenW -= n; - // Offset remaining text + // Offset remaining text (FIXME-OPT: Use memmove) const ImWchar* src = obj->TextW.Data + pos + n; while (ImWchar c = *src++) *dst++ = c; @@ -3116,7 +3118,7 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f // This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match // Note that in std::string world, capacity() would omit 1 byte used by the zero-terminator. // - When active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while the InputText is active has no effect. -// - If you want to use ImGui::InputText() with std::string, see misc/stl/imgui_stl.h +// - If you want to use ImGui::InputText() with std::string, see misc/cpp/imgui_stdlib.h // (FIXME: Rather messy function partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188) bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data) { @@ -3639,13 +3641,12 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter. searches_remaining += is_multiline ? 1 : 0; int line_count = 0; - for (const ImWchar* s = text_begin; *s != 0; s++) - if (*s == '\n') - { - line_count++; - if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; } - if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; } - } + for (const ImWchar* s = text_begin; (s = (const ImWchar*)wcschr((const wchar_t*)s, (wchar_t)'\n')) != NULL; s++) + { + line_count++; + if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; } + if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; } + } line_count++; if (searches_result_line_number[0] == -1) searches_result_line_number[0] = line_count; if (searches_result_line_number[1] == -1) searches_result_line_number[1] = line_count; @@ -3713,9 +3714,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 break; if (rect_pos.y < clip_rect.y) { - while (p < text_selected_end) - if (*p++ == '\n') - break; + p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p) + 1; } else { diff --git a/misc/README.txt b/misc/README.txt new file mode 100644 index 00000000..70f835cf --- /dev/null +++ b/misc/README.txt @@ -0,0 +1,18 @@ + +misc/cpp/ + InputText() wrappers for C++ standard library (STL) types (std::string, etc.). + This is also an example of how you may wrap your own similar types. + +misc/fonts/ + Fonts loading/merging instructions (e.g. How to handle glyph ranges, how to merge icons fonts). + Command line tool "binary_to_compressed_c" to create compressed arrays to embed data in source code. + Suggested fonts and links. + +misc/freetype/ + Font atlas builder/rasterizer using FreeType instead of stb_truetype. + Benefit from better FreeType rasterization, in particular for small fonts. + +misc/natnis/ + Natvis file to describe dear imgui types in the Visual Studio debugger. + With this, types like ImVector<> will be displayed nicely in the debugger. + You can include this file a Visual Studio project file, or install it in Visual Studio folder. diff --git a/misc/stl/imgui_stl.cpp b/misc/cpp/imgui_stdlib.cpp similarity index 88% rename from misc/stl/imgui_stl.cpp rename to misc/cpp/imgui_stdlib.cpp index 014f0c1e..790d8d80 100644 --- a/misc/stl/imgui_stl.cpp +++ b/misc/cpp/imgui_stdlib.cpp @@ -1,4 +1,4 @@ -// imgui_stl.cpp +// imgui_stdlib.cpp // Wrappers for C++ standard library (STL) types (std::string, etc.) // This is also an example of how you may wrap your own similar types. @@ -6,8 +6,11 @@ // - std::string support is only guaranteed to work from C++11. // If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture) +// Changelog: +// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string + #include "imgui.h" -#include "imgui_stl.h" +#include "imgui_stdlib.h" struct InputTextCallback_UserData { @@ -22,6 +25,7 @@ static int InputTextCallback(ImGuiInputTextCallbackData* data) if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) { // Resize string callback + // If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want. std::string* str = user_data->Str; IM_ASSERT(data->Buf == str->c_str()); str->resize(data->BufTextLen); diff --git a/misc/stl/imgui_stl.h b/misc/cpp/imgui_stdlib.h similarity index 98% rename from misc/stl/imgui_stl.h rename to misc/cpp/imgui_stdlib.h index 7837ff6a..200c45a5 100644 --- a/misc/stl/imgui_stl.h +++ b/misc/cpp/imgui_stdlib.h @@ -1,4 +1,4 @@ -// imgui_stl.h +// imgui_stdlib.h // Wrappers for C++ standard library (STL) types (std::string, etc.) // This is also an example of how you may wrap your own similar types. diff --git a/misc/natvis/README.txt b/misc/natvis/README.txt index 821014e2..60073874 100644 --- a/misc/natvis/README.txt +++ b/misc/natvis/README.txt @@ -1,3 +1,4 @@ -Natvis file to describe types in Visual Studio debugger. -You can include this in a project file, or install in Visual Studio folder. +Natvis file to describe dear imgui types in the Visual Studio debugger. +With this, types like ImVector<> will be displayed nicely in the debugger. +You can include this file a Visual Studio project file, or install it in Visual Studio folder.