Update imgui to 1.90.7-docking.

This commit is contained in:
Bartosz Taudul 2024-05-31 17:20:48 +02:00
parent 982d6ddcdc
commit 0d5bd53be3
No known key found for this signature in database
GPG Key ID: B7FE2008B7575DF3
15 changed files with 2018 additions and 935 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// dear imgui, v1.90.4 // dear imgui, v1.90.7
// (headers) // (headers)
// Help: // Help:
@ -7,15 +7,19 @@
// - Read top of imgui.cpp for more details, links and comments. // - Read top of imgui.cpp for more details, links and comments.
// Resources: // Resources:
// - FAQ https://dearimgui.com/faq // - FAQ ........................ https://dearimgui.com/faq (in repository as docs/FAQ.md)
// - Getting Started https://dearimgui.com/getting-started // - Homepage ................... https://github.com/ocornut/imgui
// - Homepage https://github.com/ocornut/imgui // - Releases & changelog ....... https://github.com/ocornut/imgui/releases
// - Releases & changelog https://github.com/ocornut/imgui/releases // - Gallery .................... https://github.com/ocornut/imgui/issues/7503 (please post your screenshots/video there!)
// - Gallery https://github.com/ocornut/imgui/issues/6897 (please post your screenshots/video there!) // - Wiki ....................... https://github.com/ocornut/imgui/wiki (lots of good stuff there)
// - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started (how to integrate in an existing app by adding ~25 lines of code)
// - Third-party Extensions https://github.com/ocornut/imgui/wiki/Useful-Extensions (ImPlot & many more)
// - Bindings/Backends https://github.com/ocornut/imgui/wiki/Bindings (language bindings, backends for various tech/engines)
// - Glossary https://github.com/ocornut/imgui/wiki/Glossary // - Glossary https://github.com/ocornut/imgui/wiki/Glossary
// - Issues & support https://github.com/ocornut/imgui/issues // - Debug Tools https://github.com/ocornut/imgui/wiki/Debug-Tools
// - Tests & Automation https://github.com/ocornut/imgui_test_engine // - Software using Dear ImGui https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui
// - Issues & support ........... https://github.com/ocornut/imgui/issues
// - Test Engine & Automation ... https://github.com/ocornut/imgui_test_engine (test suite, test engine to automate your apps)
// For first-time users having issues compiling/linking/running/loading fonts: // For first-time users having issues compiling/linking/running/loading fonts:
// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above. // please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
@ -23,8 +27,8 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.90.4" #define IMGUI_VERSION "1.90.7"
#define IMGUI_VERSION_NUM 19040 #define IMGUI_VERSION_NUM 19070
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch #define IMGUI_HAS_DOCK // Docking WIP branch
@ -88,6 +92,8 @@ Index of this file:
#endif #endif
#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers! #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers!
#define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds. #define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds.
// Check that version and structures layouts are matching between compiled imgui code and caller. Read comments above DebugCheckVersionAndDataLayout() for details.
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
// Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions. // Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions.
@ -128,6 +134,7 @@ Index of this file:
#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter #pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
#elif defined(__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
@ -176,8 +183,9 @@ struct ImGuiWindowClass; // Window class (rare/advanced uses: provide
// Enumerations // Enumerations
// - We don't use strongly typed enums much because they add constraints (can't extend in private code, can't store typed in bit fields, extra casting on iteration) // - We don't use strongly typed enums much because they add constraints (can't extend in private code, can't store typed in bit fields, extra casting on iteration)
// - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! // - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists!
// In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. // - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments.
enum ImGuiKey : int; // -> enum ImGuiKey // Enum: A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value) enum ImGuiKey : int; // -> enum ImGuiKey // Enum: A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value)
enum ImGuiMouseSource : int; // -> enum ImGuiMouseSource // Enum; A mouse input source identifier (Mouse, TouchScreen, Pen) enum ImGuiMouseSource : int; // -> enum ImGuiMouseSource // Enum; A mouse input source identifier (Mouse, TouchScreen, Pen)
typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling
@ -192,8 +200,9 @@ typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A
// Flags (declared as int to allow using as flags without overhead, and to not pollute the top of this file) // Flags (declared as int to allow using as flags without overhead, and to not pollute the top of this file)
// - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! // - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists!
// In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. // - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments.
typedef int ImDrawFlags; // -> enum ImDrawFlags_ // Flags: for ImDrawList functions typedef int ImDrawFlags; // -> enum ImDrawFlags_ // Flags: for ImDrawList functions
typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList instance typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList instance
typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas build typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas build
@ -207,6 +216,7 @@ typedef int ImGuiDockNodeFlags; // -> enum ImGuiDockNodeFlags_ // Flags: f
typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: for BeginDragDropSource(), AcceptDragDropPayload() typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: for BeginDragDropSource(), AcceptDragDropPayload()
typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused() typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused()
typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc. typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc.
typedef int ImGuiInputFlags; // -> enum ImGuiInputFlags_ // Flags: for Shortcut(), SetNextItemShortcut()
typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline() typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline()
typedef int ImGuiKeyChord; // -> ImGuiKey | ImGuiMod_XXX // Flags: for IsKeyChordPressed(), Shortcut() etc. an ImGuiKey optionally OR-ed with one or more ImGuiMod_XXX values. typedef int ImGuiKeyChord; // -> ImGuiKey | ImGuiMod_XXX // Flags: for IsKeyChordPressed(), Shortcut() etc. an ImGuiKey optionally OR-ed with one or more ImGuiMod_XXX values.
typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen()
@ -699,7 +709,8 @@ namespace ImGui
// Tooltips // Tooltips
// - Tooltips are windows following the mouse. They do not take focus away. // - Tooltips are windows following the mouse. They do not take focus away.
// - A tooltip window can contain items of any types. SetTooltip() is a shortcut for the 'if (BeginTooltip()) { Text(...); EndTooltip(); }' idiom. // - A tooltip window can contain items of any types.
// - SetTooltip() is more or less a shortcut for the 'if (BeginTooltip()) { Text(...); EndTooltip(); }' idiom (with a subtlety that it discard any previously submitted tooltip)
IMGUI_API bool BeginTooltip(); // begin/append a tooltip window. IMGUI_API bool BeginTooltip(); // begin/append a tooltip window.
IMGUI_API void EndTooltip(); // only call EndTooltip() if BeginTooltip()/BeginItemTooltip() returns true! IMGUI_API void EndTooltip(); // only call EndTooltip() if BeginTooltip()/BeginItemTooltip() returns true!
IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip. Often used after a ImGui::IsItemHovered() check. Override any previous call to SetTooltip(). IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip. Often used after a ImGui::IsItemHovered() check. Override any previous call to SetTooltip().
@ -710,7 +721,7 @@ namespace ImGui
// - SetItemTooltip() is a shortcut for the 'if (IsItemHovered(ImGuiHoveredFlags_ForTooltip)) { SetTooltip(...); }' idiom. // - SetItemTooltip() is a shortcut for the 'if (IsItemHovered(ImGuiHoveredFlags_ForTooltip)) { SetTooltip(...); }' idiom.
// - Where 'ImGuiHoveredFlags_ForTooltip' itself is a shortcut to use 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on active input type. For mouse it defaults to 'ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort'. // - Where 'ImGuiHoveredFlags_ForTooltip' itself is a shortcut to use 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on active input type. For mouse it defaults to 'ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort'.
IMGUI_API bool BeginItemTooltip(); // begin/append a tooltip window if preceding item was hovered. IMGUI_API bool BeginItemTooltip(); // begin/append a tooltip window if preceding item was hovered.
IMGUI_API void SetItemTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip if preceeding item was hovered. override any previous call to SetTooltip(). IMGUI_API void SetItemTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip if preceding item was hovered. override any previous call to SetTooltip().
IMGUI_API void SetItemTooltipV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void SetItemTooltipV(const char* fmt, va_list args) IM_FMTLIST(1);
// Popups, Modals // Popups, Modals
@ -838,14 +849,14 @@ namespace ImGui
// - Drag from window menu button (upper-left button) to undock an entire node (all windows). // - Drag from window menu button (upper-left button) to undock an entire node (all windows).
// - When io.ConfigDockingWithShift == true, you instead need to hold SHIFT to enable docking. // - When io.ConfigDockingWithShift == true, you instead need to hold SHIFT to enable docking.
// About dockspaces: // About dockspaces:
// - Use DockSpaceOverViewport() to create an explicit dock node covering the screen or a specific viewport. // - Use DockSpaceOverViewport() to create a window covering the screen or a specific viewport + a dockspace inside it.
// This is often used with ImGuiDockNodeFlags_PassthruCentralNode to make it transparent. // This is often used with ImGuiDockNodeFlags_PassthruCentralNode to make it transparent.
// - Use DockSpace() to create an explicit dock node _within_ an existing window. See Docking demo for details. // - Use DockSpace() to create an explicit dock node _within_ an existing window. See Docking demo for details.
// - Important: Dockspaces need to be submitted _before_ any window they can host. Submit it early in your frame! // - Important: Dockspaces need to be submitted _before_ any window they can host. Submit it early in your frame!
// - Important: Dockspaces need to be kept alive if hidden, otherwise windows docked into it will be undocked. // - Important: Dockspaces need to be kept alive if hidden, otherwise windows docked into it will be undocked.
// e.g. if you have multiple tabs with a dockspace inside each tab: submit the non-visible dockspaces with ImGuiDockNodeFlags_KeepAliveOnly. // e.g. if you have multiple tabs with a dockspace inside each tab: submit the non-visible dockspaces with ImGuiDockNodeFlags_KeepAliveOnly.
IMGUI_API ImGuiID DockSpace(ImGuiID id, const ImVec2& size = ImVec2(0, 0), ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL); IMGUI_API ImGuiID DockSpace(ImGuiID dockspace_id, const ImVec2& size = ImVec2(0, 0), ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL);
IMGUI_API ImGuiID DockSpaceOverViewport(const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL); IMGUI_API ImGuiID DockSpaceOverViewport(ImGuiID dockspace_id = 0, const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL);
IMGUI_API void SetNextWindowDockID(ImGuiID dock_id, ImGuiCond cond = 0); // set next window dock id IMGUI_API void SetNextWindowDockID(ImGuiID dock_id, ImGuiCond cond = 0); // set next window dock id
IMGUI_API void SetNextWindowClass(const ImGuiWindowClass* window_class); // set next window class (control docking compatibility + provide hints to platform backend via custom viewport flags and platform parent/child relationship) IMGUI_API void SetNextWindowClass(const ImGuiWindowClass* window_class); // set next window class (control docking compatibility + provide hints to platform backend via custom viewport flags and platform parent/child relationship)
IMGUI_API ImGuiID GetWindowDockID(); IMGUI_API ImGuiID GetWindowDockID();
@ -959,6 +970,24 @@ namespace ImGui
IMGUI_API const char* GetKeyName(ImGuiKey key); // [DEBUG] returns English name of the key. Those names a provided for debugging purpose and are not meant to be saved persistently not compared. IMGUI_API const char* GetKeyName(ImGuiKey key); // [DEBUG] returns English name of the key. Those names a provided for debugging purpose and are not meant to be saved persistently not compared.
IMGUI_API void SetNextFrameWantCaptureKeyboard(bool want_capture_keyboard); // Override io.WantCaptureKeyboard flag next frame (said flag is left for your application to handle, typically when true it instructs your app to ignore inputs). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard"; after the next NewFrame() call. IMGUI_API void SetNextFrameWantCaptureKeyboard(bool want_capture_keyboard); // Override io.WantCaptureKeyboard flag next frame (said flag is left for your application to handle, typically when true it instructs your app to ignore inputs). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard"; after the next NewFrame() call.
// Inputs Utilities: Shortcut Testing & Routing [BETA]
// - ImGuiKeyChord = a ImGuiKey + optional ImGuiMod_Alt/ImGuiMod_Ctrl/ImGuiMod_Shift/ImGuiMod_Super.
// ImGuiKey_C // Accepted by functions taking ImGuiKey or ImGuiKeyChord arguments)
// ImGuiMod_Ctrl | ImGuiKey_C // Accepted by functions taking ImGuiKeyChord arguments)
// only ImGuiMod_XXX values are legal to combine with an ImGuiKey. You CANNOT combine two ImGuiKey values.
// - The general idea is that several callers may register interest in a shortcut, and only one owner gets it.
// Parent -> call Shortcut(Ctrl+S) // When Parent is focused, Parent gets the shortcut.
// Child1 -> call Shortcut(Ctrl+S) // When Child1 is focused, Child1 gets the shortcut (Child1 overrides Parent shortcuts)
// Child2 -> no call // When Child2 is focused, Parent gets the shortcut.
// The whole system is order independent, so if Child1 makes its calls before Parent, results will be identical.
// This is an important property as it facilitate working with foreign code or larger codebase.
// - To understand the difference:
// - IsKeyChordPressed() compares mods and call IsKeyPressed() -> function has no side-effect.
// - Shortcut() submits a route, routes are resolved, if it currently can be routed it calls IsKeyChordPressed() -> function has (desirable) side-effects as it can prevents another call from getting the route.
// - Visualize registered routes in 'Metrics/Debugger->Inputs'.
IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags = 0);
IMGUI_API void SetNextItemShortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags = 0);
// Inputs Utilities: Mouse specific // Inputs Utilities: Mouse specific
// - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right. // - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right.
// - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle. // - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle.
@ -973,8 +1002,8 @@ namespace ImGui
IMGUI_API bool IsAnyMouseDown(); // [WILL OBSOLETE] is any mouse button held? This was designed for backends, but prefer having backend maintain a mask of held mouse buttons, because upcoming input queue system will make this invalid. IMGUI_API bool IsAnyMouseDown(); // [WILL OBSOLETE] is any mouse button held? This was designed for backends, but prefer having backend maintain a mask of held mouse buttons, because upcoming input queue system will make this invalid.
IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls
IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve mouse position at the time of opening popup we have BeginPopup() into (helper to avoid user backing that value themselves) IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve mouse position at the time of opening popup we have BeginPopup() into (helper to avoid user backing that value themselves)
IMGUI_API bool IsMouseDragging(ImGuiMouseButton button, float lock_threshold = -1.0f); // is mouse dragging? (if lock_threshold < -1.0f, uses io.MouseDraggingThreshold) IMGUI_API bool IsMouseDragging(ImGuiMouseButton button, float lock_threshold = -1.0f); // is mouse dragging? (uses io.MouseDraggingThreshold if lock_threshold < 0.0f)
IMGUI_API ImVec2 GetMouseDragDelta(ImGuiMouseButton button = 0, float lock_threshold = -1.0f); // return the delta from the initial clicking position while the mouse button is pressed or was just released. This is locked and return 0.0f until the mouse moves past a distance threshold at least once (if lock_threshold < -1.0f, uses io.MouseDraggingThreshold) IMGUI_API ImVec2 GetMouseDragDelta(ImGuiMouseButton button = 0, float lock_threshold = -1.0f); // return the delta from the initial clicking position while the mouse button is pressed or was just released. This is locked and return 0.0f until the mouse moves past a distance threshold at least once (uses io.MouseDraggingThreshold if lock_threshold < 0.0f)
IMGUI_API void ResetMouseDragDelta(ImGuiMouseButton button = 0); // IMGUI_API void ResetMouseDragDelta(ImGuiMouseButton button = 0); //
IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired mouse cursor shape. Important: reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired mouse cursor shape. Important: reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you
IMGUI_API void SetMouseCursor(ImGuiMouseCursor cursor_type); // set desired mouse cursor shape IMGUI_API void SetMouseCursor(ImGuiMouseCursor cursor_type); // set desired mouse cursor shape
@ -1138,11 +1167,12 @@ enum ImGuiTreeNodeFlags_
ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes).
ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow. IMPORTANT: node can still be marked open/close if you don't set the _Leaf flag! ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow. IMPORTANT: node can still be marked open/close if you don't set the _Leaf flag!
ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding(). ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding().
ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line. In the future we may refactor the hit system to be front-to-back, allowing natural overlaps and then this can become the default. ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line without using AllowOverlap mode.
ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (bypass the indented area). ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (cover the indent area).
ImGuiTreeNodeFlags_SpanAllColumns = 1 << 13, // Frame will span all columns of its container table (text will still fit in current column) ImGuiTreeNodeFlags_SpanTextWidth = 1 << 13, // Narrow hit box + narrow hovering highlight, will only cover the label text.
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 14, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) ImGuiTreeNodeFlags_SpanAllColumns = 1 << 14, // Frame will span all columns of its container table (text will still fit in current column)
//ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 15, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 15, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop)
//ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 16, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible
ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog, ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog,
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@ -1478,13 +1508,13 @@ enum ImGuiKey : int
// - In theory the value of keyboard modifiers should be roughly equivalent to a logical or of the equivalent left/right keys. // - In theory the value of keyboard modifiers should be roughly equivalent to a logical or of the equivalent left/right keys.
// In practice: it's complicated; mods are often provided from different sources. Keyboard layout, IME, sticky keys and // In practice: it's complicated; mods are often provided from different sources. Keyboard layout, IME, sticky keys and
// backends tend to interfere and break that equivalence. The safer decision is to relay that ambiguity down to the end-user... // backends tend to interfere and break that equivalence. The safer decision is to relay that ambiguity down to the end-user...
// - On macOS, we swap Cmd(Super) and Ctrl keys at the time of the io.AddKeyEvent() call.
ImGuiMod_None = 0, ImGuiMod_None = 0,
ImGuiMod_Ctrl = 1 << 12, // Ctrl ImGuiMod_Ctrl = 1 << 12, // Ctrl (non-macOS), Cmd (macOS)
ImGuiMod_Shift = 1 << 13, // Shift ImGuiMod_Shift = 1 << 13, // Shift
ImGuiMod_Alt = 1 << 14, // Option/Menu ImGuiMod_Alt = 1 << 14, // Option/Menu
ImGuiMod_Super = 1 << 15, // Cmd/Super/Windows ImGuiMod_Super = 1 << 15, // Windows/Super (non-macOS), Ctrl (macOS)
ImGuiMod_Shortcut = 1 << 11, // Alias for Ctrl (non-macOS) _or_ Super (macOS). ImGuiMod_Mask_ = 0xF000, // 4-bits
ImGuiMod_Mask_ = 0xF800, // 5-bits
// [Internal] Prior to 1.87 we required user to fill io.KeysDown[512] using their own native index + the io.KeyMap[] array. // [Internal] Prior to 1.87 we required user to fill io.KeysDown[512] using their own native index + the io.KeyMap[] array.
// We are ditching this method but keeping a legacy path for user code doing e.g. IsKeyPressed(MY_NATIVE_KEY_CODE) // We are ditching this method but keeping a legacy path for user code doing e.g. IsKeyPressed(MY_NATIVE_KEY_CODE)
@ -1501,11 +1531,37 @@ enum ImGuiKey : int
#endif #endif
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiMod_Shortcut = ImGuiMod_Ctrl, // Removed in 1.90.7, you can now simply use ImGuiMod_Ctrl
ImGuiKey_ModCtrl = ImGuiMod_Ctrl, ImGuiKey_ModShift = ImGuiMod_Shift, ImGuiKey_ModAlt = ImGuiMod_Alt, ImGuiKey_ModSuper = ImGuiMod_Super, // Renamed in 1.89 ImGuiKey_ModCtrl = ImGuiMod_Ctrl, ImGuiKey_ModShift = ImGuiMod_Shift, ImGuiKey_ModAlt = ImGuiMod_Alt, ImGuiKey_ModSuper = ImGuiMod_Super, // Renamed in 1.89
//ImGuiKey_KeyPadEnter = ImGuiKey_KeypadEnter, // Renamed in 1.87 //ImGuiKey_KeyPadEnter = ImGuiKey_KeypadEnter, // Renamed in 1.87
#endif #endif
}; };
// Flags for Shortcut(), SetNextItemShortcut(),
// (and for upcoming extended versions of IsKeyPressed(), IsMouseClicked(), Shortcut(), SetKeyOwner(), SetItemKeyOwner() that are still in imgui_internal.h)
// Don't mistake with ImGuiInputTextFlags! (which is for ImGui::InputText() function)
enum ImGuiInputFlags_
{
ImGuiInputFlags_None = 0,
ImGuiInputFlags_Repeat = 1 << 0, // Enable repeat. Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1.
// Flags for Shortcut(), SetNextItemShortcut()
// - Routing policies: RouteGlobal+OverActive >> RouteActive or RouteFocused (if owner is active item) >> RouteGlobal+OverFocused >> RouteFocused (if in focused window stack) >> RouteGlobal.
// - Default policy is RouteFocused. Can select only 1 policy among all available.
ImGuiInputFlags_RouteActive = 1 << 10, // Route to active item only.
ImGuiInputFlags_RouteFocused = 1 << 11, // Route to windows in the focus stack (DEFAULT). Deep-most focused window takes inputs. Active item takes inputs over deep-most focused window.
ImGuiInputFlags_RouteGlobal = 1 << 12, // Global route (unless a focused window or active item registered the route).
ImGuiInputFlags_RouteAlways = 1 << 13, // Do not register route, poll keys directly.
// - Routing options
ImGuiInputFlags_RouteOverFocused = 1 << 14, // Option: global route: higher priority than focused route (unless active item in focused route).
ImGuiInputFlags_RouteOverActive = 1 << 15, // Option: global route: higher priority than active item. Unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overridden by this. May not be fully honored as user/internal code is likely to always assume they can access keys when active.
ImGuiInputFlags_RouteUnlessBgFocused = 1 << 16, // Option: global route: will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications.
ImGuiInputFlags_RouteFromRootWindow = 1 << 17, // Option: route evaluated from the point of view of root window rather than current window.
// Flags for SetNextItemShortcut()
ImGuiInputFlags_Tooltip = 1 << 18, // Automatically display a tooltip when hovering item [BETA] Unsure of right api (opt-in/opt-out)
};
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
// OBSOLETED in 1.88 (from July 2022): ImGuiNavInput and io.NavInputs[]. // OBSOLETED in 1.88 (from July 2022): ImGuiNavInput and io.NavInputs[].
// Official backends between 1.60 and 1.86: will keep working and feed gamepad inputs as long as IMGUI_DISABLE_OBSOLETE_KEYIO is not set. // Official backends between 1.60 and 1.86: will keep working and feed gamepad inputs as long as IMGUI_DISABLE_OBSOLETE_KEYIO is not set.
@ -1623,12 +1679,13 @@ enum ImGuiCol_
// - The enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code. // - The enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code.
// During initialization or between frames, feel free to just poke into ImGuiStyle directly. // During initialization or between frames, feel free to just poke into ImGuiStyle directly.
// - Tip: Use your programming IDE navigation facilities on the names in the _second column_ below to find the actual members and their description. // - Tip: Use your programming IDE navigation facilities on the names in the _second column_ below to find the actual members and their description.
// In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. // - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments.
// - When changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type. // - When changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type.
enum ImGuiStyleVar_ enum ImGuiStyleVar_
{ {
// Enum name --------------------- // Member in ImGuiStyle structure (see ImGuiStyle for descriptions) // Enum name -------------------------- // Member in ImGuiStyle structure (see ImGuiStyle for descriptions)
ImGuiStyleVar_Alpha, // float Alpha ImGuiStyleVar_Alpha, // float Alpha
ImGuiStyleVar_DisabledAlpha, // float DisabledAlpha ImGuiStyleVar_DisabledAlpha, // float DisabledAlpha
ImGuiStyleVar_WindowPadding, // ImVec2 WindowPadding ImGuiStyleVar_WindowPadding, // ImVec2 WindowPadding
@ -1652,13 +1709,16 @@ enum ImGuiStyleVar_
ImGuiStyleVar_GrabMinSize, // float GrabMinSize ImGuiStyleVar_GrabMinSize, // float GrabMinSize
ImGuiStyleVar_GrabRounding, // float GrabRounding ImGuiStyleVar_GrabRounding, // float GrabRounding
ImGuiStyleVar_TabRounding, // float TabRounding ImGuiStyleVar_TabRounding, // float TabRounding
ImGuiStyleVar_TabBorderSize, // float TabBorderSize
ImGuiStyleVar_TabBarBorderSize, // float TabBarBorderSize ImGuiStyleVar_TabBarBorderSize, // float TabBarBorderSize
ImGuiStyleVar_TableAngledHeadersAngle, // float TableAngledHeadersAngle
ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
ImGuiStyleVar_SeparatorTextBorderSize,// float SeparatorTextBorderSize ImGuiStyleVar_SeparatorTextBorderSize, // float SeparatorTextBorderSize
ImGuiStyleVar_SeparatorTextAlign, // ImVec2 SeparatorTextAlign ImGuiStyleVar_SeparatorTextAlign, // ImVec2 SeparatorTextAlign
ImGuiStyleVar_SeparatorTextPadding,// ImVec2 SeparatorTextPadding ImGuiStyleVar_SeparatorTextPadding, // ImVec2 SeparatorTextPadding
ImGuiStyleVar_DockingSeparatorSize,// float DockingSeparatorSize ImGuiStyleVar_DockingSeparatorSize, // float DockingSeparatorSize
ImGuiStyleVar_COUNT ImGuiStyleVar_COUNT
}; };
@ -2073,7 +2133,7 @@ struct ImGuiStyle
float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines. ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines.
ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label). ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label).
ImVec2 CellPadding; // Padding within a table cell. CellPadding.y may be altered between different rows. ImVec2 CellPadding; // Padding within a table cell. Cellpadding.x is locked for entire table. CellPadding.y may be altered between different rows.
ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1). float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1).
@ -2087,6 +2147,7 @@ struct ImGuiStyle
float TabMinWidthForCloseButton; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. float TabMinWidthForCloseButton; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected.
float TabBarBorderSize; // Thickness of tab-bar separator, which takes on the tab active color to denote focus. float TabBarBorderSize; // Thickness of tab-bar separator, which takes on the tab active color to denote focus.
float TableAngledHeadersAngle; // Angle of angled headers (supported values range from -50.0f degrees to +50.0f degrees). float TableAngledHeadersAngle; // Angle of angled headers (supported values range from -50.0f degrees to +50.0f degrees).
ImVec2 TableAngledHeadersTextAlign;// Alignment of angled headers within the cell
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered). ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line. ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
@ -2121,6 +2182,9 @@ struct ImGuiStyle
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Communicate most settings and inputs/outputs to Dear ImGui using this structure. // Communicate most settings and inputs/outputs to Dear ImGui using this structure.
// Access via ImGui::GetIO(). Read 'Programmer guide' section in .cpp file for general usage. // Access via ImGui::GetIO(). Read 'Programmer guide' section in .cpp file for general usage.
// It is generally expected that:
// - initialization: backends and user code writes to ImGuiIO.
// - main loop: backends writes to ImGuiIO, user code and imgui code reads from ImGuiIO.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [Internal] Storage used by IsKeyDown(), IsKeyPressed() etc functions. // [Internal] Storage used by IsKeyDown(), IsKeyPressed() etc functions.
@ -2168,7 +2232,7 @@ struct ImGuiIO
// Miscellaneous options // Miscellaneous options
bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations. bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl. bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates. bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting). bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only). bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only).
@ -2280,16 +2344,6 @@ struct ImGuiIO
int MetricsActiveWindows; // Number of active windows int MetricsActiveWindows; // Number of active windows
ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta. ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta.
// Legacy: before 1.87, we required backend to fill io.KeyMap[] (imgui->native map) during initialization and io.KeysDown[] (native indices) every frame.
// This is still temporarily supported as a legacy feature. However the new preferred scheme is for backend to call io.AddKeyEvent().
// Old (<1.87): ImGui::IsKeyPressed(ImGui::GetIO().KeyMap[ImGuiKey_Space]) --> New (1.87+) ImGui::IsKeyPressed(ImGuiKey_Space)
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
int KeyMap[ImGuiKey_COUNT]; // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512.
bool KeysDown[ImGuiKey_COUNT]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). This used to be [512] sized. It is now ImGuiKey_COUNT to allow legacy io.KeysDown[GetKeyIndex(...)] to work without an overflow.
float NavInputs[ImGuiNavInput_COUNT]; // [LEGACY] Since 1.88, NavInputs[] was removed. Backends from 1.60 to 1.86 won't build. Feed gamepad inputs via io.AddKeyEvent() and ImGuiKey_GamepadXXX enums.
//void* ImeWindowHandle; // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning.
#endif
//------------------------------------------------------------------ //------------------------------------------------------------------
// [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed! // [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed!
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -2311,7 +2365,7 @@ struct ImGuiIO
bool KeySuper; // Keyboard modifier down: Cmd/Super/Windows bool KeySuper; // Keyboard modifier down: Cmd/Super/Windows
// Other state maintained from data above + IO function calls // Other state maintained from data above + IO function calls
ImGuiKeyChord KeyMods; // Key mods flags (any of ImGuiMod_Ctrl/ImGuiMod_Shift/ImGuiMod_Alt/ImGuiMod_Super flags, same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags. DOES NOT CONTAINS ImGuiMod_Shortcut which is pretranslated). Read-only, updated by NewFrame() ImGuiKeyChord KeyMods; // Key mods flags (any of ImGuiMod_Ctrl/ImGuiMod_Shift/ImGuiMod_Alt/ImGuiMod_Super flags, same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags. Read-only, updated by NewFrame()
ImGuiKeyData KeysData[ImGuiKey_KeysData_SIZE]; // Key state for all known keys. Use IsKeyXXX() functions to access this. ImGuiKeyData KeysData[ImGuiKey_KeysData_SIZE]; // Key state for all known keys. Use IsKeyXXX() functions to access this.
bool WantCaptureMouseUnlessPopupClose; // Alternative to WantCaptureMouse: (WantCaptureMouse == true && WantCaptureMouseUnlessPopupClose == false) when a click over void is expected to close a popup. bool WantCaptureMouseUnlessPopupClose; // Alternative to WantCaptureMouse: (WantCaptureMouse == true && WantCaptureMouseUnlessPopupClose == false) when a click over void is expected to close a popup.
ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid) ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid)
@ -2325,6 +2379,7 @@ struct ImGuiIO
bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds. bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds.
bool MouseDownOwnedUnlessPopupClose[5]; // Track if button was clicked inside a dear imgui window. bool MouseDownOwnedUnlessPopupClose[5]; // Track if button was clicked inside a dear imgui window.
bool MouseWheelRequestAxisSwap; // On a non-Mac system, holding SHIFT requests WheelY to perform the equivalent of a WheelX event. On a Mac system this is already enforced by the system. bool MouseWheelRequestAxisSwap; // On a non-Mac system, holding SHIFT requests WheelY to perform the equivalent of a WheelX event. On a Mac system this is already enforced by the system.
bool MouseCtrlLeftAsRightClick; // (OSX) Set to true when the current click was a ctrl-click that spawned a simulated right click
float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked)
float MouseDownDurationPrev[5]; // Previous time the mouse button has been down float MouseDownDurationPrev[5]; // Previous time the mouse button has been down
ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point
@ -2337,6 +2392,16 @@ struct ImGuiIO
ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16() ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16()
ImVector<ImWchar> InputQueueCharacters; // Queue of _characters_ input (obtained by platform backend). Fill using AddInputCharacter() helper. ImVector<ImWchar> InputQueueCharacters; // Queue of _characters_ input (obtained by platform backend). Fill using AddInputCharacter() helper.
// Legacy: before 1.87, we required backend to fill io.KeyMap[] (imgui->native map) during initialization and io.KeysDown[] (native indices) every frame.
// This is still temporarily supported as a legacy feature. However the new preferred scheme is for backend to call io.AddKeyEvent().
// Old (<1.87): ImGui::IsKeyPressed(ImGui::GetIO().KeyMap[ImGuiKey_Space]) --> New (1.87+) ImGui::IsKeyPressed(ImGuiKey_Space)
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
int KeyMap[ImGuiKey_COUNT]; // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512.
bool KeysDown[ImGuiKey_COUNT]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). This used to be [512] sized. It is now ImGuiKey_COUNT to allow legacy io.KeysDown[GetKeyIndex(...)] to work without an overflow.
float NavInputs[ImGuiNavInput_COUNT]; // [LEGACY] Since 1.88, NavInputs[] was removed. Backends from 1.60 to 1.86 won't build. Feed gamepad inputs via io.AddKeyEvent() and ImGuiKey_GamepadXXX enums.
//void* ImeWindowHandle; // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning.
#endif
IMGUI_API ImGuiIO(); IMGUI_API ImGuiIO();
}; };
@ -2361,6 +2426,8 @@ struct ImGuiInputTextCallbackData
void* UserData; // What user passed to InputText() // Read-only void* UserData; // What user passed to InputText() // Read-only
// Arguments for the different callback events // Arguments for the different callback events
// - During Resize callback, Buf will be same as your input buffer.
// - However, during Completion/History/Always callback, Buf always points to our own internal data (it is not the same as your buffer)! Changes to it will be reflected into your own buffer shortly after the callback.
// - 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. // - 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. // - 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 with another one, or set to zero to drop. 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;
@ -2826,15 +2893,15 @@ struct ImDrawList
// [Internal, used while building lists] // [Internal, used while building lists]
unsigned int _VtxCurrentIdx; // [Internal] generally == VtxBuffer.Size unless we are past 64K vertices, in which case this gets reset to 0. unsigned int _VtxCurrentIdx; // [Internal] generally == VtxBuffer.Size unless we are past 64K vertices, in which case this gets reset to 0.
ImDrawListSharedData* _Data; // Pointer to shared draw data (you can use ImGui::GetDrawListSharedData() to get the one from current ImGui context) ImDrawListSharedData* _Data; // Pointer to shared draw data (you can use ImGui::GetDrawListSharedData() to get the one from current ImGui context)
const char* _OwnerName; // Pointer to owner window's name for debugging
ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
ImVector<ImVec4> _ClipRectStack; // [Internal]
ImVector<ImTextureID> _TextureIdStack; // [Internal]
ImVector<ImVec2> _Path; // [Internal] current path building ImVector<ImVec2> _Path; // [Internal] current path building
ImDrawCmdHeader _CmdHeader; // [Internal] template of active commands. Fields should match those of CmdBuffer.back(). ImDrawCmdHeader _CmdHeader; // [Internal] template of active commands. Fields should match those of CmdBuffer.back().
ImDrawListSplitter _Splitter; // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!) ImDrawListSplitter _Splitter; // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!)
ImVector<ImVec4> _ClipRectStack; // [Internal]
ImVector<ImTextureID> _TextureIdStack; // [Internal]
float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content
const char* _OwnerName; // Pointer to owner window's name for debugging
// If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui) // If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui)
ImDrawList(ImDrawListSharedData* shared_data) { memset(this, 0, sizeof(*this)); _Data = shared_data; } ImDrawList(ImDrawListSharedData* shared_data) { memset(this, 0, sizeof(*this)); _Data = shared_data; }
@ -2867,15 +2934,20 @@ struct ImDrawList
IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 0); IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 0);
IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f); IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f);
IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments); IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments);
IMGUI_API void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f); IMGUI_API void AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f);
IMGUI_API void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0); IMGUI_API void AddEllipseFilled(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0);
IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL);
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col);
IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points) IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points)
IMGUI_API void AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0); // Quadratic Bezier (3 control points) IMGUI_API void AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0); // Quadratic Bezier (3 control points)
// General polygon
// - Only simple polygons are supported by filling functions (no self-intersections, no holes).
// - Concave polygon fill is more expensive than convex one: it has O(N^2) complexity. Provided as a convenience fo user but not used by main library.
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col);
IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col);
// Image primitives // Image primitives
// - Read FAQ to understand what ImTextureID is. // - Read FAQ to understand what ImTextureID is.
// - "p_min" and "p_max" represent the upper-left and lower-right corners of the rectangle. // - "p_min" and "p_max" represent the upper-left and lower-right corners of the rectangle.
@ -2891,10 +2963,11 @@ struct ImDrawList
inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); }
inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); } inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); }
inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; } inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; }
inline void PathFillConcave(ImU32 col) { AddConcavePolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; }
inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; } inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; }
IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0); IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0);
IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle
IMGUI_API void PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments = 0); // Ellipse IMGUI_API void PathEllipticalArcTo(const ImVec2& center, const ImVec2& radius, float rot, float a_min, float a_max, int num_segments = 0); // Ellipse
IMGUI_API void PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0); // Cubic Bezier (4 control points) IMGUI_API void PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0); // Cubic Bezier (4 control points)
IMGUI_API void PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments = 0); // Quadratic Bezier (3 control points) IMGUI_API void PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments = 0); // Quadratic Bezier (3 control points)
IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawFlags flags = 0); IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawFlags flags = 0);
@ -2927,6 +3000,9 @@ struct ImDrawList
inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } // Write vertex with unique index inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } // Write vertex with unique index
// Obsolete names // Obsolete names
//inline void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2(radius_x, radius_y), col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024)
//inline void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0) { AddEllipseFilled(center, ImVec2(radius_x, radius_y), col, rot, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024)
//inline void PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments = 0) { PathEllipticalArcTo(center, ImVec2(radius_x, radius_y), rot, a_min, a_max, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024)
//inline void AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0) { AddBezierCubic(p1, p2, p3, p4, col, thickness, num_segments); } // OBSOLETED in 1.80 (Jan 2021) //inline void AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0) { AddBezierCubic(p1, p2, p3, p4, col, thickness, num_segments); } // OBSOLETED in 1.80 (Jan 2021)
//inline void PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0) { PathBezierCubicCurveTo(p2, p3, p4, num_segments); } // OBSOLETED in 1.80 (Jan 2021) //inline void PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0) { PathBezierCubicCurveTo(p2, p3, p4, num_segments); } // OBSOLETED in 1.80 (Jan 2021)
@ -3115,7 +3191,7 @@ struct ImFontAtlas
// You can request arbitrary rectangles to be packed into the atlas, for your own purposes. // You can request arbitrary rectangles to be packed into the atlas, for your own purposes.
// - After calling Build(), you can query the rectangle position and render your pixels. // - After calling Build(), you can query the rectangle position and render your pixels.
// - If you render colored output, set 'atlas->TexPixelsUseColors = true' as this may help some backends decide of prefered texture format. // - If you render colored output, set 'atlas->TexPixelsUseColors = true' as this may help some backends decide of preferred texture format.
// - You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), // - You can also request your rectangles to be mapped as font glyph (given a font + Unicode point),
// so you can render e.g. custom colorful icons and use them as regular glyphs. // so you can render e.g. custom colorful icons and use them as regular glyphs.
// - Read docs/FONTS.md for more details about using colorful icons. // - Read docs/FONTS.md for more details about using colorful icons.
@ -3427,15 +3503,6 @@ struct ImGuiPlatformImeData
// Please keep your copy of dear imgui up to date! Occasionally set '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in imconfig.h to stay ahead. // Please keep your copy of dear imgui up to date! Occasionally set '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in imconfig.h to stay ahead.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
namespace ImGui
{
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
IMGUI_API ImGuiKey GetKeyIndex(ImGuiKey key); // map ImGuiKey_* values into legacy native key index. == io.KeyMap[key]
#else
static inline ImGuiKey GetKeyIndex(ImGuiKey key) { IM_ASSERT(key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END && "ImGuiKey and native_index was merged together and native_index is disabled by IMGUI_DISABLE_OBSOLETE_KEYIO. Please switch to ImGuiKey."); return key; }
#endif
}
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
namespace ImGui namespace ImGui
{ {
@ -3454,11 +3521,14 @@ namespace ImGui
static inline void PopAllowKeyboardFocus() { PopTabStop(); } static inline void PopAllowKeyboardFocus() { PopTabStop(); }
// OBSOLETED in 1.89 (from August 2022) // OBSOLETED in 1.89 (from August 2022)
IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // Use new ImageButton() signature (explicit item id, regular FramePadding) IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // Use new ImageButton() signature (explicit item id, regular FramePadding)
// OBSOLETED in 1.88 (from May 2022) // OBSOLETED in 1.87 (from February 2022)
static inline void CaptureKeyboardFromApp(bool want_capture_keyboard = true) { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value. IMGUI_API ImGuiKey GetKeyIndex(ImGuiKey key); // Map ImGuiKey_* values into legacy native key index. == io.KeyMap[key]. When using a 1.87+ backend using io.AddKeyEvent(), calling GetKeyIndex() with ANY ImGuiKey_XXXX values will return the same value!
static inline void CaptureMouseFromApp(bool want_capture_mouse = true) { SetNextFrameWantCaptureMouse(want_capture_mouse); } // Renamed as name was misleading + removed default value. //static inline ImGuiKey GetKeyIndex(ImGuiKey key) { IM_ASSERT(key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END); return key; }
// Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE) // Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)
//-- OBSOLETED in 1.88 (from May 2022)
//static inline void CaptureKeyboardFromApp(bool want_capture_keyboard = true) { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value.
//static inline void CaptureMouseFromApp(bool want_capture_mouse = true) { SetNextFrameWantCaptureMouse(want_capture_mouse); } // Renamed as name was misleading + removed default value.
//-- OBSOLETED in 1.86 (from November 2021) //-- OBSOLETED in 1.86 (from November 2021)
//IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Code removed, see 1.90 for last version of the code. Calculate range of visible items for large list of evenly sized items. Prefer using ImGuiListClipper. //IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Code removed, see 1.90 for last version of the code. Calculate range of visible items for large list of evenly sized items. Prefer using ImGuiListClipper.
//-- OBSOLETED in 1.85 (from August 2021) //-- OBSOLETED in 1.85 (from August 2021)

View File

@ -1,4 +1,4 @@
// dear imgui, v1.90.4 // dear imgui, v1.90.7
// (demo code) // (demo code)
// Help: // Help:
@ -7,9 +7,14 @@
// - Need help integrating Dear ImGui in your codebase? // - Need help integrating Dear ImGui in your codebase?
// - Read Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started // - Read Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started
// - Read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. // - Read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
// Read imgui.cpp for more details, documentation and comments. // Read top of imgui.cpp and imgui.h for many details, documentation, comments, links.
// Get the latest version at https://github.com/ocornut/imgui // Get the latest version at https://github.com/ocornut/imgui
// How to easily locate code?
// - Use the Item Picker to debug break in code by clicking any widgets: https://github.com/ocornut/imgui/wiki/Debug-Tools
// - Browse an online version the demo with code linked to hovered widgets: https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html
// - Find a visible string and search for it in the code!
//--------------------------------------------------- //---------------------------------------------------
// PLEASE DO NOT REMOVE THIS FILE FROM YOUR PROJECT! // PLEASE DO NOT REMOVE THIS FILE FROM YOUR PROJECT!
//--------------------------------------------------- //---------------------------------------------------
@ -54,8 +59,9 @@
// Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp. // Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.
// Navigating this file: // Navigating this file:
// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. // - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments.
/* /*
@ -131,6 +137,7 @@ Index of this file:
#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning: macro name is a reserved identifier #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning: macro name is a reserved identifier
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
#elif defined(__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
@ -271,6 +278,9 @@ void ImGui::ShowDemoWindow(bool* p_open)
// Most functions would normally just assert/crash if the context is missing. // Most functions would normally just assert/crash if the context is missing.
IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing Dear ImGui context. Refer to examples app!"); IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing Dear ImGui context. Refer to examples app!");
// Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues.
IMGUI_CHECKVERSION();
// Examples Apps (accessible from the "Examples" menu) // Examples Apps (accessible from the "Examples" menu)
static bool show_app_main_menu_bar = false; static bool show_app_main_menu_bar = false;
static bool show_app_console = false; static bool show_app_console = false;
@ -537,6 +547,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback."); ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly); ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors); ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors);
ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.");
ImGui::Text("Also see Style->Rendering for rendering options."); ImGui::Text("Also see Style->Rendering for rendering options.");
ImGui::SeparatorText("Debug"); ImGui::SeparatorText("Debug");
@ -960,13 +971,18 @@ static void ShowDemoWindowWidgets()
if (i == 0) if (i == 0)
ImGui::SetNextItemOpen(true, ImGuiCond_Once); ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i)) // Here we use PushID() to generate a unique base ID, and then the "" used as TreeNode id won't conflict.
// An alternative to using 'PushID() + TreeNode("", ...)' to generate a unique ID is to use 'TreeNode((void*)(intptr_t)i, ...)',
// aka generate a dummy pointer-sized value to be hashed. The demo below uses that technique. Both are fine.
ImGui::PushID(i);
if (ImGui::TreeNode("", "Child %d", i))
{ {
ImGui::Text("blah blah"); ImGui::Text("blah blah");
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::SmallButton("button")) {} if (ImGui::SmallButton("button")) {}
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::PopID();
} }
ImGui::TreePop(); ImGui::TreePop();
} }
@ -984,7 +1000,10 @@ static void ShowDemoWindowWidgets()
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node."); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node.");
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &base_flags, ImGuiTreeNodeFlags_SpanFullWidth); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &base_flags, ImGuiTreeNodeFlags_SpanFullWidth);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth", &base_flags, ImGuiTreeNodeFlags_SpanTextWidth); ImGui::SameLine(); HelpMarker("Reduce hit area to the text label and a bit of margin.");
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &base_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker("For use in Tables only."); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &base_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker("For use in Tables only.");
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_AllowOverlap", &base_flags, ImGuiTreeNodeFlags_AllowOverlap);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_Framed", &base_flags, ImGuiTreeNodeFlags_Framed); ImGui::SameLine(); HelpMarker("Draw frame with background (e.g. for CollapsingHeader)");
ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position); ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop); ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop);
ImGui::Text("Hello!"); ImGui::Text("Hello!");
@ -1017,6 +1036,12 @@ static void ShowDemoWindowWidgets()
ImGui::Text("This is a drag and drop source"); ImGui::Text("This is a drag and drop source");
ImGui::EndDragDropSource(); ImGui::EndDragDropSource();
} }
if (i == 2)
{
// Item 2 has an additional inline button to help demonstrate SpanTextWidth.
ImGui::SameLine();
if (ImGui::SmallButton("button")) {}
}
if (node_open) if (node_open)
{ {
ImGui::BulletText("Blah blah\nBlah Blah"); ImGui::BulletText("Blah blah\nBlah Blah");
@ -1349,6 +1374,7 @@ static void ShowDemoWindowWidgets()
} }
ImGui::EndListBox(); ImGui::EndListBox();
} }
ImGui::SameLine(); HelpMarker("Here we are sharing selection state between both boxes.");
// Custom size: use all width, 5 items tall // Custom size: use all width, 5 items tall
ImGui::Text("Full-width:"); ImGui::Text("Full-width:");
@ -1879,10 +1905,10 @@ static void ShowDemoWindowWidgets()
ImGui::Checkbox("Animate", &animate); ImGui::Checkbox("Animate", &animate);
// Plot as lines and plot as histogram // Plot as lines and plot as histogram
IMGUI_DEMO_MARKER("Widgets/Plotting/PlotLines, PlotHistogram");
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr)); ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f)); ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f));
//ImGui::SameLine(); HelpMarker("Consider using ImPlot instead!");
// Fill an array of contiguous float values to plot // Fill an array of contiguous float values to plot
// Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float
@ -1932,15 +1958,17 @@ static void ShowDemoWindowWidgets()
ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
ImGui::Separator(); ImGui::Separator();
// Animate a simple progress bar ImGui::TreePop();
IMGUI_DEMO_MARKER("Widgets/Plotting/ProgressBar"); }
static float progress = 0.0f, progress_dir = 1.0f;
if (animate) IMGUI_DEMO_MARKER("Widgets/Progress Bars");
if (ImGui::TreeNode("Progress Bars"))
{ {
// Animate a simple progress bar
static float progress = 0.0f, progress_dir = 1.0f;
progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime; progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; } if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; } if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
}
// Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width, // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width,
// or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth. // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
@ -1952,6 +1980,13 @@ static void ShowDemoWindowWidgets()
char buf[32]; char buf[32];
sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753); sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753);
ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf); ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf);
// Pass an animated negative value, e.g. -1.0f * (float)ImGui::GetTime() is the recommended value.
// Adjust the factor if you want to adjust the animation speed.
ImGui::ProgressBar(-1.0f * (float)ImGui::GetTime(), ImVec2(0.0f, 0.0f), "Searching..");
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
ImGui::Text("Indeterminate");
ImGui::TreePop(); ImGui::TreePop();
} }
@ -2542,9 +2577,7 @@ static void ShowDemoWindowWidgets()
{ {
IM_UNUSED(payload); IM_UNUSED(payload);
ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed); ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
ImGui::BeginTooltip(); ImGui::SetTooltip("Cannot drop here!");
ImGui::Text("Cannot drop here!");
ImGui::EndTooltip();
} }
ImGui::EndDragDropTarget(); ImGui::EndDragDropTarget();
} }
@ -5216,6 +5249,7 @@ static void ShowDemoWindowTables()
static ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAllColumns; static ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAllColumns;
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &tree_node_flags, ImGuiTreeNodeFlags_SpanFullWidth); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &tree_node_flags, ImGuiTreeNodeFlags_SpanFullWidth);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth", &tree_node_flags, ImGuiTreeNodeFlags_SpanTextWidth);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &tree_node_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &tree_node_flags, ImGuiTreeNodeFlags_SpanAllColumns);
HelpMarker("See \"Columns flags\" section to configure how indentation is applied to individual columns."); HelpMarker("See \"Columns flags\" section to configure how indentation is applied to individual columns.");
@ -5404,6 +5438,17 @@ static void ShowDemoWindowTables()
ImGui::SliderInt("Frozen rows", &frozen_rows, 0, 2); ImGui::SliderInt("Frozen rows", &frozen_rows, 0, 2);
ImGui::CheckboxFlags("Disable header contributing to column width", &column_flags, ImGuiTableColumnFlags_NoHeaderWidth); ImGui::CheckboxFlags("Disable header contributing to column width", &column_flags, ImGuiTableColumnFlags_NoHeaderWidth);
if (ImGui::TreeNode("Style settings"))
{
ImGui::SameLine();
HelpMarker("Giving access to some ImGuiStyle value in this demo for convenience.");
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
ImGui::SliderAngle("style.TableAngledHeadersAngle", &ImGui::GetStyle().TableAngledHeadersAngle, -50.0f, +50.0f);
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
ImGui::SliderFloat2("style.TableAngledHeadersTextAlign", (float*)&ImGui::GetStyle().TableAngledHeadersTextAlign, 0.0f, 1.0f, "%.2f");
ImGui::TreePop();
}
if (ImGui::BeginTable("table_angled_headers", columns_count, table_flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 12))) if (ImGui::BeginTable("table_angled_headers", columns_count, table_flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 12)))
{ {
ImGui::TableSetupColumn(column_names[0], ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoReorder); ImGui::TableSetupColumn(column_names[0], ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoReorder);
@ -5555,6 +5600,7 @@ static void ShowDemoWindowTables()
HelpMarker("Multiple tables with the same identifier will share their settings, width, visibility, order etc."); HelpMarker("Multiple tables with the same identifier will share their settings, width, visibility, order etc.");
static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoSavedSettings; static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoSavedSettings;
ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
ImGui::CheckboxFlags("ImGuiTableFlags_SizingFixedFit", &flags, ImGuiTableFlags_SizingFixedFit); ImGui::CheckboxFlags("ImGuiTableFlags_SizingFixedFit", &flags, ImGuiTableFlags_SizingFixedFit);
ImGui::CheckboxFlags("ImGuiTableFlags_HighlightHoveredColumn", &flags, ImGuiTableFlags_HighlightHoveredColumn); ImGui::CheckboxFlags("ImGuiTableFlags_HighlightHoveredColumn", &flags, ImGuiTableFlags_HighlightHoveredColumn);
@ -6214,12 +6260,14 @@ static void ShowDemoWindowInputs()
// Display inputs submitted to ImGuiIO // Display inputs submitted to ImGuiIO
IMGUI_DEMO_MARKER("Inputs & Focus/Inputs"); IMGUI_DEMO_MARKER("Inputs & Focus/Inputs");
ImGui::SetNextItemOpen(true, ImGuiCond_Once); ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode("Inputs")) bool inputs_opened = ImGui::TreeNode("Inputs");
{ ImGui::SameLine();
HelpMarker( HelpMarker(
"This is a simplified view. See more detailed input state:\n" "This is a simplified view. See more detailed input state:\n"
"- in 'Tools->Metrics/Debugger->Inputs'.\n" "- in 'Tools->Metrics/Debugger->Inputs'.\n"
"- in 'Tools->Debug Log->IO'."); "- in 'Tools->Debug Log->IO'.");
if (inputs_opened)
{
if (ImGui::IsMousePosValid()) if (ImGui::IsMousePosValid())
ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y); ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
else else
@ -6250,8 +6298,8 @@ static void ShowDemoWindowInputs()
// Display ImGuiIO output flags // Display ImGuiIO output flags
IMGUI_DEMO_MARKER("Inputs & Focus/Outputs"); IMGUI_DEMO_MARKER("Inputs & Focus/Outputs");
ImGui::SetNextItemOpen(true, ImGuiCond_Once); ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode("Outputs")) bool outputs_opened = ImGui::TreeNode("Outputs");
{ ImGui::SameLine();
HelpMarker( HelpMarker(
"The value of io.WantCaptureMouse and io.WantCaptureKeyboard are normally set by Dear ImGui " "The value of io.WantCaptureMouse and io.WantCaptureKeyboard are normally set by Dear ImGui "
"to instruct your application of how to route inputs. Typically, when a value is true, it means " "to instruct your application of how to route inputs. Typically, when a value is true, it means "
@ -6259,6 +6307,8 @@ static void ShowDemoWindowInputs()
"The most typical case is: when hovering a window, Dear ImGui set io.WantCaptureMouse to true, " "The most typical case is: when hovering a window, Dear ImGui set io.WantCaptureMouse to true, "
"and underlying application should ignore mouse inputs (in practice there are many and more subtle " "and underlying application should ignore mouse inputs (in practice there are many and more subtle "
"rules leading to how those flags are set)."); "rules leading to how those flags are set).");
if (outputs_opened)
{
ImGui::Text("io.WantCaptureMouse: %d", io.WantCaptureMouse); ImGui::Text("io.WantCaptureMouse: %d", io.WantCaptureMouse);
ImGui::Text("io.WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose); ImGui::Text("io.WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
ImGui::Text("io.WantCaptureKeyboard: %d", io.WantCaptureKeyboard); ImGui::Text("io.WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
@ -6292,6 +6342,102 @@ static void ShowDemoWindowInputs()
ImGui::TreePop(); ImGui::TreePop();
} }
// Demonstrate using Shortcut() and Routing Policies.
// The general flow is:
// - Code interested in a chord (e.g. "Ctrl+A") declares their intent.
// - Multiple locations may be interested in same chord! Routing helps find a winner.
// - Every frame, we resolve all claims and assign one owner if the modifiers are matching.
// - The lower-level function is 'bool SetShortcutRouting()', returns true when caller got the route.
// - Most of the times, SetShortcutRouting() is not called directly. User mostly calls Shortcut() with routing flags.
// - If you call Shortcut() WITHOUT any routing option, it uses ImGuiInputFlags_RouteFocused.
// TL;DR: Most uses will simply be:
// - Shortcut(ImGuiMod_Ctrl | ImGuiKey_A); // Use ImGuiInputFlags_RouteFocused policy.
IMGUI_DEMO_MARKER("Inputs & Focus/Shortcuts");
if (ImGui::TreeNode("Shortcuts"))
{
static ImGuiInputFlags route_options = ImGuiInputFlags_Repeat;
static ImGuiInputFlags route_type = ImGuiInputFlags_RouteFocused;
ImGui::CheckboxFlags("ImGuiInputFlags_Repeat", &route_options, ImGuiInputFlags_Repeat);
ImGui::RadioButton("ImGuiInputFlags_RouteActive", &route_type, ImGuiInputFlags_RouteActive);
ImGui::RadioButton("ImGuiInputFlags_RouteFocused (default)", &route_type, ImGuiInputFlags_RouteFocused);
ImGui::RadioButton("ImGuiInputFlags_RouteGlobal", &route_type, ImGuiInputFlags_RouteGlobal);
ImGui::Indent();
ImGui::BeginDisabled(route_type != ImGuiInputFlags_RouteGlobal);
ImGui::CheckboxFlags("ImGuiInputFlags_RouteOverFocused", &route_options, ImGuiInputFlags_RouteOverFocused);
ImGui::CheckboxFlags("ImGuiInputFlags_RouteOverActive", &route_options, ImGuiInputFlags_RouteOverActive);
ImGui::CheckboxFlags("ImGuiInputFlags_RouteUnlessBgFocused", &route_options, ImGuiInputFlags_RouteUnlessBgFocused);
ImGui::EndDisabled();
ImGui::Unindent();
ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &route_type, ImGuiInputFlags_RouteAlways);
ImGuiInputFlags flags = route_type | route_options; // Merged flags
if (route_type != ImGuiInputFlags_RouteGlobal)
route_options &= ~(ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused);
ImGui::SeparatorText("Using SetNextItemShortcut()");
ImGui::Text("Ctrl+S");
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_S, flags | ImGuiInputFlags_Tooltip);
ImGui::Button("Save");
ImGui::Text("Alt+F");
ImGui::SetNextItemShortcut(ImGuiMod_Alt | ImGuiKey_F, flags | ImGuiInputFlags_Tooltip);
static float f = 0.5f;
ImGui::SliderFloat("Factor", &f, 0.0f, 1.0f);
ImGui::SeparatorText("Using Shortcut()");
const float line_height = ImGui::GetTextLineHeightWithSpacing();
const ImGuiKeyChord key_chord = ImGuiMod_Ctrl | ImGuiKey_A;
ImGui::Text("Ctrl+A");
ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 0.0f, 1.0f, 0.1f));
ImGui::BeginChild("WindowA", ImVec2(-FLT_MIN, line_height * 14), true);
ImGui::Text("Press CTRL+A and see who receives it!");
ImGui::Separator();
// 1: Window polling for CTRL+A
ImGui::Text("(in WindowA)");
ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
// 2: InputText also polling for CTRL+A: it always uses _RouteFocused internally (gets priority when active)
// (Commmented because the owner-aware version of Shortcut() is still in imgui_internal.h)
//char str[16] = "Press CTRL+A";
//ImGui::Spacing();
//ImGui::InputText("InputTextB", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
//ImGuiID item_id = ImGui::GetItemID();
//ImGui::SameLine(); HelpMarker("Internal widgets always use _RouteFocused");
//ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags, item_id) ? "PRESSED" : "...");
// 3: Dummy child is not claiming the route: focusing them shouldn't steal route away from WindowA
ImGui::BeginChild("ChildD", ImVec2(-FLT_MIN, line_height * 4), true);
ImGui::Text("(in ChildD: not using same Shortcut)");
ImGui::Text("IsWindowFocused: %d", ImGui::IsWindowFocused());
ImGui::EndChild();
// 4: Child window polling for CTRL+A. It is deeper than WindowA and gets priority when focused.
ImGui::BeginChild("ChildE", ImVec2(-FLT_MIN, line_height * 4), true);
ImGui::Text("(in ChildE: using same Shortcut)");
ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
ImGui::EndChild();
// 5: In a popup
if (ImGui::Button("Open Popup"))
ImGui::OpenPopup("PopupF");
if (ImGui::BeginPopup("PopupF"))
{
ImGui::Text("(in PopupF)");
ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
// (Commmented because the owner-aware version of Shortcut() is still in imgui_internal.h)
//ImGui::InputText("InputTextG", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
//ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags, ImGui::GetItemID()) ? "PRESSED" : "...");
ImGui::EndPopup();
}
ImGui::EndChild();
ImGui::PopStyleColor();
ImGui::TreePop();
}
// Display mouse cursors // Display mouse cursors
IMGUI_DEMO_MARKER("Inputs & Focus/Mouse Cursors"); IMGUI_DEMO_MARKER("Inputs & Focus/Mouse Cursors");
if (ImGui::TreeNode("Mouse Cursors")) if (ImGui::TreeNode("Mouse Cursors"))
@ -6427,7 +6573,7 @@ void ImGui::ShowAboutWindow(bool* p_open)
ImGui::Separator(); ImGui::Separator();
ImGui::Text("By Omar Cornut and all Dear ImGui contributors."); ImGui::Text("By Omar Cornut and all Dear ImGui contributors.");
ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information."); ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
ImGui::Text("If your company uses this, please consider sponsoring the project!"); ImGui::Text("If your company uses this, please consider funding the project.");
static bool show_config_info = false; static bool show_config_info = false;
ImGui::Checkbox("Config/Build Information", &show_config_info); ImGui::Checkbox("Config/Build Information", &show_config_info);
@ -6713,6 +6859,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::SeparatorText("Tables"); ImGui::SeparatorText("Tables");
ImGui::SliderFloat2("CellPadding", (float*)&style.CellPadding, 0.0f, 20.0f, "%.0f"); ImGui::SliderFloat2("CellPadding", (float*)&style.CellPadding, 0.0f, 20.0f, "%.0f");
ImGui::SliderAngle("TableAngledHeadersAngle", &style.TableAngledHeadersAngle, -50.0f, +50.0f); ImGui::SliderAngle("TableAngledHeadersAngle", &style.TableAngledHeadersAngle, -50.0f, +50.0f);
ImGui::SliderFloat2("TableAngledHeadersTextAlign", (float*)&style.TableAngledHeadersTextAlign, 0.0f, 1.0f, "%.2f");
ImGui::SeparatorText("Widgets"); ImGui::SeparatorText("Widgets");
ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
@ -7179,6 +7326,7 @@ struct ExampleAppConsole
} }
// Options, Filter // Options, Filter
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_O, ImGuiInputFlags_Tooltip);
if (ImGui::Button("Options")) if (ImGui::Button("Options"))
ImGui::OpenPopup("Options"); ImGui::OpenPopup("Options");
ImGui::SameLine(); ImGui::SameLine();
@ -7187,7 +7335,7 @@ struct ExampleAppConsole
// Reserve enough left-over height for 1 separator + 1 input text // Reserve enough left-over height for 1 separator + 1 input text
const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar)) if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_NavFlattened))
{ {
if (ImGui::BeginPopupContextWindow()) if (ImGui::BeginPopupContextWindow())
{ {
@ -7889,7 +8037,7 @@ static void ShowExampleAppConstrainedResize(bool* p_open)
if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Resize vertical + lock current width if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Resize vertical + lock current width
if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Resize horizontal + lock current height if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Resize horizontal + lock current height
if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width Between and 400 and 500 if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width Between and 400 and 500
if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 500), ImVec2(-1, FLT_MAX)); // Height at least 400 if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, FLT_MAX)); // Height at least 400
if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::AspectRatio, (void*)&aspect_ratio); // Aspect ratio if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::AspectRatio, (void*)&aspect_ratio); // Aspect ratio
if (type == 7) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square if (type == 7) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square
if (type == 8) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)&fixed_step); // Fixed Step if (type == 8) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)&fixed_step); // Fixed Step
@ -8067,6 +8215,14 @@ static void ShowExampleAppWindowTitles(bool*)
// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering() // [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Add a |_| looking shape
static void PathConcaveShape(ImDrawList* draw_list, float x, float y, float sz)
{
const ImVec2 pos_norms[] = { { 0.0f, 0.0f }, { 0.3f, 0.0f }, { 0.3f, 0.7f }, { 0.7f, 0.7f }, { 0.7f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f } };
for (const ImVec2& p : pos_norms)
draw_list->PathLineTo(ImVec2(x + 0.5f + (int)(sz * p.x), y + 0.5f + (int)(sz * p.y)));
}
// Demonstrate using the low-level ImDrawList to draw custom shapes. // Demonstrate using the low-level ImDrawList to draw custom shapes.
static void ShowExampleAppCustomRendering(bool* p_open) static void ShowExampleAppCustomRendering(bool* p_open)
{ {
@ -8150,12 +8306,14 @@ static void ShowExampleAppCustomRendering(bool* p_open)
float th = (n == 0) ? 1.0f : 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->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->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th); x += sz + spacing; // Circle
draw_list->AddEllipse(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, sz*0.3f, col, -0.3f, circle_segments, th); x += sz + spacing; // Ellipse draw_list->AddEllipse(ImVec2(x + sz*0.5f, y + sz*0.5f), ImVec2(sz*0.5f, sz*0.3f), col, -0.3f, circle_segments, th); x += sz + spacing; // Ellipse
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, ImDrawFlags_None, th); x += sz + spacing; // Square draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, ImDrawFlags_None, th); x += sz + spacing; // Square
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, ImDrawFlags_None, th); x += sz + spacing; // Square with all rounded corners draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, ImDrawFlags_None, th); x += sz + spacing; // Square with all rounded corners
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners
draw_list->AddTriangle(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col, th);x += sz + spacing; // Triangle draw_list->AddTriangle(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col, th);x += sz + spacing; // Triangle
//draw_list->AddTriangle(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col, th);x+= sz*0.4f + spacing; // Thin triangle //draw_list->AddTriangle(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col, th);x+= sz*0.4f + spacing; // Thin triangle
PathConcaveShape(draw_list, x, y, sz); draw_list->PathStroke(col, ImDrawFlags_Closed, th); x += sz + spacing; // Concave Shape
//draw_list->AddPolyline(concave_shape, IM_ARRAYSIZE(concave_shape), col, ImDrawFlags_Closed, th);
draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col, th); x += sz + spacing; // Horizontal line (note: drawing a filled rectangle will be faster!) draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col, th); x += sz + spacing; // Horizontal line (note: drawing a filled rectangle will be faster!)
draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!) draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line
@ -8179,12 +8337,13 @@ static void ShowExampleAppCustomRendering(bool* p_open)
// Filled shapes // Filled shapes
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->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->AddCircleFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, circle_segments); x += sz + spacing; // Circle
draw_list->AddEllipseFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, sz * 0.3f, col, -0.3f, circle_segments); x += sz + spacing;// Ellipse draw_list->AddEllipseFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), ImVec2(sz * 0.5f, sz * 0.3f), col, -0.3f, circle_segments); x += sz + spacing;// Ellipse
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); 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); 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 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
draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col); x += sz + spacing; // Triangle draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col); x += sz + spacing; // Triangle
//draw_list->AddTriangleFilled(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col); x += sz*0.4f + spacing; // Thin triangle //draw_list->AddTriangleFilled(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col); x += sz*0.4f + spacing; // Thin triangle
PathConcaveShape(draw_list, x, y, sz); draw_list->PathFillConcave(col); x += sz + spacing; // Concave shape
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + thickness), col); x += sz + spacing; // Horizontal line (faster than AddLine, but only handle integer thickness) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + thickness), col); x += sz + spacing; // Horizontal line (faster than AddLine, but only handle integer thickness)
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + thickness, y + sz), col); x += spacing * 2.0f;// Vertical line (faster than AddLine, but only handle integer thickness) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + thickness, y + sz), col); x += spacing * 2.0f;// Vertical line (faster than AddLine, but only handle integer thickness)
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col); x += sz; // Pixel (faster than AddLine) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col); x += sz; // Pixel (faster than AddLine)
@ -8200,15 +8359,10 @@ static void ShowExampleAppCustomRendering(bool* p_open)
draw_list->PathFillConvex(col); draw_list->PathFillConvex(col);
x += sz + spacing; x += sz + spacing;
// Cubic Bezier Curve (4 control points): this is concave so not drawing it yet
//draw_list->PathLineTo(ImVec2(x + cp4[0].x, y + cp4[0].y));
//draw_list->PathBezierCubicCurveTo(ImVec2(x + cp4[1].x, y + cp4[1].y), ImVec2(x + cp4[2].x, y + cp4[2].y), ImVec2(x + cp4[3].x, y + cp4[3].y), curve_segments);
//draw_list->PathFillConvex(col);
//x += sz + spacing;
draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255)); draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255));
x += sz + spacing;
ImGui::Dummy(ImVec2((sz + spacing) * 12.2f, (sz + spacing) * 3.0f)); ImGui::Dummy(ImVec2((sz + spacing) * 13.2f, (sz + spacing) * 3.0f));
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
@ -8397,7 +8551,7 @@ void ShowExampleAppDockSpace(bool* p_open)
// If we remove all options we are showcasing, this demo would become: // If we remove all options we are showcasing, this demo would become:
// void ShowExampleAppDockSpace() // void ShowExampleAppDockSpace()
// { // {
// ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()); // ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport());
// } // }
// In most cases you should be able to just call DockSpaceOverViewport() and ignore all the code below! // In most cases you should be able to just call DockSpaceOverViewport() and ignore all the code below!
// In this specific demo, we are not using DockSpaceOverViewport() because: // In this specific demo, we are not using DockSpaceOverViewport() because:
@ -8506,91 +8660,118 @@ void ShowExampleAppDockSpace(bool* p_open)
// Simplified structure to mimic a Document model // Simplified structure to mimic a Document model
struct MyDocument struct MyDocument
{ {
const char* Name; // Document title char Name[32]; // Document title
int UID; // Unique ID (necessary as we can change title)
bool Open; // Set when open (we keep an array of all available documents to simplify demo code!) bool Open; // Set when open (we keep an array of all available documents to simplify demo code!)
bool OpenPrev; // Copy of Open from last update. bool OpenPrev; // Copy of Open from last update.
bool Dirty; // Set when the document has been modified bool Dirty; // Set when the document has been modified
bool WantClose; // Set when the document
ImVec4 Color; // An arbitrary variable associated to the document ImVec4 Color; // An arbitrary variable associated to the document
MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f)) MyDocument(int uid, const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f))
{ {
Name = name; UID = uid;
snprintf(Name, sizeof(Name), "%s", name);
Open = OpenPrev = open; Open = OpenPrev = open;
Dirty = false; Dirty = false;
WantClose = false;
Color = color; Color = color;
} }
void DoOpen() { Open = true; } void DoOpen() { Open = true; }
void DoQueueClose() { WantClose = true; }
void DoForceClose() { Open = false; Dirty = false; } void DoForceClose() { Open = false; Dirty = false; }
void DoSave() { Dirty = false; } void DoSave() { Dirty = false; }
};
struct ExampleAppDocuments
{
ImVector<MyDocument> Documents;
ImVector<MyDocument*> CloseQueue;
MyDocument* RenamingDoc = NULL;
bool RenamingStarted = false;
ExampleAppDocuments()
{
Documents.push_back(MyDocument(0, "Lettuce", true, ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
Documents.push_back(MyDocument(1, "Eggplant", true, ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
Documents.push_back(MyDocument(2, "Carrot", true, ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
Documents.push_back(MyDocument(3, "Tomato", false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
Documents.push_back(MyDocument(4, "A Rather Long Title", false, ImVec4(0.4f, 0.8f, 0.8f, 1.0f)));
Documents.push_back(MyDocument(5, "Some Document", false, ImVec4(0.8f, 0.8f, 1.0f, 1.0f)));
}
// As we allow to change document name, we append a never-changing document ID so tabs are stable
void GetTabName(MyDocument* doc, char* out_buf, size_t out_buf_size)
{
snprintf(out_buf, out_buf_size, "%s###doc%d", doc->Name, doc->UID);
}
// Display placeholder contents for the Document // Display placeholder contents for the Document
static void DisplayContents(MyDocument* doc) void DisplayDocContents(MyDocument* doc)
{ {
ImGui::PushID(doc); ImGui::PushID(doc);
ImGui::Text("Document \"%s\"", doc->Name); ImGui::Text("Document \"%s\"", doc->Name);
ImGui::PushStyleColor(ImGuiCol_Text, doc->Color); ImGui::PushStyleColor(ImGuiCol_Text, doc->Color);
ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
ImGui::PopStyleColor(); ImGui::PopStyleColor();
if (ImGui::Button("Modify", ImVec2(100, 0)))
doc->Dirty = true; ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_R, ImGuiInputFlags_Tooltip);
if (ImGui::Button("Rename.."))
{
RenamingDoc = doc;
RenamingStarted = true;
}
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Save", ImVec2(100, 0)))
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_M, ImGuiInputFlags_Tooltip);
if (ImGui::Button("Modify"))
doc->Dirty = true;
ImGui::SameLine();
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_S, ImGuiInputFlags_Tooltip);
if (ImGui::Button("Save"))
doc->DoSave(); doc->DoSave();
ImGui::SameLine();
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_W, ImGuiInputFlags_Tooltip);
if (ImGui::Button("Close"))
CloseQueue.push_back(doc);
ImGui::ColorEdit3("color", &doc->Color.x); // Useful to test drag and drop and hold-dragged-to-open-tab behavior. ImGui::ColorEdit3("color", &doc->Color.x); // Useful to test drag and drop and hold-dragged-to-open-tab behavior.
ImGui::PopID(); ImGui::PopID();
} }
// Display context menu for the Document // Display context menu for the Document
static void DisplayContextMenu(MyDocument* doc) void DisplayDocContextMenu(MyDocument* doc)
{ {
if (!ImGui::BeginPopupContextItem()) if (!ImGui::BeginPopupContextItem())
return; return;
char buf[256]; char buf[256];
sprintf(buf, "Save %s", doc->Name); sprintf(buf, "Save %s", doc->Name);
if (ImGui::MenuItem(buf, "CTRL+S", false, doc->Open)) if (ImGui::MenuItem(buf, "Ctrl+S", false, doc->Open))
doc->DoSave(); doc->DoSave();
if (ImGui::MenuItem("Close", "CTRL+W", false, doc->Open)) if (ImGui::MenuItem("Rename...", "Ctrl+R", false, doc->Open))
doc->DoQueueClose(); RenamingDoc = doc;
if (ImGui::MenuItem("Close", "Ctrl+W", false, doc->Open))
CloseQueue.push_back(doc);
ImGui::EndPopup(); ImGui::EndPopup();
} }
};
struct ExampleAppDocuments // [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
{ // If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo,
ImVector<MyDocument> Documents; // as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for
// the tab bar to notice its absence. During this frame there will be a gap in the tab bar, and if the tab that has
ExampleAppDocuments() // disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively
// give the impression of a flicker for one frame.
// We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
// Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
void NotifyOfDocumentsClosedElsewhere()
{ {
Documents.push_back(MyDocument("Lettuce", true, ImVec4(0.4f, 0.8f, 0.4f, 1.0f))); for (MyDocument& doc : Documents)
Documents.push_back(MyDocument("Eggplant", true, ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
Documents.push_back(MyDocument("Carrot", true, ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
Documents.push_back(MyDocument("Tomato", false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
Documents.push_back(MyDocument("A Rather Long Title", false));
Documents.push_back(MyDocument("Some Document", false));
}
};
// [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
// If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo,
// as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for
// the tab bar to notice its absence. During this frame there will be a gap in the tab bar, and if the tab that has
// disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively
// give the impression of a flicker for one frame.
// We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
// Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app)
{
for (MyDocument& doc : app.Documents)
{ {
if (!doc.Open && doc.OpenPrev) if (!doc.Open && doc.OpenPrev)
ImGui::SetTabItemClosed(doc.Name); ImGui::SetTabItemClosed(doc.Name);
doc.OpenPrev = doc.Open; doc.OpenPrev = doc.Open;
} }
} }
};
void ShowExampleAppDocuments(bool* p_open) void ShowExampleAppDocuments(bool* p_open)
{ {
@ -8639,8 +8820,8 @@ void ShowExampleAppDocuments(bool* p_open)
} }
if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0)) if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
for (MyDocument& doc : app.Documents) for (MyDocument& doc : app.Documents)
doc.DoQueueClose(); app.CloseQueue.push_back(&doc);
if (ImGui::MenuItem("Exit", "Ctrl+F4") && p_open) if (ImGui::MenuItem("Exit") && p_open)
*p_open = false; *p_open = false;
ImGui::EndMenu(); ImGui::EndMenu();
} }
@ -8685,7 +8866,7 @@ void ShowExampleAppDocuments(bool* p_open)
if (ImGui::BeginTabBar("##tabs", tab_bar_flags)) if (ImGui::BeginTabBar("##tabs", tab_bar_flags))
{ {
if (opt_reorderable) if (opt_reorderable)
NotifyOfDocumentsClosedElsewhere(app); app.NotifyOfDocumentsClosedElsewhere();
// [DEBUG] Stress tests // [DEBUG] Stress tests
//if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1; // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on. //if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1; // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on.
@ -8697,20 +8878,23 @@ void ShowExampleAppDocuments(bool* p_open)
if (!doc.Open) if (!doc.Open)
continue; continue;
// As we allow to change document name, we append a never-changing document id so tabs are stable
char doc_name_buf[64];
app.GetTabName(&doc, doc_name_buf, sizeof(doc_name_buf));
ImGuiTabItemFlags tab_flags = (doc.Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0); ImGuiTabItemFlags tab_flags = (doc.Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
bool visible = ImGui::BeginTabItem(doc.Name, &doc.Open, tab_flags); bool visible = ImGui::BeginTabItem(doc_name_buf, &doc.Open, tab_flags);
// Cancel attempt to close when unsaved add to save queue so we can display a popup. // Cancel attempt to close when unsaved add to save queue so we can display a popup.
if (!doc.Open && doc.Dirty) if (!doc.Open && doc.Dirty)
{ {
doc.Open = true; doc.Open = true;
doc.DoQueueClose(); app.CloseQueue.push_back(&doc);
} }
MyDocument::DisplayContextMenu(&doc); app.DisplayDocContextMenu(&doc);
if (visible) if (visible)
{ {
MyDocument::DisplayContents(&doc); app.DisplayDocContents(&doc);
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
} }
@ -8722,7 +8906,7 @@ void ShowExampleAppDocuments(bool* p_open)
{ {
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DockingEnable) if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DockingEnable)
{ {
NotifyOfDocumentsClosedElsewhere(app); app.NotifyOfDocumentsClosedElsewhere();
// Create a DockSpace node where any window can be docked // Create a DockSpace node where any window can be docked
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
@ -8743,12 +8927,12 @@ void ShowExampleAppDocuments(bool* p_open)
if (!doc->Open && doc->Dirty) if (!doc->Open && doc->Dirty)
{ {
doc->Open = true; doc->Open = true;
doc->DoQueueClose(); app.CloseQueue.push_back(doc);
} }
MyDocument::DisplayContextMenu(doc); app.DisplayDocContextMenu(doc);
if (visible) if (visible)
MyDocument::DisplayContents(doc); app.DisplayDocContents(doc);
ImGui::End(); ImGui::End();
} }
@ -8766,33 +8950,44 @@ void ShowExampleAppDocuments(bool* p_open)
return; return;
} }
// Update closing queue // Display renaming UI
static ImVector<MyDocument*> close_queue; if (app.RenamingDoc != NULL)
if (close_queue.empty())
{ {
// Close queue is locked once we started a popup if (app.RenamingStarted)
for (MyDocument& doc : app.Documents) ImGui::OpenPopup("Rename");
if (doc.WantClose) if (ImGui::BeginPopup("Rename"))
{ {
doc.WantClose = false; ImGui::SetNextItemWidth(ImGui::GetFontSize() * 30);
close_queue.push_back(&doc); if (ImGui::InputText("###Name", app.RenamingDoc->Name, IM_ARRAYSIZE(app.RenamingDoc->Name), ImGuiInputTextFlags_EnterReturnsTrue))
{
ImGui::CloseCurrentPopup();
app.RenamingDoc = NULL;
} }
if (app.RenamingStarted)
ImGui::SetKeyboardFocusHere(-1);
ImGui::EndPopup();
}
else
{
app.RenamingDoc = NULL;
}
app.RenamingStarted = false;
} }
// Display closing confirmation UI // Display closing confirmation UI
if (!close_queue.empty()) if (!app.CloseQueue.empty())
{ {
int close_queue_unsaved_documents = 0; int close_queue_unsaved_documents = 0;
for (int n = 0; n < close_queue.Size; n++) for (int n = 0; n < app.CloseQueue.Size; n++)
if (close_queue[n]->Dirty) if (app.CloseQueue[n]->Dirty)
close_queue_unsaved_documents++; close_queue_unsaved_documents++;
if (close_queue_unsaved_documents == 0) if (close_queue_unsaved_documents == 0)
{ {
// Close documents when all are unsaved // Close documents when all are unsaved
for (int n = 0; n < close_queue.Size; n++) for (int n = 0; n < app.CloseQueue.Size; n++)
close_queue[n]->DoForceClose(); app.CloseQueue[n]->DoForceClose();
close_queue.clear(); app.CloseQueue.clear();
} }
else else
{ {
@ -8803,37 +8998,35 @@ void ShowExampleAppDocuments(bool* p_open)
ImGui::Text("Save change to the following items?"); ImGui::Text("Save change to the following items?");
float item_height = ImGui::GetTextLineHeightWithSpacing(); float item_height = ImGui::GetTextLineHeightWithSpacing();
if (ImGui::BeginChild(ImGui::GetID("frame"), ImVec2(-FLT_MIN, 6.25f * item_height), ImGuiChildFlags_FrameStyle)) if (ImGui::BeginChild(ImGui::GetID("frame"), ImVec2(-FLT_MIN, 6.25f * item_height), ImGuiChildFlags_FrameStyle))
{ for (MyDocument* doc : app.CloseQueue)
for (int n = 0; n < close_queue.Size; n++) if (doc->Dirty)
if (close_queue[n]->Dirty) ImGui::Text("%s", doc->Name);
ImGui::Text("%s", close_queue[n]->Name);
}
ImGui::EndChild(); ImGui::EndChild();
ImVec2 button_size(ImGui::GetFontSize() * 7.0f, 0.0f); ImVec2 button_size(ImGui::GetFontSize() * 7.0f, 0.0f);
if (ImGui::Button("Yes", button_size)) if (ImGui::Button("Yes", button_size))
{ {
for (int n = 0; n < close_queue.Size; n++) for (MyDocument* doc : app.CloseQueue)
{ {
if (close_queue[n]->Dirty) if (doc->Dirty)
close_queue[n]->DoSave(); doc->DoSave();
close_queue[n]->DoForceClose(); doc->DoForceClose();
} }
close_queue.clear(); app.CloseQueue.clear();
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("No", button_size)) if (ImGui::Button("No", button_size))
{ {
for (int n = 0; n < close_queue.Size; n++) for (MyDocument* doc : app.CloseQueue)
close_queue[n]->DoForceClose(); doc->DoForceClose();
close_queue.clear(); app.CloseQueue.clear();
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Cancel", button_size)) if (ImGui::Button("Cancel", button_size))
{ {
close_queue.clear(); app.CloseQueue.clear();
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
ImGui::EndPopup(); ImGui::EndPopup();

View File

@ -1,4 +1,4 @@
// dear imgui, v1.90.4 // dear imgui, v1.90.7
// (drawing and font code) // (drawing and font code)
/* /*
@ -8,6 +8,7 @@ Index of this file:
// [SECTION] STB libraries implementation // [SECTION] STB libraries implementation
// [SECTION] Style functions // [SECTION] Style functions
// [SECTION] ImDrawList // [SECTION] ImDrawList
// [SECTION] ImTriangulator, ImDrawList concave polygon fill
// [SECTION] ImDrawListSplitter // [SECTION] ImDrawListSplitter
// [SECTION] ImDrawData // [SECTION] ImDrawData
// [SECTION] Helpers ShadeVertsXXX functions // [SECTION] Helpers ShadeVertsXXX functions
@ -64,6 +65,7 @@ Index of this file:
#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
#pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter #pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
#elif defined(__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
@ -389,6 +391,7 @@ void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
} }
// Initialize before use in a new frame. We always have a command ready in the buffer. // Initialize before use in a new frame. We always have a command ready in the buffer.
// In the majority of cases, you would want to call PushClipRect() and PushTextureID() after this.
void ImDrawList::_ResetForNewFrame() void ImDrawList::_ResetForNewFrame()
{ {
// Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory. // Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory.
@ -1223,10 +1226,10 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa
} }
} }
void ImDrawList::PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments) void ImDrawList::PathEllipticalArcTo(const ImVec2& center, const ImVec2& radius, float rot, float a_min, float a_max, int num_segments)
{ {
if (num_segments <= 0) if (num_segments <= 0)
num_segments = _CalcCircleAutoSegmentCount(ImMax(radius_x, radius_y)); // A bit pessimistic, maybe there's a better computation to do here. num_segments = _CalcCircleAutoSegmentCount(ImMax(radius.x, radius.y)); // A bit pessimistic, maybe there's a better computation to do here.
_Path.reserve(_Path.Size + (num_segments + 1)); _Path.reserve(_Path.Size + (num_segments + 1));
@ -1235,11 +1238,10 @@ void ImDrawList::PathEllipticalArcTo(const ImVec2& center, float radius_x, float
for (int i = 0; i <= num_segments; i++) for (int i = 0; i <= num_segments; i++)
{ {
const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min); const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min);
ImVec2 point(ImCos(a) * radius_x, ImSin(a) * radius_y); ImVec2 point(ImCos(a) * radius.x, ImSin(a) * radius.y);
const float rel_x = (point.x * cos_rot) - (point.y * sin_rot); const ImVec2 rel((point.x * cos_rot) - (point.y * sin_rot), (point.x * sin_rot) + (point.y * cos_rot));
const float rel_y = (point.x * sin_rot) + (point.y * cos_rot); point.x = rel.x + center.x;
point.x = rel_x + center.x; point.y = rel.y + center.y;
point.y = rel_y + center.y;
_Path.push_back(point); _Path.push_back(point);
} }
} }
@ -1564,31 +1566,31 @@ void ImDrawList::AddNgonFilled(const ImVec2& center, float radius, ImU32 col, in
} }
// Ellipse // Ellipse
void ImDrawList::AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot, int num_segments, float thickness) void ImDrawList::AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot, int num_segments, float thickness)
{ {
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0)
return; return;
if (num_segments <= 0) if (num_segments <= 0)
num_segments = _CalcCircleAutoSegmentCount(ImMax(radius_x, radius_y)); // A bit pessimistic, maybe there's a better computation to do here. num_segments = _CalcCircleAutoSegmentCount(ImMax(radius.x, radius.y)); // A bit pessimistic, maybe there's a better computation to do here.
// Because we are filling a closed shape we remove 1 from the count of segments/points // 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; const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
PathEllipticalArcTo(center, radius_x, radius_y, rot, 0.0f, a_max, num_segments - 1); PathEllipticalArcTo(center, radius, rot, 0.0f, a_max, num_segments - 1);
PathStroke(col, true, thickness); PathStroke(col, true, thickness);
} }
void ImDrawList::AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot, int num_segments) void ImDrawList::AddEllipseFilled(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot, int num_segments)
{ {
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0)
return; return;
if (num_segments <= 0) if (num_segments <= 0)
num_segments = _CalcCircleAutoSegmentCount(ImMax(radius_x, radius_y)); // A bit pessimistic, maybe there's a better computation to do here. num_segments = _CalcCircleAutoSegmentCount(ImMax(radius.x, radius.y)); // A bit pessimistic, maybe there's a better computation to do here.
// Because we are filling a closed shape we remove 1 from the count of segments/points // 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; const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
PathEllipticalArcTo(center, radius_x, radius_y, rot, 0.0f, a_max, num_segments - 1); PathEllipticalArcTo(center, radius, rot, 0.0f, a_max, num_segments - 1);
PathFillConvex(col); PathFillConvex(col);
} }
@ -1619,10 +1621,11 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos,
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0)
return; return;
// Accept null ranges
if (text_begin == text_end || text_begin[0] == 0)
return;
if (text_end == NULL) if (text_end == NULL)
text_end = text_begin + strlen(text_begin); text_end = text_begin + strlen(text_begin);
if (text_begin == text_end)
return;
// Pull default font/size from the shared ImDrawListSharedData instance // Pull default font/size from the shared ImDrawListSharedData instance
if (font == NULL) if (font == NULL)
@ -1706,6 +1709,316 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_mi
PopTextureID(); PopTextureID();
} }
//-----------------------------------------------------------------------------
// [SECTION] ImTriangulator, ImDrawList concave polygon fill
//-----------------------------------------------------------------------------
// Triangulate concave polygons. Based on "Triangulation by Ear Clipping" paper, O(N^2) complexity.
// Reference: https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf
// Provided as a convenience for user but not used by main library.
//-----------------------------------------------------------------------------
// - ImTriangulator [Internal]
// - AddConcavePolyFilled()
//-----------------------------------------------------------------------------
enum ImTriangulatorNodeType
{
ImTriangulatorNodeType_Convex,
ImTriangulatorNodeType_Ear,
ImTriangulatorNodeType_Reflex
};
struct ImTriangulatorNode
{
ImTriangulatorNodeType Type;
int Index;
ImVec2 Pos;
ImTriangulatorNode* Next;
ImTriangulatorNode* Prev;
void Unlink() { Next->Prev = Prev; Prev->Next = Next; }
};
struct ImTriangulatorNodeSpan
{
ImTriangulatorNode** Data = NULL;
int Size = 0;
void push_back(ImTriangulatorNode* node) { Data[Size++] = node; }
void find_erase_unsorted(int idx) { for (int i = Size - 1; i >= 0; i--) if (Data[i]->Index == idx) { Data[i] = Data[Size - 1]; Size--; return; } }
};
struct ImTriangulator
{
static int EstimateTriangleCount(int points_count) { return (points_count < 3) ? 0 : points_count - 2; }
static int EstimateScratchBufferSize(int points_count) { return sizeof(ImTriangulatorNode) * points_count + sizeof(ImTriangulatorNode*) * points_count * 2; }
void Init(const ImVec2* points, int points_count, void* scratch_buffer);
void GetNextTriangle(unsigned int out_triangle[3]); // Return relative indexes for next triangle
// Internal functions
void BuildNodes(const ImVec2* points, int points_count);
void BuildReflexes();
void BuildEars();
void FlipNodeList();
bool IsEar(int i0, int i1, int i2, const ImVec2& v0, const ImVec2& v1, const ImVec2& v2) const;
void ReclassifyNode(ImTriangulatorNode* node);
// Internal members
int _TrianglesLeft = 0;
ImTriangulatorNode* _Nodes = NULL;
ImTriangulatorNodeSpan _Ears;
ImTriangulatorNodeSpan _Reflexes;
};
// Distribute storage for nodes, ears and reflexes.
// FIXME-OPT: if everything is convex, we could report it to caller and let it switch to an convex renderer
// (this would require first building reflexes to bail to convex if empty, without even building nodes)
void ImTriangulator::Init(const ImVec2* points, int points_count, void* scratch_buffer)
{
IM_ASSERT(scratch_buffer != NULL && points_count >= 3);
_TrianglesLeft = EstimateTriangleCount(points_count);
_Nodes = (ImTriangulatorNode*)scratch_buffer; // points_count x Node
_Ears.Data = (ImTriangulatorNode**)(_Nodes + points_count); // points_count x Node*
_Reflexes.Data = (ImTriangulatorNode**)(_Nodes + points_count) + points_count; // points_count x Node*
BuildNodes(points, points_count);
BuildReflexes();
BuildEars();
}
void ImTriangulator::BuildNodes(const ImVec2* points, int points_count)
{
for (int i = 0; i < points_count; i++)
{
_Nodes[i].Type = ImTriangulatorNodeType_Convex;
_Nodes[i].Index = i;
_Nodes[i].Pos = points[i];
_Nodes[i].Next = _Nodes + i + 1;
_Nodes[i].Prev = _Nodes + i - 1;
}
_Nodes[0].Prev = _Nodes + points_count - 1;
_Nodes[points_count - 1].Next = _Nodes;
}
void ImTriangulator::BuildReflexes()
{
ImTriangulatorNode* n1 = _Nodes;
for (int i = _TrianglesLeft; i >= 0; i--, n1 = n1->Next)
{
if (ImTriangleIsClockwise(n1->Prev->Pos, n1->Pos, n1->Next->Pos))
continue;
n1->Type = ImTriangulatorNodeType_Reflex;
_Reflexes.push_back(n1);
}
}
void ImTriangulator::BuildEars()
{
ImTriangulatorNode* n1 = _Nodes;
for (int i = _TrianglesLeft; i >= 0; i--, n1 = n1->Next)
{
if (n1->Type != ImTriangulatorNodeType_Convex)
continue;
if (!IsEar(n1->Prev->Index, n1->Index, n1->Next->Index, n1->Prev->Pos, n1->Pos, n1->Next->Pos))
continue;
n1->Type = ImTriangulatorNodeType_Ear;
_Ears.push_back(n1);
}
}
void ImTriangulator::GetNextTriangle(unsigned int out_triangle[3])
{
if (_Ears.Size == 0)
{
FlipNodeList();
ImTriangulatorNode* node = _Nodes;
for (int i = _TrianglesLeft; i >= 0; i--, node = node->Next)
node->Type = ImTriangulatorNodeType_Convex;
_Reflexes.Size = 0;
BuildReflexes();
BuildEars();
// If we still don't have ears, it means geometry is degenerated.
if (_Ears.Size == 0)
{
// Return first triangle available, mimicking the behavior of convex fill.
IM_ASSERT(_TrianglesLeft > 0); // Geometry is degenerated
_Ears.Data[0] = _Nodes;
_Ears.Size = 1;
}
}
ImTriangulatorNode* ear = _Ears.Data[--_Ears.Size];
out_triangle[0] = ear->Prev->Index;
out_triangle[1] = ear->Index;
out_triangle[2] = ear->Next->Index;
ear->Unlink();
if (ear == _Nodes)
_Nodes = ear->Next;
ReclassifyNode(ear->Prev);
ReclassifyNode(ear->Next);
_TrianglesLeft--;
}
void ImTriangulator::FlipNodeList()
{
ImTriangulatorNode* prev = _Nodes;
ImTriangulatorNode* temp = _Nodes;
ImTriangulatorNode* current = _Nodes->Next;
prev->Next = prev;
prev->Prev = prev;
while (current != _Nodes)
{
temp = current->Next;
current->Next = prev;
prev->Prev = current;
_Nodes->Next = current;
current->Prev = _Nodes;
prev = current;
current = temp;
}
_Nodes = prev;
}
// A triangle is an ear is no other vertex is inside it. We can test reflexes vertices only (see reference algorithm)
bool ImTriangulator::IsEar(int i0, int i1, int i2, const ImVec2& v0, const ImVec2& v1, const ImVec2& v2) const
{
ImTriangulatorNode** p_end = _Reflexes.Data + _Reflexes.Size;
for (ImTriangulatorNode** p = _Reflexes.Data; p < p_end; p++)
{
ImTriangulatorNode* reflex = *p;
if (reflex->Index != i0 && reflex->Index != i1 && reflex->Index != i2)
if (ImTriangleContainsPoint(v0, v1, v2, reflex->Pos))
return false;
}
return true;
}
void ImTriangulator::ReclassifyNode(ImTriangulatorNode* n1)
{
// Classify node
ImTriangulatorNodeType type;
const ImTriangulatorNode* n0 = n1->Prev;
const ImTriangulatorNode* n2 = n1->Next;
if (!ImTriangleIsClockwise(n0->Pos, n1->Pos, n2->Pos))
type = ImTriangulatorNodeType_Reflex;
else if (IsEar(n0->Index, n1->Index, n2->Index, n0->Pos, n1->Pos, n2->Pos))
type = ImTriangulatorNodeType_Ear;
else
type = ImTriangulatorNodeType_Convex;
// Update lists when a type changes
if (type == n1->Type)
return;
if (n1->Type == ImTriangulatorNodeType_Reflex)
_Reflexes.find_erase_unsorted(n1->Index);
else if (n1->Type == ImTriangulatorNodeType_Ear)
_Ears.find_erase_unsorted(n1->Index);
if (type == ImTriangulatorNodeType_Reflex)
_Reflexes.push_back(n1);
else if (type == ImTriangulatorNodeType_Ear)
_Ears.push_back(n1);
n1->Type = type;
}
// Use ear-clipping algorithm to triangulate a simple polygon (no self-interaction, no holes).
// (Reminder: we don't perform any coarse clipping/culling in ImDrawList layer!
// It is up to caller to ensure not making costly calls that will be outside of visible area.
// As concave fill is noticeably more expensive than other primitives, be mindful of this...
// Caller can build AABB of points, and avoid filling if 'draw_list->_CmdHeader.ClipRect.Overlays(points_bb) == false')
void ImDrawList::AddConcavePolyFilled(const ImVec2* points, const int points_count, ImU32 col)
{
if (points_count < 3 || (col & IM_COL32_A_MASK) == 0)
return;
const ImVec2 uv = _Data->TexUvWhitePixel;
ImTriangulator triangulator;
unsigned int triangle[3];
if (Flags & ImDrawListFlags_AntiAliasedFill)
{
// Anti-aliased Fill
const float AA_SIZE = _FringeScale;
const ImU32 col_trans = col & ~IM_COL32_A_MASK;
const int idx_count = (points_count - 2) * 3 + points_count * 6;
const int vtx_count = (points_count * 2);
PrimReserve(idx_count, vtx_count);
// Add indexes for fill
unsigned int vtx_inner_idx = _VtxCurrentIdx;
unsigned int vtx_outer_idx = _VtxCurrentIdx + 1;
_Data->TempBuffer.reserve_discard((ImTriangulator::EstimateScratchBufferSize(points_count) + sizeof(ImVec2)) / sizeof(ImVec2));
triangulator.Init(points, points_count, _Data->TempBuffer.Data);
while (triangulator._TrianglesLeft > 0)
{
triangulator.GetNextTriangle(triangle);
_IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (triangle[0] << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (triangle[1] << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx + (triangle[2] << 1));
_IdxWritePtr += 3;
}
// Compute normals
_Data->TempBuffer.reserve_discard(points_count);
ImVec2* temp_normals = _Data->TempBuffer.Data;
for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++)
{
const ImVec2& p0 = points[i0];
const ImVec2& p1 = points[i1];
float dx = p1.x - p0.x;
float dy = p1.y - p0.y;
IM_NORMALIZE2F_OVER_ZERO(dx, dy);
temp_normals[i0].x = dy;
temp_normals[i0].y = -dx;
}
for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++)
{
// Average normals
const ImVec2& n0 = temp_normals[i0];
const ImVec2& n1 = temp_normals[i1];
float dm_x = (n0.x + n1.x) * 0.5f;
float dm_y = (n0.y + n1.y) * 0.5f;
IM_FIXNORMAL2F(dm_x, dm_y);
dm_x *= AA_SIZE * 0.5f;
dm_y *= AA_SIZE * 0.5f;
// Add vertices
_VtxWritePtr[0].pos.x = (points[i1].x - dm_x); _VtxWritePtr[0].pos.y = (points[i1].y - dm_y); _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; // Inner
_VtxWritePtr[1].pos.x = (points[i1].x + dm_x); _VtxWritePtr[1].pos.y = (points[i1].y + dm_y); _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; // Outer
_VtxWritePtr += 2;
// Add indexes for fringes
_IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (i0 << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1));
_IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx + (i1 << 1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1));
_IdxWritePtr += 6;
}
_VtxCurrentIdx += (ImDrawIdx)vtx_count;
}
else
{
// Non Anti-aliased Fill
const int idx_count = (points_count - 2) * 3;
const int vtx_count = points_count;
PrimReserve(idx_count, vtx_count);
for (int i = 0; i < vtx_count; i++)
{
_VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;
_VtxWritePtr++;
}
_Data->TempBuffer.reserve_discard((ImTriangulator::EstimateScratchBufferSize(points_count) + sizeof(ImVec2)) / sizeof(ImVec2));
triangulator.Init(points, points_count, _Data->TempBuffer.Data);
while (triangulator._TrianglesLeft > 0)
{
triangulator.GetNextTriangle(triangle);
_IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx + triangle[0]); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + triangle[1]); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + triangle[2]);
_IdxWritePtr += 3;
}
_VtxCurrentIdx += (ImDrawIdx)vtx_count;
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] ImDrawListSplitter // [SECTION] ImDrawListSplitter
@ -2678,8 +2991,8 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
int unscaled_ascent, unscaled_descent, unscaled_line_gap; int unscaled_ascent, unscaled_descent, unscaled_line_gap;
stbtt_GetFontVMetrics(&src_tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap); stbtt_GetFontVMetrics(&src_tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap);
const float ascent = ImTrunc(unscaled_ascent * font_scale + ((unscaled_ascent > 0.0f) ? +1 : -1)); const float ascent = ImCeil(unscaled_ascent * font_scale);
const float descent = ImTrunc(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1)); const float descent = ImFloor(unscaled_descent * font_scale);
ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
const float font_off_x = cfg.GlyphOffset.x; const float font_off_x = cfg.GlyphOffset.x;
const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent); const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent);
@ -3774,6 +4087,8 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
{ {
x = start_x; x = start_x;
y += line_height; y += line_height;
if (y > clip_rect.w)
break; // break out of main loop
word_wrap_eol = NULL; word_wrap_eol = NULL;
s = CalcWordWrapNextLineStartA(s, text_end); // Wrapping skips upcoming blanks s = CalcWordWrapNextLineStartA(s, text_end); // Wrapping skips upcoming blanks
continue; continue;

View File

@ -1,4 +1,4 @@
// dear imgui, v1.90.4 // dear imgui, v1.90.7
// (internal structures/api) // (internal structures/api)
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
@ -87,10 +87,13 @@ Index of this file:
#pragma clang diagnostic ignored "-Wdouble-promotion" #pragma clang diagnostic ignored "-Wdouble-promotion"
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
#pragma clang diagnostic ignored "-Wmissing-noreturn" // warning: function 'xxx' could be declared with attribute 'noreturn' #pragma clang diagnostic ignored "-Wmissing-noreturn" // warning: function 'xxx' could be declared with attribute 'noreturn'
#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
#elif defined(__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
#endif #endif
// In 1.89.4, we moved the implementation of "courtesy maths operators" from imgui_internal.h in imgui.h // In 1.89.4, we moved the implementation of "courtesy maths operators" from imgui_internal.h in imgui.h
@ -124,7 +127,7 @@ struct ImDrawListSharedData; // Data shared between all ImDrawList instan
struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it
struct ImGuiContext; // Main Dear ImGui context struct ImGuiContext; // Main Dear ImGui context
struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
struct ImGuiDataVarInfo; // Variable information (e.g. to avoid style variables from an enum) struct ImGuiDataVarInfo; // Variable information (e.g. to access style variables from an enum)
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
struct ImGuiDockContext; // Docking system context struct ImGuiDockContext; // Docking system context
struct ImGuiDockRequest; // Docking system dock/undock queued request struct ImGuiDockRequest; // Docking system dock/undock queued request
@ -150,6 +153,7 @@ struct ImGuiStyleMod; // Stacked style modifier, backup of modifie
struct ImGuiTabBar; // Storage for a tab bar struct ImGuiTabBar; // Storage for a tab bar
struct ImGuiTabItem; // Storage for a tab item (within a tab bar) struct ImGuiTabItem; // Storage for a tab item (within a tab bar)
struct ImGuiTable; // Storage for a table struct ImGuiTable; // Storage for a table
struct ImGuiTableHeaderData; // Storage for TableAngledHeadersRow()
struct ImGuiTableColumn; // Storage for one column of a table struct ImGuiTableColumn; // Storage for one column of a table
struct ImGuiTableInstanceData; // Storage for one instance of a same table struct ImGuiTableInstanceData; // Storage for one instance of a same table
struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables. struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables.
@ -158,6 +162,7 @@ struct ImGuiTableColumnsSettings; // Storage for a column .ini settings
struct ImGuiTypingSelectState; // Storage for GetTypingSelectRequest() struct ImGuiTypingSelectState; // Storage for GetTypingSelectRequest()
struct ImGuiTypingSelectRequest; // Storage for GetTypingSelectRequest() (aimed to be public) struct ImGuiTypingSelectRequest; // Storage for GetTypingSelectRequest() (aimed to be public)
struct ImGuiWindow; // Storage for one window struct ImGuiWindow; // Storage for one window
struct ImGuiWindowDockStyle; // Storage for window-style data which needs to be stored for docking purpose
struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame, in practice we currently keep it for each window) struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame, in practice we currently keep it for each window)
struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session) struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session)
@ -171,7 +176,6 @@ typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // E
typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later) typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later)
typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags
typedef int ImGuiFocusRequestFlags; // -> enum ImGuiFocusRequestFlags_ // Flags: for FocusWindow(); typedef int ImGuiFocusRequestFlags; // -> enum ImGuiFocusRequestFlags_ // Flags: for FocusWindow();
typedef int ImGuiInputFlags; // -> enum ImGuiInputFlags_ // Flags: for IsKeyPressed(), IsMouseClicked(), SetKeyOwner(), SetItemKeyOwner() etc.
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), g.LastItemData.InFlags typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), g.LastItemData.InFlags
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags
typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns() typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
@ -184,6 +188,7 @@ typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // F
typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx() typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx()
typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx() typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx()
typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest() typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest()
typedef int ImGuiWindowRefreshFlags; // -> enum ImGuiWindowRefreshFlags_ // Flags: for SetNextWindowRefreshPolicy()
typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...); typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...);
@ -414,6 +419,7 @@ IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char
IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8 IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8
IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8 IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8
IMGUI_API const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_text_curr); // return previous UTF-8 code-point. IMGUI_API const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_text_curr); // return previous UTF-8 code-point.
IMGUI_API int ImTextCountLines(const char* in_text, const char* in_text_end); // return number of lines taken by text. trailing carriage return doesn't count as an extra line.
// Helpers: File System // Helpers: File System
#ifdef IMGUI_DISABLE_FILE_FUNCTIONS #ifdef IMGUI_DISABLE_FILE_FUNCTIONS
@ -509,6 +515,7 @@ IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, c
IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p); IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);
IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w); IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w);
inline float ImTriangleArea(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ImFabs((a.x * (b.y - c.y)) + (b.x * (c.y - a.y)) + (c.x * (a.y - b.y))) * 0.5f; } inline float ImTriangleArea(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ImFabs((a.x * (b.y - c.y)) + (b.x * (c.y - a.y)) + (c.x * (a.y - b.y))) * 0.5f; }
inline bool ImTriangleIsClockwise(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ((b.x - a.x) * (c.y - b.y)) - ((c.x - b.x) * (b.y - a.y)) > 0.0f; }
// Helper: ImVec1 (1D vector) // Helper: ImVec1 (1D vector)
// (this odd construct is used to facilitate the transition between 1D and 2D, and the maintenance of some branches/patches) // (this odd construct is used to facilitate the transition between 1D and 2D, and the maintenance of some branches/patches)
@ -846,7 +853,8 @@ enum ImGuiItemStatusFlags_
ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set.
ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing. ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing.
ImGuiItemStatusFlags_Visible = 1 << 8, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()). ImGuiItemStatusFlags_Visible = 1 << 8, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()).
ImGuiItemStatusFlags_HasClipRect = 1 << 9, // g.LastItemData.ClipRect is valid ImGuiItemStatusFlags_HasClipRect = 1 << 9, // g.LastItemData.ClipRect is valid.
ImGuiItemStatusFlags_HasShortcut = 1 << 10, // g.LastItemData.Shortcut valid. Set by SetNextItemShortcut() -> ItemAdd().
// Additional status + semantic for ImGuiTestEngine // Additional status + semantic for ImGuiTestEngine
#ifdef IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE
@ -873,6 +881,7 @@ enum ImGuiInputTextFlagsPrivate_
ImGuiInputTextFlags_Multiline = 1 << 26, // For internal use by InputTextMultiline() ImGuiInputTextFlags_Multiline = 1 << 26, // For internal use by InputTextMultiline()
ImGuiInputTextFlags_NoMarkEdited = 1 << 27, // For internal use by functions using InputText() before reformatting data ImGuiInputTextFlags_NoMarkEdited = 1 << 27, // For internal use by functions using InputText() before reformatting data
ImGuiInputTextFlags_MergedItem = 1 << 28, // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match. ImGuiInputTextFlags_MergedItem = 1 << 28, // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match.
ImGuiInputTextFlags_LocalizeDecimalPoint= 1 << 29, // For internal use by InputScalar() and TempInputScalar()
}; };
// Extend ImGuiButtonFlags_ // Extend ImGuiButtonFlags_
@ -892,7 +901,7 @@ enum ImGuiButtonFlagsPrivate_
ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // 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_AlignTextBaseLine = 1 << 15, // 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 << 16, // disable mouse interaction if a key modifier is held ImGuiButtonFlags_NoKeyModifiers = 1 << 16, // disable mouse interaction if a key modifier is held
ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only)
ImGuiButtonFlags_NoNavFocus = 1 << 18, // don't override navigation focus when activated (FIXME: this is essentially used everytime an item uses ImGuiItemFlags_NoNav, but because legacy specs don't requires LastItemData to be set ButtonBehavior(), we can't poll g.LastItemData.InFlags) ImGuiButtonFlags_NoNavFocus = 1 << 18, // don't override navigation focus when activated (FIXME: this is essentially used every time an item uses ImGuiItemFlags_NoNav, but because legacy specs don't requires LastItemData to be set ButtonBehavior(), we can't poll g.LastItemData.InFlags)
ImGuiButtonFlags_NoHoveredOnFocus = 1 << 19, // don't report as hovered when nav focus is on this item ImGuiButtonFlags_NoHoveredOnFocus = 1 << 19, // don't report as hovered when nav focus is on this item
ImGuiButtonFlags_NoSetKeyOwner = 1 << 20, // don't set key/input owner on the initial click (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!) ImGuiButtonFlags_NoSetKeyOwner = 1 << 20, // don't set key/input owner on the initial click (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!)
ImGuiButtonFlags_NoTestKeyOwner = 1 << 21, // don't test key/input owner when polling the key (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!) ImGuiButtonFlags_NoTestKeyOwner = 1 << 21, // don't test key/input owner when polling the key (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!)
@ -1121,6 +1130,15 @@ struct IMGUI_API ImGuiInputTextState
}; };
enum ImGuiWindowRefreshFlags_
{
ImGuiWindowRefreshFlags_None = 0,
ImGuiWindowRefreshFlags_TryToAvoidRefresh = 1 << 0, // [EXPERIMENTAL] Try to keep existing contents, USER MUST NOT HONOR BEGIN() RETURNING FALSE AND NOT APPEND.
ImGuiWindowRefreshFlags_RefreshOnHover = 1 << 1, // [EXPERIMENTAL] Always refresh on hover
ImGuiWindowRefreshFlags_RefreshOnFocus = 1 << 2, // [EXPERIMENTAL] Always refresh on focus
// Refresh policy/frequency, Load Balancing etc.
};
enum ImGuiNextWindowDataFlags_ enum ImGuiNextWindowDataFlags_
{ {
ImGuiNextWindowDataFlags_None = 0, ImGuiNextWindowDataFlags_None = 0,
@ -1133,9 +1151,10 @@ enum ImGuiNextWindowDataFlags_
ImGuiNextWindowDataFlags_HasBgAlpha = 1 << 6, ImGuiNextWindowDataFlags_HasBgAlpha = 1 << 6,
ImGuiNextWindowDataFlags_HasScroll = 1 << 7, ImGuiNextWindowDataFlags_HasScroll = 1 << 7,
ImGuiNextWindowDataFlags_HasChildFlags = 1 << 8, ImGuiNextWindowDataFlags_HasChildFlags = 1 << 8,
ImGuiNextWindowDataFlags_HasViewport = 1 << 9, ImGuiNextWindowDataFlags_HasRefreshPolicy = 1 << 9,
ImGuiNextWindowDataFlags_HasDock = 1 << 10, ImGuiNextWindowDataFlags_HasViewport = 1 << 10,
ImGuiNextWindowDataFlags_HasWindowClass = 1 << 11, ImGuiNextWindowDataFlags_HasDock = 1 << 11,
ImGuiNextWindowDataFlags_HasWindowClass = 1 << 12,
}; };
// Storage for SetNexWindow** functions // Storage for SetNexWindow** functions
@ -1162,6 +1181,7 @@ struct ImGuiNextWindowData
ImGuiID DockId; ImGuiID DockId;
ImGuiWindowClass WindowClass; ImGuiWindowClass WindowClass;
ImVec2 MenuBarOffsetMinVal; // (Always on) This is not exposed publicly, so we don't clear it and it doesn't have a corresponding flag (could we? for consistency?) ImVec2 MenuBarOffsetMinVal; // (Always on) This is not exposed publicly, so we don't clear it and it doesn't have a corresponding flag (could we? for consistency?)
ImGuiWindowRefreshFlags RefreshFlagsVal;
ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); } ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); }
inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; }
@ -1187,6 +1207,7 @@ struct ImGuiNextItemData
ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values) ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values)
float Width; // Set by SetNextItemWidth() float Width; // Set by SetNextItemWidth()
ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut() ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut()
ImGuiInputFlags ShortcutFlags; // Set by SetNextItemShortcut()
bool OpenVal; // Set by SetNextItemOpen() bool OpenVal; // Set by SetNextItemOpen()
ImGuiCond OpenCond : 8; ImGuiCond OpenCond : 8;
@ -1202,9 +1223,10 @@ struct ImGuiLastItemData
ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_ ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_
ImRect Rect; // Full rectangle ImRect Rect; // Full rectangle
ImRect NavRect; // Navigation scoring rectangle (not displayed) ImRect NavRect; // Navigation scoring rectangle (not displayed)
// Rarely used fields are not explicitly cleared, only valid when the corresponding ImGuiItemStatusFlags is set. // Rarely used fields are not explicitly cleared, only valid when the corresponding ImGuiItemStatusFlags ar set.
ImRect DisplayRect; // Display rectangle (ONLY VALID IF ImGuiItemStatusFlags_HasDisplayRect is set) ImRect DisplayRect; // Display rectangle. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) is set.
ImRect ClipRect; // Clip rectangle at the time of submitting item (ONLY VALID IF ImGuiItemStatusFlags_HasClipRect is set) ImRect ClipRect; // Clip rectangle at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasClipRect) is set..
ImGuiKeyChord Shortcut; // Shortcut at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasShortcut) is set..
ImGuiLastItemData() { memset(this, 0, sizeof(*this)); } ImGuiLastItemData() { memset(this, 0, sizeof(*this)); }
}; };
@ -1310,7 +1332,7 @@ struct ImGuiPopupData
{ {
ImGuiID PopupId; // Set on OpenPopup() ImGuiID PopupId; // Set on OpenPopup()
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
ImGuiWindow* BackupNavWindow;// Set on OpenPopup(), a NavWindow that will be restored on popup close ImGuiWindow* RestoreNavWindow;// Set on OpenPopup(), a NavWindow that will be restored on popup close
int ParentNavLayer; // Resolved on BeginPopup(). Actually a ImGuiNavLayer type (declared down below), initialized to -1 which is not part of an enum, but serves well-enough as "not any of layers" value int ParentNavLayer; // Resolved on BeginPopup(). Actually a ImGuiNavLayer type (declared down below), initialized to -1 which is not part of an enum, but serves well-enough as "not any of layers" value
int OpenFrameCount; // Set on OpenPopup() int OpenFrameCount; // Set on OpenPopup()
ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items)
@ -1368,7 +1390,6 @@ enum ImGuiInputSource
ImGuiInputSource_Mouse, // Note: may be Mouse or TouchScreen or Pen. See io.MouseSource to distinguish them. ImGuiInputSource_Mouse, // Note: may be Mouse or TouchScreen or Pen. See io.MouseSource to distinguish them.
ImGuiInputSource_Keyboard, ImGuiInputSource_Keyboard,
ImGuiInputSource_Gamepad, ImGuiInputSource_Gamepad,
ImGuiInputSource_Clipboard, // Currently only used by InputText()
ImGuiInputSource_COUNT ImGuiInputSource_COUNT
}; };
@ -1404,7 +1425,8 @@ struct ImGuiInputEvent
// Input function taking an 'ImGuiID owner_id' argument defaults to (ImGuiKeyOwner_Any == 0) aka don't test ownership, which matches legacy behavior. // Input function taking an 'ImGuiID owner_id' argument defaults to (ImGuiKeyOwner_Any == 0) aka don't test ownership, which matches legacy behavior.
#define ImGuiKeyOwner_Any ((ImGuiID)0) // Accept key that have an owner, UNLESS a call to SetKeyOwner() explicitly used ImGuiInputFlags_LockThisFrame or ImGuiInputFlags_LockUntilRelease. #define ImGuiKeyOwner_Any ((ImGuiID)0) // Accept key that have an owner, UNLESS a call to SetKeyOwner() explicitly used ImGuiInputFlags_LockThisFrame or ImGuiInputFlags_LockUntilRelease.
#define ImGuiKeyOwner_None ((ImGuiID)-1) // Require key to have no owner. #define ImGuiKeyOwner_NoOwner ((ImGuiID)-1) // Require key to have no owner.
//#define ImGuiKeyOwner_None ImGuiKeyOwner_NoOwner // We previously called this 'ImGuiKeyOwner_None' but it was inconsistent with our pattern that _None values == 0 and quite dangerous. Also using _NoOwner makes the IsKeyPressed() calls more explicit.
typedef ImS16 ImGuiKeyRoutingIndex; typedef ImS16 ImGuiKeyRoutingIndex;
@ -1412,13 +1434,13 @@ typedef ImS16 ImGuiKeyRoutingIndex;
struct ImGuiKeyRoutingData struct ImGuiKeyRoutingData
{ {
ImGuiKeyRoutingIndex NextEntryIndex; ImGuiKeyRoutingIndex NextEntryIndex;
ImU16 Mods; // Technically we'd only need 4-bits but for simplify we store ImGuiMod_ values which need 16-bits. ImGuiMod_Shortcut is already translated to Ctrl/Super. ImU16 Mods; // Technically we'd only need 4-bits but for simplify we store ImGuiMod_ values which need 16-bits.
ImU8 RoutingCurrScore; // [DEBUG] For debug display ImU8 RoutingCurrScore; // [DEBUG] For debug display
ImU8 RoutingNextScore; // Lower is better (0: perfect score) ImU8 RoutingNextScore; // Lower is better (0: perfect score)
ImGuiID RoutingCurr; ImGuiID RoutingCurr;
ImGuiID RoutingNext; ImGuiID RoutingNext;
ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingCurrScore = RoutingNextScore = 255; RoutingCurr = RoutingNext = ImGuiKeyOwner_None; } ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingCurrScore = RoutingNextScore = 255; RoutingCurr = RoutingNext = ImGuiKeyOwner_NoOwner; }
}; };
// Routing table: maintain a desired owner for each possible key-chord (key + mods), and setup owner in NewFrame() when mods are matching. // Routing table: maintain a desired owner for each possible key-chord (key + mods), and setup owner in NewFrame() when mods are matching.
@ -1442,73 +1464,47 @@ struct ImGuiKeyOwnerData
bool LockThisFrame; // Reading this key requires explicit owner id (until end of frame). Set by ImGuiInputFlags_LockThisFrame. bool LockThisFrame; // Reading this key requires explicit owner id (until end of frame). Set by ImGuiInputFlags_LockThisFrame.
bool LockUntilRelease; // Reading this key requires explicit owner id (until key is released). Set by ImGuiInputFlags_LockUntilRelease. When this is true LockThisFrame is always true as well. bool LockUntilRelease; // Reading this key requires explicit owner id (until key is released). Set by ImGuiInputFlags_LockUntilRelease. When this is true LockThisFrame is always true as well.
ImGuiKeyOwnerData() { OwnerCurr = OwnerNext = ImGuiKeyOwner_None; LockThisFrame = LockUntilRelease = false; } ImGuiKeyOwnerData() { OwnerCurr = OwnerNext = ImGuiKeyOwner_NoOwner; LockThisFrame = LockUntilRelease = false; }
}; };
// Extend ImGuiInputFlags_
// Flags for extended versions of IsKeyPressed(), IsMouseClicked(), Shortcut(), SetKeyOwner(), SetItemKeyOwner() // Flags for extended versions of IsKeyPressed(), IsMouseClicked(), Shortcut(), SetKeyOwner(), SetItemKeyOwner()
// Don't mistake with ImGuiInputTextFlags! (which is for ImGui::InputText() function) // Don't mistake with ImGuiInputTextFlags! (which is for ImGui::InputText() function)
enum ImGuiInputFlags_ enum ImGuiInputFlagsPrivate_
{ {
// Flags for IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked(), Shortcut() // Flags for IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked(), Shortcut()
ImGuiInputFlags_None = 0, // - Repeat mode: Repeat rate selection
// Repeat mode
ImGuiInputFlags_Repeat = 1 << 0, // Enable repeat. Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1.
ImGuiInputFlags_RepeatRateDefault = 1 << 1, // Repeat rate: Regular (default) ImGuiInputFlags_RepeatRateDefault = 1 << 1, // Repeat rate: Regular (default)
ImGuiInputFlags_RepeatRateNavMove = 1 << 2, // Repeat rate: Fast ImGuiInputFlags_RepeatRateNavMove = 1 << 2, // Repeat rate: Fast
ImGuiInputFlags_RepeatRateNavTweak = 1 << 3, // Repeat rate: Faster ImGuiInputFlags_RepeatRateNavTweak = 1 << 3, // Repeat rate: Faster
// - Repeat mode: Specify when repeating key pressed can be interrupted.
// Repeat mode: Specify when repeating key pressed can be interrupted. // - In theory ImGuiInputFlags_RepeatUntilOtherKeyPress may be a desirable default, but it would break too many behavior so everything is opt-in.
// In theory ImGuiInputFlags_RepeatUntilOtherKeyPress may be a desirable default, but it would break too many behavior so everything is opt-in.
ImGuiInputFlags_RepeatUntilRelease = 1 << 4, // Stop repeating when released (default for all functions except Shortcut). This only exists to allow overriding Shortcut() default behavior. ImGuiInputFlags_RepeatUntilRelease = 1 << 4, // Stop repeating when released (default for all functions except Shortcut). This only exists to allow overriding Shortcut() default behavior.
ImGuiInputFlags_RepeatUntilKeyModsChange = 1 << 5, // Stop repeating when released OR if keyboard mods are changed (default for Shortcut) ImGuiInputFlags_RepeatUntilKeyModsChange = 1 << 5, // Stop repeating when released OR if keyboard mods are changed (default for Shortcut)
ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone = 1 << 6, // Stop repeating when released OR if keyboard mods are leaving the None state. Allows going from Mod+Key to Key by releasing Mod. ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone = 1 << 6, // Stop repeating when released OR if keyboard mods are leaving the None state. Allows going from Mod+Key to Key by releasing Mod.
ImGuiInputFlags_RepeatUntilOtherKeyPress = 1 << 7, // Stop repeating when released OR if any other keyboard key is pressed during the repeat ImGuiInputFlags_RepeatUntilOtherKeyPress = 1 << 7, // Stop repeating when released OR if any other keyboard key is pressed during the repeat
// Flags for SetItemKeyOwner()
ImGuiInputFlags_CondHovered = 1 << 8, // Only set if item is hovered (default to both)
ImGuiInputFlags_CondActive = 1 << 9, // Only set if item is active (default to both)
ImGuiInputFlags_CondDefault_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive,
// Flags for SetKeyOwner(), SetItemKeyOwner() // Flags for SetKeyOwner(), SetItemKeyOwner()
// Locking is useful to make input-owner-aware code steal keys from non-input-owner-aware code. If all code is input-owner-aware locking would never be necessary. // - Locking key away from non-input aware code. Locking is useful to make input-owner-aware code steal keys from non-input-owner-aware code. If all code is input-owner-aware locking would never be necessary.
ImGuiInputFlags_LockThisFrame = 1 << 10, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared at end of frame. ImGuiInputFlags_LockThisFrame = 1 << 20, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared at end of frame.
ImGuiInputFlags_LockUntilRelease = 1 << 11, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared when the key is released or at end of each frame if key is released. ImGuiInputFlags_LockUntilRelease = 1 << 21, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared when the key is released or at end of each frame if key is released.
// Routing policies for Shortcut() + low-level SetShortcutRouting() // - Condition for SetItemKeyOwner()
// - The general idea is that several callers register interest in a shortcut, and only one owner gets it. ImGuiInputFlags_CondHovered = 1 << 22, // Only set if item is hovered (default to both)
// Parent -> call Shortcut(Ctrl+S) // When Parent is focused, Parent gets the shortcut. ImGuiInputFlags_CondActive = 1 << 23, // Only set if item is active (default to both)
// Child1 -> call Shortcut(Ctrl+S) // When Child1 is focused, Child1 gets the shortcut (Child1 overrides Parent shortcuts) ImGuiInputFlags_CondDefault_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive,
// Child2 -> no call // When Child2 is focused, Parent gets the shortcut.
// The whole system is order independent, so if Child1 does it calls before Parent results will be identical.
// This is an important property as it facilitate working with foreign code or larger codebase.
// - Visualize registered routes in 'Metrics->Inputs' and submitted routes in 'Debug Log->InputRouting'.
// - When a policy (except for _RouteAlways *) is set, Shortcut() will register itself with SetShortcutRouting(),
// allowing the system to decide where to route the input among other route-aware calls.
// (* Using ImGuiInputFlags_RouteAlways is roughly equivalent to calling IsKeyChordPressed(key)).
// - Shortcut() uses ImGuiInputFlags_RouteFocused by default. Meaning that a Shortcut() call will register
// a route and only succeed when parent window is in the focus-stack and if no-one with a higher priority
// is claiming the same shortcut.
// - You can chain two unrelated windows in the focus stack using SetWindowParentWindowForFocusRoute().
// - Priorities: GlobalHigh > Focused (when owner is active item) > Global > Focused (when focused window) > GlobalLow.
// - Can select only 1 policy among all available.
ImGuiInputFlags_RouteFocused = 1 << 12, // (Default) Honor focus route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window.
ImGuiInputFlags_RouteGlobalLow = 1 << 13, // Register route globally (lowest priority: unless a focused window or active item registered the route) -> recommended Global priority IF you need a Global priority.
ImGuiInputFlags_RouteGlobal = 1 << 14, // Register route globally (medium priority: unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this).
ImGuiInputFlags_RouteGlobalHigh = 1 << 15, // Register route globally (higher priority: unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overriden by this)
ImGuiInputFlags_RouteAlways = 1 << 16, // Do not register route, poll keys directly.
// Routing polices: extra options
ImGuiInputFlags_RouteUnlessBgFocused= 1 << 17, // Global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications.
// [Internal] Mask of which function support which flags // [Internal] Mask of which function support which flags
ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak, ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak,
ImGuiInputFlags_RepeatUntilMask_ = ImGuiInputFlags_RepeatUntilRelease | ImGuiInputFlags_RepeatUntilKeyModsChange | ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone | ImGuiInputFlags_RepeatUntilOtherKeyPress, ImGuiInputFlags_RepeatUntilMask_ = ImGuiInputFlags_RepeatUntilRelease | ImGuiInputFlags_RepeatUntilKeyModsChange | ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone | ImGuiInputFlags_RepeatUntilOtherKeyPress,
ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_, ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_,
ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive,
ImGuiInputFlags_RouteMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalLow | ImGuiInputFlags_RouteGlobalHigh, // _Always not part of this! ImGuiInputFlags_RouteTypeMask_ = ImGuiInputFlags_RouteActive | ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteAlways,
ImGuiInputFlags_RouteOptionsMask_ = ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused | ImGuiInputFlags_RouteFromRootWindow,
ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_, ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_,
ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat, ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat,
ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteMask_ | ImGuiInputFlags_RouteAlways | ImGuiInputFlags_RouteUnlessBgFocused, ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteTypeMask_ | ImGuiInputFlags_RouteOptionsMask_,
ImGuiInputFlags_SupportedBySetNextItemShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteTypeMask_ | ImGuiInputFlags_RouteOptionsMask_ | ImGuiInputFlags_Tooltip,
ImGuiInputFlags_SupportedBySetKeyOwner = ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease, ImGuiInputFlags_SupportedBySetKeyOwner = ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease,
ImGuiInputFlags_SupportedBySetItemKeyOwner = ImGuiInputFlags_SupportedBySetKeyOwner | ImGuiInputFlags_CondMask_, ImGuiInputFlags_SupportedBySetItemKeyOwner = ImGuiInputFlags_SupportedBySetKeyOwner | ImGuiInputFlags_CondMask_,
}; };
@ -1599,6 +1595,7 @@ enum ImGuiNavMoveFlags_
ImGuiNavMoveFlags_Activate = 1 << 12, // Activate/select target item. ImGuiNavMoveFlags_Activate = 1 << 12, // Activate/select target item.
ImGuiNavMoveFlags_NoSelect = 1 << 13, // Don't trigger selection by not setting g.NavJustMovedTo ImGuiNavMoveFlags_NoSelect = 1 << 13, // Don't trigger selection by not setting g.NavJustMovedTo
ImGuiNavMoveFlags_NoSetNavHighlight = 1 << 14, // Do not alter the visible state of keyboard vs mouse nav highlight ImGuiNavMoveFlags_NoSetNavHighlight = 1 << 14, // Do not alter the visible state of keyboard vs mouse nav highlight
ImGuiNavMoveFlags_NoClearActiveId = 1 << 15, // (Experimental) Do not clear active id when applying move result
}; };
enum ImGuiNavLayer enum ImGuiNavLayer
@ -1615,10 +1612,10 @@ struct ImGuiNavItemData
ImGuiID FocusScopeId; // Init,Move // Best candidate focus scope ID ImGuiID FocusScopeId; // Init,Move // Best candidate focus scope ID
ImRect RectRel; // Init,Move // Best candidate bounding box in window relative space ImRect RectRel; // Init,Move // Best candidate bounding box in window relative space
ImGuiItemFlags InFlags; // ????,Move // Best candidate item flags ImGuiItemFlags InFlags; // ????,Move // Best candidate item flags
ImGuiSelectionUserData SelectionUserData;//I+Mov // Best candidate SetNextItemSelectionData() value.
float DistBox; // Move // Best candidate box distance to current NavId float DistBox; // Move // Best candidate box distance to current NavId
float DistCenter; // Move // Best candidate center distance to current NavId float DistCenter; // Move // Best candidate center distance to current NavId
float DistAxial; // Move // Best candidate axial distance to current NavId float DistAxial; // Move // Best candidate axial distance to current NavId
ImGuiSelectionUserData SelectionUserData;//I+Mov // Best candidate SetNextItemSelectionData() value.
ImGuiNavItemData() { Clear(); } ImGuiNavItemData() { Clear(); }
void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; } void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; }
@ -1867,6 +1864,7 @@ enum ImGuiWindowDockStyleCol
ImGuiWindowDockStyleCol_COUNT ImGuiWindowDockStyleCol_COUNT
}; };
// We don't store style.Alpha: dock_node->LastBgColor embeds it and otherwise it would only affect the docking tab, which intuitively I would say we don't want to.
struct ImGuiWindowDockStyle struct ImGuiWindowDockStyle
{ {
ImU32 Colors[ImGuiWindowDockStyleCol_COUNT]; ImU32 Colors[ImGuiWindowDockStyleCol_COUNT];
@ -2114,6 +2112,7 @@ struct ImGuiContext
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height. float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.
float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale
ImDrawListSharedData DrawListSharedData; ImDrawListSharedData DrawListSharedData;
double Time; double Time;
int FrameCount; int FrameCount;
@ -2140,7 +2139,7 @@ struct ImGuiContext
ImVector<ImGuiWindowStackData> CurrentWindowStack; ImVector<ImGuiWindowStackData> CurrentWindowStack;
ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow* ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow*
int WindowsActiveCount; // Number of unique windows submitted by frame int WindowsActiveCount; // Number of unique windows submitted by frame
ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING) ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING).
ImGuiID DebugBreakInWindow; // Set to break in Begin() call. ImGuiID DebugBreakInWindow; // Set to break in Begin() call.
ImGuiWindow* CurrentWindow; // Window being drawn into ImGuiWindow* CurrentWindow; // Window being drawn into
ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs. ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs.
@ -2183,9 +2182,9 @@ struct ImGuiContext
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation. ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
// [EXPERIMENTAL] Key/Input Ownership + Shortcut Routing system // Key/Input Ownership + Shortcut Routing system
// - The idea is that instead of "eating" a given key, we can link to an owner. // - The idea is that instead of "eating" a given key, we can link to an owner.
// - Input query can then read input by specifying ImGuiKeyOwner_Any (== 0), ImGuiKeyOwner_None (== -1) or a custom ID. // - Input query can then read input by specifying ImGuiKeyOwner_Any (== 0), ImGuiKeyOwner_NoOwner (== -1) or a custom ID.
// - Routing is requested ahead of time for a given chord (Key + Mods) and granted in NewFrame(). // - Routing is requested ahead of time for a given chord (Key + Mods) and granted in NewFrame().
double LastKeyModsChangeTime; // Record the last time key mods changed (affect repeat delay when using shortcut logic) double LastKeyModsChangeTime; // Record the last time key mods changed (affect repeat delay when using shortcut logic)
double LastKeyModsChangeFromNoneTime; // Record the last time key mods changed away from being 0 (affect repeat delay when using shortcut logic) double LastKeyModsChangeFromNoneTime; // Record the last time key mods changed away from being 0 (affect repeat delay when using shortcut logic)
@ -2223,7 +2222,6 @@ struct ImGuiContext
// Viewports // Viewports
ImVector<ImGuiViewportP*> Viewports; // Active viewports (always 1+, and generally 1 unless multi-viewports are enabled). Each viewports hold their copy of ImDrawData. ImVector<ImGuiViewportP*> Viewports; // Active viewports (always 1+, and generally 1 unless multi-viewports are enabled). Each viewports hold their copy of ImDrawData.
float CurrentDpiScale; // == CurrentViewport->DpiScale
ImGuiViewportP* CurrentViewport; // We track changes of viewport (happening in Begin) so we can call Platform_OnChangedViewport() ImGuiViewportP* CurrentViewport; // We track changes of viewport (happening in Begin) so we can call Platform_OnChangedViewport()
ImGuiViewportP* MouseViewport; ImGuiViewportP* MouseViewport;
ImGuiViewportP* MouseLastHoveredViewport; // Last known viewport that was hovered by mouse (even if we are not hovering any viewport any more) + honoring the _NoInputs flag. ImGuiViewportP* MouseLastHoveredViewport; // Last known viewport that was hovered by mouse (even if we are not hovering any viewport any more) + honoring the _NoInputs flag.
@ -2283,8 +2281,8 @@ struct ImGuiContext
ImGuiNavItemData NavTabbingResultFirst; // First tabbing request candidate within NavWindow and flattened hierarchy ImGuiNavItemData NavTabbingResultFirst; // First tabbing request candidate within NavWindow and flattened hierarchy
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize) // Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab, for reconfiguration (see #4828) ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiKey_Tab on OS X). For reconfiguration (see #4828)
ImGuiKeyChord ConfigNavWindowingKeyPrev; // = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab ImGuiKeyChord ConfigNavWindowingKeyPrev; // = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab on OS X)
ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most! ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f, so the fade-out can stay on it. ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f, so the fade-out can stay on it.
ImGuiWindow* NavWindowingListWindow; // Internal window actually listing the CTRL+Tab contents ImGuiWindow* NavWindowingListWindow; // Internal window actually listing the CTRL+Tab contents
@ -2459,7 +2457,7 @@ struct ImGuiContext
ConfigFlagsCurrFrame = ConfigFlagsLastFrame = ImGuiConfigFlags_None; ConfigFlagsCurrFrame = ConfigFlagsLastFrame = ImGuiConfigFlags_None;
FontAtlasOwnedByContext = shared_font_atlas ? false : true; FontAtlasOwnedByContext = shared_font_atlas ? false : true;
Font = NULL; Font = NULL;
FontSize = FontBaseSize = 0.0f; FontSize = FontBaseSize = CurrentDpiScale = 0.0f;
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)(); IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
Time = 0.0f; Time = 0.0f;
FrameCount = 0; FrameCount = 0;
@ -2519,7 +2517,6 @@ struct ImGuiContext
CurrentItemFlags = ImGuiItemFlags_None; CurrentItemFlags = ImGuiItemFlags_None;
DebugShowGroupRects = false; DebugShowGroupRects = false;
CurrentDpiScale = 0.0f;
CurrentViewport = NULL; CurrentViewport = NULL;
MouseViewport = MouseLastHoveredViewport = NULL; MouseViewport = MouseLastHoveredViewport = NULL;
PlatformLastFocusedViewportId = 0; PlatformLastFocusedViewportId = 0;
@ -2554,8 +2551,10 @@ struct ImGuiContext
NavTabbingDir = 0; NavTabbingDir = 0;
NavTabbingCounter = 0; NavTabbingCounter = 0;
ConfigNavWindowingKeyNext = ImGuiMod_Ctrl | ImGuiKey_Tab; // All platforms use Ctrl+Tab but Ctrl<>Super are swapped on Mac...
ConfigNavWindowingKeyPrev = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab; // FIXME: Because this value is stored, it annoyingly interfere with toggling io.ConfigMacOSXBehaviors updating this..
ConfigNavWindowingKeyNext = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiKey_Tab);
ConfigNavWindowingKeyPrev = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab);
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL; NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
NavWindowingToggleLayer = false; NavWindowingToggleLayer = false;
@ -2754,6 +2753,7 @@ struct IMGUI_API ImGuiWindow
bool Collapsed; // Set when collapsing window to become only title-bar bool Collapsed; // Set when collapsing window to become only title-bar
bool WantCollapseToggle; bool WantCollapseToggle;
bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed) bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed)
bool SkipRefresh; // [EXPERIMENTAL] Reuse previous frame drawn contents, Begin() returns false.
bool Appearing; // Set during the frame where the window is appearing (or re-appearing) bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
bool Hidden; // Do not display (== HiddenFrames*** > 0) bool Hidden; // Do not display (== HiddenFrames*** > 0)
bool IsFallbackWindow; // Set on the "Debug##Default" window. bool IsFallbackWindow; // Set on the "Debug##Default" window.
@ -3012,13 +3012,24 @@ struct ImGuiTableColumn
}; };
// Transient cell data stored per row. // Transient cell data stored per row.
// sizeof() ~ 6 // sizeof() ~ 6 bytes
struct ImGuiTableCellData struct ImGuiTableCellData
{ {
ImU32 BgColor; // Actual color ImU32 BgColor; // Actual color
ImGuiTableColumnIdx Column; // Column number ImGuiTableColumnIdx Column; // Column number
}; };
// Parameters for TableAngledHeadersRowEx()
// This may end up being refactored for more general purpose.
// sizeof() ~ 12 bytes
struct ImGuiTableHeaderData
{
ImGuiTableColumnIdx Index; // Column index
ImU32 TextColor;
ImU32 BgColor0;
ImU32 BgColor1;
};
// Per-instance data that needs preserving across frames (seemingly most others do not need to be preserved aside from debug needs. Does that means they could be moved to ImGuiTableTempData?) // Per-instance data that needs preserving across frames (seemingly most others do not need to be preserved aside from debug needs. Does that means they could be moved to ImGuiTableTempData?)
// sizeof() ~ 24 bytes // sizeof() ~ 24 bytes
struct ImGuiTableInstanceData struct ImGuiTableInstanceData
@ -3033,8 +3044,7 @@ struct ImGuiTableInstanceData
ImGuiTableInstanceData() { TableInstanceID = 0; LastOuterHeight = LastTopHeadersRowHeight = LastFrozenHeight = 0.0f; HoveredRowLast = HoveredRowNext = -1; } ImGuiTableInstanceData() { TableInstanceID = 0; LastOuterHeight = LastTopHeadersRowHeight = LastFrozenHeight = 0.0f; HoveredRowLast = HoveredRowNext = -1; }
}; };
// FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs, incoming RowData // sizeof() ~ 592 bytes + heap allocs described in TableBeginInitMemory()
// sizeof() ~ 580 bytes + heap allocs described in TableBeginInitMemory()
struct IMGUI_API ImGuiTable struct IMGUI_API ImGuiTable
{ {
ImGuiID ID; ImGuiID ID;
@ -3104,7 +3114,7 @@ struct IMGUI_API ImGuiTable
ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs() ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs()
ImGuiTableColumnIdx SortSpecsCount; ImGuiTableColumnIdx SortSpecsCount;
ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount) ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount)
ImGuiTableColumnIdx ColumnsEnabledFixedCount; // Number of enabled columns (<= ColumnsCount) ImGuiTableColumnIdx ColumnsEnabledFixedCount; // Number of enabled columns using fixed width (<= ColumnsCount)
ImGuiTableColumnIdx DeclColumnsCount; // Count calls to TableSetupColumn() ImGuiTableColumnIdx DeclColumnsCount; // Count calls to TableSetupColumn()
ImGuiTableColumnIdx AngledHeadersCount; // Count columns with angled headers ImGuiTableColumnIdx AngledHeadersCount; // Count columns with angled headers
ImGuiTableColumnIdx HoveredColumnBody; // Index of column whose visible region is being hovered. Important: == ColumnsCount when hovering empty region after the right-most column! ImGuiTableColumnIdx HoveredColumnBody; // Index of column whose visible region is being hovered. Important: == ColumnsCount when hovering empty region after the right-most column!
@ -3157,12 +3167,14 @@ struct IMGUI_API ImGuiTable
// Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table). // Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table).
// - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure. // - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure.
// - We also leave out of this structure data that tend to be particularly useful for debugging/metrics. // - We also leave out of this structure data that tend to be particularly useful for debugging/metrics.
// sizeof() ~ 120 bytes. // FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs.
// sizeof() ~ 136 bytes.
struct IMGUI_API ImGuiTableTempData struct IMGUI_API ImGuiTableTempData
{ {
int TableIndex; // Index in g.Tables.Buf[] pool int TableIndex; // Index in g.Tables.Buf[] pool
float LastTimeActive; // Last timestamp this structure was used float LastTimeActive; // Last timestamp this structure was used
float AngledHeadersExtraWidth; // Used in EndTable() float AngledHeadersExtraWidth; // Used in EndTable()
ImVector<ImGuiTableHeaderData> AngledHeadersRequests; // Used in TableAngledHeadersRow()
ImVec2 UserOuterSize; // outer_size.x passed to BeginTable() ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
ImDrawListSplitter DrawSplitter; ImDrawListSplitter DrawSplitter;
@ -3234,6 +3246,7 @@ namespace ImGui
IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id); IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id);
IMGUI_API ImGuiWindow* FindWindowByName(const char* name); IMGUI_API ImGuiWindow* FindWindowByName(const char* name);
IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window); IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window);
IMGUI_API void UpdateWindowSkipRefresh(ImGuiWindow* window);
IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window); IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window);
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy, bool dock_hierarchy); IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy, bool dock_hierarchy);
IMGUI_API bool IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API bool IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent);
@ -3259,6 +3272,9 @@ namespace ImGui
IMGUI_API int FindWindowDisplayIndex(ImGuiWindow* window); IMGUI_API int FindWindowDisplayIndex(ImGuiWindow* window);
IMGUI_API ImGuiWindow* FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* window); IMGUI_API ImGuiWindow* FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* window);
// Windows: Idle, Refresh Policies [EXPERIMENTAL]
IMGUI_API void SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags);
// Fonts, drawing // Fonts, drawing
IMGUI_API void SetCurrentFont(ImFont* font); IMGUI_API void SetCurrentFont(ImFont* font);
inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; } inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; }
@ -3272,6 +3288,7 @@ namespace ImGui
// NewFrame // NewFrame
IMGUI_API void UpdateInputEvents(bool trickle_fast_inputs); IMGUI_API void UpdateInputEvents(bool trickle_fast_inputs);
IMGUI_API void UpdateHoveredWindowAndCaptureFlags(); IMGUI_API void UpdateHoveredWindowAndCaptureFlags();
IMGUI_API void FindHoveredWindowEx(const ImVec2& pos, bool find_first_and_in_any_viewport, ImGuiWindow** out_hovered_window, ImGuiWindow** out_hovered_window_under_moving_window);
IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window); IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
IMGUI_API void StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node, bool undock); IMGUI_API void StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node, bool undock);
IMGUI_API void UpdateMouseMovingWindowNewFrame(); IMGUI_API void UpdateMouseMovingWindowNewFrame();
@ -3420,22 +3437,20 @@ namespace ImGui
// Inputs // Inputs
// FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
inline bool IsNamedKey(ImGuiKey key) { return key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END; } inline bool IsNamedKey(ImGuiKey key) { return key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END; }
inline bool IsNamedKeyOrModKey(ImGuiKey key) { return (key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END) || key == ImGuiMod_Ctrl || key == ImGuiMod_Shift || key == ImGuiMod_Alt || key == ImGuiMod_Super || key == ImGuiMod_Shortcut; } inline bool IsNamedKeyOrMod(ImGuiKey key) { return (key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END) || key == ImGuiMod_Ctrl || key == ImGuiMod_Shift || key == ImGuiMod_Alt || key == ImGuiMod_Super; }
inline bool IsLegacyKey(ImGuiKey key) { return key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_LegacyNativeKey_END; } inline bool IsLegacyKey(ImGuiKey key) { return key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_LegacyNativeKey_END; }
inline bool IsKeyboardKey(ImGuiKey key) { return key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END; } inline bool IsKeyboardKey(ImGuiKey key) { return key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END; }
inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; } inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; }
inline bool IsMouseKey(ImGuiKey key) { return key >= ImGuiKey_Mouse_BEGIN && key < ImGuiKey_Mouse_END; } inline bool IsMouseKey(ImGuiKey key) { return key >= ImGuiKey_Mouse_BEGIN && key < ImGuiKey_Mouse_END; }
inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; } inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; }
inline bool IsModKey(ImGuiKey key) { return key >= ImGuiKey_LeftCtrl && key <= ImGuiKey_RightSuper; } inline bool IsModKey(ImGuiKey key) { return key >= ImGuiKey_LeftCtrl && key <= ImGuiKey_RightSuper; }
ImGuiKeyChord FixupKeyChord(ImGuiContext* ctx, ImGuiKeyChord key_chord); ImGuiKeyChord FixupKeyChord(ImGuiKeyChord key_chord);
inline ImGuiKey ConvertSingleModFlagToKey(ImGuiContext* ctx, ImGuiKey key) inline ImGuiKey ConvertSingleModFlagToKey(ImGuiKey key)
{ {
ImGuiContext& g = *ctx;
if (key == ImGuiMod_Ctrl) return ImGuiKey_ReservedForModCtrl; if (key == ImGuiMod_Ctrl) return ImGuiKey_ReservedForModCtrl;
if (key == ImGuiMod_Shift) return ImGuiKey_ReservedForModShift; if (key == ImGuiMod_Shift) return ImGuiKey_ReservedForModShift;
if (key == ImGuiMod_Alt) return ImGuiKey_ReservedForModAlt; if (key == ImGuiMod_Alt) return ImGuiKey_ReservedForModAlt;
if (key == ImGuiMod_Super) return ImGuiKey_ReservedForModSuper; if (key == ImGuiMod_Super) return ImGuiKey_ReservedForModSuper;
if (key == ImGuiMod_Shortcut) return (g.IO.ConfigMacOSXBehaviors ? ImGuiKey_ReservedForModSuper : ImGuiKey_ReservedForModCtrl);
return key; return key;
} }
@ -3455,7 +3470,7 @@ namespace ImGui
// [EXPERIMENTAL] Low-Level: Key/Input Ownership // [EXPERIMENTAL] Low-Level: Key/Input Ownership
// - The idea is that instead of "eating" a given input, we can link to an owner id. // - The idea is that instead of "eating" a given input, we can link to an owner id.
// - Ownership is most often claimed as a result of reacting to a press/down event (but occasionally may be claimed ahead). // - Ownership is most often claimed as a result of reacting to a press/down event (but occasionally may be claimed ahead).
// - Input queries can then read input by specifying ImGuiKeyOwner_Any (== 0), ImGuiKeyOwner_None (== -1) or a custom ID. // - Input queries can then read input by specifying ImGuiKeyOwner_Any (== 0), ImGuiKeyOwner_NoOwner (== -1) or a custom ID.
// - Legacy input queries (without specifying an owner or _Any or _None) are equivalent to using ImGuiKeyOwner_Any (== 0). // - Legacy input queries (without specifying an owner or _Any or _None) are equivalent to using ImGuiKeyOwner_Any (== 0).
// - Input ownership is automatically released on the frame after a key is released. Therefore: // - Input ownership is automatically released on the frame after a key is released. Therefore:
// - for ownership registration happening as a result of a down/press event, the SetKeyOwner() call may be done once (common case). // - for ownership registration happening as a result of a down/press event, the SetKeyOwner() call may be done once (common case).
@ -3468,7 +3483,7 @@ namespace ImGui
IMGUI_API void SetKeyOwnersForKeyChord(ImGuiKeyChord key, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API void SetKeyOwnersForKeyChord(ImGuiKeyChord key, ImGuiID owner_id, ImGuiInputFlags flags = 0);
IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags = 0); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'. IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags = 0); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'.
IMGUI_API bool TestKeyOwner(ImGuiKey key, ImGuiID owner_id); // Test that key is either not owned, either owned by 'owner_id' IMGUI_API bool TestKeyOwner(ImGuiKey key, ImGuiID owner_id); // Test that key is either not owned, either owned by 'owner_id'
inline ImGuiKeyOwnerData* GetKeyOwnerData(ImGuiContext* ctx, ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(ctx, key); IM_ASSERT(IsNamedKey(key)); return &ctx->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; } inline ImGuiKeyOwnerData* GetKeyOwnerData(ImGuiContext* ctx, ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(key); IM_ASSERT(IsNamedKey(key)); return &ctx->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; }
// [EXPERIMENTAL] High-Level: Input Access functions w/ support for Key/Input Ownership // [EXPERIMENTAL] High-Level: Input Access functions w/ support for Key/Input Ownership
// - Important: legacy IsKeyPressed(ImGuiKey, bool repeat=true) _DEFAULTS_ to repeat, new IsKeyPressed() requires _EXPLICIT_ ImGuiInputFlags_Repeat flag. // - Important: legacy IsKeyPressed(ImGuiKey, bool repeat=true) _DEFAULTS_ to repeat, new IsKeyPressed() requires _EXPLICIT_ ImGuiInputFlags_Repeat flag.
@ -3477,30 +3492,30 @@ namespace ImGui
// Legacy functions use ImGuiKeyOwner_Any meaning that they typically ignore ownership, unless a call to SetKeyOwner() explicitly used ImGuiInputFlags_LockThisFrame or ImGuiInputFlags_LockUntilRelease. // Legacy functions use ImGuiKeyOwner_Any meaning that they typically ignore ownership, unless a call to SetKeyOwner() explicitly used ImGuiInputFlags_LockThisFrame or ImGuiInputFlags_LockUntilRelease.
// - Binding generators may want to ignore those for now, or suffix them with Ex() until we decide if this gets moved into public API. // - Binding generators may want to ignore those for now, or suffix them with Ex() until we decide if this gets moved into public API.
IMGUI_API bool IsKeyDown(ImGuiKey key, ImGuiID owner_id); IMGUI_API bool IsKeyDown(ImGuiKey key, ImGuiID owner_id);
IMGUI_API bool IsKeyPressed(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0); // Important: when transitioning from old to new IsKeyPressed(): old API has "bool repeat = true", so would default to repeat. New API requiress explicit ImGuiInputFlags_Repeat. IMGUI_API bool IsKeyPressed(ImGuiKey key, ImGuiInputFlags flags, ImGuiID owner_id = 0); // Important: when transitioning from old to new IsKeyPressed(): old API has "bool repeat = true", so would default to repeat. New API requiress explicit ImGuiInputFlags_Repeat.
IMGUI_API bool IsKeyReleased(ImGuiKey key, ImGuiID owner_id); IMGUI_API bool IsKeyReleased(ImGuiKey key, ImGuiID owner_id);
IMGUI_API bool IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id = 0);
IMGUI_API bool IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id); IMGUI_API bool IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id);
IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, ImGuiInputFlags flags, ImGuiID owner_id = 0);
IMGUI_API bool IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id); IMGUI_API bool IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id);
IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button, ImGuiID owner_id); IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button, ImGuiID owner_id);
// [EXPERIMENTAL] Shortcut Routing // Shortcut Testing & Routing
// - ImGuiKeyChord = a ImGuiKey optionally OR-red with ImGuiMod_Alt/ImGuiMod_Ctrl/ImGuiMod_Shift/ImGuiMod_Super. // - Set Shortcut() and SetNextItemShortcut() in imgui.h
// ImGuiKey_C (accepted by functions taking ImGuiKey or ImGuiKeyChord) // - When a policy (except for ImGuiInputFlags_RouteAlways *) is set, Shortcut() will register itself with SetShortcutRouting(),
// ImGuiKey_C | ImGuiMod_Ctrl (accepted by functions taking ImGuiKeyChord) // allowing the system to decide where to route the input among other route-aware calls.
// ONLY ImGuiMod_XXX values are legal to 'OR' with an ImGuiKey. You CANNOT 'OR' two ImGuiKey values. // (* using ImGuiInputFlags_RouteAlways is roughly equivalent to calling IsKeyChordPressed(key) and bypassing route registration and check)
// - When using one of the routing flags (e.g. ImGuiInputFlags_RouteFocused): routes requested ahead of time given a chord (key + modifiers) and a routing policy. // - When using one of the routing option:
// - The default route is ImGuiInputFlags_RouteFocused (accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window.)
// - Routes are requested given a chord (key + modifiers) and a routing policy.
// - Routes are resolved during NewFrame(): if keyboard modifiers are matching current ones: SetKeyOwner() is called + route is granted for the frame. // - Routes are resolved during NewFrame(): if keyboard modifiers are matching current ones: SetKeyOwner() is called + route is granted for the frame.
// - Route is granted to a single owner. When multiple requests are made we have policies to select the winning route. // - Each route may be granted to a single owner. When multiple requests are made we have policies to select the winning route (e.g. deep most window).
// - Multiple read sites may use the same owner id and will all get the granted route. // - Multiple read sites may use the same owner id can all access the granted route.
// - For routing: when owner_id is 0 we use the current Focus Scope ID as a default owner in order to identify our location. // - When owner_id is 0 we use the current Focus Scope ID as a owner ID in order to identify our location.
// - TL;DR; // - You can chain two unrelated windows in the focus stack using SetWindowParentWindowForFocusRoute()
// - IsKeyChordPressed() compares mods + call IsKeyPressed() -> function has no side-effect. // e.g. if you have a tool window associated to a document, and you want document shortcuts to run when the tool is focused.
// - Shortcut() submits a route then if currently can be routed calls IsKeyChordPressed() -> function has (desirable) side-effects. IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id);
IMGUI_API bool IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id); // owner_id needs to be explicit and cannot be 0
IMGUI_API void SetNextItemShortcut(ImGuiKeyChord key_chord);
IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0);
IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags = 0); // owner_id needs to be explicit and cannot be 0
IMGUI_API bool TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id); IMGUI_API bool TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id);
IMGUI_API ImGuiKeyRoutingData* GetShortcutRoutingData(ImGuiKeyChord key_chord); IMGUI_API ImGuiKeyRoutingData* GetShortcutRoutingData(ImGuiKeyChord key_chord);
@ -3606,7 +3621,7 @@ namespace ImGui
IMGUI_API float TableGetHeaderAngledMaxLabelWidth(); IMGUI_API float TableGetHeaderAngledMaxLabelWidth();
IMGUI_API void TablePushBackgroundChannel(); IMGUI_API void TablePushBackgroundChannel();
IMGUI_API void TablePopBackgroundChannel(); IMGUI_API void TablePopBackgroundChannel();
IMGUI_API void TableAngledHeadersRowEx(float angle, float max_label_width = 0.0f); IMGUI_API void TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label_width, const ImGuiTableHeaderData* data, int data_count);
// Tables: Internals // Tables: Internals
inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; } inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; }
@ -3820,6 +3835,8 @@ namespace ImGui
inline void SetItemUsingMouseWheel() { SetItemKeyOwner(ImGuiKey_MouseWheelY); } // Changed in 1.89 inline void SetItemUsingMouseWheel() { SetItemKeyOwner(ImGuiKey_MouseWheelY); } // Changed in 1.89
inline bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0) { return TreeNodeUpdateNextOpen(id, flags); } // Renamed in 1.89 inline bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0) { return TreeNodeUpdateNextOpen(id, flags); } // Renamed in 1.89
//inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // Removed in 1.87: Mapping from named key is always identity!
// Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister(): // Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister():
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)' // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)'
// (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0' // (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0'
@ -3827,9 +3844,6 @@ namespace ImGui
//inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd() //inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd()
//inline void FocusableItemUnregister(ImGuiWindow* window) // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem //inline void FocusableItemUnregister(ImGuiWindow* window) // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem
#endif #endif
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // Removed in 1.87: Mapping from named key is always identity!
#endif
} // namespace ImGui } // namespace ImGui

View File

@ -1,4 +1,4 @@
// dear imgui, v1.90.4 // dear imgui, v1.90.7
// (tables and columns code) // (tables and columns code)
/* /*
@ -24,8 +24,9 @@ Index of this file:
*/ */
// Navigating this file: // Navigating this file:
// - In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. // - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Commentary // [SECTION] Commentary
@ -227,6 +228,7 @@ Index of this file:
#pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') #pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_')
#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
#elif defined(__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
@ -318,6 +320,12 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
IM_ASSERT(inner_width >= 0.0f); IM_ASSERT(inner_width >= 0.0f);
// If an outer size is specified ahead we will be able to early out when not visible. Exact clipping criteria may evolve. // If an outer size is specified ahead we will be able to early out when not visible. Exact clipping criteria may evolve.
// FIXME: coarse clipping because access to table data causes two issues:
// - instance numbers varying/unstable. may not be a direct problem for users, but could make outside access broken or confusing, e.g. TestEngine.
// - can't implement support for ImGuiChildFlags_ResizeY as we need to somehow pull the height data from somewhere. this also needs stable instance numbers.
// The side-effects of accessing table data on coarse clip would be:
// - always reserving the pooled ImGuiTable data ahead for a fully clipped table (minor IMHO). Also the 'outer_window_is_measuring_size' criteria may already be defeating this in some situations.
// - always performing the GetOrAddByKey() O(log N) query in g.Tables.Map[].
const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0; const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0;
const ImVec2 avail_size = GetContentRegionAvail(); const ImVec2 avail_size = GetContentRegionAvail();
const ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f); const ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f);
@ -326,6 +334,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if (use_child_window && IsClippedEx(outer_rect, 0) && !outer_window_is_measuring_size) if (use_child_window && IsClippedEx(outer_rect, 0) && !outer_window_is_measuring_size)
{ {
ItemSize(outer_rect); ItemSize(outer_rect);
ItemAdd(outer_rect, id);
return false; return false;
} }
@ -335,7 +344,6 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// Acquire storage for the table // Acquire storage for the table
ImGuiTable* table = g.Tables.GetOrAddByKey(id); ImGuiTable* table = g.Tables.GetOrAddByKey(id);
const ImGuiTableFlags table_last_flags = table->Flags;
// Acquire temporary buffers // Acquire temporary buffers
const int table_idx = g.Tables.GetIndex(table); const int table_idx = g.Tables.GetIndex(table);
@ -353,6 +361,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// Initialize // Initialize
const int previous_frame_active = table->LastFrameActive; const int previous_frame_active = table->LastFrameActive;
const int instance_no = (previous_frame_active != g.FrameCount) ? 0 : table->InstanceCurrent + 1; const int instance_no = (previous_frame_active != g.FrameCount) ? 0 : table->InstanceCurrent + 1;
const ImGuiTableFlags previous_flags = table->Flags;
table->ID = id; table->ID = id;
table->Flags = flags; table->Flags = flags;
table->LastFrameActive = g.FrameCount; table->LastFrameActive = g.FrameCount;
@ -399,7 +408,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
SetNextWindowContentSize(ImVec2(override_content_size.x != FLT_MAX ? override_content_size.x : 0.0f, override_content_size.y != FLT_MAX ? override_content_size.y : 0.0f)); SetNextWindowContentSize(ImVec2(override_content_size.x != FLT_MAX ? override_content_size.x : 0.0f, override_content_size.y != FLT_MAX ? override_content_size.y : 0.0f));
// Reset scroll if we are reactivating it // Reset scroll if we are reactivating it
if ((table_last_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0) if ((previous_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0)
SetNextWindowScroll(ImVec2(0.0f, 0.0f)); SetNextWindowScroll(ImVec2(0.0f, 0.0f));
// Create scrolling region (without border and zero window padding) // Create scrolling region (without border and zero window padding)
@ -498,6 +507,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->DeclColumnsCount = table->AngledHeadersCount = 0; table->DeclColumnsCount = table->AngledHeadersCount = 0;
if (previous_frame_active + 1 < g.FrameCount) if (previous_frame_active + 1 < g.FrameCount)
table->IsActiveIdInTable = false; table->IsActiveIdInTable = false;
table->AngledHeadersHeight = 0.0f;
temp_data->AngledHeadersExtraWidth = 0.0f; temp_data->AngledHeadersExtraWidth = 0.0f;
// Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders() // Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders()
@ -511,7 +521,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly. if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly.
inner_window->DC.CurrentTableIdx = table_idx; inner_window->DC.CurrentTableIdx = table_idx;
if ((table_last_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0) if ((previous_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0)
table->IsResetDisplayOrderRequest = true; table->IsResetDisplayOrderRequest = true;
// Mark as used to avoid GC // Mark as used to avoid GC
@ -1066,6 +1076,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// - ClipRect.Max.x: using WorkMaxX instead of MaxX (aka including padding) makes things more consistent when resizing down, tho slightly detrimental to visibility in very-small column. // - ClipRect.Max.x: using WorkMaxX instead of MaxX (aka including padding) makes things more consistent when resizing down, tho slightly detrimental to visibility in very-small column.
// - ClipRect.Max.x: using MaxX makes it easier for header to receive hover highlight with no discontinuity and display sorting arrow. // - ClipRect.Max.x: using MaxX makes it easier for header to receive hover highlight with no discontinuity and display sorting arrow.
// - FIXME-TABLE: We want equal width columns to have equal (ClipRect.Max.x - WorkMinX) width, which means ClipRect.max.x cannot stray off host_clip_rect.Max.x else right-most column may appear shorter. // - FIXME-TABLE: We want equal width columns to have equal (ClipRect.Max.x - WorkMinX) width, which means ClipRect.max.x cannot stray off host_clip_rect.Max.x else right-most column may appear shorter.
const float previous_instance_work_min_x = column->WorkMinX;
column->WorkMinX = column->MinX + table->CellPaddingX + table->CellSpacingX1; column->WorkMinX = column->MinX + table->CellPaddingX + table->CellSpacingX1;
column->WorkMaxX = column->MaxX - table->CellPaddingX - table->CellSpacingX2; // Expected max column->WorkMaxX = column->MaxX - table->CellPaddingX - table->CellSpacingX2; // Expected max
column->ItemWidth = ImTrunc(column->WidthGiven * 0.65f); column->ItemWidth = ImTrunc(column->WidthGiven * 0.65f);
@ -1118,8 +1129,22 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// column->WorkMinX = ImLerp(column->WorkMinX, ImMax(column->StartX, column->MaxX - column->ContentWidthRowsUnfrozen), 0.5f); // column->WorkMinX = ImLerp(column->WorkMinX, ImMax(column->StartX, column->MaxX - column->ContentWidthRowsUnfrozen), 0.5f);
// Reset content width variables // Reset content width variables
column->ContentMaxXFrozen = column->ContentMaxXUnfrozen = column->WorkMinX; if (table->InstanceCurrent == 0)
column->ContentMaxXHeadersUsed = column->ContentMaxXHeadersIdeal = column->WorkMinX; {
column->ContentMaxXFrozen = column->WorkMinX;
column->ContentMaxXUnfrozen = column->WorkMinX;
column->ContentMaxXHeadersUsed = column->WorkMinX;
column->ContentMaxXHeadersIdeal = column->WorkMinX;
}
else
{
// As we store an absolute value to make per-cell updates faster, we need to offset values used for width computation.
const float offset_from_previous_instance = column->WorkMinX - previous_instance_work_min_x;
column->ContentMaxXFrozen += offset_from_previous_instance;
column->ContentMaxXUnfrozen += offset_from_previous_instance;
column->ContentMaxXHeadersUsed += offset_from_previous_instance;
column->ContentMaxXHeadersIdeal += offset_from_previous_instance;
}
// Don't decrement auto-fit counters until container window got a chance to submit its items // Don't decrement auto-fit counters until container window got a chance to submit its items
if (table->HostSkipItems == false) if (table->HostSkipItems == false)
@ -1238,9 +1263,9 @@ void ImGui::TableUpdateBorders(ImGuiTable* table)
// really problematic (whereas the actual visual will be displayed in EndTable() and using the current frame height). // really problematic (whereas the actual visual will be displayed in EndTable() and using the current frame height).
// Actual columns highlight/render will be performed in EndTable() and not be affected. // Actual columns highlight/render will be performed in EndTable() and not be affected.
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS; const float hit_half_width = ImTrunc(TABLE_RESIZE_SEPARATOR_HALF_THICKNESS * g.CurrentDpiScale);
const float hit_y1 = (table->FreezeRowsCount >= 1 ? table->OuterRect.Min.y : table->WorkRect.Min.y) + table->AngledHeadersHeight; const float hit_y1 = (table->FreezeRowsCount >= 1 ? table->OuterRect.Min.y : table->WorkRect.Min.y) + table->AngledHeadersHeight;
const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table_instance->LastOuterHeight); const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table_instance->LastOuterHeight - table->AngledHeadersHeight);
const float hit_y2_head = hit_y1 + table_instance->LastTopHeadersRowHeight; const float hit_y2_head = hit_y1 + table_instance->LastTopHeadersRowHeight;
for (int order_n = 0; order_n < table->ColumnsCount; order_n++) for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
@ -1415,7 +1440,7 @@ void ImGui::EndTable()
if (table->ResizedColumn != -1 && table->InstanceCurrent == table->InstanceInteracted) if (table->ResizedColumn != -1 && table->InstanceCurrent == table->InstanceInteracted)
{ {
ImGuiTableColumn* column = &table->Columns[table->ResizedColumn]; ImGuiTableColumn* column = &table->Columns[table->ResizedColumn];
const float new_x2 = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + TABLE_RESIZE_SEPARATOR_HALF_THICKNESS); const float new_x2 = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + ImTrunc(TABLE_RESIZE_SEPARATOR_HALF_THICKNESS * g.CurrentDpiScale));
const float new_width = ImTrunc(new_x2 - column->MinX - table->CellSpacingX1 - table->CellPaddingX * 2.0f); const float new_width = ImTrunc(new_x2 - column->MinX - table->CellSpacingX1 - table->CellPaddingX * 2.0f);
table->ResizedColumnNextWidth = new_width; table->ResizedColumnNextWidth = new_width;
} }
@ -1444,7 +1469,10 @@ void ImGui::EndTable()
// CursorPosPrevLine and CursorMaxPos manually. That should be a more general layout feature, see same problem e.g. #3414) // CursorPosPrevLine and CursorMaxPos manually. That should be a more general layout feature, see same problem e.g. #3414)
if (inner_window != outer_window) if (inner_window != outer_window)
{ {
short backup_nav_layers_active_mask = inner_window->DC.NavLayersActiveMask;
inner_window->DC.NavLayersActiveMask |= 1 << ImGuiNavLayer_Main; // So empty table don't appear to navigate differently.
EndChild(); EndChild();
inner_window->DC.NavLayersActiveMask = backup_nav_layers_active_mask;
} }
else else
{ {
@ -1890,7 +1918,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
if (is_visible) if (is_visible)
{ {
// Update data for TableGetHoveredRow() // Update data for TableGetHoveredRow()
if (table->HoveredColumnBody != -1 && g.IO.MousePos.y >= bg_y1 && g.IO.MousePos.y < bg_y2) if (table->HoveredColumnBody != -1 && g.IO.MousePos.y >= bg_y1 && g.IO.MousePos.y < bg_y2 && table_instance->HoveredRowNext < 0)
table_instance->HoveredRowNext = table->CurrentRow; table_instance->HoveredRowNext = table->CurrentRow;
// Decide of background color for the row // Decide of background color for the row
@ -1945,6 +1973,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
cell_bg_rect.ClipWith(table->BgClipRect); cell_bg_rect.ClipWith(table->BgClipRect);
cell_bg_rect.Min.x = ImMax(cell_bg_rect.Min.x, column->ClipRect.Min.x); // So that first column after frozen one gets clipped when scrolling cell_bg_rect.Min.x = ImMax(cell_bg_rect.Min.x, column->ClipRect.Min.x); // So that first column after frozen one gets clipped when scrolling
cell_bg_rect.Max.x = ImMin(cell_bg_rect.Max.x, column->MaxX); cell_bg_rect.Max.x = ImMin(cell_bg_rect.Max.x, column->MaxX);
if (cell_bg_rect.Min.y < cell_bg_rect.Max.y)
window->DrawList->AddRectFilled(cell_bg_rect.Min, cell_bg_rect.Max, cell_data->BgColor); window->DrawList->AddRectFilled(cell_bg_rect.Min, cell_bg_rect.Max, cell_data->BgColor);
} }
} }
@ -2907,6 +2936,7 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
} }
// Write output // Write output
// May be able to move all SortSpecs data from table (48 bytes) to ImGuiTableTempData if we decide to write it back on every BeginTable()
ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data; ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data;
if (dirty && sort_specs != NULL) if (dirty && sort_specs != NULL)
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
@ -2967,7 +2997,7 @@ float ImGui::TableGetHeaderAngledMaxLabelWidth()
// [Public] This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn(). // [Public] This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn().
// The intent is that advanced users willing to create customized headers would not need to use this helper // The intent is that advanced users willing to create customized headers would not need to use this helper
// and can create their own! For example: TableHeader() may be preceeded by Checkbox() or other custom widgets. // and can create their own! For example: TableHeader() may be preceded by Checkbox() or other custom widgets.
// See 'Demo->Tables->Custom headers' for a demonstration of implementing a custom version of this. // See 'Demo->Tables->Custom headers' for a demonstration of implementing a custom version of this.
// This code is constructed to not make much use of internal functions, as it is intended to be a template to copy. // This code is constructed to not make much use of internal functions, as it is intended to be a template to copy.
// FIXME-TABLE: TableOpenContextMenu() and TableGetHeaderRowHeight() are not public. // FIXME-TABLE: TableOpenContextMenu() and TableGetHeaderRowHeight() are not public.
@ -3153,15 +3183,43 @@ void ImGui::TableHeader(const char* label)
} }
// Unlike TableHeadersRow() it is not expected that you can reimplement or customize this with custom widgets. // Unlike TableHeadersRow() it is not expected that you can reimplement or customize this with custom widgets.
// FIXME: highlight without ImGuiTableFlags_HighlightHoveredColumn
// FIXME: No hit-testing/button on the angled header. // FIXME: No hit-testing/button on the angled header.
void ImGui::TableAngledHeadersRow() void ImGui::TableAngledHeadersRow()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
TableAngledHeadersRowEx(g.Style.TableAngledHeadersAngle, 0.0f); ImGuiTable* table = g.CurrentTable;
ImGuiTableTempData* temp_data = table->TempData;
temp_data->AngledHeadersRequests.resize(0);
temp_data->AngledHeadersRequests.reserve(table->ColumnsEnabledCount);
// Which column needs highlight?
const ImGuiID row_id = GetID("##AngledHeaders");
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
int highlight_column_n = table->HighlightColumnHeader;
if (highlight_column_n == -1 && table->HoveredColumnBody != -1)
if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive)))
highlight_column_n = table->HoveredColumnBody;
// Build up request
ImU32 col_header_bg = GetColorU32(ImGuiCol_TableHeaderBg);
ImU32 col_text = GetColorU32(ImGuiCol_Text);
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
if (IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n))
{
const int column_n = table->DisplayOrderToIndex[order_n];
ImGuiTableColumn* column = &table->Columns[column_n];
if ((column->Flags & ImGuiTableColumnFlags_AngledHeader) == 0) // Note: can't rely on ImGuiTableColumnFlags_IsVisible test here.
continue;
ImGuiTableHeaderData request = { (ImGuiTableColumnIdx)column_n, col_text, col_header_bg, (column_n == highlight_column_n) ? GetColorU32(ImGuiCol_Header) : 0 };
temp_data->AngledHeadersRequests.push_back(request);
}
// Render row
TableAngledHeadersRowEx(row_id, g.Style.TableAngledHeadersAngle, 0.0f, temp_data->AngledHeadersRequests.Data, temp_data->AngledHeadersRequests.Size);
} }
void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width) // Important: data must be fed left to right
void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label_width, const ImGuiTableHeaderData* data, int data_count)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
@ -3185,7 +3243,7 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
// Calculate our base metrics and set angled headers data _before_ the first call to TableNextRow() // Calculate our base metrics and set angled headers data _before_ the first call to TableNextRow()
// FIXME-STYLE: Would it be better for user to submit 'max_label_width' or 'row_height' ? One can be derived from the other. // FIXME-STYLE: Would it be better for user to submit 'max_label_width' or 'row_height' ? One can be derived from the other.
const float header_height = g.FontSize + g.Style.CellPadding.x * 2.0f; const float header_height = g.FontSize + g.Style.CellPadding.x * 2.0f;
const float row_height = ImFabs(ImRotate(ImVec2(max_label_width, flip_label ? +header_height : -header_height), cos_a, sin_a).y); const float row_height = ImTrunc(ImFabs(ImRotate(ImVec2(max_label_width, flip_label ? +header_height : -header_height), cos_a, sin_a).y));
table->AngledHeadersHeight = row_height; table->AngledHeadersHeight = row_height;
table->AngledHeadersSlope = (sin_a != 0.0f) ? (cos_a / sin_a) : 0.0f; table->AngledHeadersSlope = (sin_a != 0.0f) ? (cos_a / sin_a) : 0.0f;
const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a); // vector from bottom-left to top-left, and from bottom-right to top-right const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a); // vector from bottom-left to top-left, and from bottom-right to top-right
@ -3203,28 +3261,22 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
draw_list->AddRectFilled(ImVec2(table->BgClipRect.Min.x, row_r.Min.y), ImVec2(table->BgClipRect.Max.x, row_r.Max.y), GetColorU32(ImGuiCol_TableHeaderBg, 0.25f)); // FIXME-STYLE: Change row background with an arbitrary color. draw_list->AddRectFilled(ImVec2(table->BgClipRect.Min.x, row_r.Min.y), ImVec2(table->BgClipRect.Max.x, row_r.Max.y), GetColorU32(ImGuiCol_TableHeaderBg, 0.25f)); // FIXME-STYLE: Change row background with an arbitrary color.
PushClipRect(ImVec2(clip_rect_min_x, table->BgClipRect.Min.y), table->BgClipRect.Max, true); // Span all columns PushClipRect(ImVec2(clip_rect_min_x, table->BgClipRect.Min.y), table->BgClipRect.Max, true); // Span all columns
const ImGuiID row_id = GetID("##AngledHeaders");
ButtonBehavior(row_r, row_id, NULL, NULL); ButtonBehavior(row_r, row_id, NULL, NULL);
KeepAliveID(row_id); KeepAliveID(row_id);
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); const float ascent_scaled = g.Font->Ascent * (g.FontSize / g.Font->FontSize); // FIXME: Standardize those scaling factors better
int highlight_column_n = table->HighlightColumnHeader; const float line_off_for_ascent_x = (ImMax((g.FontSize - ascent_scaled) * 0.5f, 0.0f) / -sin_a) * (flip_label ? -1.0f : 1.0f);
if (highlight_column_n == -1 && table->HoveredColumnBody != -1) const ImVec2 padding = g.Style.CellPadding; // We will always use swapped component
if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive))) const ImVec2 align = g.Style.TableAngledHeadersTextAlign;
highlight_column_n = table->HoveredColumnBody;
// Draw background and labels in first pass, then all borders. // Draw background and labels in first pass, then all borders.
float max_x = 0.0f; float max_x = 0.0f;
ImVec2 padding = g.Style.CellPadding; // We will always use swapped component
for (int pass = 0; pass < 2; pass++) for (int pass = 0; pass < 2; pass++)
for (int order_n = 0; order_n < table->ColumnsCount; order_n++) for (int order_n = 0; order_n < data_count; order_n++)
{ {
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n)) const ImGuiTableHeaderData* request = &data[order_n];
continue; const int column_n = request->Index;
const int column_n = table->DisplayOrderToIndex[order_n];
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
if ((column->Flags & ImGuiTableColumnFlags_AngledHeader) == 0) // Note: can't rely on ImGuiTableColumnFlags_IsVisible test here.
continue;
ImVec2 bg_shape[4]; ImVec2 bg_shape[4];
bg_shape[0] = ImVec2(column->MaxX, row_r.Max.y); bg_shape[0] = ImVec2(column->MaxX, row_r.Max.y);
@ -3234,9 +3286,8 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
if (pass == 0) if (pass == 0)
{ {
// Draw shape // Draw shape
draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_TableHeaderBg)); draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], request->BgColor0);
if (column_n == highlight_column_n) draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], request->BgColor1); // Optional highlight
draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_Header)); // Highlight on hover
max_x = ImMax(max_x, bg_shape[3].x); max_x = ImMax(max_x, bg_shape[3].x);
// Draw label // Draw label
@ -3244,8 +3295,17 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
// - Handle multiple lines manually, as we want each lines to follow on the horizontal border, rather than see a whole block rotated. // - Handle multiple lines manually, as we want each lines to follow on the horizontal border, rather than see a whole block rotated.
const char* label_name = TableGetColumnName(table, column_n); const char* label_name = TableGetColumnName(table, column_n);
const char* label_name_end = FindRenderedTextEnd(label_name); const char* label_name_end = FindRenderedTextEnd(label_name);
const float line_off_step_x = g.FontSize / -sin_a; const float line_off_step_x = (g.FontSize / -sin_a);
float line_off_curr_x = 0.0f; const int label_lines = ImTextCountLines(label_name, label_name_end);
// Left<>Right alignment
float line_off_curr_x = flip_label ? (label_lines - 1) * line_off_step_x : 0.0f;
float line_off_for_align_x = ImMax((((column->MaxX - column->MinX) - padding.x * 2.0f) - (label_lines * line_off_step_x)), 0.0f) * align.x;
line_off_curr_x += line_off_for_align_x - line_off_for_ascent_x;
// Register header width
column->ContentMaxXHeadersUsed = column->ContentMaxXHeadersIdeal = column->WorkMinX + ImCeil(label_lines * line_off_step_x - line_off_for_align_x);
while (label_name < label_name_end) while (label_name < label_name_end)
{ {
const char* label_name_eol = strchr(label_name, '\n'); const char* label_name_eol = strchr(label_name, '\n');
@ -3254,26 +3314,30 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
// FIXME: Individual line clipping for right-most column is broken for negative angles. // FIXME: Individual line clipping for right-most column is broken for negative angles.
ImVec2 label_size = CalcTextSize(label_name, label_name_eol); ImVec2 label_size = CalcTextSize(label_name, label_name_eol);
float clip_width = max_label_width - padding.y; // Using padding.y*2.0f would be symetrical but hide more text. float clip_width = max_label_width - padding.y; // Using padding.y*2.0f would be symmetrical but hide more text.
float clip_height = ImMin(label_size.y, column->ClipRect.Max.x - column->WorkMinX - line_off_curr_x); float clip_height = ImMin(label_size.y, column->ClipRect.Max.x - column->WorkMinX - line_off_curr_x);
ImRect clip_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width, clip_height)); ImRect clip_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width, clip_height));
int vtx_idx_begin = draw_list->_VtxCurrentIdx; int vtx_idx_begin = draw_list->_VtxCurrentIdx;
PushStyleColor(ImGuiCol_Text, request->TextColor);
RenderTextEllipsis(draw_list, clip_r.Min, clip_r.Max, clip_r.Max.x, clip_r.Max.x, label_name, label_name_eol, &label_size); RenderTextEllipsis(draw_list, clip_r.Min, clip_r.Max, clip_r.Max.x, clip_r.Max.x, label_name, label_name_eol, &label_size);
PopStyleColor();
int vtx_idx_end = draw_list->_VtxCurrentIdx; int vtx_idx_end = draw_list->_VtxCurrentIdx;
// Up<>Down alignment
const float available_space = ImMax(clip_width - label_size.x + ImAbs(padding.x * cos_a) * 2.0f - ImAbs(padding.y * sin_a) * 2.0f, 0.0f);
const float vertical_offset = available_space * align.y * (flip_label ? -1.0f : 1.0f);
// Rotate and offset label // Rotate and offset label
ImVec2 pivot_in = ImVec2(window->ClipRect.Min.x, window->ClipRect.Min.y + label_size.y); ImVec2 pivot_in = ImVec2(window->ClipRect.Min.x - vertical_offset, window->ClipRect.Min.y + label_size.y);
ImVec2 pivot_out = ImVec2(column->WorkMinX, row_r.Max.y); ImVec2 pivot_out = ImVec2(column->WorkMinX, row_r.Max.y);
line_off_curr_x += line_off_step_x; line_off_curr_x += flip_label ? -line_off_step_x : line_off_step_x;
pivot_out += unit_right * padding.y; pivot_out += unit_right * padding.y;
if (flip_label) if (flip_label)
pivot_out += unit_right * (clip_width - ImMax(0.0f, clip_width - label_size.x)); pivot_out += unit_right * (clip_width - ImMax(0.0f, clip_width - label_size.x));
pivot_out.x += flip_label ? line_off_curr_x - line_off_step_x : line_off_curr_x; pivot_out.x += flip_label ? line_off_curr_x + line_off_step_x : line_off_curr_x;
ShadeVertsTransformPos(draw_list, vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset ShadeVertsTransformPos(draw_list, vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset
//if (g.IO.KeyShift) { ImDrawList* fg_dl = GetForegroundDrawList(); vtx_idx_begin = fg_dl->_VtxCurrentIdx; fg_dl->AddRect(clip_r.Min, clip_r.Max, IM_COL32(0, 255, 0, 255), 0.0f, 0, 2.0f); ShadeVertsTransformPos(fg_dl, vtx_idx_begin, fg_dl->_VtxCurrentIdx, pivot_in, label_cos_a, label_sin_a, pivot_out); } //if (g.IO.KeyShift) { ImDrawList* fg_dl = GetForegroundDrawList(); vtx_idx_begin = fg_dl->_VtxCurrentIdx; fg_dl->AddRect(clip_r.Min, clip_r.Max, IM_COL32(0, 255, 0, 255), 0.0f, 0, 1.0f); ShadeVertsTransformPos(fg_dl, vtx_idx_begin, fg_dl->_VtxCurrentIdx, pivot_in, label_cos_a, label_sin_a, pivot_out); }
// Register header width
column->ContentMaxXHeadersUsed = column->ContentMaxXHeadersIdeal = column->WorkMinX + ImCeil(line_off_curr_x);
label_name = label_name_eol + 1; label_name = label_name_eol + 1;
} }
} }
@ -3988,7 +4052,7 @@ float ImGui::GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offse
return offset / (columns->OffMaxX - columns->OffMinX); return offset / (columns->OffMaxX - columns->OffMinX);
} }
static const float COLUMNS_HIT_RECT_HALF_WIDTH = 4.0f; static const float COLUMNS_HIT_RECT_HALF_THICKNESS = 4.0f;
static float GetDraggedColumnOffset(ImGuiOldColumns* columns, int column_index) static float GetDraggedColumnOffset(ImGuiOldColumns* columns, int column_index)
{ {
@ -3999,7 +4063,7 @@ static float GetDraggedColumnOffset(ImGuiOldColumns* columns, int column_index)
IM_ASSERT(column_index > 0); // We are not supposed to drag column 0. IM_ASSERT(column_index > 0); // We are not supposed to drag column 0.
IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index)); IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index));
float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + COLUMNS_HIT_RECT_HALF_WIDTH - window->Pos.x; float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + ImTrunc(COLUMNS_HIT_RECT_HALF_THICKNESS * g.CurrentDpiScale) - window->Pos.x;
x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing); x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing);
if ((columns->Flags & ImGuiOldColumnFlags_NoPreserveWidths)) if ((columns->Flags & ImGuiOldColumnFlags_NoPreserveWidths))
x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing); x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing);
@ -4314,7 +4378,7 @@ void ImGui::EndColumns()
ImGuiOldColumnData* column = &columns->Columns[n]; ImGuiOldColumnData* column = &columns->Columns[n];
float x = window->Pos.x + GetColumnOffset(n); float x = window->Pos.x + GetColumnOffset(n);
const ImGuiID column_id = columns->ID + ImGuiID(n); const ImGuiID column_id = columns->ID + ImGuiID(n);
const float column_hit_hw = COLUMNS_HIT_RECT_HALF_WIDTH; const float column_hit_hw = ImTrunc(COLUMNS_HIT_RECT_HALF_THICKNESS * g.CurrentDpiScale);
const ImRect column_hit_rect(ImVec2(x - column_hit_hw, y1), ImVec2(x + column_hit_hw, y2)); const ImRect column_hit_rect(ImVec2(x - column_hit_hw, y1), ImVec2(x + column_hit_hw, y2));
if (!ItemAdd(column_hit_rect, column_id, NULL, ImGuiItemFlags_NoNav)) if (!ItemAdd(column_hit_rect, column_id, NULL, ImGuiItemFlags_NoNav))
continue; continue;

