diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 04f8f6dc..a874bfff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,6 +10,7 @@ jobs: Windows: runs-on: windows-2019 env: + VS_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\ MSBUILD_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\ # Until gh-actions allow us to use env variables inside other env variables (because we need %GITHUB_WORKSPACE%) we have to use relative path to imgui/examples/example_name directory. SDL2_DIR: ..\..\SDL2-devel-2.0.10-VC\SDL2-2.0.10\ @@ -41,9 +42,15 @@ jobs: } # Not using matrix here because it would inflate job count too much. Check out and setup is done for every job and that makes build times way too long. - - name: Build example_null (extra warnings) + - name: Build example_null (extra warnings, mingw 64-bit) run: mingw32-make -C examples/example_null EXTRA_WARNINGS=1 + - name: Build example_null (extra warnings, msvc 64-bit) + shell: cmd + run: | + cd examples\example_null + "%VS_PATH%\VC\Auxiliary\Build\vcvarsall.bat" x64 && .\build_win32.bat /W4 + - name: Build example_null (single file build) shell: bash run: | @@ -214,7 +221,7 @@ jobs: brew install glfw3 brew install sdl2 - - name: Build example_null (extra warnings) + - name: Build example_null (extra warnings, clang 64-bit) run: make -C examples/example_null EXTRA_WARNINGS=1 - name: Build example_null (single file build) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b134d931..1b918d75 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -124,6 +124,7 @@ Breaking Changes: documented (can only unreserve from the last reserve call). If you suspect you ever used that feature before, #define IMGUI_DEBUG_PARANOID in imconfig.h to catch existing calls. [@ShironekoBen] +- ImDrawList::AddCircle()/AddCircleFilled() functions don't accept negative radius. - Limiting Columns()/BeginColumns() api to 64 columns with an assert. While the current code technically supports it, future code may not so we're putting the restriction ahead. - imgui_internal.h: changed ImRect() default constructor initializes all fields to 0.0f instead @@ -139,11 +140,15 @@ Other Changes: those improvements in 1.73 makes them unnecessary. (#2722, #2770). [@rokups] - ColorEdit: "Copy As" context-menu tool shows hex values with a '#' prefix instead of '0x'. - ColorEdit: "Copy As" content-menu tool shows hex values both with/without alpha when available. +- ImDrawList: AddCircle(), AddCircleFilled() API can now auto-tessellate when provided a segment + count of zero. Alter tessellation quality with 'style.CircleSegmentMaxError'. [@ShironekoBen] - ImDrawList: Add AddNgon(), AddNgonFilled() API with a guarantee on the explicit segment count. In the current branch they are essentially the same as AddCircle(), AddCircleFilled() but as we will rework the circle rendering functions to use textures and automatic segment count selection, those new api can fill a gap. [@ShironekoBen] - Misc: Added ImGuiMouseCursor_NotAllowed enum so it can be used by more shared widgets. [@rokups] +- Misc: Disable format checks when using stb_printf, to allow using extra formats. + Made IMGUI_USE_STB_SPRINTF a properly documented imconfig.h flag. (#2954) [@loicmolinari] - Misc: Added misc/single_file/imgui_single_file.h, We use this to validate compiling all *.cpp files in a same compilation unit. Actual users of that technique (also called "Unity builds") can generally provide this themselves, so we don't really recommend you use this. [@rokups] @@ -151,10 +156,15 @@ Other Changes: - Backends: GLFW: Added support for the missing mouse cursors newly added in GLFW 3.4+. [@rokups] - Backends: SDL: Wayland: use SDL_GetMouseState (because there is no global mouse state available on Wayland). (#2800, #2802) [@NeroBurner] +- Backends: GLFW, SDL: report Windows key (io.KeySuper) as always released. Neither GLFW nor SDL can + correctly report the key release in every cases (e.g. when using Win+V) causing problems with some + widgets. The next release of GLFW (3.4+) will have a fix for it. However since it is both difficult + and discouraged to make use of this key for Windows application anyway, we just hide it. (#2976) - Backends: Win32: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD to disable all XInput using code, and IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT to disable linking with XInput, the later may be problematic if compiling with recent Windows SDK and you want your app to run on Windows 7. You can instead try linking with Xinput9_1_0.lib instead. (#2716) +- Backends: Glut: Improved FreeGLUT support for MinGW. (#3004) [@podsvirov] - CI: Added PVS-Studio static analysis on the continuous-integration server. [@rokups] - Examples: Explicitly adding -DIMGUI_IMPL_OPENGL_LOADER_GL3W to Makefile to match linking settings (otherwise if another loader such as Glew is accessible, the OpenGL3 backend might @@ -231,6 +241,8 @@ Other Changes: - Examples: DX12: Using IDXGIDebug1::ReportLiveObjects() when DX12_ENABLE_DEBUG_LAYER is enabled. - Examples: Emscripten: Removed BINARYEN_TRAP_MODE=clamp from Makefile which was removed in Emscripten 1.39.0 but required prior to 1.39.0, making life easier for absolutely no-one. (#2877, #2878) [@podsvirov] +- Backends: OpenGL2: Explicitly backup, setup and restore GL_TEXTURE_ENV to increase compatibility with + legacy OpenGL applications. (#3000) - Backends: OpenGL3: Fix building with pre-3.2 GL loaders which do not expose glDrawElementsBaseVertex(), using runtime GL version to decide if we set ImGuiBackendFlags_RendererHasVtxOffset. (#2866, #2852) [@dpilawa] - Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics] diff --git a/docs/FAQ.md b/docs/FAQ.md index 3216a524..571c94c7 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -54,6 +54,8 @@ or view this file with any Markdown viewer. - Your programming IDE is your friend, find the type or function declaration to find comments associated to it. - The `ImGui::ShowMetricsWindow()` function exposes lots of internal information and tools. Although it is primary designed as a debugging tool, having access to that information tends to help understands concepts. +##### [Return to Index](#index) + --- ### Q. What is this library called? @@ -62,6 +64,8 @@ or view this file with any Markdown viewer. (The library misleadingly started its life in 2014 as "ImGui" due to the fact that I didn't give it a proper name when when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations e.g. Unity uses it own implementation of the IMGUI paradigm. To reduce the ambiguity without affecting existing code bases, I have decided in December 2015 a fully qualified name "Dear ImGui" for this library. +##### [Return to Index](#index) + --- ### Q: Which version should I get? @@ -73,10 +77,9 @@ You may use the [docking](https://github.com/ocornut/imgui/tree/docking) branch Many projects are using this branch and it is kept in sync with master regularly. ---- - ##### [Return to Index](#index) +---- # Q&A: Integration @@ -97,6 +100,8 @@ e.g. `if (ImGui::GetIO().WantCaptureMouse) { ... }` **Note:** Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically have `io.WantCaptureKeyboard == false`. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) +##### [Return to Index](#index) + --- ### Q: How can I enable keyboard or gamepad controls? @@ -106,6 +111,8 @@ e.g. `if (ImGui::GetIO().WantCaptureMouse) { ... }` - See [Control Sheets for Gamepads](http://www.dearimgui.org/controls_sheets) (reference PNG/PSD for for PS4, XB1, Switch gamepads). - See `USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS` section of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) for more details. +##### [Return to Index](#index) + --- ### Q: How can I use this on a machine without mouse, keyboard or screen? (input share, remote display) @@ -117,9 +124,9 @@ to your host computer, based on the Synergy 1.x protocol. Make sure you download Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-like protocols. - Game console users: consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui) or [imgui-ws](https://github.com/ggerganov/imgui-ws) which sends the vertices to render over the local network, allowing you to use Dear ImGui even on a screen-less machine. See [Wiki](https://github.com/ocornut/imgui/wiki) index for most details. -- For touch inputs, you can increase the hit box of widgets (via the `style.TouchPadding` setting) to accommodate -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. +- For touch inputs, you can increase the hit box of widgets (via the `style.TouchPadding` setting) to accommodate 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. + +##### [Return to Index](#index) --- @@ -127,6 +134,8 @@ for screen real-estate and precision. In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f). Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. +##### [Return to Index](#index) + --- ### Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. @@ -138,6 +147,7 @@ and **NOT** as ##### [Return to Index](#index) +--- # Q&A: Usage @@ -257,6 +267,8 @@ will preserve your node open/closed state when the targeted object change. e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. See what makes more sense in your situation! +##### [Return to Index](#index) + --- ### Q: How can I display an image? What is ImTextureID, how does it work? @@ -337,6 +349,8 @@ my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr; // cast a void* into a I ``` Finally, you may call `ImGui::ShowMetricsWindow()` to explore/visualize/understand how the ImDrawList are generated. +##### [Return to Index](#index) + --- ### Q: How can I use my own math types instead of ImVec2/ImVec4? @@ -344,6 +358,8 @@ Finally, you may call `ImGui::ShowMetricsWindow()` to explore/visualize/understa You can edit [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) and setup the `IM_VEC2_CLASS_EXTRA`/`IM_VEC4_CLASS_EXTRA` macros to add implicit type conversions. This way you'll be able to use your own types everywhere, e.g. passing `MyVector2` or `glm::vec2` to ImGui functions instead of `ImVec2`. +##### [Return to Index](#index) + --- ### Q: How can I interact with standard C++ types (such as std::string and std::vector)? @@ -366,6 +382,8 @@ One possible implementation of a helper to facilitate printf-style building of s This is a small helper where you can instance strings with configurable local buffers length. Many game engines will provide similar or better string helpers. +##### [Return to Index](#index) + --- ### Q: How can I display custom shapes? (using low-level ImDrawList API) @@ -402,6 +420,7 @@ ImGui::End(); ##### [Return to Index](#index) +--- # Q&A: Fonts, Text @@ -429,6 +448,8 @@ io.Fonts->AddFontFromFileTTF("MyFolder\\MyFont.ttf", size; // CORRECT io.Fonts->AddFontFromFileTTF("MyFolder/MyFont.ttf", size); // ALSO CORRECT ``` +##### [Return to Index](#index) + --- ### Q: How can I easily use icons in my application? @@ -439,6 +460,8 @@ You may want to see `ImFontConfig::GlyphMinAdvanceX` to make your icon look mono With some extra effort, you may use colorful icon by registering custom rectangle space inside the font atlas, and copying your own graphics data into it. See docs/FONTS.txt about using the AddCustomRectFontGlyph API. +##### [Return to Index](#index) + --- ### Q: How can I load multiple fonts? @@ -471,6 +494,8 @@ io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs ``` +##### [Return to Index](#index) + --- ### Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? @@ -504,6 +529,7 @@ the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft ##### [Return to Index](#index) +--- # Q&A: Concerns @@ -515,6 +541,10 @@ You may take a look at: - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [Gallery](https://github.com/ocornut/imgui/issues/2847) +##### [Return to Index](#index) + +--- + ### Q: Can you create elaborate/serious tools with Dear ImGui? Yes. People have written game editors, data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). The list of sponsors below is also an indicator that serious game teams have been using the library. @@ -523,6 +553,10 @@ Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might Dear ImGui is built to be efficient and scalable toward the needs for AAA-quality applications running all day. The IMGUI paradigm offers different opportunities for optimization that the more typical RMGUI paradigm. +##### [Return to Index](#index) + +--- + ### Q: Can you reskin the look of Dear ImGui? Somehow. 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. Dear ImGui is NOT designed to create user interface for games, although with ingenious use of the low-level API you can do it. @@ -530,6 +564,10 @@ Somehow. You can alter the look of the interface to some degree: changing colors A reasonably skinned application may look like (screenshot from [#2529](https://github.com/ocornut/imgui/issues/2529#issuecomment-524281119)) ![minipars](https://user-images.githubusercontent.com/314805/63589441-d9794f00-c5b1-11e9-8d96-cfc1b93702f7.png) +##### [Return to Index](#index) + +--- + ### Q: Why using C++ (as opposed to C)? 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. @@ -538,6 +576,7 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci ##### [Return to Index](#index) +--- # Q&A: Community diff --git a/docs/README.md b/docs/README.md index 97b7812c..37952f06 100644 --- a/docs/README.md +++ b/docs/README.md @@ -113,20 +113,20 @@ Officially maintained bindings (in repository): - Frameworks: Emscripten, Allegro5, Marmalade. Third-party bindings (see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/) page): -- Languages: C, C#/.Net, ChaiScript, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... -- Frameworks: Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/GameMakerStudio2, Irrlicht, Ogre, OpenFrameworks, OpenSceneGraph/OSG, ORX, px_render, LÖVE+Lua, Magnum, NanoRT, Qt, QtDirect3D, SFML, Software Rasterizers, Unreal Engine 4... +- Languages: C, C#/.Net, ChaiScript, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... +- Frameworks: AGS/Adventure Game Studio, Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, NanoRT, Nim Game Lib, Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, px_render, Qt/QtDirect3D, SFML, Sokol, Unreal Engine 4, vtk, Win32 GDI. - Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages. Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. ### Upcoming Changes -Some of the goals for 2019-2020 are: +Some of the goals for 2020 are: - Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback) - Finish work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback) - Finish work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787)) +- Finish work on new Tables API (to replace Columns). (see [#2957](https://github.com/ocornut/imgui/issues/2957)) - Add an automation and testing system, both to test the library and end-user apps. (see [#435](https://github.com/ocornut/imgui/issues/435)) -- Make Columns better. They are currently pretty terrible! New Tables API coming Q4 2019! - Make the examples look better, improve styles, improve font support, make the examples hi-DPI and multi-DPI aware. ### Gallery diff --git a/docs/TODO.txt b/docs/TODO.txt index 4952fb30..ab724270 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -246,21 +246,11 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - menus: hovering from menu to menu on a menu-bar has 1 frame without any menu, which is a little annoying. ideally either 0 either longer. - menus: could merge draw call in most cases (how about storing an optional aabb in ImDrawCmd to move the burden of merging in a single spot). - - text: selectable text (for copy) as a generic feature (ItemFlags?) - - text: proper alignment options in imgui_internal.h - - text: it's currently impossible to have a window title with "##". perhaps an official workaround would be nice. \ style inhibitor? non-visible ascii code to insert between #? - - text: provided a framed text helper, e.g. https://pastebin.com/1Laxy8bT - - text: refactor TextUnformatted (or underlying function) to more explicitly request if we need width measurement or not - - text link/url button: underlined. should api expose an ID or use text contents as ID? which colors enum to use? - - text/wrapped: should be a more first-class citizen, e.g. wrapped text within a Selectable with known width - - text/wrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249) - - tree node: add treenode/treepush int variants? not there because (void*) cast from int warns on some platforms/settings? - tree node: try to apply scrolling at time of TreePop() if node was just opened and end of node is past scrolling limits? - tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer) - tree node: tweak color scheme to distinguish headers from selected tree node (#581) - tree node: leaf/non-leaf highlight mismatch. - - tree node: _NoIndentOnOpen flag? would require to store a per-depth bit mask to store info for pop (or whatever is cheaper) - tree node/opt: could avoid formatting when clipped (flag assuming we don't care about width/height, assume single line height?) - settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes? @@ -309,6 +299,17 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - pie menus patterns (#434) - markup: simple markup language for color change? (#902) + - text: selectable text (for copy) as a generic feature (ItemFlags?) + - text: proper alignment options in imgui_internal.h + - text: it's currently impossible to have a window title with "##". perhaps an official workaround would be nice. \ style inhibitor? non-visible ascii code to insert between #? + - text: provided a framed text helper, e.g. https://pastebin.com/1Laxy8bT + - text: refactor TextUnformatted (or underlying function) to more explicitly request if we need width measurement or not + - text link/url button: underlined. should api expose an ID or use text contents as ID? which colors enum to use? + - text/wrapped: should be a more first-class citizen, e.g. wrapped text within a Selectable with known width. + - text/wrapped: custom separator for text wrapping. (#3002) + - text/wrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249) + + - font: arbitrary line spacing. (#2945) - font: MergeMode: flags to select overwriting or not (this is now very easy with refactored ImFontAtlasBuildWithStbTruetype) - font: free the Alpha buffer if user only requested RGBA. !- font: better CalcTextSizeA() API, at least for simple use cases. current one is horrible (perhaps have simple vs extended versions). @@ -340,8 +341,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line?) ! nav: never clear NavId on some setup (e.g. gamepad centric) - - nav: restore NavId on reappearing non-child window. - - nav: code to focus child-window on restoring NavId appears to have issue (to investigate) + - nav: code to focus child-window on restoring NavId appears to have issue: e.g. when focus change is implicit because of window closure. - nav: configuration flag to disable global shortcuts (currently only CTRL-Tab) ? - nav: Home/End behavior when navigable item is not fully visible at the edge of scrolling? should be backtrack to keep item into view? - nav: NavScrollToBringItemIntoView() with item bigger than view should focus top-right? Repro: using Nav in "About Window" @@ -349,20 +349,21 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav: patterns to make it possible for arrows key to update selection - nav: restore/find nearest NavId when current one disappear (e.g. pressed a button that disappear, or perhaps auto restoring when current button change name) - nav: SetItemDefaultFocus() level of priority, so widget like Selectable when inside a popup could claim a low-priority default focus on the first selected iem - - nav: ESC within a menu of a child window seems to exit the child window. - nav: NavFlattened: ESC on a flattened child should select something. - nav: NavFlattened: broken: in typical usage scenario, the items of a fully clipped child are currently not considered to enter into a NavFlattened child. - nav: NavFlattened: init request doesn't select items that are part of a NavFlattened child - nav: NavFlattened: cannot access menu-bar of a flattened child window with Alt/menu key (not a very common use case..). - - nav: Left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?) + - nav/treenode: Left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?) - nav/menus: pressing left-right on a vertically clipped menu bar tends to jump to the collapse/close buttons. - nav/menus: allow pressing Menu to leave a sub-menu. - - nav/menus: a way to access the main menu bar with Alt? (currently needs CTRL+TAB) + - nav/menus: a way to access the main menu bar with Alt? (currently needs CTRL+TAB) or last focused window menu bar? - nav/menus: when using the main menu bar, even though we restore focus after, the underlying window loses its title bar highlight during menu manipulation. could we prevent it? - nav/menus: main menu bar currently cannot restore a NULL focus. Could save NavWindow at the time of being focused, similarly to what popup do? + - nav/menus: Alt,Up could open the first menu (e.g. "File") currently it tends to nav into the window/collapse menu. Do do that we would need custom transition? + - nav/windowing: configure fade-in/fade-out delay on Ctrl+Tab? + - nav/windowing: when CTRL-Tab/windowing is active, the HoveredWindow detection doesn't take account of the window display re-ordering. - nav: simulate right-click or context activation? (SHIFT+F10) - nav: tabs should go through most/all widgets (in submission order?). - - nav: when CTRL-Tab/windowing is active, the HoveredWindow detection doesn't take account of the window display re-ordering. - nav: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys. - nav: when activating a button that changes label (without a static ID) or disappear, can we somehow automatically recover into a nearest highlight item? - nav: there's currently no way to completely clear focus with the keyboard. depending on patterns used by the application to dispatch inputs, it may be desirable. diff --git a/examples/README.txt b/examples/README.txt index cc20367f..97938953 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -113,7 +113,7 @@ List of Platforms Bindings in this repository: imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl back-ends) imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org imgui_impl_win32.cpp ; Win32 native API (Windows) - imgui_impl_glut.cpp ; GLUT/FreeGLUT (absolutely not recommended in 2019) + imgui_impl_glut.cpp ; GLUT/FreeGLUT (absolutely not recommended in 2020!) List of Renderer Bindings in this repository: @@ -138,22 +138,18 @@ Third-party framework, graphics API and languages bindings are listed at: https://github.com/ocornut/imgui/wiki/Bindings - Languages: - C, C#, ChaiScript, CovScript, D, Go, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Nim, - Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... +Including backends for: - Frameworks: - Amethyst, bsf, Cinder, Cocoa2d-x, Diligent Engine, Flexium, GML/GameMaker Studio, - GTK3 + OpenGL, Irrlicht, Ogre, OpenSceneGraph/OSG, openFrameworks, Orx, LÖVE+LUA, - Magnum, NanoRT, Nim Game Lib, px_render, Qt, Qt3d, SFML, Sokol, Unreal Engine 4, vtk... - - Miscellaneous: Software Renderer, RemoteImgui, imgui-ws, etc. + AGS/Adventure Game Studio, Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, + GML/Game Maker Studio2, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, NanoRT, Nim Game Lib, + Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, px_render, Qt/QtDirect3D, SFML, Sokol, + Unreal Engine 4, vtk, Win32 GDI, etc. Not sure which to use? Recommended platform/frameworks: GLFW https://github.com/glfw/glfw Use imgui_impl_glfw.cpp - SDL2 https://www.libsdl.org Use imgui_impl_sdl.cp + SDL2 https://www.libsdl.org Use imgui_impl_sdl.cpp Sokol https://github.com/floooh/sokol Use util/sokol_imgui.h in Sokol repository. Those will allow you to create portable applications and will solve and abstract away many issues. diff --git a/examples/example_glut_opengl2/Makefile b/examples/example_glut_opengl2/Makefile index c381c0c9..70576b8f 100644 --- a/examples/example_glut_opengl2/Makefile +++ b/examples/example_glut_opengl2/Makefile @@ -41,7 +41,13 @@ endif ifeq ($(findstring MINGW,$(UNAME_S)),MINGW) ECHO_MESSAGE = "MinGW" - LIBS += -lgdi32 -lopengl32 -limm32 -lglut + LIBS += -lgdi32 -lopengl32 -limm32 +ifeq ($(shell pkg-config freeglut --exists 2> /dev/null && echo yes || echo no),yes) + CXXFLAGS += $(shell pkg-config freeglut --cflags) + LIBS += $(shell pkg-config freeglut --libs) +else + LIBS += -lglut +endif CFLAGS = $(CXXFLAGS) endif diff --git a/examples/example_glut_opengl2/main.cpp b/examples/example_glut_opengl2/main.cpp index 26a351f8..b790c8c0 100644 --- a/examples/example_glut_opengl2/main.cpp +++ b/examples/example_glut_opengl2/main.cpp @@ -2,12 +2,12 @@ // If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp. // !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! -// !!! If someone or something is teaching you GLUT in 2019, you are being abused. Please show some resistance. !!! +// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!! // !!! Nowadays, prefer using GLFW or SDL instead! #include "imgui.h" -#include "../imgui_impl_glut.h" -#include "../imgui_impl_opengl2.h" +#include "imgui_impl_glut.h" +#include "imgui_impl_opengl2.h" #ifdef __APPLE__ #include #else diff --git a/examples/example_null/build_win32.bat b/examples/example_null/build_win32.bat index 12cb70ab..38e79148 100644 --- a/examples/example_null/build_win32.bat +++ b/examples/example_null/build_win32.bat @@ -1,3 +1,3 @@ @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. mkdir Debug -cl /nologo /Zi /MD /I ..\.. *.cpp ..\..\*.cpp /FeDebug/example_null.exe /FoDebug/ /link gdi32.lib shell32.lib +cl /nologo /Zi /MD /I ..\.. %* *.cpp ..\..\*.cpp /FeDebug/example_null.exe /FoDebug/ /link gdi32.lib shell32.lib diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 388942c6..2d3431e9 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -17,6 +17,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors. // 2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor). // 2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown. // 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter. @@ -132,7 +133,11 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int a io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; +#ifdef _WIN32 + io.KeySuper = false; +#else io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; +#endif } void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) @@ -187,6 +192,11 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; io.ClipboardUserData = g_Window; + // Create mouse cursors + // (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist, + // GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting. + // Missing cursors will return NULL and our _UpdateMouseCursor() function will use the Arrow cursor instead.) + GLFWerrorfun prev_error_callback = glfwSetErrorCallback(NULL); g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); @@ -203,6 +213,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); g_MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); #endif + glfwSetErrorCallback(prev_error_callback); // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. g_PrevUserCallbackMousebutton = NULL; diff --git a/examples/imgui_impl_glut.cpp b/examples/imgui_impl_glut.cpp index 56d8c553..3c17bbfc 100644 --- a/examples/imgui_impl_glut.cpp +++ b/examples/imgui_impl_glut.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Renderer (e.g. OpenGL2) // !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! -// !!! If someone or something is teaching you GLUT in 2019, you are being abused. Please show some resistance. !!! +// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!! // !!! Nowadays, prefer using GLFW or SDL instead! // Issues: @@ -39,7 +39,12 @@ static int g_Time = 0; // Current time, in milliseconds bool ImGui_ImplGLUT_Init() { ImGuiIO& io = ImGui::GetIO(); + +#ifdef FREEGLUT + io.BackendPlatformName ="imgui_impl_glut (freeglut)"; +#else io.BackendPlatformName ="imgui_impl_glut"; +#endif g_Time = 0; diff --git a/examples/imgui_impl_glut.h b/examples/imgui_impl_glut.h index 506c3867..0c561207 100644 --- a/examples/imgui_impl_glut.h +++ b/examples/imgui_impl_glut.h @@ -2,7 +2,7 @@ // This needs to be used along with a Renderer (e.g. OpenGL2) // !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! -// !!! If someone or something is teaching you GLUT in 2019, you are being abused. Please show some resistance. !!! +// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!! // !!! Nowadays, prefer using GLFW or SDL instead! // Issues: diff --git a/examples/imgui_impl_opengl2.cpp b/examples/imgui_impl_opengl2.cpp index 6bdb876b..ba440957 100644 --- a/examples/imgui_impl_opengl2.cpp +++ b/examples/imgui_impl_opengl2.cpp @@ -19,7 +19,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2020-01-23: OpenGL: Explicitly backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications. // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. @@ -100,6 +101,7 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid glEnableClientState(GL_COLOR_ARRAY); glEnable(GL_TEXTURE_2D); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!), // you may need to backup/reset/restore current shader using the lines below. DO NOT MODIFY THIS FILE! Add the code in your calling function: @@ -137,6 +139,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); + GLint last_tex_env_mode; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); // Setup desired GL state @@ -204,6 +207,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode); } bool ImGui_ImplOpenGL2_CreateFontsTexture() diff --git a/examples/imgui_impl_sdl.cpp b/examples/imgui_impl_sdl.cpp index ebb1ff15..32ac4022 100644 --- a/examples/imgui_impl_sdl.cpp +++ b/examples/imgui_impl_sdl.cpp @@ -131,7 +131,11 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0); io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0); io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0); +#ifdef _WIN32 + io.KeySuper = false; +#else io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0); +#endif return true; } // Multi-viewport support diff --git a/imconfig.h b/imconfig.h index c4f7891e..6724e40f 100644 --- a/imconfig.h +++ b/imconfig.h @@ -53,6 +53,10 @@ //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION +//---- Unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined, use the much faster STB sprintf library implementation of vsnprintf instead of the one from the default C library. +// Note that stb_sprintf.h is meant to be provided by the user and available in the include path at compile time. Also, the compatibility checks of the arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf. +// #define IMGUI_USE_STB_SPRINTF + //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. // This will be inlined as part of ImVec2 and ImVec4 class declarations. /* diff --git a/imgui.cpp b/imgui.cpp index 642ebed9..a9615907 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -373,6 +373,7 @@ CODE - 2019/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api. + - 2020/01/22 (1.75) - ImDrawList::AddCircle()/AddCircleFilled() functions don't accept negative radius any more. - 2019/12/17 (1.75) - made Columns() limited to 64 columns by asserting above that limit. While the current code technically supports it, future code may not so we're putting the restriction ahead. - 2019/12/13 (1.75) - [imgui_internal.h] changed ImRect() default constructor initializes all fields to 0.0f instead of (FLT_MAX,FLT_MAX,-FLT_MAX,-FLT_MAX). If you used ImRect::Add() to create bounding boxes by adding multiple points into it, you may need to fix your initial value. - 2019/12/08 (1.75) - removed redirecting functions/enums that were marked obsolete in 1.53 (December 2017): @@ -824,6 +825,9 @@ CODE #ifdef _MSC_VER #pragma warning (disable: 4127) // condition expression is constant #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later +#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types +#endif #endif // Clang/GCC warnings with -Weverything @@ -1013,6 +1017,7 @@ ImGuiStyle::ImGuiStyle() AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU. AntiAliasedFill = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. + CircleSegmentMaxError = 1.60f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. // Default theme ImGui::StyleColorsDark(this); @@ -1392,7 +1397,6 @@ const char* ImStrSkipBlank(const char* str) // You may set IMGUI_USE_STB_SPRINTF to use our default wrapper, or set IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // and setup the wrapper yourself. (FIXME-OPT: Some of our high-level operations such as ImGuiTextBuffer::appendfv() are // designed using two-passes worst case, which probably could be improved using the stbsp_vsprintfcb() function.) -//#define IMGUI_USE_STB_SPRINTF #ifdef IMGUI_USE_STB_SPRINTF #define STB_SPRINTF_IMPLEMENTATION #include "stb_sprintf.h" @@ -2804,27 +2808,6 @@ void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window) window->MemoryDrawListIdxCapacity = window->MemoryDrawListVtxCapacity = 0; } -// FIXME-NAV: Refactor those functions into a single, more explicit one. -void ImGui::SetNavID(ImGuiID id, int nav_layer, int focus_scope_id) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.NavWindow); - IM_ASSERT(nav_layer == 0 || nav_layer == 1); - g.NavId = id; - g.NavFocusScopeId = focus_scope_id; - g.NavWindow->NavLastIds[nav_layer] = id; -} - -void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, int focus_scope_id, const ImRect& rect_rel) -{ - ImGuiContext& g = *GImGui; - SetNavID(id, nav_layer, focus_scope_id); - g.NavWindow->NavRectRel[nav_layer] = rect_rel; - g.NavMousePosDirty = true; - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; -} - void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) { ImGuiContext& g = *GImGui; @@ -2857,31 +2840,6 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) g.ActiveIdUsingKeyInputMask = 0x00; } -// FIXME-NAV: The existence of SetNavID/SetNavIDWithRectRel/SetFocusID is incredibly messy and confusing and needs some explanation or refactoring. -void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(id != 0); - - // Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and window->DC.NavFocusScopeIdCurrent are valid. - // Note that window may be != g.CurrentWindow (e.g. SetFocusID call in InputTextEx for multi-line text) - const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent; - if (g.NavWindow != window) - g.NavInitRequest = false; - g.NavWindow = window; - g.NavId = id; - g.NavLayer = nav_layer; - g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; - window->NavLastIds[nav_layer] = id; - if (window->DC.LastItemId == id) - window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos); - - if (g.ActiveIdSource == ImGuiInputSource_Nav) - g.NavDisableMouseHover = true; - else - g.NavDisableHighlight = true; -} - void ImGui::ClearActiveID() { SetActiveID(0, NULL); @@ -3015,10 +2973,10 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) // [DEBUG] Item Picker tool, when enabling the "extended" version we perform the check in ItemAdd() #ifdef IMGUI_DEBUG_TOOL_ITEM_PICKER_EX - if (id == g.DebugItemPickerBreakID) + if (id == g.DebugItemPickerBreakId) { IM_DEBUG_BREAK(); - g.DebugItemPickerBreakID = 0; + g.DebugItemPickerBreakId = 0; } #endif } @@ -3117,7 +3075,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) // #define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX in imconfig.h if you want this check to also be performed in ItemAdd(). if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id) GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)); - if (g.DebugItemPickerBreakID == id) + if (g.DebugItemPickerBreakId == id) IM_DEBUG_BREAK(); return true; @@ -3778,6 +3736,7 @@ static void NewFrameSanityChecks() IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!"); + IM_ASSERT(g.Style.CircleSegmentMaxError > 0.0f && "Invalid style setting!"); IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)!"); IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting."); IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); @@ -3891,6 +3850,7 @@ void ImGui::NewFrame() virtual_space.Add(g.Viewports[n]->GetRect()); g.DrawListSharedData.ClipRectFullscreen = ImVec4(virtual_space.Min.x, virtual_space.Min.y, virtual_space.Max.x, virtual_space.Max.y); g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol; + g.DrawListSharedData.SetCircleSegmentMaxError(g.Style.CircleSegmentMaxError); g.DrawListSharedData.InitialFlags = ImDrawListFlags_None; if (g.Style.AntiAliasedLines) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines; @@ -4071,7 +4031,7 @@ void ImGui::NewFrame() void ImGui::UpdateDebugToolItemPicker() { ImGuiContext& g = *GImGui; - g.DebugItemPickerBreakID = 0; + g.DebugItemPickerBreakId = 0; if (g.DebugItemPickerActive) { const ImGuiID hovered_id = g.HoveredIdPreviousFrame; @@ -4080,7 +4040,7 @@ void ImGui::UpdateDebugToolItemPicker() g.DebugItemPickerActive = false; if (ImGui::IsMouseClicked(0) && hovered_id) { - g.DebugItemPickerBreakID = hovered_id; + g.DebugItemPickerBreakId = hovered_id; g.DebugItemPickerActive = false; } ImGui::SetNextWindowBgAlpha(0.60f); @@ -7644,6 +7604,22 @@ void ImGui::ActivateItem(ImGuiID id) g.NavNextActivateId = id; } +void ImGui::PushFocusScope(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + window->IDStack.push_back(window->DC.NavFocusScopeIdCurrent); + window->DC.NavFocusScopeIdCurrent = id; +} + +void ImGui::PopFocusScope() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + window->DC.NavFocusScopeIdCurrent = window->IDStack.back(); + window->IDStack.pop_back(); +} + void ImGui::SetKeyboardFocusHere(int offset) { IM_ASSERT(offset >= -1); // -1 is allowed but not below @@ -8596,6 +8572,52 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window) // [SECTION] KEYBOARD/GAMEPAD NAVIGATION //----------------------------------------------------------------------------- +// FIXME-NAV: The existance of SetNavID vs SetNavIDWithRectRel vs SetFocusID is incredibly messy and confusing, +// and needs some explanation or serious refactoring. +void ImGui::SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.NavWindow); + IM_ASSERT(nav_layer == 0 || nav_layer == 1); + g.NavId = id; + g.NavFocusScopeId = focus_scope_id; + g.NavWindow->NavLastIds[nav_layer] = id; +} + +void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel) +{ + ImGuiContext& g = *GImGui; + SetNavID(id, nav_layer, focus_scope_id); + g.NavWindow->NavRectRel[nav_layer] = rect_rel; + g.NavMousePosDirty = true; + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; +} + +void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(id != 0); + + // Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and window->DC.NavFocusScopeIdCurrent are valid. + // Note that window may be != g.CurrentWindow (e.g. SetFocusID call in InputTextEx for multi-line text) + const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent; + if (g.NavWindow != window) + g.NavInitRequest = false; + g.NavWindow = window; + g.NavId = id; + g.NavLayer = nav_layer; + g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; + window->NavLastIds[nav_layer] = id; + if (window->DC.LastItemId == id) + window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos); + + if (g.ActiveIdSource == ImGuiInputSource_Nav) + g.NavDisableMouseHover = true; + else + g.NavDisableHighlight = true; +} + ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy) { if (ImFabs(dx) > ImFabs(dy)) diff --git a/imgui.h b/imgui.h index 7d9c4750..8cd0263a 100644 --- a/imgui.h +++ b/imgui.h @@ -79,7 +79,7 @@ Index of this file: #include #define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h #endif -#if defined(__clang__) || defined(__GNUC__) +#if !defined(IMGUI_USE_STB_SPRINTF) && (defined(__clang__) || defined(__GNUC__)) #define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) // To apply printf-style warnings to our functions. #define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) #else @@ -607,7 +607,7 @@ namespace ImGui // - You can also use SameLine(pos_x) to mimic simplified columns. // - The columns API is work-in-progress and rather lacking (columns are arguably the worst part of dear imgui at the moment!) // - There is a maximum of 64 columns. - // - By end of the 2019 we will expose a new 'Table' api which will replace columns. + // - Currently working on new 'Tables' api which will replace columns (see GitHub #2957) IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API int GetColumnIndex(); // get current column index @@ -1433,6 +1433,7 @@ struct ImGuiStyle bool AntiAliasedLines; // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU. bool AntiAliasedFill; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. + float CircleSegmentMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. ImVec4 Colors[ImGuiCol_COUNT]; IMGUI_API ImGuiStyle(); @@ -2043,6 +2044,9 @@ struct ImDrawList // Primitives // - For rectangular primitives, "p_min" and "p_max" represent the upper-left and lower-right corners. + // - For circle primitives, use "num_segments == 0" to automatically calculate tessellation (preferred). + // In future versions we will use textures to provide cheaper and higher-quality circles. + // Use AddNgon() and AddNgonFilled() functions if you need to guaranteed a specific number of sides. IMGUI_API void AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f); IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size), rounding_corners_flags: 4 bits corresponding to which corner to round IMGUI_API void AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); // a: upper-left, b: lower-right (== upper-left + size) @@ -2332,10 +2336,10 @@ struct ImFont short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont. ImWchar FallbackChar; // 2 // in // = '?' // Replacement character if a glyph isn't found. Only set via SetFallbackChar() ImWchar EllipsisChar; // 2 // out // = -1 // Character used for ellipsis rendering. + bool DirtyLookupTables; // 1 // out // float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) - bool DirtyLookupTables; // 1 // out // // Methods IMGUI_API ImFont(); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 80624563..9c321b85 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3453,9 +3453,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) filter.Draw("Filter colors", ImGui::GetFontSize() * 16); static ImGuiColorEditFlags alpha_flags = 0; - ImGui::RadioButton("Opaque", &alpha_flags, 0); ImGui::SameLine(); - ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine(); - ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf); ImGui::SameLine(); + if (ImGui::RadioButton("Opaque", alpha_flags == 0)) { alpha_flags = 0; } ImGui::SameLine(); + if (ImGui::RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_AlphaPreview)) { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine(); + if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine(); HelpMarker("In the color list:\nLeft-click on colored square to open color picker,\nRight-click to open edit options menu."); ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened); @@ -3510,8 +3510,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) const float surface_sqrt = sqrtf((float)font->MetricsTotalSurface); ImGui::Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, (int)surface_sqrt, (int)surface_sqrt); for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) - if (const ImFontConfig* cfg = &font->ConfigData[config_i]) - ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); + if (font->ConfigData) + if (const ImFontConfig* cfg = &font->ConfigData[config_i]) + ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size)) { // Display all glyphs of the fonts in separate pages of 256 characters @@ -3578,8 +3579,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); ImGui::SameLine(); HelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well."); ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill); ImGui::PushItemWidth(100); - ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, "%.2f", 2.0f); + ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f"); if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f; + ImGui::DragFloat("Circle segment Max Error", &style.CircleSegmentMaxError, 0.01f, 0.10f, 10.0f, "%.2f"); ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. ImGui::PopItemWidth(); @@ -4537,24 +4539,33 @@ static void ShowExampleAppCustomRendering(bool* p_open) static float sz = 36.0f; static float thickness = 3.0f; static int ngon_sides = 6; + static bool circle_segments_override = false; + static int circle_segments_override_v = 12; static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f); + ImGui::PushItemWidth(-ImGui::GetFontSize() * 10); ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f"); ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f"); - ImGui::SliderInt("n-gon sides", &ngon_sides, 3, 12); + ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12); + ImGui::Checkbox("##circlesegmentoverride", &circle_segments_override); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + if (ImGui::SliderInt("Circle segments", &circle_segments_override_v, 3, 40)) + circle_segments_override = true; ImGui::ColorEdit4("Color", &colf.x); + ImGui::PopItemWidth(); const ImVec2 p = ImGui::GetCursorScreenPos(); const ImU32 col = ImColor(colf); + const float spacing = 10.0f; + const ImDrawCornerFlags corners_none = 0; + const ImDrawCornerFlags corners_all = ImDrawCornerFlags_All; + const ImDrawCornerFlags corners_tl_br = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight; + const int circle_segments = circle_segments_override ? circle_segments_override_v : 0; float x = p.x + 4.0f, y = p.y + 4.0f; - float spacing = 10.0f; - ImDrawCornerFlags corners_none = 0; - ImDrawCornerFlags corners_all = ImDrawCornerFlags_All; - ImDrawCornerFlags corners_tl_br = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight; for (int n = 0; n < 2; n++) { // First line uses a thickness of 1.0f, second line uses the configurable thickness float th = (n == 0) ? 1.0f : thickness; - draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // n-gon - draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, 20, th); x += sz + spacing; // Circle + draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // N-gon + draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th); x += sz + spacing; // Circle draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, corners_none, th); x += sz + spacing; // Square draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_all, th); x += sz + spacing; // Square with all rounded corners draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners @@ -4567,8 +4578,8 @@ static void ShowExampleAppCustomRendering(bool* p_open) x = p.x + 4; y += sz + spacing; } - draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col, ngon_sides); x += sz + spacing; // n-gon - draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, 32); x += sz + spacing; // Circle + draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col, ngon_sides); x += sz + spacing; // N-gon + draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments);x += sz + spacing; // Circle draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col); x += sz + spacing; // Square draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f); x += sz + spacing; // Square with all rounded corners draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br); x += sz + spacing; // Square with two rounded corners diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 99713440..627e3e25 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -354,15 +354,30 @@ ImDrawListSharedData::ImDrawListSharedData() Font = NULL; FontSize = 0.0f; CurveTessellationTol = 0.0f; + CircleSegmentMaxError = 0.0f; ClipRectFullscreen = ImVec4(-8192.0f, -8192.0f, +8192.0f, +8192.0f); InitialFlags = ImDrawListFlags_None; - // Const data + // Lookup tables for (int i = 0; i < IM_ARRAYSIZE(CircleVtx12); i++) { const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(CircleVtx12); CircleVtx12[i] = ImVec2(ImCos(a), ImSin(a)); } + memset(CircleSegmentCounts, 0, sizeof(CircleSegmentCounts)); // This will be set by +} + +void ImDrawListSharedData::SetCircleSegmentMaxError(float max_error) +{ + if (CircleSegmentMaxError == max_error) + return; + CircleSegmentMaxError = max_error; + for (int i = 0; i < IM_ARRAYSIZE(CircleSegmentCounts); i++) + { + const float radius = i + 1.0f; + const int segment_count = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError); + CircleSegmentCounts[i] = (ImU8)ImMin(segment_count, 255); + } } void ImDrawList::Clear() @@ -1091,23 +1106,61 @@ void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImV void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness) { - if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) + if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f) return; + // Obtain segment count + if (num_segments <= 0) + { + // Automatic segment count + const int radius_idx = (int)radius - 1; + if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts)) + num_segments = _Data->CircleSegmentCounts[radius_idx]; // Use cached value + else + num_segments = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError); + } + else + { + // Explicit segment count (still clamp to avoid drawing insanely tessellated shapes) + num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX); + } + // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; - PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1); + if (num_segments == 12) + PathArcToFast(center, radius - 0.5f, 0, 12); + else + PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1); PathStroke(col, true, thickness); } void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments) { - if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) + if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f) return; + // Obtain segment count + if (num_segments <= 0) + { + // Automatic segment count + const int radius_idx = (int)radius - 1; + if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts)) + num_segments = _Data->CircleSegmentCounts[radius_idx]; // Use cached value + else + num_segments = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError); + } + else + { + // Explicit segment count (still clamp to avoid drawing insanely tessellated shapes) + num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX); + } + // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; - PathArcTo(center, radius, 0.0f, a_max, num_segments - 1); + if (num_segments == 12) + PathArcToFast(center, radius, 0, 12); + else + PathArcTo(center, radius, 0.0f, a_max, num_segments - 1); PathFillConvex(col); } diff --git a/imgui_internal.h b/imgui_internal.h index e4a4cab9..f17a48d8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -308,22 +308,21 @@ IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* // Helpers: Maths // - Wrapper for standard libs functions. (Note that imgui_demo.cpp does _not_ use them to keep the code easy to copy) #ifndef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS -static inline float ImFabs(float x) { return fabsf(x); } -static inline float ImSqrt(float x) { return sqrtf(x); } -static inline float ImPow(float x, float y) { return powf(x, y); } -static inline double ImPow(double x, double y) { return pow(x, y); } -static inline float ImFmod(float x, float y) { return fmodf(x, y); } -static inline double ImFmod(double x, double y) { return fmod(x, y); } -static inline float ImCos(float x) { return cosf(x); } -static inline float ImSin(float x) { return sinf(x); } -static inline float ImAcos(float x) { return acosf(x); } -static inline float ImAtan2(float y, float x) { return atan2f(y, x); } -static inline double ImAtof(const char* s) { return atof(s); } -static inline float ImFloorStd(float x) { return floorf(x); } // we already uses our own ImFloor() { return (float)(int)v } internally so the standard one wrapper is named differently (it's used by stb_truetype) -static inline float ImCeil(float x) { return ceilf(x); } +#define ImFabs(X) fabsf(X) +#define ImSqrt(X) sqrtf(X) +#define ImFmod(X, Y) fmodf((X), (Y)) +#define ImCos(X) cosf(X) +#define ImSin(X) sinf(X) +#define ImAcos(X) acosf(X) +#define ImAtan2(Y, X) atan2f((Y), (X)) +#define ImAtof(STR) atof(STR) +#define ImFloorStd(X) floorf(X) // We already uses our own ImFloor() { return (float)(int)v } internally so the standard one wrapper is named differently (it's used by e.g. stb_truetype) +#define ImCeil(X) ceilf(X) +static inline float ImPow(float x, float y) { return powf(x, y); } // DragBehaviorT/SliderBehaviorT uses ImPow with either float/double and need the precision +static inline double ImPow(double x, double y) { return pow(x, y); } #endif -// - ImMin/ImMax/ImClamp/ImLerp/ImSwap are used by widgets which support for variety of types: signed/unsigned int/long long float/double -// (Exceptionally using templates here but we could also redefine them for variety of types) +// - ImMin/ImMax/ImClamp/ImLerp/ImSwap are used by widgets which support variety of types: signed/unsigned int/long long float/double +// (Exceptionally using templates here but we could also redefine them for those types) template static inline T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; } template static inline T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; } template static inline T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } @@ -441,7 +440,7 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_Disabled = 1 << 10, // disable interactions ImGuiButtonFlags_AlignTextBaseLine = 1 << 11, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine ImGuiButtonFlags_NoKeyModifiers = 1 << 12, // disable mouse interaction if a key modifier is held - ImGuiButtonFlags_NoHoldingActiveID = 1 << 13, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) + ImGuiButtonFlags_NoHoldingActiveId = 1 << 13, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) ImGuiButtonFlags_NoNavFocus = 1 << 14, // don't override navigation focus when activated ImGuiButtonFlags_NoHoveredOnNav = 1 << 15, // don't report as hovered when navigated on ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold @@ -866,21 +865,29 @@ struct ImGuiColumns } }; +// Helper function to calculate a circle's segment count given its radius and a "maximum error" value. +#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN 12 +#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX 512 +#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(_RAD,_MAXERROR) ImClamp((int)((IM_PI * 2.0f) / ImAcos((_RAD - _MAXERROR) / _RAD)), IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX) + // Data shared between all ImDrawList instances +// You may want to create your own instance of this if you want to use ImDrawList completely without ImGui. In that case, watch out for future changes to this structure. struct IMGUI_API ImDrawListSharedData { ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas ImFont* Font; // Current/default font (optional, for simplified AddText overload) float FontSize; // Current/default font size (optional, for simplified AddText overload) float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() + float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards) - // Const data - // FIXME: Bake rounded corners fill/borders in atlas - ImVec2 CircleVtx12[12]; + // [Internal] Lookup tables + ImVec2 CircleVtx12[12]; // FIXME: Bake rounded corners fill/borders in atlas + ImU8 CircleSegmentCounts[64]; // Precomputed segment count for given radius (array index + 1) before we calculate it dynamically (to avoid calculation overhead) ImDrawListSharedData(); + void SetCircleSegmentMaxError(float max_error); }; struct ImDrawDataBuilder @@ -1205,17 +1212,10 @@ struct ImGuiContext ImGuiID NavJustTabbedId; // Just tabbed to this id. ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest). ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest). - ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame. ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard. ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. int NavScoringCount; // Metrics for debugging - ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed top-most. - ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f - ImGuiWindow* NavWindowingList; - float NavWindowingTimer; - float NavWindowingHighlightAlpha; - bool NavWindowingToggleLayer; ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid @@ -1237,6 +1237,14 @@ struct ImGuiContext ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag) ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) + // Navigation: Windowing (CTRL+TAB, holding Menu button + directional pads to move/resize) + ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed top-most. + ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f + ImGuiWindow* NavWindowingList; + float NavWindowingTimer; + float NavWindowingHighlightAlpha; + bool NavWindowingToggleLayer; + // Legacy Focus/Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!) ImGuiWindow* FocusRequestCurrWindow; // ImGuiWindow* FocusRequestNextWindow; // @@ -1319,7 +1327,7 @@ struct ImGuiContext // Debug Tools bool DebugItemPickerActive; - ImGuiID DebugItemPickerBreakID; // Will call IM_DEBUG_BREAK() when encountering this id + ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this id // Misc float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds. @@ -1389,9 +1397,6 @@ struct ImGuiContext NavInputSource = ImGuiInputSource_None; NavScoringRectScreen = ImRect(); NavScoringCount = 0; - NavWindowingTarget = NavWindowingTargetAnim = NavWindowingList = NULL; - NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; - NavWindowingToggleLayer = false; NavLayer = ImGuiNavLayer_Main; NavIdTabCounter = INT_MAX; NavIdIsAlive = false; @@ -1408,6 +1413,10 @@ struct ImGuiContext NavMoveRequestForward = ImGuiNavForward_None; NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None; + NavWindowingTarget = NavWindowingTargetAnim = NavWindowingList = NULL; + NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; + NavWindowingToggleLayer = false; + FocusRequestCurrWindow = FocusRequestNextWindow = NULL; FocusRequestCurrCounterRegular = FocusRequestCurrCounterTabStop = INT_MAX; FocusRequestNextCounterRegular = FocusRequestNextCounterTabStop = INT_MAX; @@ -1457,7 +1466,7 @@ struct ImGuiContext LogDepthToExpand = LogDepthToExpandDefault = 2; DebugItemPickerActive = false; - DebugItemPickerBreakID = 0; + DebugItemPickerBreakId = 0; memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); FramerateSecPerFrameIdx = 0; @@ -1858,7 +1867,7 @@ namespace ImGui IMGUI_API void SetHoveredID(ImGuiID id); IMGUI_API void KeepAliveID(ImGuiID id); IMGUI_API void MarkItemEdited(ImGuiID id); - IMGUI_API void PushOverrideID(ImGuiID id); + IMGUI_API void PushOverrideID(ImGuiID id); // Push given value at the top of the ID stack (whereas PushID combines old and new hashes) // Basic Helpers for widget code IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f); @@ -1903,8 +1912,13 @@ namespace ImGui IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate); IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. - IMGUI_API void SetNavID(ImGuiID id, int nav_layer, int focus_scope_id); - IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, int focus_scope_id, const ImRect& rect_rel); + IMGUI_API void SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id); + IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); + + // Focus scope (WIP) + IMGUI_API void PushFocusScope(ImGuiID id); // Note: this is storing in same stack as IDStack, so Push/Pop mismatch will be reported there. + IMGUI_API void PopFocusScope(); + inline ImGuiID GetFocusScopeID() { ImGuiContext& g = *GImGui; return g.NavFocusScopeId; } // Inputs // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. @@ -2026,7 +2040,7 @@ 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); IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_node); - IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags); + IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); IMGUI_API void Scrollbar(ImGuiAxis axis); IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float avail_v, float contents_v, ImDrawCornerFlags rounding_corners); IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 5a75082a..b033ca2d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -47,8 +47,11 @@ Index of this file: // Visual Studio warnings #ifdef _MSC_VER -#pragma warning (disable: 4127) // condition expression is constant -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#pragma warning (disable: 4127) // condition expression is constant +#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later +#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types +#endif #endif // Clang/GCC warnings with -Weverything @@ -517,7 +520,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0])) { pressed = true; - if (flags & ImGuiButtonFlags_NoHoldingActiveID) + if (flags & ImGuiButtonFlags_NoHoldingActiveId) ClearActiveID(); else SetActiveID(id, window); // Hold on ID @@ -717,7 +720,7 @@ bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiBu bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir) { float sz = GetFrameHeight(); - return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), 0); + return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), ImGuiButtonFlags_None); } // Button to close a window @@ -5590,7 +5593,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries ImGuiButtonFlags button_flags = 0; - if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveID; } + if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; } if (flags & ImGuiSelectableFlags_PressedOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; } if (flags & ImGuiSelectableFlags_PressedOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; } if (flags & ImGuiSelectableFlags_Disabled) { button_flags |= ImGuiButtonFlags_Disabled; }