View File

@ -1,4 +1,4 @@
// dear imgui, v1.90.4 // dear imgui, v1.90.7
// (widgets code) // (widgets code)
/* /*
@ -75,6 +75,7 @@ Index of this file:
#pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') #pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_')
#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
#elif defined(__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
@ -122,7 +123,7 @@ static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1);
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// For InputTextEx() // For InputTextEx()
static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source); static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, bool input_source_is_clipboard = false);
static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end); static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);
static ImVec2 InputTextCalcTextSizeW(ImGuiContext* ctx, const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); static ImVec2 InputTextCalcTextSizeW(ImGuiContext* ctx, const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false);
@ -508,7 +509,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
#ifdef IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE
// Alternate registration spot, for when caller didn't use ItemAdd() // Alternate registration spot, for when caller didn't use ItemAdd()
if (id != 0 && g.LastItemData.ID != id) if (g.LastItemData.ID != id)
IMGUI_TEST_ENGINE_ITEM_ADD(id, bb, NULL); IMGUI_TEST_ENGINE_ITEM_ADD(id, bb, NULL);
#endif #endif
@ -536,6 +537,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
const ImGuiID test_owner_id = (flags & ImGuiButtonFlags_NoTestKeyOwner) ? ImGuiKeyOwner_Any : id; const ImGuiID test_owner_id = (flags & ImGuiButtonFlags_NoTestKeyOwner) ? ImGuiKeyOwner_Any : id;
if (hovered) if (hovered)
{ {
IM_ASSERT(id != 0); // Lazily check inside rare path.
// Poll mouse buttons // Poll mouse buttons
// - 'mouse_button_clicked' is generally carried into ActiveIdMouseButton when setting ActiveId. // - 'mouse_button_clicked' is generally carried into ActiveIdMouseButton when setting ActiveId.
// - Technically we only need some values in one code path, but since this is gated by hovered test this is fine. // - Technically we only need some values in one code path, but since this is gated by hovered test this is fine.
@ -544,7 +547,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
for (int button = 0; button < 3; button++) for (int button = 0; button < 3; button++)
if (flags & (ImGuiButtonFlags_MouseButtonLeft << button)) // Handle ImGuiButtonFlags_MouseButtonRight and ImGuiButtonFlags_MouseButtonMiddle here. if (flags & (ImGuiButtonFlags_MouseButtonLeft << button)) // Handle ImGuiButtonFlags_MouseButtonRight and ImGuiButtonFlags_MouseButtonMiddle here.
{ {
if (IsMouseClicked(button, test_owner_id) && mouse_button_clicked == -1) { mouse_button_clicked = button; } if (IsMouseClicked(button, ImGuiInputFlags_None, test_owner_id) && mouse_button_clicked == -1) { mouse_button_clicked = button; }
if (IsMouseReleased(button, test_owner_id) && mouse_button_released == -1) { mouse_button_released = button; } if (IsMouseReleased(button, test_owner_id) && mouse_button_released == -1) { mouse_button_released = button; }
} }
@ -592,7 +595,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
// 'Repeat' mode acts when held regardless of _PressedOn flags (see table above). // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above).
// Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings. // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings.
if (g.ActiveId == id && (item_flags & ImGuiItemFlags_ButtonRepeat)) if (g.ActiveId == id && (item_flags & ImGuiItemFlags_ButtonRepeat))
if (g.IO.MouseDownDuration[g.ActiveIdMouseButton] > 0.0f && IsMouseClicked(g.ActiveIdMouseButton, test_owner_id, ImGuiInputFlags_Repeat)) if (g.IO.MouseDownDuration[g.ActiveIdMouseButton] > 0.0f && IsMouseClicked(g.ActiveIdMouseButton, ImGuiInputFlags_Repeat, test_owner_id))
pressed = true; pressed = true;
} }
@ -1004,7 +1007,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max); scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max);
grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
// Update distance to grab now that we have seeked and saturated // Update distance to grab now that we have seek'ed and saturated
if (seek_absolute) if (seek_absolute)
g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f; g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
} }
@ -1294,15 +1297,34 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over
if (!ItemAdd(bb, 0)) if (!ItemAdd(bb, 0))
return; return;
// Render // Fraction < 0.0f will display an indeterminate progress bar animation
// The value must be animated along with time, so e.g. passing '-1.0f * ImGui::GetTime()' as fraction works.
const bool is_indeterminate = (fraction < 0.0f);
if (!is_indeterminate)
fraction = ImSaturate(fraction); fraction = ImSaturate(fraction);
// Out of courtesy we accept a NaN fraction without crashing
float fill_n0 = 0.0f;
float fill_n1 = (fraction == fraction) ? fraction : 0.0f;
if (is_indeterminate)
{
const float fill_width_n = 0.2f;
fill_n0 = ImFmod(-fraction, 1.0f) * (1.0f + fill_width_n) - fill_width_n;
fill_n1 = ImSaturate(fill_n0 + fill_width_n);
fill_n0 = ImSaturate(fill_n0);
}
// Render
RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize)); bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize));
const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y); RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), fill_n0, fill_n1, style.FrameRounding);
RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding);
// Default displaying the fraction as percentage string, but user can override it // Default displaying the fraction as percentage string, but user can override it
// Don't display text for indeterminate bars by default
char overlay_buf[32]; char overlay_buf[32];
if (!is_indeterminate || overlay != NULL)
{
if (!overlay) if (!overlay)
{ {
ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction * 100 + 0.01f); ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction * 100 + 0.01f);
@ -1311,7 +1333,11 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over
ImVec2 overlay_size = CalcTextSize(overlay, NULL); ImVec2 overlay_size = CalcTextSize(overlay, NULL);
if (overlay_size.x > 0.0f) if (overlay_size.x > 0.0f)
RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f, 0.5f), &bb); {
float text_x = is_indeterminate ? (bb.Min.x + bb.Max.x - overlay_size.x) * 0.5f : ImLerp(bb.Min.x, bb.Max.x, fill_n1) + style.ItemSpacing.x;
RenderTextClipped(ImVec2(ImClamp(text_x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f, 0.5f), &bb);
}
}
} }
void ImGui::Bullet() void ImGui::Bullet()
@ -2289,7 +2315,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0; const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
const bool tweak_slow = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakSlow : ImGuiKey_NavKeyboardTweakSlow); const bool tweak_slow = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakSlow : ImGuiKey_NavKeyboardTweakSlow);
const bool tweak_fast = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakFast : ImGuiKey_NavKeyboardTweakFast); const bool tweak_fast = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakFast : ImGuiKey_NavKeyboardTweakFast);
const float tweak_factor = tweak_slow ? 1.0f / 1.0f : tweak_fast ? 10.0f : 1.0f; const float tweak_factor = tweak_slow ? 1.0f / 10.0f : tweak_fast ? 10.0f : 1.0f;
adjust_delta = GetNavTweakPressedAmount(axis) * tweak_factor; adjust_delta = GetNavTweakPressedAmount(axis) * tweak_factor;
v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision));
} }
@ -2448,7 +2474,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
if (!temp_input_is_active) if (!temp_input_is_active)
{ {
// Tabbing or CTRL-clicking on Drag turns it into an InputText // Tabbing or CTRL-clicking on Drag turns it into an InputText
const bool clicked = hovered && IsMouseClicked(0, id); const bool clicked = hovered && IsMouseClicked(0, ImGuiInputFlags_None, id);
const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2 && TestKeyOwner(ImGuiKey_MouseLeft, id)); const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2 && TestKeyOwner(ImGuiKey_MouseLeft, id));
const bool make_active = (clicked || double_clicked || g.NavActivateId == id); const bool make_active = (clicked || double_clicked || g.NavActivateId == id);
if (make_active && (clicked || double_clicked)) if (make_active && (clicked || double_clicked))
@ -3039,7 +3065,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
if (!temp_input_is_active) if (!temp_input_is_active)
{ {
// Tabbing or CTRL-clicking on Slider turns it into an input box // Tabbing or CTRL-clicking on Slider turns it into an input box
const bool clicked = hovered && IsMouseClicked(0, id); const bool clicked = hovered && IsMouseClicked(0, ImGuiInputFlags_None, id);
const bool make_active = (clicked || g.NavActivateId == id); const bool make_active = (clicked || g.NavActivateId == id);
if (make_active && clicked) if (make_active && clicked)
SetKeyOwner(ImGuiKey_MouseLeft, id); SetKeyOwner(ImGuiKey_MouseLeft, id);
@ -3201,7 +3227,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
format = DataTypeGetInfo(data_type)->PrintFmt; format = DataTypeGetInfo(data_type)->PrintFmt;
const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags); const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags);
const bool clicked = hovered && IsMouseClicked(0, id); const bool clicked = hovered && IsMouseClicked(0, ImGuiInputFlags_None, id);
if (clicked || g.NavActivateId == id) if (clicked || g.NavActivateId == id)
{ {
if (clicked) if (clicked)
@ -3432,7 +3458,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format); DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format);
ImStrTrimBlanks(data_buf); ImStrTrimBlanks(data_buf);
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
bool value_changed = false; bool value_changed = false;
if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags)) if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags))
@ -3477,6 +3503,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format); DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string. flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
flags |= (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
bool value_changed = false; bool value_changed = false;
if (p_step == NULL) if (p_step == NULL)
@ -3922,9 +3949,8 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
} }
// Return false to discard a character. // Return false to discard a character.
static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source) static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, bool input_source_is_clipboard)
{ {
IM_ASSERT(input_source == ImGuiInputSource_Keyboard || input_source == ImGuiInputSource_Clipboard);
unsigned int c = *p_char; unsigned int c = *p_char;
// Filter non-printable (NB: isprint is unreliable! see #2467) // Filter non-printable (NB: isprint is unreliable! see #2467)
@ -3939,7 +3965,7 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im
apply_named_filters = false; // Override named filters below so newline and tabs can still be inserted. apply_named_filters = false; // Override named filters below so newline and tabs can still be inserted.
} }
if (input_source != ImGuiInputSource_Clipboard) if (input_source_is_clipboard == false)
{ {
// We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817) // We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817)
if (c == 127) if (c == 127)
@ -3955,7 +3981,7 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im
return false; return false;
// Generic named filters // Generic named filters
if (apply_named_filters && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific))) if (apply_named_filters && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint)))
{ {
// The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf to use e.g. ',' instead of '.'. // The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf to use e.g. ',' instead of '.'.
// The standard mandate that programs starts in the "C" locale where the decimal point is '.'. // The standard mandate that programs starts in the "C" locale where the decimal point is '.'.
@ -3965,7 +3991,7 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im
// Users of non-default decimal point (in particular ',') may be affected by word-selection logic (is_word_boundary_from_right/is_word_boundary_from_left) functions. // Users of non-default decimal point (in particular ',') may be affected by word-selection logic (is_word_boundary_from_right/is_word_boundary_from_left) functions.
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
const unsigned c_decimal_point = (unsigned int)g.IO.PlatformLocaleDecimalPoint; const unsigned c_decimal_point = (unsigned int)g.IO.PlatformLocaleDecimalPoint;
if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific)) if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint))
if (c == '.' || c == ',') if (c == '.' || c == ',')
c = c_decimal_point; c = c_decimal_point;
@ -4289,6 +4315,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
SetKeyOwner(ImGuiKey_PageUp, id); SetKeyOwner(ImGuiKey_PageUp, id);
SetKeyOwner(ImGuiKey_PageDown, id); SetKeyOwner(ImGuiKey_PageDown, id);
} }
// FIXME: May be a problem to always steal Alt on OSX, would ideally still allow an uninterrupted Alt down-up to toggle menu
if (is_osx) if (is_osx)
SetKeyOwner(ImGuiMod_Alt, id); SetKeyOwner(ImGuiMod_Alt, id);
} }
@ -4421,15 +4448,15 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// (For Tab and Enter: Win32/SFML/Allegro are sending both keys and chars, GLFW and SDL are only sending keys. For Space they all send all threes) // (For Tab and Enter: Win32/SFML/Allegro are sending both keys and chars, GLFW and SDL are only sending keys. For Space they all send all threes)
if ((flags & ImGuiInputTextFlags_AllowTabInput) && !is_readonly) if ((flags & ImGuiInputTextFlags_AllowTabInput) && !is_readonly)
{ {
if (Shortcut(ImGuiKey_Tab, id, ImGuiInputFlags_Repeat)) if (Shortcut(ImGuiKey_Tab, ImGuiInputFlags_Repeat, id))
{ {
unsigned int c = '\t'; // Insert TAB unsigned int c = '\t'; // Insert TAB
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
state->OnKeyPressed((int)c); state->OnKeyPressed((int)c);
} }
// FIXME: Implement Shift+Tab // FIXME: Implement Shift+Tab
/* /*
if (Shortcut(ImGuiKey_Tab | ImGuiMod_Shift, id, ImGuiInputFlags_Repeat)) if (Shortcut(ImGuiKey_Tab | ImGuiMod_Shift, ImGuiInputFlags_Repeat, id))
{ {
} }
*/ */
@ -4437,7 +4464,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Process regular text input (before we check for Return because using some IME will effectively send a Return?) // Process regular text input (before we check for Return because using some IME will effectively send a Return?)
// We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters. // We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters.
const bool ignore_char_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper); const bool ignore_char_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeyCtrl);
if (io.InputQueueCharacters.Size > 0) if (io.InputQueueCharacters.Size > 0)
{ {
if (!ignore_char_inputs && !is_readonly && !input_requested_by_nav) if (!ignore_char_inputs && !is_readonly && !input_requested_by_nav)
@ -4447,7 +4474,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
unsigned int c = (unsigned int)io.InputQueueCharacters[n]; unsigned int c = (unsigned int)io.InputQueueCharacters[n];
if (c == '\t') // Skip Tab, see above. if (c == '\t') // Skip Tab, see above.
continue; continue;
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
state->OnKeyPressed((int)c); state->OnKeyPressed((int)c);
} }
@ -4467,25 +4494,26 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);
const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl
const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End const bool is_startend_key_down = is_osx && io.KeyCtrl && !io.KeySuper && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End
// Using Shortcut() with ImGuiInputFlags_RouteFocused (default policy) to allow routing operations for other code (e.g. calling window trying to use CTRL+A and CTRL+B: formet would be handled by InputText) // Using Shortcut() with ImGuiInputFlags_RouteFocused (default policy) to allow routing operations for other code (e.g. calling window trying to use CTRL+A and CTRL+B: formet would be handled by InputText)
// Otherwise we could simply assume that we own the keys as we are active. // Otherwise we could simply assume that we own the keys as we are active.
const ImGuiInputFlags f_repeat = ImGuiInputFlags_Repeat; const ImGuiInputFlags f_repeat = ImGuiInputFlags_Repeat;
const bool is_cut = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_X, id, f_repeat) || Shortcut(ImGuiMod_Shift | ImGuiKey_Delete, id, f_repeat)) && !is_readonly && !is_password && (!is_multiline || state->HasSelection()); const bool is_cut = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_X, f_repeat, id) || Shortcut(ImGuiMod_Shift | ImGuiKey_Delete, f_repeat, id)) && !is_readonly && !is_password && (!is_multiline || state->HasSelection());
const bool is_copy = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_C, id) || Shortcut(ImGuiMod_Ctrl | ImGuiKey_Insert, id)) && !is_password && (!is_multiline || state->HasSelection()); const bool is_copy = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, 0, id) || Shortcut(ImGuiMod_Ctrl | ImGuiKey_Insert, 0, id)) && !is_password && (!is_multiline || state->HasSelection());
const bool is_paste = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_V, id, f_repeat) || Shortcut(ImGuiMod_Shift | ImGuiKey_Insert, id, f_repeat)) && !is_readonly; const bool is_paste = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_V, f_repeat, id) || Shortcut(ImGuiMod_Shift | ImGuiKey_Insert, f_repeat, id)) && !is_readonly;
const bool is_undo = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_Z, id, f_repeat)) && !is_readonly && is_undoable; const bool is_undo = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_Z, f_repeat, id)) && !is_readonly && is_undoable;
const bool is_redo = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_Y, id, f_repeat) || (is_osx && Shortcut(ImGuiMod_Shortcut | ImGuiMod_Shift | ImGuiKey_Z, id, f_repeat))) && !is_readonly && is_undoable; const bool is_redo = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_Y, f_repeat, id) || (is_osx && Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Z, f_repeat, id))) && !is_readonly && is_undoable;
const bool is_select_all = Shortcut(ImGuiMod_Shortcut | ImGuiKey_A, id); const bool is_select_all = Shortcut(ImGuiMod_Ctrl | ImGuiKey_A, 0, id);
// We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful. // We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful.
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
const bool is_enter_pressed = IsKeyPressed(ImGuiKey_Enter, true) || IsKeyPressed(ImGuiKey_KeypadEnter, true); const bool is_enter_pressed = IsKeyPressed(ImGuiKey_Enter, true) || IsKeyPressed(ImGuiKey_KeypadEnter, true);
const bool is_gamepad_validate = nav_gamepad_active && (IsKeyPressed(ImGuiKey_NavGamepadActivate, false) || IsKeyPressed(ImGuiKey_NavGamepadInput, false)); const bool is_gamepad_validate = nav_gamepad_active && (IsKeyPressed(ImGuiKey_NavGamepadActivate, false) || IsKeyPressed(ImGuiKey_NavGamepadInput, false));
const bool is_cancel = Shortcut(ImGuiKey_Escape, id, f_repeat) || (nav_gamepad_active && Shortcut(ImGuiKey_NavGamepadCancel, id, f_repeat)); const bool is_cancel = Shortcut(ImGuiKey_Escape, f_repeat, id) || (nav_gamepad_active && Shortcut(ImGuiKey_NavGamepadCancel, f_repeat, id));
// FIXME: Should use more Shortcut() and reduce IsKeyPressed()+SetKeyOwner(), but requires modifiers combination to be taken account of. // FIXME: Should use more Shortcut() and reduce IsKeyPressed()+SetKeyOwner(), but requires modifiers combination to be taken account of.
// FIXME-OSX: Missing support for Alt(option)+Right/Left = go to end of line, or next line if already in end of line.
if (IsKeyPressed(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } if (IsKeyPressed(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
else if (IsKeyPressed(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } else if (IsKeyPressed(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
else if (IsKeyPressed(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); } else if (IsKeyPressed(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); }
@ -4510,7 +4538,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{ {
if (is_wordmove_key_down) if (is_wordmove_key_down)
state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT); state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT);
else if (is_osx && io.KeySuper && !io.KeyAlt && !io.KeyCtrl) else if (is_osx && io.KeyCtrl && !io.KeyAlt && !io.KeySuper)
state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT); state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT);
} }
state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
@ -4530,7 +4558,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
else if (!is_readonly) else if (!is_readonly)
{ {
unsigned int c = '\n'; // Insert new line unsigned int c = '\n'; // Insert new line
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
state->OnKeyPressed((int)c); state->OnKeyPressed((int)c);
} }
} }
@ -4597,7 +4625,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{ {
unsigned int c; unsigned int c;
s += ImTextCharFromUtf8(&c, s, NULL); s += ImTextCharFromUtf8(&c, s, NULL);
if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Clipboard)) if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, true))
continue; continue;
clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c; clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c;
} }
@ -4680,7 +4708,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment. // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment.
ImGuiInputTextFlags event_flag = 0; ImGuiInputTextFlags event_flag = 0;
ImGuiKey event_key = ImGuiKey_None; ImGuiKey event_key = ImGuiKey_None;
if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && Shortcut(ImGuiKey_Tab, id)) if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && Shortcut(ImGuiKey_Tab, 0, id))
{ {
event_flag = ImGuiInputTextFlags_CallbackCompletion; event_flag = ImGuiInputTextFlags_CallbackCompletion;
event_key = ImGuiKey_Tab; event_key = ImGuiKey_Tab;
@ -6186,13 +6214,17 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
label_end = FindRenderedTextEnd(label); label_end = FindRenderedTextEnd(label);
const ImVec2 label_size = CalcTextSize(label, label_end, false); const ImVec2 label_size = CalcTextSize(label, label_end, false);
const float text_offset_x = g.FontSize + (display_frame ? padding.x * 3 : padding.x * 2); // Collapsing arrow width + Spacing
const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
const float text_width = g.FontSize + label_size.x + padding.x * 2; // Include collapsing arrow
// We vertically grow up to current line height up the typical widget height. // We vertically grow up to current line height up the typical widget height.
const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y * 2), label_size.y + padding.y * 2); const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y * 2), label_size.y + padding.y * 2);
const bool span_all_columns = (flags & ImGuiTreeNodeFlags_SpanAllColumns) != 0 && (g.CurrentTable != NULL); const bool span_all_columns = (flags & ImGuiTreeNodeFlags_SpanAllColumns) != 0 && (g.CurrentTable != NULL);
ImRect frame_bb; ImRect frame_bb;
frame_bb.Min.x = span_all_columns ? window->ParentWorkRect.Min.x : (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x; frame_bb.Min.x = span_all_columns ? window->ParentWorkRect.Min.x : (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x;
frame_bb.Min.y = window->DC.CursorPos.y; frame_bb.Min.y = window->DC.CursorPos.y;
frame_bb.Max.x = span_all_columns ? window->ParentWorkRect.Max.x : window->WorkRect.Max.x; frame_bb.Max.x = span_all_columns ? window->ParentWorkRect.Max.x : (flags & ImGuiTreeNodeFlags_SpanTextWidth) ? window->DC.CursorPos.x + text_width + padding.x : window->WorkRect.Max.x;
frame_bb.Max.y = window->DC.CursorPos.y + frame_height; frame_bb.Max.y = window->DC.CursorPos.y + frame_height;
if (display_frame) if (display_frame)
{ {
@ -6202,16 +6234,13 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
frame_bb.Max.x += IM_TRUNC(window->WindowPadding.x * 0.5f); frame_bb.Max.x += IM_TRUNC(window->WindowPadding.x * 0.5f);
} }
const float text_offset_x = g.FontSize + (display_frame ? padding.x * 3 : padding.x * 2); // Collapsing arrow width + Spacing
const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x * 2 : 0.0f); // Include collapsing
ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y); ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y);
ItemSize(ImVec2(text_width, frame_height), padding.y); ItemSize(ImVec2(text_width, frame_height), padding.y);
// For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
ImRect interact_bb = frame_bb; ImRect interact_bb = frame_bb;
if (!display_frame && (flags & (ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_SpanAllColumns)) == 0) if ((flags & (ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_SpanTextWidth | ImGuiTreeNodeFlags_SpanAllColumns)) == 0)
interact_bb.Max.x = frame_bb.Min.x + text_width + style.ItemSpacing.x * 2.0f; interact_bb.Max.x = frame_bb.Min.x + text_width + (label_size.x > 0.0f ? style.ItemSpacing.x * 2.0f : 0.0f);
// Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable..
const float backup_clip_rect_min_x = window->ClipRect.Min.x; const float backup_clip_rect_min_x = window->ClipRect.Min.x;
@ -6747,7 +6776,7 @@ ImGuiTypingSelectRequest* ImGui::GetTypingSelectRequest(ImGuiTypingSelectFlags f
g.IO.InputQueueCharacters.resize(0); g.IO.InputQueueCharacters.resize(0);
// Handle backspace // Handle backspace
if ((flags & ImGuiTypingSelectFlags_AllowBackspace) && IsKeyPressed(ImGuiKey_Backspace, 0, ImGuiInputFlags_Repeat)) if ((flags & ImGuiTypingSelectFlags_AllowBackspace) && IsKeyPressed(ImGuiKey_Backspace, ImGuiInputFlags_Repeat))
{ {
char* p = (char*)(void*)ImTextFindPreviousUtf8Codepoint(data->SearchBuffer, data->SearchBuffer + buffer_len); char* p = (char*)(void*)ImTextFindPreviousUtf8Codepoint(data->SearchBuffer, data->SearchBuffer + buffer_len);
*p = 0; *p = 0;
@ -6935,6 +6964,7 @@ bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
ImVec2 label_pos = ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y); ImVec2 label_pos = ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y);
RenderText(label_pos, label); RenderText(label_pos, label);
window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, label_pos + label_size); window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, label_pos + label_size);
AlignTextToFramePadding();
} }
BeginChild(id, frame_bb.GetSize(), ImGuiChildFlags_FrameStyle); BeginChild(id, frame_bb.GetSize(), ImGuiChildFlags_FrameStyle);
@ -7281,7 +7311,7 @@ bool ImGui::BeginMenuBar()
// We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect. // We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect.
// We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy. // We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy.
ImRect bar_rect = window->MenuBarRect(); ImRect bar_rect = window->MenuBarRect();
ImRect clip_rect(IM_ROUND(bar_rect.Min.x + window->WindowBorderSize), IM_ROUND(bar_rect.Min.y + window->WindowBorderSize), IM_ROUND(ImMax(bar_rect.Min.x, bar_rect.Max.x - ImMax(window->WindowRounding, window->WindowBorderSize))), IM_ROUND(bar_rect.Max.y)); ImRect clip_rect(ImFloor(bar_rect.Min.x + window->WindowBorderSize), ImFloor(bar_rect.Min.y + window->WindowBorderSize), ImFloor(ImMax(bar_rect.Min.x, bar_rect.Max.x - ImMax(window->WindowRounding, window->WindowBorderSize))), ImFloor(bar_rect.Max.y));
clip_rect.ClipWith(window->OuterRectClipped); clip_rect.ClipWith(window->OuterRectClipped);
PushClipRect(clip_rect.Min, clip_rect.Max, false); PushClipRect(clip_rect.Min, clip_rect.Max, false);

View File

@ -41,7 +41,7 @@
// 1.13 (2019-02-07) fix bug in undo size management // 1.13 (2019-02-07) fix bug in undo size management
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash // 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield // 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual // 1.10 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
// 1.9 (2016-08-27) customizable move-by-word // 1.9 (2016-08-27) customizable move-by-word
// 1.8 (2016-04-02) better keyboard handling when mouse button is down // 1.8 (2016-04-02) better keyboard handling when mouse button is down
// 1.7 (2015-09-13) change y range handling in case baseline is non-0 // 1.7 (2015-09-13) change y range handling in case baseline is non-0

View File

@ -656,7 +656,7 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
// If skip != 0, this tells stb_truetype to skip any codepoints for which // If skip != 0, this tells stb_truetype to skip any codepoints for which
// there is no corresponding glyph. If skip=0, which is the default, then // there is no corresponding glyph. If skip=0, which is the default, then
// codepoints without a glyph recived the font's "missing character" glyph, // codepoints without a glyph received the font's "missing character" glyph,
// typically an empty box by convention. // typically an empty box by convention.
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above

View File

@ -11,7 +11,7 @@
// 2023/01/04: fixed a packing issue which in some occurrences would prevent large amount of glyphs from being packed correctly. // 2023/01/04: fixed a packing issue which in some occurrences would prevent large amount of glyphs from being packed correctly.
// 2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL. // 2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL.
// 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs. // 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs.
// 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a prefered texture format. // 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a preferred texture format.
// 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+). // 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+).
// 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'. renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas(). // 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'. renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas().
// 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails. // 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails.

View File

@ -10,9 +10,8 @@
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Issues: // Issues:
// [ ] Platform: Multi-viewport support: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). // [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@ -91,11 +90,15 @@
#ifdef _WIN32 #ifdef _WIN32
#undef APIENTRY #undef APIENTRY
#ifndef GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WIN32 #define GLFW_EXPOSE_NATIVE_WIN32
#endif
#include <GLFW/glfw3native.h> // for glfwGetWin32Window() #include <GLFW/glfw3native.h> // for glfwGetWin32Window()
#endif #endif
#ifdef __APPLE__ #ifdef __APPLE__
#ifndef GLFW_EXPOSE_NATIVE_COCOA
#define GLFW_EXPOSE_NATIVE_COCOA #define GLFW_EXPOSE_NATIVE_COCOA
#endif
#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow() #include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
#endif #endif
@ -569,6 +572,7 @@ void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows)
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api) static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
//printf("GLFW_VERSION: %d.%d.%d (%d)", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED); //printf("GLFW_VERSION: %d.%d.%d (%d)", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED);
@ -899,7 +903,7 @@ void ImGui_ImplGlfw_NewFrame()
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplGlfw_InitForXXX()?"); IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplGlfw_InitForXXX()?");
// Setup display size (every frame to accommodate for window resizing) // Setup display size (every frame to accommodate for window resizing)
int w, h; int w, h;
@ -952,7 +956,7 @@ void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_sel
{ {
IM_ASSERT(canvas_selector != nullptr); IM_ASSERT(canvas_selector != nullptr);
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplGlfw_InitForXXX()?"); IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplGlfw_InitForXXX()?");
bd->CanvasSelector = canvas_selector; bd->CanvasSelector = canvas_selector;
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, bd, false, ImGui_ImplGlfw_OnCanvasSizeChange); emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, bd, false, ImGui_ImplGlfw_OnCanvasSizeChange);

View File

@ -8,11 +8,10 @@
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only). // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// Issues: // Issues:
// [ ] Platform: Multi-viewport support: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). // [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.

View File

@ -23,7 +23,9 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-05-07: OpenGL: Update loader for Linux to support EGL/GLVND. (#7562)
// 2024-04-16: OpenGL: Detect ES3 contexts on desktop based on version string, to e.g. avoid calling glPolygonMode() on them. (#7447)
// 2024-01-09: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" and variants, fixing regression on distros missing a symlink. // 2024-01-09: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" and variants, fixing regression on distros missing a symlink.
// 2023-11-08: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" instead of "libGL.so.1", accommodating for NetBSD systems having only "libGL.so.3" available. (#6983) // 2023-11-08: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" instead of "libGL.so.1", accommodating for NetBSD systems having only "libGL.so.3" available. (#6983)
// 2023-10-05: OpenGL: Rename symbols in our internal loader so that LTO compilation with another copy of gl3w is possible. (#6875, #6668, #4445) // 2023-10-05: OpenGL: Rename symbols in our internal loader so that LTO compilation with another copy of gl3w is possible. (#6875, #6668, #4445)
@ -178,9 +180,21 @@
#define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES #define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES
#endif #endif
// Desktop GL 2.0+ has glPolygonMode() which GL ES and WebGL don't have. // Desktop GL 2.0+ has extension and glPolygonMode() which GL ES and WebGL don't have..
#ifdef GL_POLYGON_MODE // A desktop ES context can technically compile fine with our loader, so we also perform a runtime checks
#define IMGUI_IMPL_HAS_POLYGON_MODE #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
#define IMGUI_IMPL_OPENGL_HAS_EXTENSIONS // has glGetIntegerv(GL_NUM_EXTENSIONS)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE // may have glPolygonMode()
#endif
// Desktop GL 2.1+ and GL ES 3.0+ have glBindBuffer() with GL_PIXEL_UNPACK_BUFFER target.
#if !defined(IMGUI_IMPL_OPENGL_ES2)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK
#endif
// Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
#endif #endif
// Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have. // Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have.
@ -193,16 +207,6 @@
#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER #define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
#endif #endif
// Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
#endif
// Desktop GL use extension detection
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
#endif
// [Debugging] // [Debugging]
//#define IMGUI_IMPL_OPENGL_DEBUG //#define IMGUI_IMPL_OPENGL_DEBUG
#ifdef IMGUI_IMPL_OPENGL_DEBUG #ifdef IMGUI_IMPL_OPENGL_DEBUG
@ -231,6 +235,7 @@ struct ImGui_ImplOpenGL3_Data
unsigned int VboHandle, ElementsHandle; unsigned int VboHandle, ElementsHandle;
GLsizeiptr VertexBufferSize; GLsizeiptr VertexBufferSize;
GLsizeiptr IndexBufferSize; GLsizeiptr IndexBufferSize;
bool HasPolygonMode;
bool HasClipOrigin; bool HasClipOrigin;
bool UseBufferSubData; bool UseBufferSubData;
@ -276,6 +281,7 @@ struct ImGui_ImplOpenGL3_VtxAttribState
bool ImGui_ImplOpenGL3_Init(const char* glsl_version) bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Initialize our loader // Initialize our loader
@ -299,16 +305,13 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
bd->GlProfileIsES2 = true; bd->GlProfileIsES2 = true;
#else #else
// Desktop or GLES 3 // Desktop or GLES 3
const char* gl_version_str = (const char*)glGetString(GL_VERSION);
GLint major = 0; GLint major = 0;
GLint minor = 0; GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor); glGetIntegerv(GL_MINOR_VERSION, &minor);
if (major == 0 && minor == 0) if (major == 0 && minor == 0)
{ sscanf(gl_version_str, "%d.%d", &major, &minor); // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
// Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
const char* gl_version = (const char*)glGetString(GL_VERSION);
sscanf(gl_version, "%d.%d", &major, &minor);
}
bd->GlVersion = (GLuint)(major * 100 + minor * 10); bd->GlVersion = (GLuint)(major * 100 + minor * 10);
#if defined(GL_CONTEXT_PROFILE_MASK) #if defined(GL_CONTEXT_PROFILE_MASK)
if (bd->GlVersion >= 320) if (bd->GlVersion >= 320)
@ -318,6 +321,9 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
#if defined(IMGUI_IMPL_OPENGL_ES3) #if defined(IMGUI_IMPL_OPENGL_ES3)
bd->GlProfileIsES3 = true; bd->GlProfileIsES3 = true;
#else
if (strncmp(gl_version_str, "OpenGL ES 3", 11) == 0)
bd->GlProfileIsES3 = true;
#endif #endif
bd->UseBufferSubData = false; bd->UseBufferSubData = false;
@ -332,7 +338,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
#endif #endif
#ifdef IMGUI_IMPL_OPENGL_DEBUG #ifdef IMGUI_IMPL_OPENGL_DEBUG
printf("GlVersion = %d\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG] printf("GlVersion = %d, \"%s\"\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, gl_version_str, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
#endif #endif
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
@ -365,8 +371,11 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
// Detect extensions we support // Detect extensions we support
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
bd->HasPolygonMode = (!bd->GlProfileIsES2 && !bd->GlProfileIsES3);
#endif
bd->HasClipOrigin = (bd->GlVersion >= 450); bd->HasClipOrigin = (bd->GlVersion >= 450);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS #ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS
GLint num_extensions = 0; GLint num_extensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
for (GLint i = 0; i < num_extensions; i++) for (GLint i = 0; i < num_extensions; i++)
@ -400,7 +409,7 @@ void ImGui_ImplOpenGL3_Shutdown()
void ImGui_ImplOpenGL3_NewFrame() void ImGui_ImplOpenGL3_NewFrame()
{ {
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplOpenGL3_Init()?"); IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL3_Init()?");
if (!bd->ShaderHandle) if (!bd->ShaderHandle)
ImGui_ImplOpenGL3_CreateDeviceObjects(); ImGui_ImplOpenGL3_CreateDeviceObjects();
@ -422,7 +431,8 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
if (bd->GlVersion >= 310) if (bd->GlVersion >= 310)
glDisable(GL_PRIMITIVE_RESTART); glDisable(GL_PRIMITIVE_RESTART);
#endif #endif
#ifdef IMGUI_IMPL_HAS_POLYGON_MODE #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
if (bd->HasPolygonMode)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif #endif
@ -511,8 +521,8 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object); GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object);
#endif #endif
#ifdef IMGUI_IMPL_HAS_POLYGON_MODE #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_polygon_mode[2]; if (bd->HasPolygonMode) { glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); }
#endif #endif
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
@ -650,18 +660,10 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }
#endif #endif
#ifdef IMGUI_IMPL_HAS_POLYGON_MODE #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
// Desktop OpenGL 3.0 and OpenGL 3.1 had separate polygon draw modes for front-facing and back-facing faces of polygons // Desktop OpenGL 3.0 and OpenGL 3.1 had separate polygon draw modes for front-facing and back-facing faces of polygons
if (bd->GlVersion <= 310 || bd->GlProfileIsCompat) if (bd->HasPolygonMode) { if (bd->GlVersion <= 310 || bd->GlProfileIsCompat) { glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); } else { glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); } }
{ #endif // IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]);
glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
}
else
{
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
}
#endif // IMGUI_IMPL_HAS_POLYGON_MODE
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); 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]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
@ -758,6 +760,10 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
GLint last_texture, last_array_buffer; GLint last_texture, last_array_buffer;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK
GLint last_pixel_unpack_buffer = 0;
if (bd->GlVersion >= 210) { glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &last_pixel_unpack_buffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); }
#endif
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GLint last_vertex_array; GLint last_vertex_array;
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
@ -931,6 +937,9 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
// Restore modified GL state // Restore modified GL state
glBindTexture(GL_TEXTURE_2D, last_texture); glBindTexture(GL_TEXTURE_2D, last_texture);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK
if (bd->GlVersion >= 210) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, last_pixel_unpack_buffer); }
#endif
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
glBindVertexArray(last_vertex_array); glBindVertexArray(last_vertex_array);
#endif #endif

View File

@ -42,9 +42,9 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture();
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
// Specific OpenGL ES versions // Configuration flags to add in your imconfig file:
//#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten //#define IMGUI_IMPL_OPENGL_ES2 // Enable ES 2 (Auto-detected on Emscripten)
//#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android //#define IMGUI_IMPL_OPENGL_ES3 // Enable ES 3 (Auto-detected on iOS/Android)
// You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. // You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line.
#if !defined(IMGUI_IMPL_OPENGL_ES2) \ #if !defined(IMGUI_IMPL_OPENGL_ES2) \

View File

@ -355,6 +355,10 @@ GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean
GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
#endif #endif
#endif /* GL_VERSION_2_0 */ #endif /* GL_VERSION_2_0 */
#ifndef GL_VERSION_2_1
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
#endif /* GL_VERSION_2_1 */
#ifndef GL_VERSION_3_0 #ifndef GL_VERSION_3_0
typedef khronos_uint16_t GLhalf; typedef khronos_uint16_t GLhalf;
#define GL_MAJOR_VERSION 0x821B #define GL_MAJOR_VERSION 0x821B
@ -672,31 +676,123 @@ static GL3WglProc get_proc(const char *proc)
#else #else
#include <dlfcn.h> #include <dlfcn.h>
static void *libgl; static void* libgl; // OpenGL library
static GL3WglProc (*glx_get_proc_address)(const GLubyte *); static void* libglx; // GLX library
static void* libegl; // EGL library
static GL3WGetProcAddressProc gl_get_proc_address;
static int open_libgl(void) static void close_libgl(void)
{ {
if (libgl) {
dlclose(libgl);
libgl = NULL;
}
if (libegl) {
dlclose(libegl);
libegl = NULL;
}
if (libglx) {
dlclose(libglx);
libglx = NULL;
}
}
static int is_library_loaded(const char* name, void** lib)
{
*lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
return *lib != NULL;
}
static int open_libs(void)
{
// On Linux we have two APIs to get process addresses: EGL and GLX.
// EGL is supported under both X11 and Wayland, whereas GLX is X11-specific.
libgl = NULL;
libegl = NULL;
libglx = NULL;
// First check what's already loaded, the windowing library might have
// already loaded either EGL or GLX and we want to use the same one.
if (is_library_loaded("libEGL.so.1", &libegl) ||
is_library_loaded("libGLX.so.0", &libglx)) {
libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
if (libgl)
return GL3W_OK;
else
close_libgl();
}
if (is_library_loaded("libGL.so", &libgl))
return GL3W_OK;
if (is_library_loaded("libGL.so.1", &libgl))
return GL3W_OK;
if (is_library_loaded("libGL.so.3", &libgl))
return GL3W_OK;
// Neither is already loaded, so we have to load one. Try EGL first
// because it is supported under both X11 and Wayland.
// Load OpenGL + EGL
libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
libegl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL);
if (libgl && libegl)
return GL3W_OK;
else
close_libgl();
// Fall back to legacy libGL, which includes GLX
// While most systems use libGL.so.1, NetBSD seems to use that libGL.so.3. See https://github.com/ocornut/imgui/issues/6983 // While most systems use libGL.so.1, NetBSD seems to use that libGL.so.3. See https://github.com/ocornut/imgui/issues/6983
libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL); libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
if (!libgl) if (!libgl)
libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL); libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
if (!libgl) if (!libgl)
libgl = dlopen("libGL.so.3", RTLD_LAZY | RTLD_LOCAL); libgl = dlopen("libGL.so.3", RTLD_LAZY | RTLD_LOCAL);
if (!libgl)
if (libgl)
return GL3W_OK;
return GL3W_ERROR_LIBRARY_OPEN; return GL3W_ERROR_LIBRARY_OPEN;
*(void **)(&glx_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB"); }
static int open_libgl(void)
{
int res = open_libs();
if (res)
return res;
if (libegl)
*(void**)(&gl_get_proc_address) = dlsym(libegl, "eglGetProcAddress");
else if (libglx)
*(void**)(&gl_get_proc_address) = dlsym(libglx, "glXGetProcAddressARB");
else
*(void**)(&gl_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB");
if (!gl_get_proc_address) {
close_libgl();
return GL3W_ERROR_LIBRARY_OPEN;
}
return GL3W_OK; return GL3W_OK;
} }
static void close_libgl(void) { dlclose(libgl); } static GL3WglProc get_proc(const char* proc)
static GL3WglProc get_proc(const char *proc)
{ {
GL3WglProc res; GL3WglProc res = NULL;
res = glx_get_proc_address((const GLubyte *)proc);
// Before EGL version 1.5, eglGetProcAddress doesn't support querying core
// functions and may return a dummy function if we try, so try to load the
// function from the GL library directly first.
if (libegl)
*(void**)(&res) = dlsym(libgl, proc);
if (!res) if (!res)
*(void **)(&res) = dlsym(libgl, proc); res = gl_get_proc_address(proc);
if (!libegl && !res)
*(void**)(&res) = dlsym(libgl, proc);
return res; return res;
} }
#endif #endif