chore: update to zgui v1.89.6

This commit is contained in:
Rekai Nyangadzayi Musuka 2023-06-19 10:44:38 -05:00
parent 666b7201ff
commit fc608f4798
17 changed files with 1352 additions and 871 deletions

View File

@ -1,4 +1,4 @@
# zgui v0.9.6 - dear imgui (1.89.4) bindings # zgui v1.89.6 - dear imgui bindings
Easy to use, hand-crafted API with default arguments, named parameters and Zig style text formatting. For a test application please see [here](https://github.com/michal-z/zig-gamedev/tree/main/samples/gui_test_wgpu). Easy to use, hand-crafted API with default arguments, named parameters and Zig style text formatting. For a test application please see [here](https://github.com/michal-z/zig-gamedev/tree/main/samples/gui_test_wgpu).

View File

@ -38,7 +38,7 @@ pub fn package(
const zgui_options = step.createModule(); const zgui_options = step.createModule();
const zgui = b.createModule(.{ const zgui = b.createModule(.{
.source_file = .{ .path = thisDir() ++ "/src/main.zig" }, .source_file = .{ .path = thisDir() ++ "/src/gui.zig" },
.dependencies = &.{ .dependencies = &.{
.{ .name = "zgui_options", .module = zgui_options }, .{ .name = "zgui_options", .module = zgui_options },
}, },

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,17 @@
// dear imgui, v1.89.4 // dear imgui, v1.89.6
// (headers) // (headers)
// Help: // Help:
// - Read FAQ at http://dearimgui.org/faq // - Read FAQ at http://dearimgui.com/faq
// - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. // - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that. // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
// Read imgui.cpp for details, links and comments. // Read imgui.cpp for details, links and comments.
// Resources: // Resources:
// - FAQ http://dearimgui.org/faq // - FAQ http://dearimgui.com/faq
// - Homepage & latest https://github.com/ocornut/imgui // - Homepage & latest 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/5886 (please post your screenshots/video there!) // - Gallery https://github.com/ocornut/imgui/issues/6478 (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)
// - Glossary https://github.com/ocornut/imgui/wiki/Glossary // - Glossary https://github.com/ocornut/imgui/wiki/Glossary
// - Issues & support https://github.com/ocornut/imgui/issues // - Issues & support https://github.com/ocornut/imgui/issues
@ -21,9 +21,9 @@
// 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.
// 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.89.4" #define IMGUI_VERSION "1.89.6"
#define IMGUI_VERSION_NUM 18940 #define IMGUI_VERSION_NUM 18960
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
/* /*
@ -167,6 +167,7 @@ struct ImGuiViewport; // A Platform Window (always only one in 'ma
// In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. // With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in 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)
typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling
typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions
typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type
@ -255,8 +256,8 @@ struct ImVec2
float x, y; float x, y;
constexpr ImVec2() : x(0.0f), y(0.0f) { } constexpr ImVec2() : x(0.0f), y(0.0f) { }
constexpr ImVec2(float _x, float _y) : x(_x), y(_y) { } constexpr ImVec2(float _x, float _y) : x(_x), y(_y) { }
float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine. float& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((float*)(void*)(char*)this)[idx]; } // We very rarely use this [] operator, so the assert overhead is fine.
float& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine. float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const float*)(const void*)(const char*)this)[idx]; }
#ifdef IM_VEC2_CLASS_EXTRA #ifdef IM_VEC2_CLASS_EXTRA
IM_VEC2_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec2. IM_VEC2_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec2.
#endif #endif
@ -460,7 +461,7 @@ namespace ImGui
IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets)
// ID stack/scopes // ID stack/scopes
// Read the FAQ (docs/FAQ.md or http://dearimgui.org/faq) for more details about how ID are handled in dear imgui. // Read the FAQ (docs/FAQ.md or http://dearimgui.com/faq) for more details about how ID are handled in dear imgui.
// - Those questions are answered and impacted by understanding of the ID stack system: // - Those questions are answered and impacted by understanding of the ID stack system:
// - "Q: Why is my widget not reacting when I click on it?" // - "Q: Why is my widget not reacting when I click on it?"
// - "Q: How can I have widgets with an empty label?" // - "Q: How can I have widgets with an empty label?"
@ -1407,7 +1408,7 @@ enum ImGuiKey : int
ImGuiKey_KeypadEqual, ImGuiKey_KeypadEqual,
// Gamepad (some of those are analog values, 0.0f to 1.0f) // NAVIGATION ACTION // Gamepad (some of those are analog values, 0.0f to 1.0f) // NAVIGATION ACTION
// (download controller mapping PNG/PSD at http://dearimgui.org/controls_sheets) // (download controller mapping PNG/PSD at http://dearimgui.com/controls_sheets)
ImGuiKey_GamepadStart, // Menu (Xbox) + (Switch) Start/Options (PS) ImGuiKey_GamepadStart, // Menu (Xbox) + (Switch) Start/Options (PS)
ImGuiKey_GamepadBack, // View (Xbox) - (Switch) Share (PS) ImGuiKey_GamepadBack, // View (Xbox) - (Switch) Share (PS)
ImGuiKey_GamepadFaceLeft, // X (Xbox) Y (Switch) Square (PS) // Tap: Toggle Menu. Hold: Windowing mode (Focus/Move/Resize windows) ImGuiKey_GamepadFaceLeft, // X (Xbox) Y (Switch) Square (PS) // Tap: Toggle Menu. Hold: Windowing mode (Focus/Move/Resize windows)
@ -1715,6 +1716,18 @@ enum ImGuiMouseCursor_
ImGuiMouseCursor_COUNT ImGuiMouseCursor_COUNT
}; };
// Enumeration for AddMouseSourceEvent() actual source of Mouse Input data.
// Historically we use "Mouse" terminology everywhere to indicate pointer data, e.g. MousePos, IsMousePressed(), io.AddMousePosEvent()
// But that "Mouse" data can come from different source which occasionally may be useful for application to know about.
// You can submit a change of pointer type using io.AddMouseSourceEvent().
enum ImGuiMouseSource : int
{
ImGuiMouseSource_Mouse = 0, // Input is coming from an actual mouse.
ImGuiMouseSource_TouchScreen, // Input is coming from a touch screen (no hovering prior to initial press, less precise initial press aiming, dual-axis wheeling possible).
ImGuiMouseSource_Pen, // Input is coming from a pressure/magnetic pen (often used in conjunction with high-sampling rates).
ImGuiMouseSource_COUNT
};
// Enumeration for ImGui::SetWindow***(), SetNextWindow***(), SetNextItem***() functions // Enumeration for ImGui::SetWindow***(), SetNextWindow***(), SetNextItem***() functions
// Represent a condition. // Represent a condition.
// Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always. // Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always.
@ -1939,11 +1952,15 @@ struct ImGuiIO
// Debug options // Debug options
// - tools to test correct Begin/End and BeginChild/EndChild behaviors. // - tools to test correct Begin/End and BeginChild/EndChild behaviors.
// - presently Begn()/End() and BeginChild()EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX() // - presently Begin()/End() and BeginChild()/EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX()
// this is inconsistent with other BeginXXX functions and create confusion for many users. // this is inconsistent with other BeginXXX functions and create confusion for many users.
// - we expect to update the API eventually. In the meanwhile we provided tools to facilitate checking user-code behavior. // - we expect to update the API eventually. In the meanwhile we provide tools to facilitate checking user-code behavior.
bool ConfigDebugBeginReturnValueOnce; // = false // First-time calls to Begin()/BeginChild() will return false. NEEDS TO BE SET AT APPLICATION BOOT TIME if you don't want to miss windows. bool ConfigDebugBeginReturnValueOnce;// = false // First-time calls to Begin()/BeginChild() will return false. NEEDS TO BE SET AT APPLICATION BOOT TIME if you don't want to miss windows.
bool ConfigDebugBeginReturnValueLoop; // = false // Some calls to Begin()/BeginChild() will return false. Will cycle through window depths then repeat. Suggested use: add "io.ConfigDebugBeginReturnValue = io.KeyShift" in your main loop then occasionally press SHIFT. Windows should be flickering while running. bool ConfigDebugBeginReturnValueLoop;// = false // Some calls to Begin()/BeginChild() will return false. Will cycle through window depths then repeat. Suggested use: add "io.ConfigDebugBeginReturnValue = io.KeyShift" in your main loop then occasionally press SHIFT. Windows should be flickering while running.
// - option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data.
// - backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them.
// - consider using e.g. Win32's IsDebuggerPresent() as an additional filter (or see ImOsIsDebuggerPresent() in imgui_test_engine/imgui_te_utils.cpp for a Unix compatible version).
bool ConfigDebugIgnoreFocusLoss; // = false // Ignore io.AddFocusEvent(false), consequently not calling io.ClearInputKeys() in input processing.
//------------------------------------------------------------------ //------------------------------------------------------------------
// Platform Functions // Platform Functions
@ -1982,6 +1999,7 @@ struct ImGuiIO
IMGUI_API void AddMousePosEvent(float x, float y); // Queue a mouse position update. Use -FLT_MAX,-FLT_MAX to signify no mouse (e.g. app not focused and not hovered) IMGUI_API void AddMousePosEvent(float x, float y); // Queue a mouse position update. Use -FLT_MAX,-FLT_MAX to signify no mouse (e.g. app not focused and not hovered)
IMGUI_API void AddMouseButtonEvent(int button, bool down); // Queue a mouse button change IMGUI_API void AddMouseButtonEvent(int button, bool down); // Queue a mouse button change
IMGUI_API void AddMouseWheelEvent(float wheel_x, float wheel_y); // Queue a mouse wheel update. wheel_y<0: scroll down, wheel_y>0: scroll up, wheel_x<0: scroll right, wheel_x>0: scroll left. IMGUI_API void AddMouseWheelEvent(float wheel_x, float wheel_y); // Queue a mouse wheel update. wheel_y<0: scroll down, wheel_y>0: scroll up, wheel_x<0: scroll right, wheel_x>0: scroll left.
IMGUI_API void AddMouseSourceEvent(ImGuiMouseSource source); // Queue a mouse source change (Mouse/TouchScreen/Pen)
IMGUI_API void AddFocusEvent(bool focused); // Queue a gain/loss of focus for the application (generally based on OS/platform focus of your window) IMGUI_API void AddFocusEvent(bool focused); // Queue a gain/loss of focus for the application (generally based on OS/platform focus of your window)
IMGUI_API void AddInputCharacter(unsigned int c); // Queue a new character input IMGUI_API void AddInputCharacter(unsigned int c); // Queue a new character input
IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue a new character input from a UTF-16 character, it can be a surrogate IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue a new character input from a UTF-16 character, it can be a surrogate
@ -2035,6 +2053,7 @@ struct ImGuiIO
bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Other buttons allow us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Other buttons allow us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text. >0 scrolls Up, <0 scrolls Down. Hold SHIFT to turn vertical scroll into horizontal scroll. float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text. >0 scrolls Up, <0 scrolls Down. Hold SHIFT to turn vertical scroll into horizontal scroll.
float MouseWheelH; // Mouse wheel Horizontal. >0 scrolls Left, <0 scrolls Right. Most users don't have a mouse with a horizontal wheel, may not be filled by all backends. float MouseWheelH; // Mouse wheel Horizontal. >0 scrolls Left, <0 scrolls Right. Most users don't have a mouse with a horizontal wheel, may not be filled by all backends.
ImGuiMouseSource MouseSource; // Mouse actual input peripheral (Mouse/TouchScreen/Pen).
bool KeyCtrl; // Keyboard modifier down: Control bool KeyCtrl; // Keyboard modifier down: Control
bool KeyShift; // Keyboard modifier down: Shift bool KeyShift; // Keyboard modifier down: Shift
bool KeyAlt; // Keyboard modifier down: Alt bool KeyAlt; // Keyboard modifier down: Alt
@ -2054,6 +2073,7 @@ struct ImGuiIO
bool MouseReleased[5]; // Mouse button went from Down to !Down bool MouseReleased[5]; // Mouse button went from Down to !Down
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.
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
float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point (used for moving thresholds) float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point (used for moving thresholds)
@ -2324,11 +2344,13 @@ struct ImGuiListClipper
IMGUI_API void End(); // Automatically called on the last call of Step() that returns false. IMGUI_API void End(); // Automatically called on the last call of Step() that returns false.
IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items. IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items.
// Call ForceDisplayRangeByIndices() before first call to Step() if you need a range of items to be displayed regardless of visibility. // Call IncludeRangeByIndices() *BEFORE* first call to Step() if you need a range of items to not be clipped, regardless of their visibility.
IMGUI_API void ForceDisplayRangeByIndices(int item_min, int item_max); // item_max is exclusive e.g. use (42, 42+1) to make item 42 always visible BUT due to alignment/padding of certain items it is likely that an extra item may be included on either end of the display range. // (Due to alignment / padding of certain items it is possible that an extra item may be included on either end of the display range).
IMGUI_API void IncludeRangeByIndices(int item_begin, int item_end); // item_end is exclusive e.g. use (42, 42+1) to make item 42 never clipped.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79] inline void ForceDisplayRangeByIndices(int item_begin, int item_end) { IncludeRangeByIndices(item_begin, item_end); } // [renamed in 1.89.6]
//inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79]
#endif #endif
}; };
@ -2336,7 +2358,6 @@ struct ImGuiListClipper
// - It is important that we are keeping those disabled by default so they don't leak in user space. // - It is important that we are keeping those disabled by default so they don't leak in user space.
// - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h) // - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h)
// - You can use '#define IMGUI_DEFINE_MATH_OPERATORS' to import our operators, provided as a courtesy. // - You can use '#define IMGUI_DEFINE_MATH_OPERATORS' to import our operators, provided as a courtesy.
// - We unfortunately don't have a unary- operator for ImVec2 because this would needs to be defined inside the class itself.
#ifdef IMGUI_DEFINE_MATH_OPERATORS #ifdef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED #define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED
IM_MSVC_RUNTIME_CHECKS_OFF IM_MSVC_RUNTIME_CHECKS_OFF
@ -2346,6 +2367,7 @@ static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return
static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); } static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }
static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); } static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }
static inline ImVec2 operator-(const ImVec2& lhs) { return ImVec2(-lhs.x, -lhs.y); }
static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
@ -2812,7 +2834,8 @@ struct ImFontAtlas
//------------------------------------------- //-------------------------------------------
// Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list) // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list)
// NB: Make sure that your string are UTF-8 and NOT in your local code page. In C++11, you can create UTF-8 string literal using the u8"Hello world" syntax. See FAQ for details. // NB: Make sure that your string are UTF-8 and NOT in your local code page.
// Read https://github.com/ocornut/imgui/blob/master/docs/FONTS.md/#about-utf-8-encoding for details.
// NB: Consider using ImFontGlyphRangesBuilder to build glyph ranges from textual data. // NB: Consider using ImFontGlyphRangesBuilder to build glyph ranges from textual data.
IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin
IMGUI_API const ImWchar* GetGlyphRangesGreek(); // Default + Greek and Coptic IMGUI_API const ImWchar* GetGlyphRangesGreek(); // Default + Greek and Coptic
@ -3019,12 +3042,12 @@ namespace ImGui
IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Calculate coarse clipping for large list of evenly sized items. Prefer using ImGuiListClipper. IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Calculate coarse clipping for large list of evenly sized items. Prefer using ImGuiListClipper.
// OBSOLETED in 1.85 (from August 2021) // OBSOLETED in 1.85 (from August 2021)
static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; } static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; }
// OBSOLETED in 1.81 (from February 2021)
IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // Helper to calculate size from items_count and height_in_items
static inline bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)) { return BeginListBox(label, size); }
static inline void ListBoxFooter() { EndListBox(); }
// 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.81 (from February 2021)
//static inline bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)) { return BeginListBox(label, size); }
//static inline bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1) { float height = GetTextLineHeightWithSpacing() * ((height_in_items < 0 ? ImMin(items_count, 7) : height_in_items) + 0.25f) + GetStyle().FramePadding.y * 2.0f; return BeginListBox(label, ImVec2(0.0f, height)); } // Helper to calculate size from items_count and height_in_items
//static inline void ListBoxFooter() { EndListBox(); }
//-- OBSOLETED in 1.79 (from August 2020) //-- OBSOLETED in 1.79 (from August 2020)
//static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry! //static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry!
//-- OBSOLETED in 1.78 (from June 2020): Old drag/sliders functions that took a 'float power > 1.0f' argument instead of ImGuiSliderFlags_Logarithmic. See github.com/ocornut/imgui/issues/3361 for details. //-- OBSOLETED in 1.78 (from June 2020): Old drag/sliders functions that took a 'float power > 1.0f' argument instead of ImGuiSliderFlags_Logarithmic. See github.com/ocornut/imgui/issues/3361 for details.

View File

@ -1,8 +1,8 @@
// dear imgui, v1.89.4 // dear imgui, v1.89.6
// (demo code) // (demo code)
// Help: // Help:
// - Read FAQ at http://dearimgui.org/faq // - Read FAQ at http://dearimgui.com/faq
// - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. // - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that. // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
// Read imgui.cpp for more details, documentation and comments. // Read imgui.cpp for more details, documentation and comments.
@ -398,23 +398,21 @@ void ImGui::ShowDemoWindow(bool* p_open)
IMGUI_DEMO_MARKER("Help"); IMGUI_DEMO_MARKER("Help");
if (ImGui::CollapsingHeader("Help")) if (ImGui::CollapsingHeader("Help"))
{ {
ImGui::Text("ABOUT THIS DEMO:"); ImGui::SeparatorText("ABOUT THIS DEMO:");
ImGui::BulletText("Sections below are demonstrating many aspects of the library."); ImGui::BulletText("Sections below are demonstrating many aspects of the library.");
ImGui::BulletText("The \"Examples\" menu above leads to more demo contents."); ImGui::BulletText("The \"Examples\" menu above leads to more demo contents.");
ImGui::BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n" ImGui::BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n"
"and Metrics/Debugger (general purpose Dear ImGui debugging tool)."); "and Metrics/Debugger (general purpose Dear ImGui debugging tool).");
ImGui::Separator();
ImGui::Text("PROGRAMMER GUIDE:"); ImGui::SeparatorText("PROGRAMMER GUIDE:");
ImGui::BulletText("See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!"); ImGui::BulletText("See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
ImGui::BulletText("See comments in imgui.cpp."); ImGui::BulletText("See comments in imgui.cpp.");
ImGui::BulletText("See example applications in the examples/ folder."); ImGui::BulletText("See example applications in the examples/ folder.");
ImGui::BulletText("Read the FAQ at http://www.dearimgui.org/faq/"); ImGui::BulletText("Read the FAQ at http://www.dearimgui.com/faq/");
ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls."); ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls."); ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
ImGui::Separator();
ImGui::Text("USER GUIDE:"); ImGui::SeparatorText("USER GUIDE:");
ImGui::ShowUserGuide(); ImGui::ShowUserGuide();
} }
@ -471,6 +469,8 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::SameLine(); HelpMarker("First calls to Begin()/BeginChild() will return false.\n\nTHIS OPTION IS DISABLED because it needs to be set at application boot-time to make sense. Showing the disabled option is a way to make this feature easier to discover"); ImGui::SameLine(); HelpMarker("First calls to Begin()/BeginChild() will return false.\n\nTHIS OPTION IS DISABLED because it needs to be set at application boot-time to make sense. Showing the disabled option is a way to make this feature easier to discover");
ImGui::Checkbox("io.ConfigDebugBeginReturnValueLoop", &io.ConfigDebugBeginReturnValueLoop); ImGui::Checkbox("io.ConfigDebugBeginReturnValueLoop", &io.ConfigDebugBeginReturnValueLoop);
ImGui::SameLine(); HelpMarker("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running."); ImGui::SameLine(); HelpMarker("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running.");
ImGui::Checkbox("io.ConfigDebugIgnoreFocusLoss", &io.ConfigDebugIgnoreFocusLoss);
ImGui::SameLine(); HelpMarker("Option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data.");
ImGui::TreePop(); ImGui::TreePop();
ImGui::Spacing(); ImGui::Spacing();
@ -483,13 +483,13 @@ void ImGui::ShowDemoWindow(bool* p_open)
"Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n" "Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n"
"Here we expose them as read-only fields to avoid breaking interactions with your backend."); "Here we expose them as read-only fields to avoid breaking interactions with your backend.");
// Make a local copy to avoid modifying actual backend flags. // FIXME: Maybe we need a BeginReadonly() equivalent to keep label bright?
// FIXME: We don't use BeginDisabled() to keep label bright, maybe we need a BeginReadonly() equivalent.. ImGui::BeginDisabled();
ImGuiBackendFlags backend_flags = io.BackendFlags; ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", &io.BackendFlags, ImGuiBackendFlags_HasGamepad);
ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", &backend_flags, ImGuiBackendFlags_HasGamepad); ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &io.BackendFlags, ImGuiBackendFlags_HasMouseCursors);
ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &backend_flags, ImGuiBackendFlags_HasMouseCursors); ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", &io.BackendFlags, ImGuiBackendFlags_HasSetMousePos);
ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", &backend_flags, ImGuiBackendFlags_HasSetMousePos); ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &io.BackendFlags, ImGuiBackendFlags_RendererHasVtxOffset);
ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &backend_flags, ImGuiBackendFlags_RendererHasVtxOffset); ImGui::EndDisabled();
ImGui::TreePop(); ImGui::TreePop();
ImGui::Spacing(); ImGui::Spacing();
} }
@ -631,7 +631,7 @@ static void ShowDemoWindowWidgets()
ImGui::Text("Tooltips:"); ImGui::Text("Tooltips:");
ImGui::SameLine(); ImGui::SameLine();
ImGui::SmallButton("Button"); ImGui::SmallButton("Basic");
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
ImGui::SetTooltip("I am a tooltip"); ImGui::SetTooltip("I am a tooltip");
@ -744,7 +744,7 @@ static void ShowDemoWindowWidgets()
static int elem = Element_Fire; static int elem = Element_Fire;
const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" }; const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" };
const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown"; const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown";
ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name); ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name); // Use ImGuiSliderFlags_NoInput flag to disable CTRL+Click here.
ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer."); ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer.");
} }
@ -1390,7 +1390,15 @@ static void ShowDemoWindowWidgets()
{ {
struct TextFilters struct TextFilters
{ {
// Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i' // Modify character input by altering 'data->Eventchar' (ImGuiInputTextFlags_CallbackCharFilter callback)
static int FilterCasingSwap(ImGuiInputTextCallbackData* data)
{
if (data->EventChar >= 'a' && data->EventChar <= 'z') { data->EventChar = data->EventChar - 'A' - 'a'; } // Lowercase becomes uppercase
else if (data->EventChar >= 'A' && data->EventChar <= 'Z') { data->EventChar = data->EventChar + 'a' - 'A'; } // Uppercase becomes lowercase
return 0;
}
// Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i', otherwise return 1 (filter out)
static int FilterImGuiLetters(ImGuiInputTextCallbackData* data) static int FilterImGuiLetters(ImGuiInputTextCallbackData* data)
{ {
if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar))
@ -1399,12 +1407,13 @@ static void ShowDemoWindowWidgets()
} }
}; };
static char buf1[64] = ""; ImGui::InputText("default", buf1, 64); static char buf1[32] = ""; ImGui::InputText("default", buf1, 32);
static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal); static char buf2[32] = ""; ImGui::InputText("decimal", buf2, 32, ImGuiInputTextFlags_CharsDecimal);
static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); static char buf3[32] = ""; ImGui::InputText("hexadecimal", buf3, 32, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase); static char buf4[32] = ""; ImGui::InputText("uppercase", buf4, 32, ImGuiInputTextFlags_CharsUppercase);
static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank); static char buf5[32] = ""; ImGui::InputText("no blank", buf5, 32, ImGuiInputTextFlags_CharsNoBlank);
static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); static char buf6[32] = ""; ImGui::InputText("casing swap", buf6, 32, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterCasingSwap); // Use CharFilter callback to replace characters.
static char buf7[32] = ""; ImGui::InputText("\"imgui\"", buf7, 32, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); // Use CharFilter callback to disable some characters.
ImGui::TreePop(); ImGui::TreePop();
} }
@ -5713,8 +5722,6 @@ static void ShowDemoWindowColumns()
ImGui::TreePop(); ImGui::TreePop();
} }
namespace ImGui { extern ImGuiKeyData* GetKeyData(ImGuiKey key); }
static void ShowDemoWindowInputs() static void ShowDemoWindowInputs()
{ {
IMGUI_DEMO_MARKER("Inputs & Focus"); IMGUI_DEMO_MARKER("Inputs & Focus");
@ -5749,7 +5756,7 @@ static void ShowDemoWindowInputs()
struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array
ImGuiKey start_key = (ImGuiKey)0; ImGuiKey start_key = (ImGuiKey)0;
#endif #endif
ImGui::Text("Keys down:"); for (ImGuiKey key = start_key; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key)) continue; ImGui::SameLine(); ImGui::Text((key < ImGuiKey_NamedKey_BEGIN) ? "\"%s\"" : "\"%s\" %d", ImGui::GetKeyName(key), key); ImGui::SameLine(); ImGui::Text("(%.02f)", ImGui::GetKeyData(key)->DownDuration); } ImGui::Text("Keys down:"); for (ImGuiKey key = start_key; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key)) continue; ImGui::SameLine(); ImGui::Text((key < ImGuiKey_NamedKey_BEGIN) ? "\"%s\"" : "\"%s\" %d", ImGui::GetKeyName(key), key); }
ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public. ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
@ -7443,7 +7450,7 @@ static void ShowExampleAppFullscreen(bool* p_open)
static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings; static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings;
// We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.) // We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.)
// Based on your use case you may want one of the other. // Based on your use case you may want one or the other.
const ImGuiViewport* viewport = ImGui::GetMainViewport(); const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos); ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos);
ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size); ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size);

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.4 // dear imgui, v1.89.6
// (drawing and font code) // (drawing and font code)
/* /*
@ -2553,13 +2553,10 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
// 9. Setup ImFont and glyphs for runtime // 9. Setup ImFont and glyphs for runtime
for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
{ {
ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
if (src_tmp.GlyphsCount == 0)
continue;
// When merging fonts with MergeMode=true: // When merging fonts with MergeMode=true:
// - We can have multiple input fonts writing into a same destination font. // - We can have multiple input fonts writing into a same destination font.
// - dst_font->ConfigData is != from cfg which is our source configuration. // - dst_font->ConfigData is != from cfg which is our source configuration.
ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
ImFontConfig& cfg = atlas->ConfigData[src_i]; ImFontConfig& cfg = atlas->ConfigData[src_i];
ImFont* dst_font = cfg.DstFont; ImFont* dst_font = cfg.DstFont;
@ -2623,6 +2620,9 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opa
ImVector<ImFontAtlasCustomRect>& user_rects = atlas->CustomRects; ImVector<ImFontAtlasCustomRect>& user_rects = atlas->CustomRects;
IM_ASSERT(user_rects.Size >= 1); // We expect at least the default custom rects to be registered, else something went wrong. IM_ASSERT(user_rects.Size >= 1); // We expect at least the default custom rects to be registered, else something went wrong.
#ifdef __GNUC__
if (user_rects.Size < 1) { __builtin_unreachable(); } // Workaround for GCC bug if IM_ASSERT() is defined to conditionally throw (see #5343)
#endif
ImVector<stbrp_rect> pack_rects; ImVector<stbrp_rect> pack_rects;
pack_rects.resize(user_rects.Size); pack_rects.resize(user_rects.Size);
@ -3200,7 +3200,25 @@ void ImFont::BuildLookupTable()
SetGlyphVisible((ImWchar)' ', false); SetGlyphVisible((ImWchar)' ', false);
SetGlyphVisible((ImWchar)'\t', false); SetGlyphVisible((ImWchar)'\t', false);
// Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis). // Setup Fallback character
const ImWchar fallback_chars[] = { (ImWchar)IM_UNICODE_CODEPOINT_INVALID, (ImWchar)'?', (ImWchar)' ' };
FallbackGlyph = FindGlyphNoFallback(FallbackChar);
if (FallbackGlyph == NULL)
{
FallbackChar = FindFirstExistingGlyph(this, fallback_chars, IM_ARRAYSIZE(fallback_chars));
FallbackGlyph = FindGlyphNoFallback(FallbackChar);
if (FallbackGlyph == NULL)
{
FallbackGlyph = &Glyphs.back();
FallbackChar = (ImWchar)FallbackGlyph->Codepoint;
}
}
FallbackAdvanceX = FallbackGlyph->AdvanceX;
for (int i = 0; i < max_codepoint + 1; i++)
if (IndexAdvanceX[i] < 0.0f)
IndexAdvanceX[i] = FallbackAdvanceX;
// Setup Ellipsis character. It is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis).
// However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character. // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character.
// FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots. // FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots.
const ImWchar ellipsis_chars[] = { (ImWchar)0x2026, (ImWchar)0x0085 }; const ImWchar ellipsis_chars[] = { (ImWchar)0x2026, (ImWchar)0x0085 };
@ -3221,25 +3239,6 @@ void ImFont::BuildLookupTable()
EllipsisCharStep = (glyph->X1 - glyph->X0) + 1.0f; EllipsisCharStep = (glyph->X1 - glyph->X0) + 1.0f;
EllipsisWidth = EllipsisCharStep * 3.0f - 1.0f; EllipsisWidth = EllipsisCharStep * 3.0f - 1.0f;
} }
// Setup fallback character
const ImWchar fallback_chars[] = { (ImWchar)IM_UNICODE_CODEPOINT_INVALID, (ImWchar)'?', (ImWchar)' ' };
FallbackGlyph = FindGlyphNoFallback(FallbackChar);
if (FallbackGlyph == NULL)
{
FallbackChar = FindFirstExistingGlyph(this, fallback_chars, IM_ARRAYSIZE(fallback_chars));
FallbackGlyph = FindGlyphNoFallback(FallbackChar);
if (FallbackGlyph == NULL)
{
FallbackGlyph = &Glyphs.back();
FallbackChar = (ImWchar)FallbackGlyph->Codepoint;
}
}
FallbackAdvanceX = FallbackGlyph->AdvanceX;
for (int i = 0; i < max_codepoint + 1; i++)
if (IndexAdvanceX[i] < 0.0f)
IndexAdvanceX[i] = FallbackAdvanceX;
} }
// API is designed this way to avoid exposing the 4K page size // API is designed this way to avoid exposing the 4K page size
@ -3790,6 +3789,7 @@ void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir d
void ImGui::RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col) void ImGui::RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col)
{ {
// FIXME-OPT: This should be baked in font.
draw_list->AddCircleFilled(pos, draw_list->_Data->FontSize * 0.20f, col, 8); draw_list->AddCircleFilled(pos, draw_list->_Data->FontSize * 0.20f, col, 8);
} }

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.4 // dear imgui, v1.89.6
// (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.
@ -130,6 +130,7 @@ struct ImGuiDataVarInfo; // Variable information (e.g. to avoid style
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup() struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup()
struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box
struct ImGuiInputTextDeactivateData;// Short term storage to backup text of a deactivating InputText() while another is stealing active id
struct ImGuiLastItemData; // Status storage for last submitted items struct ImGuiLastItemData; // Status storage for last submitted items
struct ImGuiLocEntry; // A localization entry. struct ImGuiLocEntry; // A localization entry.
struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
@ -163,6 +164,7 @@ typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // E
// Flags // Flags
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 ImGuiInputFlags; // -> enum ImGuiInputFlags_ // Flags: for IsKeyPressed(), IsMouseClicked(), SetKeyOwner(), SetItemKeyOwner() etc. 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
@ -229,6 +231,7 @@ namespace ImStb
#define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
@ -476,7 +479,6 @@ 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; }
IMGUI_API ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy);
// 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)
@ -901,7 +903,17 @@ enum ImGuiSeparatorFlags_
ImGuiSeparatorFlags_None = 0, ImGuiSeparatorFlags_None = 0,
ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar
ImGuiSeparatorFlags_Vertical = 1 << 1, ImGuiSeparatorFlags_Vertical = 1 << 1,
ImGuiSeparatorFlags_SpanAllColumns = 1 << 2, ImGuiSeparatorFlags_SpanAllColumns = 1 << 2, // Make separator cover all columns of a legacy Columns() set.
};
// Flags for FocusWindow(). This is not called ImGuiFocusFlags to avoid confusion with public-facing ImGuiFocusedFlags.
// FIXME: Once we finishing replacing more uses of GetTopMostPopupModal()+IsWindowWithinBeginStackOf()
// and FindBlockingModal() with this, we may want to change the flag to be opt-out instead of opt-in.
enum ImGuiFocusRequestFlags_
{
ImGuiFocusRequestFlags_None = 0,
ImGuiFocusRequestFlags_RestoreFocusedChild = 1 << 0, // Find last focused child (if any) and focus it instead.
ImGuiFocusRequestFlags_UnlessBelowModal = 1 << 1, // Do not set focus if the window is below a modal.
}; };
enum ImGuiTextFlags_ enum ImGuiTextFlags_
@ -1048,6 +1060,15 @@ struct IMGUI_API ImGuiMenuColumns
void CalcNextTotalWidth(bool update_offsets); void CalcNextTotalWidth(bool update_offsets);
}; };
// Internal temporary state for deactivating InputText() instances.
struct IMGUI_API ImGuiInputTextDeactivatedState
{
ImGuiID ID; // widget id owning the text state (which just got deactivated)
ImVector<char> TextA; // text buffer
ImGuiInputTextDeactivatedState() { memset(this, 0, sizeof(*this)); }
void ClearFreeMemory() { ID = 0; TextA.clear(); }
};
// Internal state of the currently focused/edited text input box // Internal state of the currently focused/edited text input box
// For a given item ID, access with ImGui::GetInputTextState() // For a given item ID, access with ImGui::GetInputTextState()
struct IMGUI_API ImGuiInputTextState struct IMGUI_API ImGuiInputTextState
@ -1254,19 +1275,18 @@ enum ImGuiInputEventType
enum ImGuiInputSource enum ImGuiInputSource
{ {
ImGuiInputSource_None = 0, ImGuiInputSource_None = 0,
ImGuiInputSource_Mouse, 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_Clipboard, // Currently only used by InputText()
ImGuiInputSource_Nav, // Stored in g.ActiveIdSource only
ImGuiInputSource_COUNT ImGuiInputSource_COUNT
}; };
// FIXME: Structures in the union below need to be declared as anonymous unions appears to be an extension? // FIXME: Structures in the union below need to be declared as anonymous unions appears to be an extension?
// Using ImVec2() would fail on Clang 'union member 'MousePos' has a non-trivial default constructor' // Using ImVec2() would fail on Clang 'union member 'MousePos' has a non-trivial default constructor'
struct ImGuiInputEventMousePos { float PosX, PosY; }; struct ImGuiInputEventMousePos { float PosX, PosY; ImGuiMouseSource MouseSource; };
struct ImGuiInputEventMouseWheel { float WheelX, WheelY; }; struct ImGuiInputEventMouseWheel { float WheelX, WheelY; ImGuiMouseSource MouseSource; };
struct ImGuiInputEventMouseButton { int Button; bool Down; }; struct ImGuiInputEventMouseButton { int Button; bool Down; ImGuiMouseSource MouseSource; };
struct ImGuiInputEventKey { ImGuiKey Key; bool Down; float AnalogValue; }; struct ImGuiInputEventKey { ImGuiKey Key; bool Down; float AnalogValue; };
struct ImGuiInputEventText { unsigned int Char; }; struct ImGuiInputEventText { unsigned int Char; };
struct ImGuiInputEventAppFocused { bool Focused; }; struct ImGuiInputEventAppFocused { bool Focused; };
@ -1275,6 +1295,7 @@ struct ImGuiInputEvent
{ {
ImGuiInputEventType Type; ImGuiInputEventType Type;
ImGuiInputSource Source; ImGuiInputSource Source;
ImU32 EventId; // Unique, sequential increasing integer to identify an event (if you need to correlate them to other data).
union union
{ {
ImGuiInputEventMousePos MousePos; // if Type == ImGuiInputEventType_MousePos ImGuiInputEventMousePos MousePos; // if Type == ImGuiInputEventType_MousePos
@ -1383,6 +1404,7 @@ enum ImGuiInputFlags_
// [SECTION] Clipper support // [SECTION] Clipper support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Note that Max is exclusive, so perhaps should be using a Begin/End convention.
struct ImGuiListClipperRange struct ImGuiListClipperRange
{ {
int Min; int Min;
@ -1451,6 +1473,7 @@ enum ImGuiNavMoveFlags_
ImGuiNavMoveFlags_LoopY = 1 << 1, ImGuiNavMoveFlags_LoopY = 1 << 1,
ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left) ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left)
ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful but provided for completeness ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful but provided for completeness
ImGuiNavMoveFlags_WrapMask_ = ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_LoopY | ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_WrapY,
ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place) ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place)
ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisible that only comprise elements that are already fully visible (used by PageUp/PageDown) ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisible that only comprise elements that are already fully visible (used by PageUp/PageDown)
ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary
@ -1660,8 +1683,9 @@ enum ImGuiDebugLogFlags_
ImGuiDebugLogFlags_EventPopup = 1 << 2, ImGuiDebugLogFlags_EventPopup = 1 << 2,
ImGuiDebugLogFlags_EventNav = 1 << 3, ImGuiDebugLogFlags_EventNav = 1 << 3,
ImGuiDebugLogFlags_EventClipper = 1 << 4, ImGuiDebugLogFlags_EventClipper = 1 << 4,
ImGuiDebugLogFlags_EventIO = 1 << 5, ImGuiDebugLogFlags_EventSelection = 1 << 5,
ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventIO, ImGuiDebugLogFlags_EventIO = 1 << 6,
ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO,
ImGuiDebugLogFlags_OutputToTTY = 1 << 10, // Also send output to TTY ImGuiDebugLogFlags_OutputToTTY = 1 << 10, // Also send output to TTY
}; };
@ -1730,8 +1754,6 @@ struct ImGuiContext
bool Initialized; bool Initialized;
bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it. bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
ImGuiIO IO; ImGuiIO IO;
ImVector<ImGuiInputEvent> InputEventsQueue; // Input events which will be tricked/written into IO structure.
ImVector<ImGuiInputEvent> InputEventsTrail; // Past input events processed in NewFrame(). This is to allow domain-specific application to access e.g mouse/pen trail.
ImGuiStyle Style; ImGuiStyle Style;
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.
@ -1748,6 +1770,12 @@ struct ImGuiContext
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log() bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
void* TestEngine; // Test engine user data void* TestEngine; // Test engine user data
// Inputs
ImVector<ImGuiInputEvent> InputEventsQueue; // Input events which will be trickled/written into IO structure.
ImVector<ImGuiInputEvent> InputEventsTrail; // Past input events processed in NewFrame(). This is to allow domain-specific application to access e.g mouse/pen trail.
ImGuiMouseSource InputEventsNextMouseSource;
ImU32 InputEventsNextEventId;
// Windows state // Windows state
ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front
ImVector<ImGuiWindow*> WindowsFocusOrder; // Root windows, sorted in focus order, back to front. ImVector<ImGuiWindow*> WindowsFocusOrder; // Root windows, sorted in focus order, back to front.
@ -1786,7 +1814,7 @@ struct ImGuiContext
bool ActiveIdHasBeenEditedThisFrame; bool ActiveIdHasBeenEditedThisFrame;
ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
ImGuiWindow* ActiveIdWindow; ImGuiWindow* ActiveIdWindow;
ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard) ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad
int ActiveIdMouseButton; int ActiveIdMouseButton;
ImGuiID ActiveIdPreviousFrame; ImGuiID ActiveIdPreviousFrame;
bool ActiveIdPreviousFrameIsAlive; bool ActiveIdPreviousFrameIsAlive;
@ -1842,7 +1870,7 @@ struct ImGuiContext
ImGuiKeyChord NavJustMovedToKeyMods; ImGuiKeyChord NavJustMovedToKeyMods;
ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame. ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
ImGuiActivateFlags NavNextActivateFlags; ImGuiActivateFlags NavNextActivateFlags;
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard. ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later.
bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid
bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default) bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
@ -1853,8 +1881,7 @@ struct ImGuiContext
bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd() bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
bool NavInitRequest; // Init request for appearing window to select first item bool NavInitRequest; // Init request for appearing window to select first item
bool NavInitRequestFromMove; bool NavInitRequestFromMove;
ImGuiID NavInitResultId; // Init request result (first item of the window, or one for which SetItemDefaultFocus() was called) ImGuiNavItemData NavInitResult; // Init request result (first item of the window, or one for which SetItemDefaultFocus() was called)
ImRect NavInitResultRectRel; // Init request result rectangle (relative to parent window)
bool NavMoveSubmitted; // Move request submitted, will process result on next NewFrame() bool NavMoveSubmitted; // Move request submitted, will process result on next NewFrame()
bool NavMoveScoringItems; // Move request submitted, still scoring incoming items bool NavMoveScoringItems; // Move request submitted, still scoring incoming items
bool NavMoveForwardToNextFrame; bool NavMoveForwardToNextFrame;
@ -1936,6 +1963,7 @@ struct ImGuiContext
// Widget state // Widget state
ImVec2 MouseLastValidPos; ImVec2 MouseLastValidPos;
ImGuiInputTextState InputTextState; ImGuiInputTextState InputTextState;
ImGuiInputTextDeactivatedState InputTextDeactivatedState;
ImFont InputTextPasswordFont; ImFont InputTextPasswordFont;
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
@ -2031,6 +2059,9 @@ struct ImGuiContext
TestEngineHookItems = false; TestEngineHookItems = false;
TestEngine = NULL; TestEngine = NULL;
InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
InputEventsNextEventId = 1;
WindowsActiveCount = 0; WindowsActiveCount = 0;
CurrentWindow = NULL; CurrentWindow = NULL;
HoveredWindow = NULL; HoveredWindow = NULL;
@ -2080,7 +2111,7 @@ struct ImGuiContext
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None; NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavJustMovedToKeyMods = ImGuiMod_None; NavJustMovedToKeyMods = ImGuiMod_None;
NavInputSource = ImGuiInputSource_None; NavInputSource = ImGuiInputSource_Keyboard;
NavLayer = ImGuiNavLayer_Main; NavLayer = ImGuiNavLayer_Main;
NavIdIsAlive = false; NavIdIsAlive = false;
NavMousePosDirty = false; NavMousePosDirty = false;
@ -2089,7 +2120,6 @@ struct ImGuiContext
NavAnyRequest = false; NavAnyRequest = false;
NavInitRequest = false; NavInitRequest = false;
NavInitRequestFromMove = false; NavInitRequestFromMove = false;
NavInitResultId = 0;
NavMoveSubmitted = false; NavMoveSubmitted = false;
NavMoveScoringItems = false; NavMoveScoringItems = false;
NavMoveForwardToNextFrame = false; NavMoveForwardToNextFrame = false;
@ -2206,14 +2236,15 @@ struct IMGUI_API ImGuiWindowTempData
ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
ImVec1 GroupOffset; ImVec1 GroupOffset;
ImVec2 CursorStartPosLossyness;// Record the loss of precision of CursorStartPos due to really large scrolling amount. This is used by clipper to compensentate and fix the most common use case of large scroll area. ImVec2 CursorStartPosLossyness;// Record the loss of precision of CursorStartPos due to really large scrolling amount. This is used by clipper to compensate and fix the most common use case of large scroll area.
// Keyboard/Gamepad navigation // Keyboard/Gamepad navigation
ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1)
short NavLayersActiveMask; // Which layers have been written to (result from previous frame) short NavLayersActiveMask; // Which layers have been written to (result from previous frame)
short NavLayersActiveMaskNext;// Which layers have been written to (accumulator for current frame) short NavLayersActiveMaskNext;// Which layers have been written to (accumulator for current frame)
bool NavIsScrollPushableX; // Set when current work location may be scrolled horizontally when moving left / right. This is generally always true UNLESS within a column.
bool NavHideHighlightOneFrame; bool NavHideHighlightOneFrame;
bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) bool NavWindowHasScrollY; // Set per window when scrolling can be used (== ScrollMax.y > 0.0f)
// Miscellaneous // Miscellaneous
bool MenuBarAppending; // FIXME: Remove this bool MenuBarAppending; // FIXME: Remove this
@ -2333,6 +2364,7 @@ struct IMGUI_API ImGuiWindow
ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.) ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.)
ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1) ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1)
ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space
ImVec2 NavPreferredScoringPosRel[ImGuiNavLayer_COUNT]; // Preferred X/Y position updated when moving on a given axis, reset to FLT_MAX.
ImGuiID NavRootFocusScopeId; // Focus Scope ID at the time of Begin() ImGuiID NavRootFocusScopeId; // Focus Scope ID at the time of Begin()
int MemoryDrawListIdxCapacity; // Backup of last idx/vtx count, so when waking up the window we can preallocate and avoid iterative alloc/copy int MemoryDrawListIdxCapacity; // Backup of last idx/vtx count, so when waking up the window we can preallocate and avoid iterative alloc/copy
@ -2445,7 +2477,7 @@ struct IMGUI_API ImGuiTabBar
typedef ImS16 ImGuiTableColumnIdx; typedef ImS16 ImGuiTableColumnIdx;
typedef ImU16 ImGuiTableDrawChannelIdx; typedef ImU16 ImGuiTableDrawChannelIdx;
// [Internal] sizeof() ~ 104 // [Internal] sizeof() ~ 112
// We use the terminology "Enabled" to refer to a column that is not Hidden by user/api. // We use the terminology "Enabled" to refer to a column that is not Hidden by user/api.
// We use the terminology "Clipped" to refer to a column that is out of sight because of scrolling/clipping. // We use the terminology "Clipped" to refer to a column that is out of sight because of scrolling/clipping.
// This is in contrast with some user-facing api such as IsItemVisible() / IsRectVisible() which use "Visible" to mean "not clipped". // This is in contrast with some user-facing api such as IsItemVisible() / IsRectVisible() which use "Visible" to mean "not clipped".
@ -2491,7 +2523,7 @@ struct ImGuiTableColumn
ImU8 SortDirection : 2; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending ImU8 SortDirection : 2; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
ImU8 SortDirectionsAvailCount : 2; // Number of available sort directions (0 to 3) ImU8 SortDirectionsAvailCount : 2; // Number of available sort directions (0 to 3)
ImU8 SortDirectionsAvailMask : 4; // Mask of available sort directions (1-bit each) ImU8 SortDirectionsAvailMask : 4; // Mask of available sort directions (1-bit each)
ImU8 SortDirectionsAvailList; // Ordered of available sort directions (2-bits each) ImU8 SortDirectionsAvailList; // Ordered list of available sort directions (2-bits each, total 8-bits)
ImGuiTableColumn() ImGuiTableColumn()
{ {
@ -2526,6 +2558,7 @@ struct ImGuiTableInstanceData
}; };
// FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs, incoming RowData // FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs, incoming RowData
// sizeof() ~ 580 bytes + heap allocs described in TableBeginInitMemory()
struct IMGUI_API ImGuiTable struct IMGUI_API ImGuiTable
{ {
ImGuiID ID; ImGuiID ID;
@ -2641,6 +2674,7 @@ 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() ~ 112 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
@ -2728,10 +2762,11 @@ namespace ImGui
IMGUI_API void SetWindowHiddendAndSkipItemsForCurrentFrame(ImGuiWindow* window); IMGUI_API void SetWindowHiddendAndSkipItemsForCurrentFrame(ImGuiWindow* window);
inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); } inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); }
inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); } inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); }
inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); }
// Windows: Display Order and Focus Order // Windows: Display Order and Focus Order
IMGUI_API void FocusWindow(ImGuiWindow* window); IMGUI_API void FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags = 0);
IMGUI_API void FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window); IMGUI_API void FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags);
IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window); IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window);
IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window); IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window);
IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window); IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window);
@ -2818,6 +2853,7 @@ namespace ImGui
inline void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f) { ItemSize(bb.GetSize(), text_baseline_y); } // FIXME: This is a misleading API since we expect CursorPos to be bb.Min. inline void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f) { ItemSize(bb.GetSize(), text_baseline_y); } // FIXME: This is a misleading API since we expect CursorPos to be bb.Min.
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemFlags extra_flags = 0); IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemFlags extra_flags = 0);
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
IMGUI_API bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags = 0);
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id);
IMGUI_API void SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags status_flags, const ImRect& item_rect); IMGUI_API void SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags status_flags, const ImRect& item_rect);
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);
@ -2850,6 +2886,7 @@ namespace ImGui
IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window); IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window);
IMGUI_API ImGuiWindow* GetTopMostPopupModal(); IMGUI_API ImGuiWindow* GetTopMostPopupModal();
IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal(); IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal();
IMGUI_API ImGuiWindow* FindBlockingModal(ImGuiWindow* window);
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window); IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy); IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
@ -2873,6 +2910,8 @@ namespace ImGui
IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestCancel();
IMGUI_API void NavMoveRequestApplyResult(); IMGUI_API void NavMoveRequestApplyResult();
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
IMGUI_API void NavClearPreferredPosForAxis(ImGuiAxis axis);
IMGUI_API void NavUpdateCurrentWindowIsScrollPushableX();
IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again.
IMGUI_API void SetNavWindow(ImGuiWindow* window); IMGUI_API void SetNavWindow(ImGuiWindow* window);
IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
@ -2887,9 +2926,9 @@ namespace ImGui
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 ImGuiKeyChord ConvertShortcutMod(ImGuiKeyChord key_chord) { ImGuiContext& g = *GImGui; IM_ASSERT_PARANOID(key_chord & ImGuiMod_Shortcut); return (key_chord & ~ImGuiMod_Shortcut) | (g.IO.ConfigMacOSXBehaviors ? ImGuiMod_Super : ImGuiMod_Ctrl); } inline ImGuiKeyChord ConvertShortcutMod(ImGuiKeyChord key_chord) { ImGuiContext& g = *GImGui; IM_ASSERT_PARANOID(key_chord & ImGuiMod_Shortcut); return (key_chord & ~ImGuiMod_Shortcut) | (g.IO.ConfigMacOSXBehaviors ? ImGuiMod_Super : ImGuiMod_Ctrl); }
inline ImGuiKey ConvertSingleModFlagToKey(ImGuiKey key) inline ImGuiKey ConvertSingleModFlagToKey(ImGuiContext* ctx, ImGuiKey key)
{ {
ImGuiContext& g = *GImGui; 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;
@ -2898,7 +2937,8 @@ namespace ImGui
return key; return key;
} }
IMGUI_API ImGuiKeyData* GetKeyData(ImGuiKey key); IMGUI_API ImGuiKeyData* GetKeyData(ImGuiContext* ctx, ImGuiKey key);
inline ImGuiKeyData* GetKeyData(ImGuiKey key) { ImGuiContext& g = *GImGui; return GetKeyData(&g, key); }
IMGUI_API void GetKeyChordName(ImGuiKeyChord key_chord, char* out_buf, int out_buf_size); IMGUI_API void GetKeyChordName(ImGuiKeyChord key_chord, char* out_buf, int out_buf_size);
inline ImGuiKey MouseButtonToKey(ImGuiMouseButton button) { IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); return (ImGuiKey)(ImGuiKey_MouseLeft + button); } inline ImGuiKey MouseButtonToKey(ImGuiMouseButton button) { IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); return (ImGuiKey)(ImGuiKey_MouseLeft + button); }
IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f); IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f);
@ -2922,9 +2962,10 @@ namespace ImGui
// Please open a GitHub Issue to submit your usage scenario or if there's a use case you need solved. // Please open a GitHub Issue to submit your usage scenario or if there's a use case you need solved.
IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key); IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key);
IMGUI_API void SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API void SetKeyOwner(ImGuiKey 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(ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(key); IM_ASSERT(IsNamedKey(key)); return &GImGui->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; } 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]; }
// [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.
@ -3087,7 +3128,7 @@ namespace ImGui
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0); IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0);
IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags); IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags, float thickness = 1.0f);
IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width); IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width);
IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value); IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value);
IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value); IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value);
@ -3132,6 +3173,7 @@ namespace ImGui
// InputText // InputText
IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API void InputTextDeactivateHook(ImGuiID id);
IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags); IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags);
IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL); IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL);
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); } inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); }

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.4 // dear imgui, v1.89.6
// (tables and columns code) // (tables and columns code)
/* /*
@ -80,20 +80,20 @@ Index of this file:
// - outer_size.x <= 0.0f -> Right-align from window/work-rect right-most edge. With -FLT_MIN or 0.0f will align exactly on right-most edge. // - outer_size.x <= 0.0f -> Right-align from window/work-rect right-most edge. With -FLT_MIN or 0.0f will align exactly on right-most edge.
// - outer_size.x > 0.0f -> Set Fixed width. // - outer_size.x > 0.0f -> Set Fixed width.
// Y with ScrollX/ScrollY disabled: we output table directly in current window // Y with ScrollX/ScrollY disabled: we output table directly in current window
// - outer_size.y < 0.0f -> Bottom-align (but will auto extend, unless _NoHostExtendY is set). Not meaningful is parent window can vertically scroll. // - outer_size.y < 0.0f -> Bottom-align (but will auto extend, unless _NoHostExtendY is set). Not meaningful if parent window can vertically scroll.
// - outer_size.y = 0.0f -> No minimum height (but will auto extend, unless _NoHostExtendY is set) // - outer_size.y = 0.0f -> No minimum height (but will auto extend, unless _NoHostExtendY is set)
// - outer_size.y > 0.0f -> Set Minimum height (but will auto extend, unless _NoHostExtenY is set) // - outer_size.y > 0.0f -> Set Minimum height (but will auto extend, unless _NoHostExtenY is set)
// Y with ScrollX/ScrollY enabled: using a child window for scrolling // Y with ScrollX/ScrollY enabled: using a child window for scrolling
// - outer_size.y < 0.0f -> Bottom-align. Not meaningful is parent window can vertically scroll. // - outer_size.y < 0.0f -> Bottom-align. Not meaningful if parent window can vertically scroll.
// - outer_size.y = 0.0f -> Bottom-align, consistent with BeginChild(). Not recommended unless table is last item in parent window. // - outer_size.y = 0.0f -> Bottom-align, consistent with BeginChild(). Not recommended unless table is last item in parent window.
// - outer_size.y > 0.0f -> Set Exact height. Recommended when using Scrolling on any axis. // - outer_size.y > 0.0f -> Set Exact height. Recommended when using Scrolling on any axis.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Outer size is also affected by the NoHostExtendX/NoHostExtendY flags. // Outer size is also affected by the NoHostExtendX/NoHostExtendY flags.
// Important to that note how the two flags have slightly different behaviors! // Important to note how the two flags have slightly different behaviors!
// - ImGuiTableFlags_NoHostExtendX -> Make outer width auto-fit to columns (overriding outer_size.x value). Only available when ScrollX/ScrollY are disabled and Stretch columns are not used. // - ImGuiTableFlags_NoHostExtendX -> Make outer width auto-fit to columns (overriding outer_size.x value). Only available when ScrollX/ScrollY are disabled and Stretch columns are not used.
// - ImGuiTableFlags_NoHostExtendY -> Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY is disabled. Data below the limit will be clipped and not visible. // - ImGuiTableFlags_NoHostExtendY -> Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY is disabled. Data below the limit will be clipped and not visible.
// In theory ImGuiTableFlags_NoHostExtendY could be the default and any non-scrolling tables with outer_size.y != 0.0f would use exact height. // In theory ImGuiTableFlags_NoHostExtendY could be the default and any non-scrolling tables with outer_size.y != 0.0f would use exact height.
// This would be consistent but perhaps less useful and more confusing (as vertically clipped items are not easily noticeable) // This would be consistent but perhaps less useful and more confusing (as vertically clipped items are not useful and not easily noticeable).
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// About 'inner_width': // About 'inner_width':
// With ScrollX disabled: // With ScrollX disabled:
@ -112,15 +112,16 @@ Index of this file:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// COLUMNS SIZING POLICIES // COLUMNS SIZING POLICIES
// (Reference: ImGuiTableFlags_SizingXXX flags and ImGuiTableColumnFlags_WidthXXX flags)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// About overriding column sizing policy and width/weight with TableSetupColumn(): // About overriding column sizing policy and width/weight with TableSetupColumn():
// We use a default parameter of 'init_width_or_weight == -1'. // We use a default parameter of -1 for 'init_width'/'init_weight'.
// - with ImGuiTableColumnFlags_WidthFixed, init_width <= 0 (default) --> width is automatic // - with ImGuiTableColumnFlags_WidthFixed, init_width <= 0 (default) --> width is automatic
// - with ImGuiTableColumnFlags_WidthFixed, init_width > 0 (explicit) --> width is custom // - with ImGuiTableColumnFlags_WidthFixed, init_width > 0 (explicit) --> width is custom
// - with ImGuiTableColumnFlags_WidthStretch, init_weight <= 0 (default) --> weight is 1.0f // - with ImGuiTableColumnFlags_WidthStretch, init_weight <= 0 (default) --> weight is 1.0f
// - with ImGuiTableColumnFlags_WidthStretch, init_weight > 0 (explicit) --> weight is custom // - with ImGuiTableColumnFlags_WidthStretch, init_weight > 0 (explicit) --> weight is custom
// Widths are specified _without_ CellPadding. If you specify a width of 100.0f, the column will be cover (100.0f + Padding * 2.0f) // Widths are specified _without_ CellPadding. If you specify a width of 100.0f, the column will be cover (100.0f + Padding * 2.0f)
// and you can fit a 100.0f wide item in it without clipping and with full padding. // and you can fit a 100.0f wide item in it without clipping and with padding honored.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// About default sizing policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag) // About default sizing policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag)
// - with Table policy ImGuiTableFlags_SizingFixedFit --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is equal to contents width // - with Table policy ImGuiTableFlags_SizingFixedFit --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is equal to contents width
@ -134,10 +135,10 @@ Index of this file:
// - using mixed policies with ScrollX does not make much sense, as using Stretch columns with ScrollX does not make much sense in the first place! // - using mixed policies with ScrollX does not make much sense, as using Stretch columns with ScrollX does not make much sense in the first place!
// that is, unless 'inner_width' is passed to BeginTable() to explicitly provide a total width to layout columns in. // that is, unless 'inner_width' is passed to BeginTable() to explicitly provide a total width to layout columns in.
// - when using ImGuiTableFlags_SizingFixedSame with mixed columns, only the Fixed/Auto columns will match their widths to the width of the maximum contents. // - when using ImGuiTableFlags_SizingFixedSame with mixed columns, only the Fixed/Auto columns will match their widths to the width of the maximum contents.
// - when using ImGuiTableFlags_SizingStretchSame with mixed columns, only the Stretch columns will match their weight/widths. // - when using ImGuiTableFlags_SizingStretchSame with mixed columns, only the Stretch columns will match their weights/widths.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// About using column width: // About using column width:
// If a column is manual resizable or has a width specified with TableSetupColumn(): // If a column is manually resizable or has a width specified with TableSetupColumn():
// - you may use GetContentRegionAvail().x to query the width available in a given column. // - you may use GetContentRegionAvail().x to query the width available in a given column.
// - right-side alignment features such as SetNextItemWidth(-x) or PushItemWidth(-x) will rely on this width. // - right-side alignment features such as SetNextItemWidth(-x) or PushItemWidth(-x) will rely on this width.
// If the column is not resizable and has no width specified with TableSetupColumn(): // If the column is not resizable and has no width specified with TableSetupColumn():
@ -151,7 +152,7 @@ Index of this file:
// TABLES CLIPPING/CULLING // TABLES CLIPPING/CULLING
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// About clipping/culling of Rows in Tables: // About clipping/culling of Rows in Tables:
// - For large numbers of rows, it is recommended you use ImGuiListClipper to only submit visible rows. // - For large numbers of rows, it is recommended you use ImGuiListClipper to submit only visible rows.
// ImGuiListClipper is reliant on the fact that rows are of equal height. // ImGuiListClipper is reliant on the fact that rows are of equal height.
// See 'Demo->Tables->Vertical Scrolling' or 'Demo->Tables->Advanced' for a demo of using the clipper. // See 'Demo->Tables->Vertical Scrolling' or 'Demo->Tables->Advanced' for a demo of using the clipper.
// - Note that auto-resizing columns don't play well with using the clipper. // - Note that auto-resizing columns don't play well with using the clipper.
@ -168,7 +169,7 @@ Index of this file:
// - Case C: column is hidden explicitly by the user (e.g. via the context menu, or _DefaultHide column flag, etc.). // - Case C: column is hidden explicitly by the user (e.g. via the context menu, or _DefaultHide column flag, etc.).
// //
// [A] [B] [C] // [A] [B] [C]
// TableNextColumn(): true false false -> [userland] when TableNextColumn() / TableSetColumnIndex() return false, user can skip submitting items but only if the column doesn't contribute to row height. // TableNextColumn(): true false false -> [userland] when TableNextColumn() / TableSetColumnIndex() returns false, user can skip submitting items but only if the column doesn't contribute to row height.
// SkipItems: false false true -> [internal] when SkipItems is true, most widgets will early out if submitted, resulting is no layout output. // SkipItems: false false true -> [internal] when SkipItems is true, most widgets will early out if submitted, resulting is no layout output.
// ClipRect: normal zero-width zero-width -> [internal] when ClipRect is zero, ItemAdd() will return false and most widgets will early out mid-way. // ClipRect: normal zero-width zero-width -> [internal] when ClipRect is zero, ItemAdd() will return false and most widgets will early out mid-way.
// ImDrawList output: normal dummy dummy -> [internal] when using the dummy channel, ImDrawList submissions (if any) will be wasted (because cliprect is zero-width anyway). // ImDrawList output: normal dummy dummy -> [internal] when using the dummy channel, ImDrawList submissions (if any) will be wasted (because cliprect is zero-width anyway).
@ -319,7 +320,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if (flags & ImGuiTableFlags_ScrollX) if (flags & ImGuiTableFlags_ScrollX)
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 rules may evolve. // If an outer size is specified ahead we will be able to early out when not visible. Exact clipping criteria may evolve.
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();
ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f); ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f);
@ -366,7 +367,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID"); IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID");
if (table->InstanceDataExtra.Size < instance_no) if (table->InstanceDataExtra.Size < instance_no)
table->InstanceDataExtra.push_back(ImGuiTableInstanceData()); table->InstanceDataExtra.push_back(ImGuiTableInstanceData());
instance_id = GetIDWithSeed(instance_no, GetIDWithSeed("##Instances", NULL, id)); // Push "##Instance" followed by (int)instance_no in ID stack. instance_id = GetIDWithSeed(instance_no, GetIDWithSeed("##Instances", NULL, id)); // Push "##Instances" followed by (int)instance_no in ID stack.
} }
else else
{ {
@ -477,12 +478,13 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->IsUnfrozenRows = true; table->IsUnfrozenRows = true;
table->DeclColumnsCount = 0; table->DeclColumnsCount = 0;
// Using opaque colors facilitate overlapping elements of the grid // Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders()
table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong); table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong);
table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight); table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight);
// Make table current // Make table current
g.CurrentTable = table; g.CurrentTable = table;
outer_window->DC.NavIsScrollPushableX = false; // Shortcut for NavUpdateCurrentWindowIsScrollPushableX();
outer_window->DC.CurrentTableIdx = table_idx; outer_window->DC.CurrentTableIdx = table_idx;
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;
@ -490,7 +492,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if ((table_last_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0) if ((table_last_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0)
table->IsResetDisplayOrderRequest = true; table->IsResetDisplayOrderRequest = true;
// Mark as used // Mark as used to avoid GC
if (table_idx >= g.TablesLastTimeActive.Size) if (table_idx >= g.TablesLastTimeActive.Size)
g.TablesLastTimeActive.resize(table_idx + 1, -1.0f); g.TablesLastTimeActive.resize(table_idx + 1, -1.0f);
g.TablesLastTimeActive[table_idx] = (float)g.Time; g.TablesLastTimeActive[table_idx] = (float)g.Time;
@ -583,13 +585,13 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
} }
// For reference, the average total _allocation count_ for a table is: // For reference, the average total _allocation count_ for a table is:
// + 0 (for ImGuiTable instance, we are pooling allocations in g.Tables) // + 0 (for ImGuiTable instance, we are pooling allocations in g.Tables[])
// + 1 (for table->RawData allocated below) // + 1 (for table->RawData allocated below)
// + 1 (for table->ColumnsNames, if names are used) // + 1 (for table->ColumnsNames, if names are used)
// Shared allocations per number of nested tables // Shared allocations for the maximum number of simultaneously nested tables (generally a very small number)
// + 1 (for table->Splitter._Channels) // + 1 (for table->Splitter._Channels)
// + 2 * active_channels_count (for ImDrawCmd and ImDrawIdx buffers inside channels) // + 2 * active_channels_count (for ImDrawCmd and ImDrawIdx buffers inside channels)
// Where active_channels_count is variable but often == columns_count or columns_count + 1, see TableSetupDrawChannels() for details. // Where active_channels_count is variable but often == columns_count or == columns_count + 1, see TableSetupDrawChannels() for details.
// Unused channels don't perform their +2 allocations. // Unused channels don't perform their +2 allocations.
void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count) void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count)
{ {
@ -616,7 +618,7 @@ void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count)
void ImGui::TableBeginApplyRequests(ImGuiTable* table) void ImGui::TableBeginApplyRequests(ImGuiTable* table)
{ {
// Handle resizing request // Handle resizing request
// (We process this at the first TableBegin of the frame) // (We process this in the TableBegin() of the first instance of each table)
// FIXME-TABLE: Contains columns if our work area doesn't allow for scrolling? // FIXME-TABLE: Contains columns if our work area doesn't allow for scrolling?
if (table->InstanceCurrent == 0) if (table->InstanceCurrent == 0)
{ {
@ -661,8 +663,7 @@ void ImGui::TableBeginApplyRequests(ImGuiTable* table)
table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder -= (ImGuiTableColumnIdx)reorder_dir; table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder -= (ImGuiTableColumnIdx)reorder_dir;
IM_ASSERT(dst_column->DisplayOrder == dst_order - reorder_dir); IM_ASSERT(dst_column->DisplayOrder == dst_order - reorder_dir);
// Display order is stored in both columns->IndexDisplayOrder and table->DisplayOrder[], // Display order is stored in both columns->IndexDisplayOrder and table->DisplayOrder[]. Rebuild later from the former.
// rebuild the later from the former.
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImGuiTableColumnIdx)column_n; table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImGuiTableColumnIdx)column_n;
table->ReorderColumnDir = 0; table->ReorderColumnDir = 0;
@ -736,8 +737,8 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I
} }
} }
// Layout columns for the frame. This is in essence the followup to BeginTable(). // Layout columns for the frame. This is in essence the followup to BeginTable() and this is our largest function.
// Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() to be called first. // Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() and other TableSetupXXXXX() functions to be called first.
// FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for _WidthAuto columns. // FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for _WidthAuto columns.
// Increase feedback side-effect with widgets relying on WorkRect.Max.x... Maybe provide a default distribution for _WidthAuto columns? // Increase feedback side-effect with widgets relying on WorkRect.Max.x... Maybe provide a default distribution for _WidthAuto columns?
void ImGui::TableUpdateLayout(ImGuiTable* table) void ImGui::TableUpdateLayout(ImGuiTable* table)
@ -858,8 +859,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
table->IsSettingsDirty = true; table->IsSettingsDirty = true;
// [Part 3] Fix column flags and record a few extra information. // [Part 3] Fix column flags and record a few extra information.
float sum_width_requests = 0.0f; // Sum of all width for fixed and auto-resize columns, excluding width contributed by Stretch columns but including spacing/padding. float sum_width_requests = 0.0f; // Sum of all width for fixed and auto-resize columns, excluding width contributed by Stretch columns but including spacing/padding.
float stretch_sum_weights = 0.0f; // Sum of all weights for stretch columns. float stretch_sum_weights = 0.0f; // Sum of all weights for stretch columns.
table->LeftMostStretchedColumn = table->RightMostStretchedColumn = -1; table->LeftMostStretchedColumn = table->RightMostStretchedColumn = -1;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{ {
@ -1144,7 +1145,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
EndPopup(); EndPopup();
} }
// [Part 12] Sanitize and build sort specs before we have a change to use them for display. // [Part 12] Sanitize and build sort specs before we have a chance to use them for display.
// This path will only be exercised when sort specs are modified before header rows (e.g. init or visibility change) // This path will only be exercised when sort specs are modified before header rows (e.g. init or visibility change)
if (table->IsSortSpecsDirty && (table->Flags & ImGuiTableFlags_Sortable)) if (table->IsSortSpecsDirty && (table->Flags & ImGuiTableFlags_Sortable))
TableSortSpecsBuild(table); TableSortSpecsBuild(table);
@ -1165,9 +1166,9 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
} }
// Process hit-testing on resizing borders. Actual size change will be applied in EndTable() // Process hit-testing on resizing borders. Actual size change will be applied in EndTable()
// - Set table->HoveredColumnBorder with a short delay/timer to reduce feedback noise // - Set table->HoveredColumnBorder with a short delay/timer to reduce visual feedback noise.
// - Submit ahead of table contents and header, use ImGuiButtonFlags_AllowItemOverlap to prioritize widgets // - Submit ahead of table contents and header, use ImGuiButtonFlags_AllowItemOverlap to prioritize
// overlapping the same area. // widgets overlapping the same area.
void ImGui::TableUpdateBorders(ImGuiTable* table) void ImGui::TableUpdateBorders(ImGuiTable* table)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -1436,6 +1437,7 @@ void ImGui::EndTable()
g.CurrentTable->DrawSplitter = &temp_data->DrawSplitter; g.CurrentTable->DrawSplitter = &temp_data->DrawSplitter;
} }
outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1; outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1;
NavUpdateCurrentWindowIsScrollPushableX();
} }
// See "COLUMN SIZING POLICIES" comments at the top of this file // See "COLUMN SIZING POLICIES" comments at the top of this file
@ -1641,7 +1643,7 @@ ImGuiID ImGui::TableGetColumnResizeID(ImGuiTable* table, int column_n, int insta
return instance_id + 1 + column_n; // FIXME: #6140: still not ideal return instance_id + 1 + column_n; // FIXME: #6140: still not ideal
} }
// Return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered. // Return -1 when table is not hovered. return columns_count if hovering the unused space at the right of the right-most visible column.
int ImGui::TableGetHoveredColumn() int ImGui::TableGetHoveredColumn()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -1978,6 +1980,7 @@ bool ImGui::TableNextColumn()
// FIXME-TABLE FIXME-OPT: Could probably shortcut some things for non-active or clipped columns. // FIXME-TABLE FIXME-OPT: Could probably shortcut some things for non-active or clipped columns.
void ImGui::TableBeginCell(ImGuiTable* table, int column_n) void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
{ {
ImGuiContext& g = *GImGui;
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
ImGuiWindow* window = table->InnerWindow; ImGuiWindow* window = table->InnerWindow;
table->CurrentColumn = column_n; table->CurrentColumn = column_n;
@ -2002,7 +2005,6 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
window->SkipItems = column->IsSkipItems; window->SkipItems = column->IsSkipItems;
if (column->IsSkipItems) if (column->IsSkipItems)
{ {
ImGuiContext& g = *GImGui;
g.LastItemData.ID = 0; g.LastItemData.ID = 0;
g.LastItemData.StatusFlags = 0; g.LastItemData.StatusFlags = 0;
} }
@ -2021,7 +2023,6 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
} }
// Logging // Logging
ImGuiContext& g = *GImGui;
if (g.LogEnabled && !column->IsSkipItems) if (g.LogEnabled && !column->IsSkipItems)
{ {
LogRenderedText(&window->DC.CursorPos, "|"); LogRenderedText(&window->DC.CursorPos, "|");
@ -2141,7 +2142,7 @@ void ImGui::TableSetColumnWidth(int column_n, float width)
// - All stretch: easy. // - All stretch: easy.
// - One or more fixed + one stretch: easy. // - One or more fixed + one stretch: easy.
// - One or more fixed + more than one stretch: tricky. // - One or more fixed + more than one stretch: tricky.
// Qt when manual resize is enabled only support a single _trailing_ stretch column. // Qt when manual resize is enabled only supports a single _trailing_ stretch column, we support more cases here.
// When forwarding resize from Wn| to Fn+1| we need to be considerate of the _NoResize flag on Fn+1. // When forwarding resize from Wn| to Fn+1| we need to be considerate of the _NoResize flag on Fn+1.
// FIXME-TABLE: Find a way to rewrite all of this so interactions feel more consistent for the user. // FIXME-TABLE: Find a way to rewrite all of this so interactions feel more consistent for the user.
@ -2224,7 +2225,7 @@ void ImGui::TableUpdateColumnsWeightFromWidth(ImGuiTable* table)
{ {
IM_ASSERT(table->LeftMostStretchedColumn != -1 && table->RightMostStretchedColumn != -1); IM_ASSERT(table->LeftMostStretchedColumn != -1 && table->RightMostStretchedColumn != -1);
// Measure existing quantity // Measure existing quantities
float visible_weight = 0.0f; float visible_weight = 0.0f;
float visible_width = 0.0f; float visible_width = 0.0f;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
@ -2381,11 +2382,11 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
struct MergeGroup struct MergeGroup
{ {
ImRect ClipRect; ImRect ClipRect;
int ChannelsCount; int ChannelsCount = 0;
ImBitArrayPtr ChannelsMask; ImBitArrayPtr ChannelsMask = NULL;
}; };
int merge_group_mask = 0x00; int merge_group_mask = 0x00;
MergeGroup merge_groups[4] = {}; MergeGroup merge_groups[4];
// Use a reusable temp buffer for the merge masks as they are dynamically sized. // Use a reusable temp buffer for the merge masks as they are dynamically sized.
const int max_draw_channels = (4 + table->ColumnsCount * 2); const int max_draw_channels = (4 + table->ColumnsCount * 2);
@ -2499,11 +2500,9 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
merge_clip_rect.Max.x = ImMax(merge_clip_rect.Max.x, host_rect.Max.x); merge_clip_rect.Max.x = ImMax(merge_clip_rect.Max.x, host_rect.Max.x);
if ((merge_group_n & 2) != 0 && (table->Flags & ImGuiTableFlags_NoHostExtendY) == 0) if ((merge_group_n & 2) != 0 && (table->Flags & ImGuiTableFlags_NoHostExtendY) == 0)
merge_clip_rect.Max.y = ImMax(merge_clip_rect.Max.y, host_rect.Max.y); merge_clip_rect.Max.y = ImMax(merge_clip_rect.Max.y, host_rect.Max.y);
#if 0 //GetForegroundDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 0, 0, 200), 0.0f, 0, 1.0f); // [DEBUG]
GetOverlayDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 0, 0, 200), 0.0f, 0, 1.0f); //GetForegroundDrawList()->AddLine(merge_group->ClipRect.Min, merge_clip_rect.Min, IM_COL32(255, 100, 0, 200));
GetOverlayDrawList()->AddLine(merge_group->ClipRect.Min, merge_clip_rect.Min, IM_COL32(255, 100, 0, 200)); //GetForegroundDrawList()->AddLine(merge_group->ClipRect.Max, merge_clip_rect.Max, IM_COL32(255, 100, 0, 200));
GetOverlayDrawList()->AddLine(merge_group->ClipRect.Max, merge_clip_rect.Max, IM_COL32(255, 100, 0, 200));
#endif
remaining_count -= merge_group->ChannelsCount; remaining_count -= merge_group->ChannelsCount;
for (int n = 0; n < (size_for_masks_bitarrays_one >> 2); n++) for (int n = 0; n < (size_for_masks_bitarrays_one >> 2); n++)
remaining_mask[n] &= ~merge_group->ChannelsMask[n]; remaining_mask[n] &= ~merge_group->ChannelsMask[n];
@ -2667,7 +2666,6 @@ ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
TableUpdateLayout(table); TableUpdateLayout(table);
TableSortSpecsBuild(table); TableSortSpecsBuild(table);
return &table->SortSpecs; return &table->SortSpecs;
} }
@ -2786,7 +2784,7 @@ void ImGui::TableSortSpecsSanitize(ImGuiTable* table)
} }
} }
// Fallback default sort order (if no column had the ImGuiTableColumnFlags_DefaultSort flag) // Fallback default sort order (if no column with the ImGuiTableColumnFlags_DefaultSort flag)
if (sort_order_count == 0 && !(table->Flags & ImGuiTableFlags_SortTristate)) if (sort_order_count == 0 && !(table->Flags & ImGuiTableFlags_SortTristate))
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{ {
@ -3007,7 +3005,7 @@ void ImGui::TableHeader(const char* label)
} }
// Sort order arrow // Sort order arrow
const float ellipsis_max = cell_r.Max.x - w_arrow - w_sort_text; const float ellipsis_max = ImMax(cell_r.Max.x - w_arrow - w_sort_text, label_pos.x);
if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort)) if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort))
{ {
if (column->SortOrder != -1) if (column->SortOrder != -1)
@ -3477,12 +3475,12 @@ static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandle
if (!save_column) if (!save_column)
continue; continue;
buf->appendf("Column %-2d", column_n); buf->appendf("Column %-2d", column_n);
if (column->UserID != 0) buf->appendf(" UserID=%08X", column->UserID); if (column->UserID != 0) { buf->appendf(" UserID=%08X", column->UserID); }
if (save_size && column->IsStretch) buf->appendf(" Weight=%.4f", column->WidthOrWeight); if (save_size && column->IsStretch) { buf->appendf(" Weight=%.4f", column->WidthOrWeight); }
if (save_size && !column->IsStretch) buf->appendf(" Width=%d", (int)column->WidthOrWeight); if (save_size && !column->IsStretch) { buf->appendf(" Width=%d", (int)column->WidthOrWeight); }
if (save_visible) buf->appendf(" Visible=%d", column->IsEnabled); if (save_visible) { buf->appendf(" Visible=%d", column->IsEnabled); }
if (save_order) buf->appendf(" Order=%d", column->DisplayOrder); if (save_order) { buf->appendf(" Order=%d", column->DisplayOrder); }
if (save_sort && column->SortOrder != -1) buf->appendf(" Sort=%d%c", column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? 'v' : '^'); if (save_sort && column->SortOrder != -1) { buf->appendf(" Sort=%d%c", column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? 'v' : '^'); }
buf->append("\n"); buf->append("\n");
} }
buf->append("\n"); buf->append("\n");
@ -3530,7 +3528,7 @@ void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table)
IM_ASSERT(table->MemoryCompacted == false); IM_ASSERT(table->MemoryCompacted == false);
table->SortSpecs.Specs = NULL; table->SortSpecs.Specs = NULL;
table->SortSpecsMulti.clear(); table->SortSpecsMulti.clear();
table->IsSortSpecsDirty = true; // FIXME: shouldn't have to leak into user performing a sort table->IsSortSpecsDirty = true; // FIXME: In theory shouldn't have to leak into user performing a sort on resume.
table->ColumnsNames.clear(); table->ColumnsNames.clear();
table->MemoryCompacted = true; table->MemoryCompacted = true;
for (int n = 0; n < table->ColumnsCount; n++) for (int n = 0; n < table->ColumnsCount; n++)
@ -3583,13 +3581,9 @@ static const char* DebugNodeTableGetSizingPolicyDesc(ImGuiTableFlags sizing_poli
void ImGui::DebugNodeTable(ImGuiTable* table) void ImGui::DebugNodeTable(ImGuiTable* table)
{ {
char buf[512]; const bool is_active = (table->LastFrameActive >= GetFrameCount() - 2); // Note that fully clipped early out scrolling tables will appear as inactive here.
char* p = buf;
const char* buf_end = buf + IM_ARRAYSIZE(buf);
const bool is_active = (table->LastFrameActive >= ImGui::GetFrameCount() - 2); // Note that fully clipped early out scrolling tables will appear as inactive here.
ImFormatString(p, buf_end - p, "Table 0x%08X (%d columns, in '%s')%s", table->ID, table->ColumnsCount, table->OuterWindow->Name, is_active ? "" : " *Inactive*");
if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
bool open = TreeNode(table, "%s", buf); bool open = TreeNode(table, "Table 0x%08X (%d columns, in '%s')%s", table->ID, table->ColumnsCount, table->OuterWindow->Name, is_active ? "" : " *Inactive*");
if (!is_active) { PopStyleColor(); } if (!is_active) { PopStyleColor(); }
if (IsItemHovered()) if (IsItemHovered())
GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255)); GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255));
@ -3598,7 +3592,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
if (!open) if (!open)
return; return;
if (table->InstanceCurrent > 0) if (table->InstanceCurrent > 0)
ImGui::Text("** %d instances of same table! Some data below will refer to last instance.", table->InstanceCurrent + 1); Text("** %d instances of same table! Some data below will refer to last instance.", table->InstanceCurrent + 1);
bool clear_settings = SmallButton("Clear settings"); bool clear_settings = SmallButton("Clear settings");
BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags)); BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags));
BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : ""); BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");
@ -3614,6 +3608,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
{ {
ImGuiTableColumn* column = &table->Columns[n]; ImGuiTableColumn* column = &table->Columns[n];
const char* name = TableGetColumnName(table, n); const char* name = TableGetColumnName(table, n);
char buf[512];
ImFormatString(buf, IM_ARRAYSIZE(buf), ImFormatString(buf, IM_ARRAYSIZE(buf),
"Column %d order %d '%s': offset %+.2f to %+.2f%s\n" "Column %d order %d '%s': offset %+.2f to %+.2f%s\n"
"Enabled: %d, VisibleX/Y: %d/%d, RequestOutput: %d, SkipItems: %d, DrawChannels: %d,%d\n" "Enabled: %d, VisibleX/Y: %d/%d, RequestOutput: %d, SkipItems: %d, DrawChannels: %d,%d\n"
@ -3902,6 +3897,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiOldColumnFl
columns->Count = columns_count; columns->Count = columns_count;
columns->Flags = flags; columns->Flags = flags;
window->DC.CurrentColumns = columns; window->DC.CurrentColumns = columns;
window->DC.NavIsScrollPushableX = false; // Shortcut for NavUpdateCurrentWindowIsScrollPushableX();
columns->HostCursorPosY = window->DC.CursorPos.y; columns->HostCursorPosY = window->DC.CursorPos.y;
columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x;
@ -4092,6 +4088,7 @@ void ImGui::EndColumns()
window->DC.CurrentColumns = NULL; window->DC.CurrentColumns = NULL;
window->DC.ColumnsOffset.x = 0.0f; window->DC.ColumnsOffset.x = 0.0f;
window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
NavUpdateCurrentWindowIsScrollPushableX();
} }
void ImGui::Columns(int columns_count, const char* id, bool border) void ImGui::Columns(int columns_count, const char* id, bool border)

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.4 // dear imgui, v1.89.6
// (widgets code) // (widgets code)
/* /*
@ -622,7 +622,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
// Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button.
pressed = true; pressed = true;
SetActiveID(id, window); SetActiveID(id, window);
g.ActiveIdSource = ImGuiInputSource_Nav; g.ActiveIdSource = g.NavInputSource;
if (!(flags & ImGuiButtonFlags_NoNavFocus)) if (!(flags & ImGuiButtonFlags_NoNavFocus))
SetFocusID(id, window); SetFocusID(id, window);
} }
@ -638,7 +638,12 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; g.ActiveIdClickOffset = g.IO.MousePos - bb.Min;
const int mouse_button = g.ActiveIdMouseButton; const int mouse_button = g.ActiveIdMouseButton;
if (IsMouseDown(mouse_button, test_owner_id)) if (mouse_button == -1)
{
// Fallback for the rare situation were g.ActiveId was set programmatically or from another widget (e.g. #6304).
ClearActiveID();
}
else if (IsMouseDown(mouse_button, test_owner_id))
{ {
held = true; held = true;
} }
@ -660,7 +665,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
if (!(flags & ImGuiButtonFlags_NoNavFocus)) if (!(flags & ImGuiButtonFlags_NoNavFocus))
g.NavDisableHighlight = true; g.NavDisableHighlight = true;
} }
else if (g.ActiveIdSource == ImGuiInputSource_Nav) else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
{ {
// When activated using Nav, we hold on the ActiveID until activation button is released // When activated using Nav, we hold on the ActiveID until activation button is released
if (g.NavActivateDownId != id) if (g.NavActivateDownId != id)
@ -827,7 +832,7 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered); ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered);
ImVec2 center = bb.GetCenter(); ImVec2 center = bb.GetCenter();
if (hovered) if (hovered)
window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col, 12); window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col);
float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f; float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
ImU32 cross_col = GetColorU32(ImGuiCol_Text); ImU32 cross_col = GetColorU32(ImGuiCol_Text);
@ -852,7 +857,7 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos)
ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
ImU32 text_col = GetColorU32(ImGuiCol_Text); ImU32 text_col = GetColorU32(ImGuiCol_Text);
if (hovered || held) if (hovered || held)
window->DrawList->AddCircleFilled(bb.GetCenter()/*+ ImVec2(0.0f, -0.5f)*/, g.FontSize * 0.5f + 1.0f, bg_col, 12); window->DrawList->AddCircleFilled(bb.GetCenter()/*+ ImVec2(0.0f, -0.5f)*/, g.FontSize * 0.5f + 1.0f, bg_col);
RenderArrow(window->DrawList, bb.Min + g.Style.FramePadding, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); RenderArrow(window->DrawList, bb.Min + g.Style.FramePadding, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f);
// Switch to moving the window after mouse is moved beyond the initial drag threshold // Switch to moving the window after mouse is moved beyond the initial drag threshold
@ -1233,17 +1238,18 @@ bool ImGui::RadioButton(const char* label, bool active)
MarkItemEdited(id); MarkItemEdited(id);
RenderNavHighlight(total_bb, id); RenderNavHighlight(total_bb, id);
window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); const int num_segment = window->DrawList->_CalcCircleAutoSegmentCount(radius);
window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), num_segment);
if (active) if (active)
{ {
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark), 16); window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark));
} }
if (style.FrameBorderSize > 0.0f) if (style.FrameBorderSize > 0.0f)
{ {
window->DrawList->AddCircle(center + ImVec2(1, 1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize); window->DrawList->AddCircle(center + ImVec2(1, 1), radius, GetColorU32(ImGuiCol_BorderShadow), num_segment, style.FrameBorderSize);
window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize); window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), num_segment, style.FrameBorderSize);
} }
ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
@ -1386,8 +1392,9 @@ void ImGui::AlignTextToFramePadding()
} }
// Horizontal/vertical separating line // Horizontal/vertical separating line
// FIXME: Surprisingly, this seemingly simple widget is adjacent to MANY different legacy/tricky layout issues. // FIXME: Surprisingly, this seemingly trivial widget is a victim of many different legacy/tricky layout issues.
void ImGui::SeparatorEx(ImGuiSeparatorFlags flags) // Note how thickness == 1.0f is handled specifically as not moving CursorPos by 'thickness', but other values are.
void ImGui::SeparatorEx(ImGuiSeparatorFlags flags, float thickness)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
@ -1395,8 +1402,8 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical))); // Check that only 1 option is selected IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical))); // Check that only 1 option is selected
IM_ASSERT(thickness > 0.0f);
const float thickness = 1.0f; // Cannot use g.Style.SeparatorTextSize yet for various reasons.
if (flags & ImGuiSeparatorFlags_Vertical) if (flags & ImGuiSeparatorFlags_Vertical)
{ {
// Vertical separator, for menu bars (use current line height). // Vertical separator, for menu bars (use current line height).
@ -1430,6 +1437,8 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
x2 = table->Columns[table->CurrentColumn].MaxX; x2 = table->Columns[table->CurrentColumn].MaxX;
} }
// Before Tables API happened, we relied on Separator() to span all columns of a Columns() set.
// We currently don't need to provide the same feature for tables because tables naturally have border features.
ImGuiOldColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL; ImGuiOldColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL;
if (columns) if (columns)
PushColumnsBackground(); PushColumnsBackground();
@ -1439,8 +1448,8 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
const float thickness_for_layout = (thickness == 1.0f) ? 0.0f : thickness; // FIXME: See 1.70/1.71 Separator() change: makes legacy 1-px separator not affect layout yet. Should change. const float thickness_for_layout = (thickness == 1.0f) ? 0.0f : thickness; // FIXME: See 1.70/1.71 Separator() change: makes legacy 1-px separator not affect layout yet. Should change.
const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness)); const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness));
ItemSize(ImVec2(0.0f, thickness_for_layout)); ItemSize(ImVec2(0.0f, thickness_for_layout));
const bool item_visible = ItemAdd(bb, 0);
if (item_visible) if (ItemAdd(bb, 0))
{ {
// Draw // Draw
window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator)); window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator));
@ -1463,10 +1472,11 @@ void ImGui::Separator()
if (window->SkipItems) if (window->SkipItems)
return; return;
// Those flags should eventually be overridable by the user // Those flags should eventually be configurable by the user
// FIXME: We cannot g.Style.SeparatorTextBorderSize for thickness as it relates to SeparatorText() which is a decorated separator, not defaulting to 1.0f.
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal; ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
flags |= ImGuiSeparatorFlags_SpanAllColumns; // NB: this only applies to legacy Columns() api as they relied on Separator() a lot. flags |= ImGuiSeparatorFlags_SpanAllColumns; // NB: this only applies to legacy Columns() api as they relied on Separator() a lot.
SeparatorEx(flags); SeparatorEx(flags, 1.0f);
} }
void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_w) void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_w)
@ -1526,8 +1536,8 @@ void ImGui::SeparatorText(const char* label)
return; return;
// The SeparatorText() vs SeparatorTextEx() distinction is designed to be considerate that we may want: // The SeparatorText() vs SeparatorTextEx() distinction is designed to be considerate that we may want:
// - allow headers to be draggable items (would require a stable ID + a noticeable highlight) // - allow separator-text to be draggable items (would require a stable ID + a noticeable highlight)
// - this high-level entry point to allow formatting? (may require ID separate from formatted string) // - this high-level entry point to allow formatting? (which in turns may require ID separate from formatted string)
// - because of this we probably can't turn 'const char* label' into 'const char* fmt, ...' // - because of this we probably can't turn 'const char* label' into 'const char* fmt, ...'
// Otherwise, we can decide that users wanting to drag this would layout a dedicated drag-item, // Otherwise, we can decide that users wanting to drag this would layout a dedicated drag-item,
// and then we can turn this into a format function. // and then we can turn this into a format function.
@ -2084,7 +2094,8 @@ bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void
memcpy(&data_backup, p_data, type_info->Size); memcpy(&data_backup, p_data, type_info->Size);
// Sanitize format // Sanitize format
// For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf // - For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf
// - In theory could treat empty format as using default, but this would only cover rare/bizarre case of using InputScalar() + integer + format string without %.
char format_sanitized[32]; char format_sanitized[32];
if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
format = type_info->ScanFmt; format = type_info->ScanFmt;
@ -2245,7 +2256,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
if (g.IO.KeyShift) if (g.IO.KeyShift)
adjust_delta *= 10.0f; adjust_delta *= 10.0f;
} }
else if (g.ActiveIdSource == ImGuiInputSource_Nav) else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
{ {
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);
@ -2352,7 +2363,7 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v
// Those are the things we can do easily outside the DragBehaviorT<> template, saves code generation. // Those are the things we can do easily outside the DragBehaviorT<> template, saves code generation.
if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0]) if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0])
ClearActiveID(); ClearActiveID();
else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) else if ((g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
ClearActiveID(); ClearActiveID();
} }
if (g.ActiveId != id) if (g.ActiveId != id)
@ -2821,7 +2832,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
set_new_value = true; set_new_value = true;
} }
} }
else if (g.ActiveIdSource == ImGuiInputSource_Nav) else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
{ {
if (g.ActiveIdIsJustActivated) if (g.ActiveIdIsJustActivated)
{ {
@ -3267,7 +3278,7 @@ const char* ImParseFormatFindEnd(const char* fmt)
} }
// Extract the format out of a format string with leading or trailing decorations // Extract the format out of a format string with leading or trailing decorations
// fmt = "blah blah" -> return fmt // fmt = "blah blah" -> return ""
// fmt = "%.3f" -> return fmt // fmt = "%.3f" -> return fmt
// fmt = "hello %.3f" -> return fmt + 6 // fmt = "hello %.3f" -> return fmt + 6
// fmt = "%.3f hello" -> return buf written with "%.3f" // fmt = "%.3f hello" -> return buf written with "%.3f"
@ -3275,7 +3286,7 @@ const char* ImParseFormatTrimDecorations(const char* fmt, char* buf, size_t buf_
{ {
const char* fmt_start = ImParseFormatFindStart(fmt); const char* fmt_start = ImParseFormatFindStart(fmt);
if (fmt_start[0] != '%') if (fmt_start[0] != '%')
return fmt; return "";
const char* fmt_end = ImParseFormatFindEnd(fmt_start); const char* fmt_end = ImParseFormatFindEnd(fmt_start);
if (fmt_end[0] == 0) // If we only have leading decoration, we don't need to copy the data. if (fmt_end[0] == 0) // If we only have leading decoration, we don't need to copy the data.
return fmt_start; return fmt_start;
@ -3300,7 +3311,7 @@ void ImParseFormatSanitizeForPrinting(const char* fmt_in, char* fmt_out, size_t
*fmt_out = 0; // Zero-terminate *fmt_out = 0; // Zero-terminate
} }
// - For scanning we need to remove all width and precision fields "%3.7f" -> "%f". BUT don't strip types like "%I64d" which includes digits. ! "%07I64d" -> "%I64d" // - For scanning we need to remove all width and precision fields and flags "%+3.7f" -> "%f". BUT don't strip types like "%I64d" which includes digits. ! "%07I64d" -> "%I64d"
const char* ImParseFormatSanitizeForScanning(const char* fmt_in, char* fmt_out, size_t fmt_out_size) const char* ImParseFormatSanitizeForScanning(const char* fmt_in, char* fmt_out, size_t fmt_out_size)
{ {
const char* fmt_end = ImParseFormatFindEnd(fmt_in); const char* fmt_end = ImParseFormatFindEnd(fmt_in);
@ -3311,7 +3322,7 @@ const char* ImParseFormatSanitizeForScanning(const char* fmt_in, char* fmt_out,
while (fmt_in < fmt_end) while (fmt_in < fmt_end)
{ {
char c = *fmt_in++; char c = *fmt_in++;
if (!has_type && ((c >= '0' && c <= '9') || c == '.')) if (!has_type && ((c >= '0' && c <= '9') || c == '.' || c == '+' || c == '#'))
continue; continue;
has_type |= ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); // Stop skipping digits has_type |= ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); // Stop skipping digits
if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '. if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '.
@ -3393,9 +3404,14 @@ static inline ImGuiInputTextFlags InputScalar_DefaultCharsFilter(ImGuiDataType d
// However this may not be ideal for all uses, as some user code may break on out of bound values. // However this may not be ideal for all uses, as some user code may break on out of bound values.
bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max) bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max)
{ {
// FIXME: May need to clarify display behavior if format doesn't contain %.
// "%d" -> "%d" / "There are %d items" -> "%d" / "items" -> "%d" (fallback). Also see #6405
const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type);
char fmt_buf[32]; char fmt_buf[32];
char data_buf[32]; char data_buf[32];
format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf)); format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
if (format[0] == 0)
format = type_info->PrintFmt;
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);
@ -3406,7 +3422,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags)) if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags))
{ {
// Backup old value // Backup old value
size_t data_type_size = DataTypeGetInfo(data_type)->Size; size_t data_type_size = type_info->Size;
ImGuiDataTypeTempStorage data_backup; ImGuiDataTypeTempStorage data_backup;
memcpy(&data_backup, p_data, data_type_size); memcpy(&data_backup, p_data, data_type_size);
@ -3450,7 +3466,12 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
flags |= ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string. flags |= ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
bool value_changed = false; bool value_changed = false;
if (p_step != NULL) if (p_step == NULL)
{
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
}
else
{ {
const float button_size = GetFrameHeight(); const float button_size = GetFrameHeight();
@ -3493,11 +3514,6 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
PopID(); PopID();
EndGroup(); EndGroup();
} }
else
{
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
}
if (value_changed) if (value_changed)
MarkItemEdited(g.LastItemData.ID); MarkItemEdited(g.LastItemData.ID);
@ -3699,10 +3715,34 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob
r->num_chars = (int)(text_remaining - (text + line_start_idx)); r->num_chars = (int)(text_remaining - (text + line_start_idx));
} }
// When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators. static bool is_separator(unsigned int c)
static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r'; } {
static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; } return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r' || c=='.' || c=='!';
static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx])) : 1; } }
static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
{
// When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators.
if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
return 0;
bool prev_white = ImCharIsBlankW(obj->TextW[idx - 1]);
bool prev_separ = is_separator(obj->TextW[idx - 1]);
bool curr_white = ImCharIsBlankW(obj->TextW[idx]);
bool curr_separ = is_separator(obj->TextW[idx]);
return ((prev_white || prev_separ) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
}
static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
{
if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
return 0;
bool prev_white = ImCharIsBlankW(obj->TextW[idx]);
bool prev_separ = is_separator(obj->TextW[idx]);
bool curr_white = ImCharIsBlankW(obj->TextW[idx - 1]);
bool curr_separ = is_separator(obj->TextW[idx - 1]);
return ((prev_white) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
}
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
static int STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } static int STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
static int STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } static int STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
@ -3999,6 +4039,21 @@ static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* st
p[i] = ImStb::STB_TEXTEDIT_GETCHAR(state, first_diff + i); p[i] = ImStb::STB_TEXTEDIT_GETCHAR(state, first_diff + i);
} }
// As InputText() retain textual data and we currently provide a path for user to not retain it (via local variables)
// we need some form of hook to reapply data back to user buffer on deactivation frame. (#4714)
// It would be more desirable that we discourage users from taking advantage of the "user not retaining data" trick,
// but that more likely be attractive when we do have _NoLiveEdit flag available.
void ImGui::InputTextDeactivateHook(ImGuiID id)
{
ImGuiContext& g = *GImGui;
ImGuiInputTextState* state = &g.InputTextState;
if (id == 0 || state->ID != id)
return;
g.InputTextDeactivatedState.ID = state->ID;
g.InputTextDeactivatedState.TextA.resize(state->CurLenA + 1);
memcpy(g.InputTextDeactivatedState.TextA.Data, state->TextA.Data ? state->TextA.Data : "", state->CurLenA + 1);
}
// Edit a string of text // Edit a string of text
// - buf_size account for the zero-terminator, so a buf_size of 6 can hold "Hello" but not "Hello!". // - buf_size account for the zero-terminator, so a buf_size of 6 can hold "Hello" but not "Hello!".
// This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match // This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match
@ -4104,7 +4159,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); // state != NULL means its our state.
const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_tabbing); const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_tabbing);
const bool init_state = (init_make_active || user_scroll_active); const bool init_state = (init_make_active || user_scroll_active);
if ((init_state && g.ActiveId != id) || init_changed_specs) if ((init_state && g.ActiveId != id) || init_changed_specs)
@ -4113,6 +4168,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state = &g.InputTextState; state = &g.InputTextState;
state->CursorAnimReset(); state->CursorAnimReset();
// Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714)
InputTextDeactivateHook(state->ID);
// Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar) // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
// From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode) // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)
const int buf_len = (int)strlen(buf); const int buf_len = (int)strlen(buf);
@ -4248,7 +4306,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget. // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
// Down the line we should have a cleaner library-wide concept of Selected vs Active. // Down the line we should have a cleaner library-wide concept of Selected vs Active.
g.ActiveIdAllowOverlap = !io.MouseDown[0]; g.ActiveIdAllowOverlap = !io.MouseDown[0];
g.WantTextInputNextFrame = 1;
// Edit in progress // Edit in progress
const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX; const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX;
@ -4525,6 +4582,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Push records into the undo stack so we can CTRL+Z the revert operation itself // Push records into the undo stack so we can CTRL+Z the revert operation itself
apply_new_text = state->InitialTextA.Data; apply_new_text = state->InitialTextA.Data;
apply_new_text_length = state->InitialTextA.Size - 1; apply_new_text_length = state->InitialTextA.Size - 1;
value_changed = true;
ImVector<ImWchar> w_text; ImVector<ImWchar> w_text;
if (apply_new_text_length > 0) if (apply_new_text_length > 0)
{ {
@ -4638,10 +4696,24 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{ {
apply_new_text = state->TextA.Data; apply_new_text = state->TextA.Data;
apply_new_text_length = state->CurLenA; apply_new_text_length = state->CurLenA;
value_changed = true;
} }
} }
} }
// Handle reapplying final data on deactivation (see InputTextDeactivateHook() for details)
if (g.InputTextDeactivatedState.ID == id)
{
if (g.ActiveId != id && IsItemDeactivatedAfterEdit() && !is_readonly)
{
apply_new_text = g.InputTextDeactivatedState.TextA.Data;
apply_new_text_length = g.InputTextDeactivatedState.TextA.Size - 1;
value_changed |= (strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0);
//IMGUI_DEBUG_LOG("InputText(): apply Deactivated data for 0x%08X: \"%.*s\".\n", id, apply_new_text_length, apply_new_text);
}
g.InputTextDeactivatedState.ID = 0;
}
// Copy result to user buffer. This can currently only happen when (g.ActiveId == id) // Copy result to user buffer. This can currently only happen when (g.ActiveId == id)
if (apply_new_text != NULL) if (apply_new_text != NULL)
{ {
@ -4669,12 +4741,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size. // If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size.
ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size)); ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size));
value_changed = true;
} }
// Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value) // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)
if (clear_active_id && g.ActiveId == id) // Otherwise request text input ahead for next frame.
if (g.ActiveId == id && clear_active_id)
ClearActiveID(); ClearActiveID();
else if (g.ActiveId == id)
g.WantTextInputNextFrame = 1;
// Render frame // Render frame
if (!is_multiline) if (!is_multiline)
@ -5582,7 +5656,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
float sin_hue_angle = ImSin(H * 2.0f * IM_PI); float sin_hue_angle = ImSin(H * 2.0f * IM_PI);
ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f); ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f);
float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f; float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32); int hue_cursor_segments = draw_list->_CalcCircleAutoSegmentCount(hue_cursor_rad); // Lock segment count so the +1 one matches others.
draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments); draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad + 1, col_midgrey, hue_cursor_segments); draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad + 1, col_midgrey, hue_cursor_segments);
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments); draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments);
@ -5592,13 +5666,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle); ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);
ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle); ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);
ImVec2 uv_white = GetFontTexUvWhitePixel(); ImVec2 uv_white = GetFontTexUvWhitePixel();
draw_list->PrimReserve(6, 6); draw_list->PrimReserve(3, 3);
draw_list->PrimVtx(tra, uv_white, hue_color32); draw_list->PrimVtx(tra, uv_white, hue_color32);
draw_list->PrimVtx(trb, uv_white, hue_color32);
draw_list->PrimVtx(trc, uv_white, col_white);
draw_list->PrimVtx(tra, uv_white, 0);
draw_list->PrimVtx(trb, uv_white, col_black); draw_list->PrimVtx(trb, uv_white, col_black);
draw_list->PrimVtx(trc, uv_white, 0); draw_list->PrimVtx(trc, uv_white, col_white);
draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f); draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f);
sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V)); sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));
} }
@ -5621,9 +5692,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
// Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range) // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)
float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f; float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12); int sv_cursor_segments = draw_list->_CalcCircleAutoSegmentCount(sv_cursor_rad); // Lock segment count so the +1 one matches others.
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, 12); draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, sv_cursor_segments);
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12); draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, sv_cursor_segments);
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, sv_cursor_segments);
// Render alpha bar // Render alpha bar
if (alpha_bar) if (alpha_bar)
@ -6151,11 +6223,13 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
if (g.NavId == id && g.NavMoveDir == ImGuiDir_Left && is_open) if (g.NavId == id && g.NavMoveDir == ImGuiDir_Left && is_open)
{ {
toggled = true; toggled = true;
NavClearPreferredPosForAxis(ImGuiAxis_X);
NavMoveRequestCancel(); NavMoveRequestCancel();
} }
if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority? if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority?
{ {
toggled = true; toggled = true;
NavClearPreferredPosForAxis(ImGuiAxis_X);
NavMoveRequestCancel(); NavMoveRequestCancel();
} }
@ -6545,20 +6619,6 @@ bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
return true; return true;
} }
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// OBSOLETED in 1.81 (from February 2021)
bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items)
{
// If height_in_items == -1, default height is maximum 7.
ImGuiContext& g = *GImGui;
float height_in_items_f = (height_in_items < 0 ? ImMin(items_count, 7) : height_in_items) + 0.25f;
ImVec2 size;
size.x = 0.0f;
size.y = GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f;
return BeginListBox(label, size);
}
#endif
void ImGui::EndListBox() void ImGui::EndListBox()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -7022,7 +7082,7 @@ void ImGui::EndMainMenuBar()
// FIXME: With this strategy we won't be able to restore a NULL focus. // FIXME: With this strategy we won't be able to restore a NULL focus.
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest) if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest)
FocusTopMostWindowUnderOne(g.NavWindow, NULL); FocusTopMostWindowUnderOne(g.NavWindow, NULL, NULL, ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild);
End(); End();
} }
@ -7036,9 +7096,9 @@ static bool IsRootOfOpenMenuSet()
// Initially we used 'upper_popup->OpenParentId == window->IDStack.back()' to differentiate multiple menu sets from each others // Initially we used 'upper_popup->OpenParentId == window->IDStack.back()' to differentiate multiple menu sets from each others
// (e.g. inside menu bar vs loose menu items) based on parent ID. // (e.g. inside menu bar vs loose menu items) based on parent ID.
// This would however prevent the use of e.g. PuhsID() user code submitting menus. // This would however prevent the use of e.g. PushID() user code submitting menus.
// Previously this worked between popup and a first child menu because the first child menu always had the _ChildWindow flag, // Previously this worked between popup and a first child menu because the first child menu always had the _ChildWindow flag,
// making hovering on parent popup possible while first child menu was focused - but this was generally a bug with other side effects. // making hovering on parent popup possible while first child menu was focused - but this was generally a bug with other side effects.
// Instead we don't treat Popup specifically (in order to consistently support menu features in them), maybe the first child menu of a Popup // Instead we don't treat Popup specifically (in order to consistently support menu features in them), maybe the first child menu of a Popup
// doesn't have the _ChildWindow flag, and we rely on this IsRootOfOpenMenuSet() check to allow hovering between root window/popup and first child menu. // doesn't have the _ChildWindow flag, and we rely on this IsRootOfOpenMenuSet() check to allow hovering between root window/popup and first child menu.
// In the end, lack of ID check made it so we could no longer differentiate between separate menu sets. To compensate for that, we at least check parent window nav layer. // In the end, lack of ID check made it so we could no longer differentiate between separate menu sets. To compensate for that, we at least check parent window nav layer.
@ -7046,7 +7106,9 @@ static bool IsRootOfOpenMenuSet()
// open on hover, but that should be a lesser problem, because if such menus are close in proximity in window content then it won't feel weird and if they are far apart // open on hover, but that should be a lesser problem, because if such menus are close in proximity in window content then it won't feel weird and if they are far apart
// it likely won't be a problem anyone runs into. // it likely won't be a problem anyone runs into.
const ImGuiPopupData* upper_popup = &g.OpenPopupStack[g.BeginPopupStack.Size]; const ImGuiPopupData* upper_popup = &g.OpenPopupStack[g.BeginPopupStack.Size];
return (window->DC.NavLayerCurrent == upper_popup->ParentNavLayer && upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu)); if (window->DC.NavLayerCurrent != upper_popup->ParentNavLayer)
return false;
return upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu) && ImGui::IsWindowChildOf(upper_popup->Window, window, true);
} }
bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
@ -7563,6 +7625,12 @@ void ImGui::EndTabBar()
g.CurrentTabBar = g.CurrentTabBarStack.empty() ? NULL : GetTabBarFromTabBarRef(g.CurrentTabBarStack.back()); g.CurrentTabBar = g.CurrentTabBarStack.empty() ? NULL : GetTabBarFromTabBarRef(g.CurrentTabBarStack.back());
} }
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
static float TabBarCalcScrollableWidth(ImGuiTabBar* tab_bar, ImGuiTabBarSection* sections)
{
return tab_bar->BarRect.GetWidth() - sections[0].Width - sections[2].Width - sections[1].Spacing;
}
// This is called only once a frame before by the first call to ItemTab() // This is called only once a frame before by the first call to ItemTab()
// The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions. // The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions.
static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
@ -7765,9 +7833,23 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
tab_bar->VisibleTabId = tab_bar->SelectedTabId; tab_bar->VisibleTabId = tab_bar->SelectedTabId;
tab_bar->VisibleTabWasSubmitted = false; tab_bar->VisibleTabWasSubmitted = false;
// Update scrolling // Apply request requests
if (scroll_to_tab_id != 0) if (scroll_to_tab_id != 0)
TabBarScrollToTab(tab_bar, scroll_to_tab_id, sections); TabBarScrollToTab(tab_bar, scroll_to_tab_id, sections);
else if ((tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll) && IsMouseHoveringRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, true) && IsWindowContentHoverable(g.CurrentWindow))
{
const float wheel = g.IO.MouseWheelRequestAxisSwap ? g.IO.MouseWheel : g.IO.MouseWheelH;
const ImGuiKey wheel_key = g.IO.MouseWheelRequestAxisSwap ? ImGuiKey_MouseWheelY : ImGuiKey_MouseWheelX;
if (TestKeyOwner(wheel_key, tab_bar->ID) && wheel != 0.0f)
{
const float scroll_step = wheel * TabBarCalcScrollableWidth(tab_bar, sections) / 3.0f;
tab_bar->ScrollingTargetDistToVisibility = 0.0f;
tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget - scroll_step);
}
SetKeyOwner(wheel_key, tab_bar->ID);
}
// Update scrolling
tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim); tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim);
tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget); tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget);
if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget) if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget)
@ -7904,8 +7986,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
int order = TabBarGetTabOrder(tab_bar, tab); int order = TabBarGetTabOrder(tab_bar, tab);
// Scrolling happens only in the central section (leading/trailing sections are not scrolling) // Scrolling happens only in the central section (leading/trailing sections are not scrolling)
// FIXME: This is all confusing. float scrollable_width = TabBarCalcScrollableWidth(tab_bar, sections);
float scrollable_width = tab_bar->BarRect.GetWidth() - sections[0].Width - sections[2].Width - sections[1].Spacing;
// We make all tabs positions all relative Sections[0].Width to make code simpler // We make all tabs positions all relative Sections[0].Width to make code simpler
float tab_x1 = tab->Offset - sections[0].Width + (order > sections[0].TabCount - 1 ? -margin : 0.0f); float tab_x1 = tab->Offset - sections[0].Width + (order > sections[0].TabCount - 1 ? -margin : 0.0f);

File diff suppressed because it is too large Load Diff

View File

@ -145,7 +145,7 @@ enum ImPlotFlags_ {
// Options for plot axes (see SetupAxis). // Options for plot axes (see SetupAxis).
enum ImPlotAxisFlags_ { enum ImPlotAxisFlags_ {
ImPlotAxisFlags_None = 0, // default ImPlotAxisFlags_None = 0, // default
ImPlotAxisFlags_NoLabel = 1 << 0, // the axis label will not be displayed (axis labels are also hidden if the supplied string name is NULL) ImPlotAxisFlags_NoLabel = 1 << 0, // the axis label will not be displayed (axis labels are also hidden if the supplied string name is nullptr)
ImPlotAxisFlags_NoGridLines = 1 << 1, // no grid lines will be displayed ImPlotAxisFlags_NoGridLines = 1 << 1, // no grid lines will be displayed
ImPlotAxisFlags_NoTickMarks = 1 << 2, // no tick marks will be displayed ImPlotAxisFlags_NoTickMarks = 1 << 2, // no tick marks will be displayed
ImPlotAxisFlags_NoTickLabels = 1 << 3, // no text labels will be displayed ImPlotAxisFlags_NoTickLabels = 1 << 3, // no text labels will be displayed
@ -596,9 +596,9 @@ namespace ImPlot {
// Creates a new ImPlot context. Call this after ImGui::CreateContext. // Creates a new ImPlot context. Call this after ImGui::CreateContext.
IMPLOT_API ImPlotContext* CreateContext(); IMPLOT_API ImPlotContext* CreateContext();
// Destroys an ImPlot context. Call this before ImGui::DestroyContext. NULL = destroy current context. // Destroys an ImPlot context. Call this before ImGui::DestroyContext. nullptr = destroy current context.
IMPLOT_API void DestroyContext(ImPlotContext* ctx = NULL); IMPLOT_API void DestroyContext(ImPlotContext* ctx = nullptr);
// Returns the current ImPlot context. NULL if no context has ben set. // Returns the current ImPlot context. nullptr if no context has ben set.
IMPLOT_API ImPlotContext* GetCurrentContext(); IMPLOT_API ImPlotContext* GetCurrentContext();
// Sets the current ImPlot context. // Sets the current ImPlot context.
IMPLOT_API void SetCurrentContext(ImPlotContext* ctx); IMPLOT_API void SetCurrentContext(ImPlotContext* ctx);
@ -690,8 +690,8 @@ IMPLOT_API bool BeginSubplots(const char* title_id,
int cols, int cols,
const ImVec2& size, const ImVec2& size,
ImPlotSubplotFlags flags = 0, ImPlotSubplotFlags flags = 0,
float* row_ratios = NULL, float* row_ratios = nullptr,
float* col_ratios = NULL); float* col_ratios = nullptr);
// Only call EndSubplots() if BeginSubplots() returns true! Typically called at the end // Only call EndSubplots() if BeginSubplots() returns true! Typically called at the end
// of an if statement conditioned on BeginSublots(). See example above. // of an if statement conditioned on BeginSublots(). See example above.
@ -726,24 +726,24 @@ IMPLOT_API void EndSubplots();
// call it yourself, then the first subsequent plotting or utility function will // call it yourself, then the first subsequent plotting or utility function will
// call it for you. // call it for you.
// Enables an axis or sets the label and/or flags for an existing axis. Leave #label = NULL for no label. // Enables an axis or sets the label and/or flags for an existing axis. Leave #label = nullptr for no label.
IMPLOT_API void SetupAxis(ImAxis axis, const char* label=NULL, ImPlotAxisFlags flags=0); IMPLOT_API void SetupAxis(ImAxis axis, const char* label=nullptr, ImPlotAxisFlags flags=0);
// Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked. // Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked.
IMPLOT_API void SetupAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once); IMPLOT_API void SetupAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once);
// Links an axis range limits to external values. Set to NULL for no linkage. The pointer data must remain valid until EndPlot. // Links an axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot.
IMPLOT_API void SetupAxisLinks(ImAxis axis, double* link_min, double* link_max); IMPLOT_API void SetupAxisLinks(ImAxis axis, double* link_min, double* link_max);
// Sets the format of numeric axis labels via formater specifier (default="%g"). Formated values will be double (i.e. use %f). // Sets the format of numeric axis labels via formater specifier (default="%g"). Formated values will be double (i.e. use %f).
IMPLOT_API void SetupAxisFormat(ImAxis axis, const char* fmt); IMPLOT_API void SetupAxisFormat(ImAxis axis, const char* fmt);
// Sets the format of numeric axis labels via formatter callback. Given #value, write a label into #buff. Optionally pass user data. // Sets the format of numeric axis labels via formatter callback. Given #value, write a label into #buff. Optionally pass user data.
IMPLOT_API void SetupAxisFormat(ImAxis axis, ImPlotFormatter formatter, void* data=NULL); IMPLOT_API void SetupAxisFormat(ImAxis axis, ImPlotFormatter formatter, void* data=nullptr);
// Sets an axis' ticks and optionally the labels. To keep the default ticks, set #keep_default=true. // Sets an axis' ticks and optionally the labels. To keep the default ticks, set #keep_default=true.
IMPLOT_API void SetupAxisTicks(ImAxis axis, const double* values, int n_ticks, const char* const labels[]=NULL, bool keep_default=false); IMPLOT_API void SetupAxisTicks(ImAxis axis, const double* values, int n_ticks, const char* const labels[]=nullptr, bool keep_default=false);
// Sets an axis' ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true. // Sets an axis' ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true.
IMPLOT_API void SetupAxisTicks(ImAxis axis, double v_min, double v_max, int n_ticks, const char* const labels[]=NULL, bool keep_default=false); IMPLOT_API void SetupAxisTicks(ImAxis axis, double v_min, double v_max, int n_ticks, const char* const labels[]=nullptr, bool keep_default=false);
// Sets an axis' scale using built-in options. // Sets an axis' scale using built-in options.
IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotScale scale); IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotScale scale);
// Sets an axis' scale using user supplied forward and inverse transfroms. // Sets an axis' scale using user supplied forward and inverse transfroms.
IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotTransform forward, ImPlotTransform inverse, void* data=NULL); IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotTransform forward, ImPlotTransform inverse, void* data=nullptr);
// Sets an axis' limits constraints. // Sets an axis' limits constraints.
IMPLOT_API void SetupAxisLimitsConstraints(ImAxis axis, double v_min, double v_max); IMPLOT_API void SetupAxisLimitsConstraints(ImAxis axis, double v_min, double v_max);
// Sets an axis' zoom constraints. // Sets an axis' zoom constraints.
@ -788,7 +788,7 @@ IMPLOT_API void SetupFinish();
// Sets an upcoming axis range limits. If ImPlotCond_Always is used, the axes limits will be locked. // Sets an upcoming axis range limits. If ImPlotCond_Always is used, the axes limits will be locked.
IMPLOT_API void SetNextAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once); IMPLOT_API void SetNextAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once);
// Links an upcoming axis range limits to external values. Set to NULL for no linkage. The pointer data must remain valid until EndPlot! // Links an upcoming axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot!
IMPLOT_API void SetNextAxisLinks(ImAxis axis, double* link_min, double* link_max); IMPLOT_API void SetNextAxisLinks(ImAxis axis, double* link_min, double* link_max);
// Set an upcoming axis to auto fit to its data. // Set an upcoming axis to auto fit to its data.
IMPLOT_API void SetNextAxisToFit(ImAxis axis); IMPLOT_API void SetNextAxisToFit(ImAxis axis);
@ -890,10 +890,10 @@ IMPLOT_TMP void PlotStems(const char* label_id, const T* xs, const T* ys, int co
// Plots infinite vertical or horizontal lines (e.g. for references or asymptotes). // Plots infinite vertical or horizontal lines (e.g. for references or asymptotes).
IMPLOT_TMP void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags=0, int offset=0, int stride=sizeof(T)); IMPLOT_TMP void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags=0, int offset=0, int stride=sizeof(T));
// Plots a pie chart. Center and radius are in plot units. #label_fmt can be set to NULL for no labels. // Plots a pie chart. Center and radius are in plot units. #label_fmt can be set to nullptr for no labels.
IMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* label_fmt="%.1f", double angle0=90, ImPlotPieChartFlags flags=0); IMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* label_fmt="%.1f", double angle0=90, ImPlotPieChartFlags flags=0);
// Plots a 2D heatmap chart. Values are expected to be in row-major order by default. Leave #scale_min and scale_max both at 0 for automatic color scaling, or set them to a predefined range. #label_fmt can be set to NULL for no labels. // Plots a 2D heatmap chart. Values are expected to be in row-major order by default. Leave #scale_min and scale_max both at 0 for automatic color scaling, or set them to a predefined range. #label_fmt can be set to nullptr for no labels.
IMPLOT_TMP void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min=0, double scale_max=0, const char* label_fmt="%.1f", const ImPlotPoint& bounds_min=ImPlotPoint(0,0), const ImPlotPoint& bounds_max=ImPlotPoint(1,1), ImPlotHeatmapFlags flags=0); IMPLOT_TMP void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min=0, double scale_max=0, const char* label_fmt="%.1f", const ImPlotPoint& bounds_min=ImPlotPoint(0,0), const ImPlotPoint& bounds_max=ImPlotPoint(1,1), ImPlotHeatmapFlags flags=0);
// Plots a horizontal histogram. #bins can be a positive integer or an ImPlotBin_ method. If #range is left unspecified, the min/max of #values will be used as the range. // Plots a horizontal histogram. #bins can be a positive integer or an ImPlotBin_ method. If #range is left unspecified, the min/max of #values will be used as the range.
@ -1077,13 +1077,13 @@ IMPLOT_API void EndDragDropSource();
IMPLOT_API ImPlotStyle& GetStyle(); IMPLOT_API ImPlotStyle& GetStyle();
// Style plot colors for current ImGui style (default). // Style plot colors for current ImGui style (default).
IMPLOT_API void StyleColorsAuto(ImPlotStyle* dst = NULL); IMPLOT_API void StyleColorsAuto(ImPlotStyle* dst = nullptr);
// Style plot colors for ImGui "Classic". // Style plot colors for ImGui "Classic".
IMPLOT_API void StyleColorsClassic(ImPlotStyle* dst = NULL); IMPLOT_API void StyleColorsClassic(ImPlotStyle* dst = nullptr);
// Style plot colors for ImGui "Dark". // Style plot colors for ImGui "Dark".
IMPLOT_API void StyleColorsDark(ImPlotStyle* dst = NULL); IMPLOT_API void StyleColorsDark(ImPlotStyle* dst = nullptr);
// Style plot colors for ImGui "Light". // Style plot colors for ImGui "Light".
IMPLOT_API void StyleColorsLight(ImPlotStyle* dst = NULL); IMPLOT_API void StyleColorsLight(ImPlotStyle* dst = nullptr);
// Use PushStyleX to temporarily modify your ImPlotStyle. The modification // Use PushStyleX to temporarily modify your ImPlotStyle. The modification
// will last until the matching call to PopStyleX. You MUST call a pop for // will last until the matching call to PopStyleX. You MUST call a pop for
@ -1150,7 +1150,7 @@ IMPLOT_API ImPlotColormap AddColormap(const char* name, const ImU32* cols, int
// Returns the number of available colormaps (i.e. the built-in + user-added count). // Returns the number of available colormaps (i.e. the built-in + user-added count).
IMPLOT_API int GetColormapCount(); IMPLOT_API int GetColormapCount();
// Returns a null terminated string name for a colormap given an index. Returns NULL if index is invalid. // Returns a null terminated string name for a colormap given an index. Returns nullptr if index is invalid.
IMPLOT_API const char* GetColormapName(ImPlotColormap cmap); IMPLOT_API const char* GetColormapName(ImPlotColormap cmap);
// Returns an index number for a colormap given a valid string name. Returns -1 if name is invalid. // Returns an index number for a colormap given a valid string name. Returns -1 if name is invalid.
IMPLOT_API ImPlotColormap GetColormapIndex(const char* name); IMPLOT_API ImPlotColormap GetColormapIndex(const char* name);
@ -1179,18 +1179,18 @@ IMPLOT_API ImVec4 SampleColormap(float t, ImPlotColormap cmap = IMPLOT_AUTO);
// Shows a vertical color scale with linear spaced ticks using the specified color map. Use double hashes to hide label (e.g. "##NoLabel"). If scale_min > scale_max, the scale to color mapping will be reversed. // Shows a vertical color scale with linear spaced ticks using the specified color map. Use double hashes to hide label (e.g. "##NoLabel"). If scale_min > scale_max, the scale to color mapping will be reversed.
IMPLOT_API void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0), const char* format = "%g", ImPlotColormapScaleFlags flags = 0, ImPlotColormap cmap = IMPLOT_AUTO); IMPLOT_API void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0), const char* format = "%g", ImPlotColormapScaleFlags flags = 0, ImPlotColormap cmap = IMPLOT_AUTO);
// Shows a horizontal slider with a colormap gradient background. Optionally returns the color sampled at t in [0 1]. // Shows a horizontal slider with a colormap gradient background. Optionally returns the color sampled at t in [0 1].
IMPLOT_API bool ColormapSlider(const char* label, float* t, ImVec4* out = NULL, const char* format = "", ImPlotColormap cmap = IMPLOT_AUTO); IMPLOT_API bool ColormapSlider(const char* label, float* t, ImVec4* out = nullptr, const char* format = "", ImPlotColormap cmap = IMPLOT_AUTO);
// Shows a button with a colormap gradient brackground. // Shows a button with a colormap gradient brackground.
IMPLOT_API bool ColormapButton(const char* label, const ImVec2& size = ImVec2(0,0), ImPlotColormap cmap = IMPLOT_AUTO); IMPLOT_API bool ColormapButton(const char* label, const ImVec2& size = ImVec2(0,0), ImPlotColormap cmap = IMPLOT_AUTO);
// When items in a plot sample their color from a colormap, the color is cached and does not change // When items in a plot sample their color from a colormap, the color is cached and does not change
// unless explicitly overriden. Therefore, if you change the colormap after the item has already been plotted, // unless explicitly overriden. Therefore, if you change the colormap after the item has already been plotted,
// item colors will NOT update. If you need item colors to resample the new colormap, then use this // item colors will NOT update. If you need item colors to resample the new colormap, then use this
// function to bust the cached colors. If #plot_title_id is NULL, then every item in EVERY existing plot // function to bust the cached colors. If #plot_title_id is nullptr, then every item in EVERY existing plot
// will be cache busted. Otherwise only the plot specified by #plot_title_id will be busted. For the // will be cache busted. Otherwise only the plot specified by #plot_title_id will be busted. For the
// latter, this function must be called in the same ImGui ID scope that the plot is in. You should rarely if ever // latter, this function must be called in the same ImGui ID scope that the plot is in. You should rarely if ever
// need this function, but it is available for applications that require runtime colormap swaps (e.g. Heatmaps demo). // need this function, but it is available for applications that require runtime colormap swaps (e.g. Heatmaps demo).
IMPLOT_API void BustColorCache(const char* plot_title_id = NULL); IMPLOT_API void BustColorCache(const char* plot_title_id = nullptr);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Input Mapping // [SECTION] Input Mapping
@ -1200,9 +1200,9 @@ IMPLOT_API void BustColorCache(const char* plot_title_id = NULL);
IMPLOT_API ImPlotInputMap& GetInputMap(); IMPLOT_API ImPlotInputMap& GetInputMap();
// Default input mapping: pan = LMB drag, box select = RMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll. // Default input mapping: pan = LMB drag, box select = RMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll.
IMPLOT_API void MapInputDefault(ImPlotInputMap* dst = NULL); IMPLOT_API void MapInputDefault(ImPlotInputMap* dst = nullptr);
// Reverse input mapping: pan = RMB drag, box select = LMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll. // Reverse input mapping: pan = RMB drag, box select = LMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll.
IMPLOT_API void MapInputReverse(ImPlotInputMap* dst = NULL); IMPLOT_API void MapInputReverse(ImPlotInputMap* dst = nullptr);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Miscellaneous // [SECTION] Miscellaneous
@ -1227,18 +1227,18 @@ IMPLOT_API bool ShowColormapSelector(const char* label);
// Shows ImPlot input map selector dropdown menu. // Shows ImPlot input map selector dropdown menu.
IMPLOT_API bool ShowInputMapSelector(const char* label); IMPLOT_API bool ShowInputMapSelector(const char* label);
// Shows ImPlot style editor block (not a window). // Shows ImPlot style editor block (not a window).
IMPLOT_API void ShowStyleEditor(ImPlotStyle* ref = NULL); IMPLOT_API void ShowStyleEditor(ImPlotStyle* ref = nullptr);
// Add basic help/info block for end users (not a window). // Add basic help/info block for end users (not a window).
IMPLOT_API void ShowUserGuide(); IMPLOT_API void ShowUserGuide();
// Shows ImPlot metrics/debug information window. // Shows ImPlot metrics/debug information window.
IMPLOT_API void ShowMetricsWindow(bool* p_popen = NULL); IMPLOT_API void ShowMetricsWindow(bool* p_popen = nullptr);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Demo // [SECTION] Demo
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Shows the ImPlot demo window (add implot_demo.cpp to your sources!) // Shows the ImPlot demo window (add implot_demo.cpp to your sources!)
IMPLOT_API void ShowDemoWindow(bool* p_open = NULL); IMPLOT_API void ShowDemoWindow(bool* p_open = nullptr);
} // namespace ImPlot } // namespace ImPlot
@ -1276,16 +1276,16 @@ namespace ImPlot {
// OBSOLETED in v0.13 -> PLANNED REMOVAL in v1.0 // OBSOLETED in v0.13 -> PLANNED REMOVAL in v1.0
IMPLOT_DEPRECATED( IMPLOT_API bool BeginPlot(const char* title_id, IMPLOT_DEPRECATED( IMPLOT_API bool BeginPlot(const char* title_id,
const char* x_label, // = NULL, const char* x_label, // = nullptr,
const char* y_label, // = NULL, const char* y_label, // = nullptr,
const ImVec2& size = ImVec2(-1,0), const ImVec2& size = ImVec2(-1,0),
ImPlotFlags flags = ImPlotFlags_None, ImPlotFlags flags = ImPlotFlags_None,
ImPlotAxisFlags x_flags = 0, ImPlotAxisFlags x_flags = 0,
ImPlotAxisFlags y_flags = 0, ImPlotAxisFlags y_flags = 0,
ImPlotAxisFlags y2_flags = ImPlotAxisFlags_AuxDefault, ImPlotAxisFlags y2_flags = ImPlotAxisFlags_AuxDefault,
ImPlotAxisFlags y3_flags = ImPlotAxisFlags_AuxDefault, ImPlotAxisFlags y3_flags = ImPlotAxisFlags_AuxDefault,
const char* y2_label = NULL, const char* y2_label = nullptr,
const char* y3_label = NULL) ); const char* y3_label = nullptr) );
} // namespace ImPlot } // namespace ImPlot

View File

@ -232,11 +232,11 @@ void ModSelector(const char* label, int* k) {
void InputMapping(const char* label, ImGuiMouseButton* b, int* k) { void InputMapping(const char* label, ImGuiMouseButton* b, int* k) {
ImGui::LabelText("##","%s",label); ImGui::LabelText("##","%s",label);
if (b != NULL) { if (b != nullptr) {
ImGui::SameLine(100); ImGui::SameLine(100);
ButtonSelector(label,b); ButtonSelector(label,b);
} }
if (k != NULL) { if (k != nullptr) {
ImGui::SameLine(300); ImGui::SameLine(300);
ModSelector(label,k); ModSelector(label,k);
} }
@ -245,14 +245,14 @@ void InputMapping(const char* label, ImGuiMouseButton* b, int* k) {
void ShowInputMapping() { void ShowInputMapping() {
ImPlotInputMap& map = ImPlot::GetInputMap(); ImPlotInputMap& map = ImPlot::GetInputMap();
InputMapping("Pan",&map.Pan,&map.PanMod); InputMapping("Pan",&map.Pan,&map.PanMod);
InputMapping("Fit",&map.Fit,NULL); InputMapping("Fit",&map.Fit,nullptr);
InputMapping("Select",&map.Select,&map.SelectMod); InputMapping("Select",&map.Select,&map.SelectMod);
InputMapping("SelectHorzMod",NULL,&map.SelectHorzMod); InputMapping("SelectHorzMod",nullptr,&map.SelectHorzMod);
InputMapping("SelectVertMod",NULL,&map.SelectVertMod); InputMapping("SelectVertMod",nullptr,&map.SelectVertMod);
InputMapping("SelectCancel",&map.SelectCancel,NULL); InputMapping("SelectCancel",&map.SelectCancel,nullptr);
InputMapping("Menu",&map.Menu,NULL); InputMapping("Menu",&map.Menu,nullptr);
InputMapping("OverrideMod",NULL,&map.OverrideMod); InputMapping("OverrideMod",nullptr,&map.OverrideMod);
InputMapping("ZoomMod",NULL,&map.ZoomMod); InputMapping("ZoomMod",nullptr,&map.ZoomMod);
ImGui::SliderFloat("ZoomRate",&map.ZoomRate,-1,1); ImGui::SliderFloat("ZoomRate",&map.ZoomRate,-1,1);
} }
@ -268,7 +268,7 @@ void Demo_Config() {
ImGui::Checkbox("Use 24 Hour Clock", &ImPlot::GetStyle().Use24HourClock); ImGui::Checkbox("Use 24 Hour Clock", &ImPlot::GetStyle().Use24HourClock);
ImGui::Separator(); ImGui::Separator();
if (ImPlot::BeginPlot("Preview")) { if (ImPlot::BeginPlot("Preview")) {
static double now = (double)time(0); static double now = (double)time(nullptr);
ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time); ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);
ImPlot::SetupAxisLimits(ImAxis_X1, now, now + 24*3600); ImPlot::SetupAxisLimits(ImAxis_X1, now, now + 24*3600);
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
@ -530,7 +530,7 @@ void Demo_BarStacks() {
ImPlot::PushColormap(Liars); ImPlot::PushColormap(Liars);
if (ImPlot::BeginPlot("PolitiFact: Who Lies More?",ImVec2(-1,400),ImPlotFlags_NoMouseText)) { if (ImPlot::BeginPlot("PolitiFact: Who Lies More?",ImVec2(-1,400),ImPlotFlags_NoMouseText)) {
ImPlot::SetupLegend(ImPlotLocation_South, ImPlotLegendFlags_Outside|ImPlotLegendFlags_Horizontal); ImPlot::SetupLegend(ImPlotLocation_South, ImPlotLegendFlags_Outside|ImPlotLegendFlags_Horizontal);
ImPlot::SetupAxes(NULL,NULL,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_Invert); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_Invert);
ImPlot::SetupAxisTicks(ImAxis_Y1,0,19,20,politicians,false); ImPlot::SetupAxisTicks(ImAxis_Y1,0,19,20,politicians,false);
if (diverging) if (diverging)
ImPlot::PlotBarGroups(labels_div,data_div,9,20,0.75,0,ImPlotBarGroupsFlags_Stacked|ImPlotBarGroupsFlags_Horizontal); ImPlot::PlotBarGroups(labels_div,data_div,9,20,0.75,0,ImPlotBarGroupsFlags_Stacked|ImPlotBarGroupsFlags_Horizontal);
@ -595,7 +595,7 @@ void Demo_StemPlots() {
void Demo_InfiniteLines() { void Demo_InfiniteLines() {
static double vals[] = {0.25, 0.5, 0.75}; static double vals[] = {0.25, 0.5, 0.75};
if (ImPlot::BeginPlot("##Infinite")) { if (ImPlot::BeginPlot("##Infinite")) {
ImPlot::SetupAxes(NULL,NULL,ImPlotAxisFlags_NoInitialFit,ImPlotAxisFlags_NoInitialFit); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoInitialFit,ImPlotAxisFlags_NoInitialFit);
ImPlot::PlotInfLines("Vertical",vals,3); ImPlot::PlotInfLines("Vertical",vals,3);
ImPlot::PlotInfLines("Horizontal",vals,3,ImPlotInfLinesFlags_Horizontal); ImPlot::PlotInfLines("Horizontal",vals,3,ImPlotInfLinesFlags_Horizontal);
ImPlot::EndPlot(); ImPlot::EndPlot();
@ -616,7 +616,7 @@ void Demo_PieCharts() {
} }
if (ImPlot::BeginPlot("##Pie1", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) { if (ImPlot::BeginPlot("##Pie1", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) {
ImPlot::SetupAxes(NULL, NULL, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(0, 1, 0, 1); ImPlot::SetupAxesLimits(0, 1, 0, 1);
ImPlot::PlotPieChart(labels1, data1, 4, 0.5, 0.5, 0.4, "%.2f", 90, flags); ImPlot::PlotPieChart(labels1, data1, 4, 0.5, 0.5, 0.4, "%.2f", 90, flags);
ImPlot::EndPlot(); ImPlot::EndPlot();
@ -629,7 +629,7 @@ void Demo_PieCharts() {
ImPlot::PushColormap(ImPlotColormap_Pastel); ImPlot::PushColormap(ImPlotColormap_Pastel);
if (ImPlot::BeginPlot("##Pie2", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) { if (ImPlot::BeginPlot("##Pie2", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) {
ImPlot::SetupAxes(NULL, NULL, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(0, 1, 0, 1); ImPlot::SetupAxesLimits(0, 1, 0, 1);
ImPlot::PlotPieChart(labels2, data2, 5, 0.5, 0.5, 0.4, "%.0f", 180, flags); ImPlot::PlotPieChart(labels2, data2, 5, 0.5, 0.5, 0.4, "%.0f", 180, flags);
ImPlot::EndPlot(); ImPlot::EndPlot();
@ -676,7 +676,7 @@ void Demo_Heatmaps() {
ImPlot::PushColormap(map); ImPlot::PushColormap(map);
if (ImPlot::BeginPlot("##Heatmap1",ImVec2(225,225),ImPlotFlags_NoLegend|ImPlotFlags_NoMouseText)) { if (ImPlot::BeginPlot("##Heatmap1",ImVec2(225,225),ImPlotFlags_NoLegend|ImPlotFlags_NoMouseText)) {
ImPlot::SetupAxes(NULL, NULL, axes_flags, axes_flags); ImPlot::SetupAxes(nullptr, nullptr, axes_flags, axes_flags);
ImPlot::SetupAxisTicks(ImAxis_X1,0 + 1.0/14.0, 1 - 1.0/14.0, 7, xlabels); ImPlot::SetupAxisTicks(ImAxis_X1,0 + 1.0/14.0, 1 - 1.0/14.0, 7, xlabels);
ImPlot::SetupAxisTicks(ImAxis_Y1,1 - 1.0/14.0, 0 + 1.0/14.0, 7, ylabels); ImPlot::SetupAxisTicks(ImAxis_Y1,1 - 1.0/14.0, 0 + 1.0/14.0, 7, ylabels);
ImPlot::PlotHeatmap("heat",values1[0],7,7,scale_min,scale_max,"%g",ImPlotPoint(0,0),ImPlotPoint(1,1),hm_flags); ImPlot::PlotHeatmap("heat",values1[0],7,7,scale_min,scale_max,"%g",ImPlotPoint(0,0),ImPlotPoint(1,1),hm_flags);
@ -694,10 +694,10 @@ void Demo_Heatmaps() {
values2[i] = RandomRange(0.0,1.0); values2[i] = RandomRange(0.0,1.0);
if (ImPlot::BeginPlot("##Heatmap2",ImVec2(225,225))) { if (ImPlot::BeginPlot("##Heatmap2",ImVec2(225,225))) {
ImPlot::SetupAxes(NULL, NULL, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(-1,1,-1,1); ImPlot::SetupAxesLimits(-1,1,-1,1);
ImPlot::PlotHeatmap("heat1",values2,size,size,0,1,NULL); ImPlot::PlotHeatmap("heat1",values2,size,size,0,1,nullptr);
ImPlot::PlotHeatmap("heat2",values2,size,size,0,1,NULL, ImPlotPoint(-1,-1), ImPlotPoint(0,0)); ImPlot::PlotHeatmap("heat2",values2,size,size,0,1,nullptr, ImPlotPoint(-1,-1), ImPlotPoint(0,0));
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
ImPlot::PopColormap(); ImPlot::PopColormap();
@ -756,7 +756,7 @@ void Demo_Histogram() {
} }
if (ImPlot::BeginPlot("##Histograms")) { if (ImPlot::BeginPlot("##Histograms")) {
ImPlot::SetupAxes(NULL,NULL,ImPlotAxisFlags_AutoFit,ImPlotAxisFlags_AutoFit); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_AutoFit,ImPlotAxisFlags_AutoFit);
ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL,0.5f); ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL,0.5f);
ImPlot::PlotHistogram("Empirical", dist.Data, 10000, bins, 1.0, range ? ImPlotRange(rmin,rmax) : ImPlotRange(), hist_flags); ImPlot::PlotHistogram("Empirical", dist.Data, 10000, bins, 1.0, range ? ImPlotRange(rmin,rmax) : ImPlotRange(), hist_flags);
if ((hist_flags & ImPlotHistogramFlags_Density) && !(hist_flags & ImPlotHistogramFlags_NoOutliers)) { if ((hist_flags & ImPlotHistogramFlags_Density) && !(hist_flags & ImPlotHistogramFlags_NoOutliers)) {
@ -788,7 +788,7 @@ void Demo_Histogram2D() {
ImPlotAxisFlags flags = ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_Foreground; ImPlotAxisFlags flags = ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_Foreground;
ImPlot::PushColormap("Hot"); ImPlot::PushColormap("Hot");
if (ImPlot::BeginPlot("##Hist2D",ImVec2(ImGui::GetContentRegionAvail().x-100-ImGui::GetStyle().ItemSpacing.x,0))) { if (ImPlot::BeginPlot("##Hist2D",ImVec2(ImGui::GetContentRegionAvail().x-100-ImGui::GetStyle().ItemSpacing.x,0))) {
ImPlot::SetupAxes(NULL, NULL, flags, flags); ImPlot::SetupAxes(nullptr, nullptr, flags, flags);
ImPlot::SetupAxesLimits(-6,6,-6,6); ImPlot::SetupAxesLimits(-6,6,-6,6);
max_count = ImPlot::PlotHistogram2D("Hist2D",dist1.Data,dist2.Data,count,xybins[0],xybins[1],ImPlotRect(-6,6,-6,6), hist_flags); max_count = ImPlot::PlotHistogram2D("Hist2D",dist1.Data,dist2.Data,count,xybins[0],xybins[1],ImPlotRect(-6,6,-6,6), hist_flags);
ImPlot::EndPlot(); ImPlot::EndPlot();
@ -897,7 +897,7 @@ void Demo_RealtimePlots() {
static ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels; static ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels;
if (ImPlot::BeginPlot("##Scrolling", ImVec2(-1,150))) { if (ImPlot::BeginPlot("##Scrolling", ImVec2(-1,150))) {
ImPlot::SetupAxes(NULL, NULL, flags, flags); ImPlot::SetupAxes(nullptr, nullptr, flags, flags);
ImPlot::SetupAxisLimits(ImAxis_X1,t - history, t, ImGuiCond_Always); ImPlot::SetupAxisLimits(ImAxis_X1,t - history, t, ImGuiCond_Always);
ImPlot::SetupAxisLimits(ImAxis_Y1,0,1); ImPlot::SetupAxisLimits(ImAxis_Y1,0,1);
ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL,0.5f); ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL,0.5f);
@ -906,7 +906,7 @@ void Demo_RealtimePlots() {
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
if (ImPlot::BeginPlot("##Rolling", ImVec2(-1,150))) { if (ImPlot::BeginPlot("##Rolling", ImVec2(-1,150))) {
ImPlot::SetupAxes(NULL, NULL, flags, flags); ImPlot::SetupAxes(nullptr, nullptr, flags, flags);
ImPlot::SetupAxisLimits(ImAxis_X1,0,history, ImGuiCond_Always); ImPlot::SetupAxisLimits(ImAxis_X1,0,history, ImGuiCond_Always);
ImPlot::SetupAxisLimits(ImAxis_Y1,0,1); ImPlot::SetupAxisLimits(ImAxis_Y1,0,1);
ImPlot::PlotLine("Mouse X", &rdata1.Data[0].x, &rdata1.Data[0].y, rdata1.Data.size(), 0, 0, 2 * sizeof(float)); ImPlot::PlotLine("Mouse X", &rdata1.Data[0].x, &rdata1.Data[0].y, rdata1.Data.size(), 0, 0, 2 * sizeof(float));
@ -925,7 +925,7 @@ void Demo_MarkersAndText() {
if (ImPlot::BeginPlot("##MarkerStyles", ImVec2(-1,0), ImPlotFlags_CanvasOnly)) { if (ImPlot::BeginPlot("##MarkerStyles", ImVec2(-1,0), ImPlotFlags_CanvasOnly)) {
ImPlot::SetupAxes(NULL, NULL, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(0, 10, 0, 12); ImPlot::SetupAxesLimits(0, 10, 0, 12);
ImS8 xs[2] = {1,4}; ImS8 xs[2] = {1,4};
@ -1040,8 +1040,8 @@ void Demo_TimeScale() {
ImGui::SameLine(); ImGui::SameLine();
ImGui::Checkbox("24 Hour Clock",&ImPlot::GetStyle().Use24HourClock); ImGui::Checkbox("24 Hour Clock",&ImPlot::GetStyle().Use24HourClock);
static HugeTimeData* data = NULL; static HugeTimeData* data = nullptr;
if (data == NULL) { if (data == nullptr) {
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Generate Huge Data (~500MB!)")) { if (ImGui::Button("Generate Huge Data (~500MB!)")) {
static HugeTimeData sdata(t_min); static HugeTimeData sdata(t_min);
@ -1052,7 +1052,7 @@ void Demo_TimeScale() {
if (ImPlot::BeginPlot("##Time", ImVec2(-1,0))) { if (ImPlot::BeginPlot("##Time", ImVec2(-1,0))) {
ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time); ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);
ImPlot::SetupAxesLimits(t_min,t_max,0,1); ImPlot::SetupAxesLimits(t_min,t_max,0,1);
if (data != NULL) { if (data != nullptr) {
// downsample our data // downsample our data
int downsample = (int)ImPlot::GetPlotLimits().X.Size() / 1000 + 1; int downsample = (int)ImPlot::GetPlotLimits().X.Size() / 1000 + 1;
int start = (int)(ImPlot::GetPlotLimits().X.Min - t_min); int start = (int)(ImPlot::GetPlotLimits().X.Min - t_min);
@ -1064,7 +1064,7 @@ void Demo_TimeScale() {
ImPlot::PlotLine("Time Series", &data->Ts[start], &data->Ys[start], size, 0, 0, sizeof(double)*downsample); ImPlot::PlotLine("Time Series", &data->Ts[start], &data->Ys[start], size, 0, 0, sizeof(double)*downsample);
} }
// plot time now // plot time now
double t_now = (double)time(0); double t_now = (double)time(nullptr);
double y_now = HugeTimeData::GetY(t_now); double y_now = HugeTimeData::GetY(t_now);
ImPlot::PlotScatter("Now",&t_now,&y_now,1); ImPlot::PlotScatter("Now",&t_now,&y_now,1);
ImPlot::Annotation(t_now,y_now,ImPlot::GetLastItemColor(),ImVec2(10,10),false,"Now"); ImPlot::Annotation(t_now,y_now,ImPlot::GetLastItemColor(),ImVec2(10,10),false,"Now");
@ -1169,14 +1169,14 @@ void Demo_LinkedAxes() {
if (BeginAlignedPlots("AlignedGroup")) { if (BeginAlignedPlots("AlignedGroup")) {
if (ImPlot::BeginPlot("Plot A")) { if (ImPlot::BeginPlot("Plot A")) {
ImPlot::SetupAxisLinks(ImAxis_X1, linkx ? &lims.X.Min : NULL, linkx ? &lims.X.Max : NULL); ImPlot::SetupAxisLinks(ImAxis_X1, linkx ? &lims.X.Min : nullptr, linkx ? &lims.X.Max : nullptr);
ImPlot::SetupAxisLinks(ImAxis_Y1, linky ? &lims.Y.Min : NULL, linky ? &lims.Y.Max : NULL); ImPlot::SetupAxisLinks(ImAxis_Y1, linky ? &lims.Y.Min : nullptr, linky ? &lims.Y.Max : nullptr);
ImPlot::PlotLine("Line",data,2); ImPlot::PlotLine("Line",data,2);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
if (ImPlot::BeginPlot("Plot B")) { if (ImPlot::BeginPlot("Plot B")) {
ImPlot::SetupAxisLinks(ImAxis_X1, linkx ? &lims.X.Min : NULL, linkx ? &lims.X.Max : NULL); ImPlot::SetupAxisLinks(ImAxis_X1, linkx ? &lims.X.Min : nullptr, linkx ? &lims.X.Max : nullptr);
ImPlot::SetupAxisLinks(ImAxis_Y1, linky ? &lims.Y.Min : NULL, linky ? &lims.Y.Max : NULL); ImPlot::SetupAxisLinks(ImAxis_Y1, linky ? &lims.Y.Min : nullptr, linky ? &lims.Y.Max : nullptr);
ImPlot::PlotLine("Line",data,2); ImPlot::PlotLine("Line",data,2);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
@ -1215,8 +1215,8 @@ void Demo_EqualAxes() {
float xs2[] = {-1,0,1,0,-1}; float xs2[] = {-1,0,1,0,-1};
float ys2[] = {0,1,0,-1,0}; float ys2[] = {0,1,0,-1,0};
if (ImPlot::BeginPlot("##EqualAxes",ImVec2(-1,0),ImPlotFlags_Equal)) { if (ImPlot::BeginPlot("##EqualAxes",ImVec2(-1,0),ImPlotFlags_Equal)) {
ImPlot::SetupAxis(ImAxis_X2, NULL, ImPlotAxisFlags_AuxDefault); ImPlot::SetupAxis(ImAxis_X2, nullptr, ImPlotAxisFlags_AuxDefault);
ImPlot::SetupAxis(ImAxis_Y2, NULL, ImPlotAxisFlags_AuxDefault); ImPlot::SetupAxis(ImAxis_Y2, nullptr, ImPlotAxisFlags_AuxDefault);
ImPlot::PlotLine("Circle",xs1,ys1,360); ImPlot::PlotLine("Circle",xs1,ys1,360);
ImPlot::SetAxes(ImAxis_X2, ImAxis_Y2); ImPlot::SetAxes(ImAxis_X2, ImAxis_Y2);
ImPlot::PlotLine("Diamond",xs2,ys2,5); ImPlot::PlotLine("Diamond",xs2,ys2,5);
@ -1274,12 +1274,12 @@ void Demo_SubplotsSizing() {
ImGui::SliderInt("Cols",&cols,1,5); ImGui::SliderInt("Cols",&cols,1,5);
static float rratios[] = {5,1,1,1,1,1}; static float rratios[] = {5,1,1,1,1,1};
static float cratios[] = {5,1,1,1,1,1}; static float cratios[] = {5,1,1,1,1,1};
ImGui::DragScalarN("Row Ratios",ImGuiDataType_Float,rratios,rows,0.01f,0); ImGui::DragScalarN("Row Ratios",ImGuiDataType_Float,rratios,rows,0.01f,nullptr);
ImGui::DragScalarN("Col Ratios",ImGuiDataType_Float,cratios,cols,0.01f,0); ImGui::DragScalarN("Col Ratios",ImGuiDataType_Float,cratios,cols,0.01f,nullptr);
if (ImPlot::BeginSubplots("My Subplots", rows, cols, ImVec2(-1,400), flags, rratios, cratios)) { if (ImPlot::BeginSubplots("My Subplots", rows, cols, ImVec2(-1,400), flags, rratios, cratios)) {
for (int i = 0; i < rows*cols; ++i) { for (int i = 0; i < rows*cols; ++i) {
if (ImPlot::BeginPlot("",ImVec2(),ImPlotFlags_NoLegend)) { if (ImPlot::BeginPlot("",ImVec2(),ImPlotFlags_NoLegend)) {
ImPlot::SetupAxes(NULL,NULL,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);
float fi = 0.01f * (i+1); float fi = 0.01f * (i+1);
ImPlot::SetNextLineStyle(SampleColormap((float)i/(float)(rows*cols-1),ImPlotColormap_Jet)); ImPlot::SetNextLineStyle(SampleColormap((float)i/(float)(rows*cols-1),ImPlotColormap_Jet));
ImPlot::PlotLineG("data",SinewaveGetter,&fi,1000); ImPlot::PlotLineG("data",SinewaveGetter,&fi,1000);
@ -1314,7 +1314,7 @@ void Demo_SubplotItemSharing() {
ImPlot::PlotLineG(label,SinewaveGetter,&fj,1000); ImPlot::PlotLineG(label,SinewaveGetter,&fj,1000);
if (ImPlot::BeginDragDropSourceItem(label)) { if (ImPlot::BeginDragDropSourceItem(label)) {
curj = j; curj = j;
ImGui::SetDragDropPayload("MY_DND",NULL,0); ImGui::SetDragDropPayload("MY_DND",nullptr,0);
ImPlot::ItemIcon(GetLastItemColor()); ImGui::SameLine(); ImPlot::ItemIcon(GetLastItemColor()); ImGui::SameLine();
ImGui::TextUnformatted(label); ImGui::TextUnformatted(label);
ImPlot::EndDragDropSource(); ImPlot::EndDragDropSource();
@ -1404,7 +1404,7 @@ void Demo_DragPoints() {
ImGui::CheckboxFlags("NoInput", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs); ImGui::CheckboxFlags("NoInput", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs);
ImPlotAxisFlags ax_flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks; ImPlotAxisFlags ax_flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks;
if (ImPlot::BeginPlot("##Bezier",ImVec2(-1,0),ImPlotFlags_CanvasOnly)) { if (ImPlot::BeginPlot("##Bezier",ImVec2(-1,0),ImPlotFlags_CanvasOnly)) {
ImPlot::SetupAxes(0,0,ax_flags,ax_flags); ImPlot::SetupAxes(nullptr,nullptr,ax_flags,ax_flags);
ImPlot::SetupAxesLimits(0,1,0,1); ImPlot::SetupAxesLimits(0,1,0,1);
static ImPlotPoint P[] = {ImPlotPoint(.05f,.05f), ImPlotPoint(0.2,0.4), ImPlotPoint(0.8,0.6), ImPlotPoint(.95f,.95f)}; static ImPlotPoint P[] = {ImPlotPoint(.05f,.05f), ImPlotPoint(0.2,0.4), ImPlotPoint(0.8,0.6), ImPlotPoint(.95f,.95f)};
@ -1492,7 +1492,7 @@ void Demo_DragRects() {
ImGui::CheckboxFlags("NoInput", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs); ImGui::CheckboxFlags("NoInput", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs);
if (ImPlot::BeginPlot("##Main",ImVec2(-1,150))) { if (ImPlot::BeginPlot("##Main",ImVec2(-1,150))) {
ImPlot::SetupAxes(NULL,NULL,ImPlotAxisFlags_NoTickLabels,ImPlotAxisFlags_NoTickLabels); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoTickLabels,ImPlotAxisFlags_NoTickLabels);
ImPlot::SetupAxesLimits(0,0.01,-1,1); ImPlot::SetupAxesLimits(0,0.01,-1,1);
ImPlot::PlotLine("Signal 1", x_data, y_data1, 512); ImPlot::PlotLine("Signal 1", x_data, y_data1, 512);
ImPlot::PlotLine("Signal 2", x_data, y_data2, 512); ImPlot::PlotLine("Signal 2", x_data, y_data2, 512);
@ -1501,7 +1501,7 @@ void Demo_DragRects() {
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
if (ImPlot::BeginPlot("##rect",ImVec2(-1,150), ImPlotFlags_CanvasOnly)) { if (ImPlot::BeginPlot("##rect",ImVec2(-1,150), ImPlotFlags_CanvasOnly)) {
ImPlot::SetupAxes(NULL,NULL,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(rect.X.Min, rect.X.Max, rect.Y.Min, rect.Y.Max, ImGuiCond_Always); ImPlot::SetupAxesLimits(rect.X.Min, rect.X.Max, rect.Y.Min, rect.Y.Max, ImGuiCond_Always);
ImPlot::PlotLine("Signal 1", x_data, y_data1, 512); ImPlot::PlotLine("Signal 1", x_data, y_data1, 512);
ImPlot::PlotLine("Signal 2", x_data, y_data2, 512); ImPlot::PlotLine("Signal 2", x_data, y_data2, 512);
@ -1678,15 +1678,15 @@ void Demo_DragAndDrop() {
const int k_dnd = 20; const int k_dnd = 20;
static MyDndItem dnd[k_dnd]; static MyDndItem dnd[k_dnd];
static MyDndItem* dndx = NULL; // for plot 2 static MyDndItem* dndx = nullptr; // for plot 2
static MyDndItem* dndy = NULL; // for plot 2 static MyDndItem* dndy = nullptr; // for plot 2
// child window to serve as initial source for our DND items // child window to serve as initial source for our DND items
ImGui::BeginChild("DND_LEFT",ImVec2(100,400)); ImGui::BeginChild("DND_LEFT",ImVec2(100,400));
if (ImGui::Button("Reset Data")) { if (ImGui::Button("Reset Data")) {
for (int k = 0; k < k_dnd; ++k) for (int k = 0; k < k_dnd; ++k)
dnd[k].Reset(); dnd[k].Reset();
dndx = dndy = NULL; dndx = dndy = nullptr;
} }
for (int k = 0; k < k_dnd; ++k) { for (int k = 0; k < k_dnd; ++k) {
if (dnd[k].Plt > 0) if (dnd[k].Plt > 0)
@ -1713,7 +1713,7 @@ void Demo_DragAndDrop() {
// plot 1 (time series) // plot 1 (time series)
ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoHighlight; ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoHighlight;
if (ImPlot::BeginPlot("##DND1", ImVec2(-1,195))) { if (ImPlot::BeginPlot("##DND1", ImVec2(-1,195))) {
ImPlot::SetupAxis(ImAxis_X1, NULL, flags|ImPlotAxisFlags_Lock); ImPlot::SetupAxis(ImAxis_X1, nullptr, flags|ImPlotAxisFlags_Lock);
ImPlot::SetupAxis(ImAxis_Y1, "[drop here]", flags); ImPlot::SetupAxis(ImAxis_Y1, "[drop here]", flags);
ImPlot::SetupAxis(ImAxis_Y2, "[drop here]", flags|ImPlotAxisFlags_Opposite); ImPlot::SetupAxis(ImAxis_Y2, "[drop here]", flags|ImPlotAxisFlags_Opposite);
ImPlot::SetupAxis(ImAxis_Y3, "[drop here]", flags|ImPlotAxisFlags_Opposite); ImPlot::SetupAxis(ImAxis_Y3, "[drop here]", flags|ImPlotAxisFlags_Opposite);
@ -1759,12 +1759,12 @@ void Demo_DragAndDrop() {
} }
// plot 2 (Lissajous) // plot 2 (Lissajous)
if (ImPlot::BeginPlot("##DND2", ImVec2(-1,195))) { if (ImPlot::BeginPlot("##DND2", ImVec2(-1,195))) {
ImPlot::PushStyleColor(ImPlotCol_AxisBg, dndx != NULL ? dndx->Color : ImPlot::GetStyle().Colors[ImPlotCol_AxisBg]); ImPlot::PushStyleColor(ImPlotCol_AxisBg, dndx != nullptr ? dndx->Color : ImPlot::GetStyle().Colors[ImPlotCol_AxisBg]);
ImPlot::SetupAxis(ImAxis_X1, dndx == NULL ? "[drop here]" : dndx->Label, flags); ImPlot::SetupAxis(ImAxis_X1, dndx == nullptr ? "[drop here]" : dndx->Label, flags);
ImPlot::PushStyleColor(ImPlotCol_AxisBg, dndy != NULL ? dndy->Color : ImPlot::GetStyle().Colors[ImPlotCol_AxisBg]); ImPlot::PushStyleColor(ImPlotCol_AxisBg, dndy != nullptr ? dndy->Color : ImPlot::GetStyle().Colors[ImPlotCol_AxisBg]);
ImPlot::SetupAxis(ImAxis_Y1, dndy == NULL ? "[drop here]" : dndy->Label, flags); ImPlot::SetupAxis(ImAxis_Y1, dndy == nullptr ? "[drop here]" : dndy->Label, flags);
ImPlot::PopStyleColor(2); ImPlot::PopStyleColor(2);
if (dndx != NULL && dndy != NULL) { if (dndx != nullptr && dndy != nullptr) {
ImVec4 mixed((dndx->Color.x + dndy->Color.x)/2,(dndx->Color.y + dndy->Color.y)/2,(dndx->Color.z + dndy->Color.z)/2,(dndx->Color.w + dndy->Color.w)/2); ImVec4 mixed((dndx->Color.x + dndy->Color.x)/2,(dndx->Color.y + dndy->Color.y)/2,(dndx->Color.z + dndy->Color.z)/2,(dndx->Color.w + dndy->Color.w)/2);
ImPlot::SetNextLineStyle(mixed); ImPlot::SetNextLineStyle(mixed);
ImPlot::PlotLine("##dndxy", &dndx->Data[0].y, &dndy->Data[0].y, dndx->Data.size(), 0, 0, 2 * sizeof(float)); ImPlot::PlotLine("##dndxy", &dndx->Data[0].y, &dndy->Data[0].y, dndx->Data.size(), 0, 0, 2 * sizeof(float));
@ -1777,7 +1777,7 @@ void Demo_DragAndDrop() {
ImPlot::EndDragDropTarget(); ImPlot::EndDragDropTarget();
} }
// allow the x-axis to be a DND source // allow the x-axis to be a DND source
if (dndx != NULL && ImPlot::BeginDragDropSourceAxis(ImAxis_X1)) { if (dndx != nullptr && ImPlot::BeginDragDropSourceAxis(ImAxis_X1)) {
ImGui::SetDragDropPayload("MY_DND", &dndx->Idx, sizeof(int)); ImGui::SetDragDropPayload("MY_DND", &dndx->Idx, sizeof(int));
ImPlot::ItemIcon(dndx->Color); ImGui::SameLine(); ImPlot::ItemIcon(dndx->Color); ImGui::SameLine();
ImGui::TextUnformatted(dndx->Label); ImGui::TextUnformatted(dndx->Label);
@ -1791,7 +1791,7 @@ void Demo_DragAndDrop() {
ImPlot::EndDragDropTarget(); ImPlot::EndDragDropTarget();
} }
// allow the y-axis to be a DND source // allow the y-axis to be a DND source
if (dndy != NULL && ImPlot::BeginDragDropSourceAxis(ImAxis_Y1)) { if (dndy != nullptr && ImPlot::BeginDragDropSourceAxis(ImAxis_Y1)) {
ImGui::SetDragDropPayload("MY_DND", &dndy->Idx, sizeof(int)); ImGui::SetDragDropPayload("MY_DND", &dndy->Idx, sizeof(int));
ImPlot::ItemIcon(dndy->Color); ImGui::SameLine(); ImPlot::ItemIcon(dndy->Color); ImGui::SameLine();
ImGui::TextUnformatted(dndy->Label); ImGui::TextUnformatted(dndy->Label);
@ -1907,7 +1907,7 @@ void Demo_CustomDataAndGetters() {
ImPlot::PlotLine("Vector2f", &vec2_data[0].x, &vec2_data[0].y, 2, 0, 0, sizeof(MyImPlot::Vector2f) /* or sizeof(float) * 2 */); ImPlot::PlotLine("Vector2f", &vec2_data[0].x, &vec2_data[0].y, 2, 0, 0, sizeof(MyImPlot::Vector2f) /* or sizeof(float) * 2 */);
// custom getter example 1: // custom getter example 1:
ImPlot::PlotLineG("Spiral", MyImPlot::Spiral, NULL, 1000); ImPlot::PlotLineG("Spiral", MyImPlot::Spiral, nullptr, 1000);
// custom getter example 2: // custom getter example 2:
static MyImPlot::WaveData data1(0.001, 0.2, 2, 0.75); static MyImPlot::WaveData data1(0.001, 0.2, 2, 0.75);
@ -1962,8 +1962,8 @@ void Demo_TickLabels() {
static const char* ylabels_aux[] = {"A","B","C","D","E","F"}; static const char* ylabels_aux[] = {"A","B","C","D","E","F"};
if (ImPlot::BeginPlot("##Ticks")) { if (ImPlot::BeginPlot("##Ticks")) {
ImPlot::SetupAxesLimits(2.5,5,0,1000); ImPlot::SetupAxesLimits(2.5,5,0,1000);
ImPlot::SetupAxis(ImAxis_Y2, NULL, ImPlotAxisFlags_AuxDefault); ImPlot::SetupAxis(ImAxis_Y2, nullptr, ImPlotAxisFlags_AuxDefault);
ImPlot::SetupAxis(ImAxis_Y3, NULL, ImPlotAxisFlags_AuxDefault); ImPlot::SetupAxis(ImAxis_Y3, nullptr, ImPlotAxisFlags_AuxDefault);
if (custom_fmt) { if (custom_fmt) {
ImPlot::SetupAxisFormat(ImAxis_X1, "%g ms"); ImPlot::SetupAxisFormat(ImAxis_X1, "%g ms");
ImPlot::SetupAxisFormat(ImAxis_Y1, MetricFormatter, (void*)"Hz"); ImPlot::SetupAxisFormat(ImAxis_Y1, MetricFormatter, (void*)"Hz");
@ -1971,10 +1971,10 @@ void Demo_TickLabels() {
ImPlot::SetupAxisFormat(ImAxis_Y3, MetricFormatter, (void*)"m"); ImPlot::SetupAxisFormat(ImAxis_Y3, MetricFormatter, (void*)"m");
} }
if (custom_ticks) { if (custom_ticks) {
ImPlot::SetupAxisTicks(ImAxis_X1, &pi,1,custom_labels ? pi_str : NULL, true); ImPlot::SetupAxisTicks(ImAxis_X1, &pi,1,custom_labels ? pi_str : nullptr, true);
ImPlot::SetupAxisTicks(ImAxis_Y1, yticks, 4, custom_labels ? ylabels : NULL, false); ImPlot::SetupAxisTicks(ImAxis_Y1, yticks, 4, custom_labels ? ylabels : nullptr, false);
ImPlot::SetupAxisTicks(ImAxis_Y2, yticks_aux, 3, custom_labels ? ylabels_aux : NULL, false); ImPlot::SetupAxisTicks(ImAxis_Y2, yticks_aux, 3, custom_labels ? ylabels_aux : nullptr, false);
ImPlot::SetupAxisTicks(ImAxis_Y3, 0, 1, 6, custom_labels ? ylabels_aux : NULL, false); ImPlot::SetupAxisTicks(ImAxis_Y3, 0, 1, 6, custom_labels ? ylabels_aux : nullptr, false);
} }
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
@ -2116,7 +2116,7 @@ void Demo_CustomPlottersAndTooltips() {
ImPlot::GetStyle().UseLocalTime = false; ImPlot::GetStyle().UseLocalTime = false;
if (ImPlot::BeginPlot("Candlestick Chart",ImVec2(-1,0))) { if (ImPlot::BeginPlot("Candlestick Chart",ImVec2(-1,0))) {
ImPlot::SetupAxes(NULL,NULL,0,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_RangeFit); ImPlot::SetupAxes(nullptr,nullptr,0,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_RangeFit);
ImPlot::SetupAxesLimits(1546300800, 1571961600, 1250, 1600); ImPlot::SetupAxesLimits(1546300800, 1571961600, 1250, 1600);
ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time); ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);
ImPlot::SetupAxisLimitsConstraints(ImAxis_X1, 1546300800, 1571961600); ImPlot::SetupAxisLimitsConstraints(ImAxis_X1, 1546300800, 1571961600);
@ -2170,12 +2170,12 @@ void ShowDemoWindow(bool* p_open) {
ImGui::Begin("ImPlot Demo", p_open, ImGuiWindowFlags_MenuBar); ImGui::Begin("ImPlot Demo", p_open, ImGuiWindowFlags_MenuBar);
if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenuBar()) {
if (ImGui::BeginMenu("Tools")) { if (ImGui::BeginMenu("Tools")) {
ImGui::MenuItem("Metrics", NULL, &show_implot_metrics); ImGui::MenuItem("Metrics", nullptr, &show_implot_metrics);
ImGui::MenuItem("Style Editor", NULL, &show_implot_style_editor); ImGui::MenuItem("Style Editor", nullptr, &show_implot_style_editor);
ImGui::Separator(); ImGui::Separator();
ImGui::MenuItem("ImGui Metrics", NULL, &show_imgui_metrics); ImGui::MenuItem("ImGui Metrics", nullptr, &show_imgui_metrics);
ImGui::MenuItem("ImGui Style Editor", NULL, &show_imgui_style_editor); ImGui::MenuItem("ImGui Style Editor", nullptr, &show_imgui_style_editor);
ImGui::MenuItem("ImGui Demo", NULL, &show_imgui_demo); ImGui::MenuItem("ImGui Demo", nullptr, &show_imgui_demo);
ImGui::EndMenu(); ImGui::EndMenu();
} }
ImGui::EndMenuBar(); ImGui::EndMenuBar();
@ -2300,7 +2300,7 @@ ImPlotPoint Spiral(int idx, void*) {
void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size) { void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size) {
ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, ImVec2(0,0)); ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, ImVec2(0,0));
if (ImPlot::BeginPlot(id,size,ImPlotFlags_CanvasOnly|ImPlotFlags_NoChild)) { if (ImPlot::BeginPlot(id,size,ImPlotFlags_CanvasOnly|ImPlotFlags_NoChild)) {
ImPlot::SetupAxes(0,0,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(0, count - 1, min_v, max_v, ImGuiCond_Always); ImPlot::SetupAxesLimits(0, count - 1, min_v, max_v, ImGuiCond_Always);
ImPlot::SetNextLineStyle(col); ImPlot::SetNextLineStyle(col);
ImPlot::SetNextFillStyle(col, 0.25); ImPlot::SetNextFillStyle(col, 0.25);

View File

@ -396,18 +396,18 @@ struct ImPlotColormapData {
_AppendTable(i); _AppendTable(i);
} }
inline bool IsQual(ImPlotColormap cmap) const { return Quals[cmap]; } inline bool IsQual(ImPlotColormap cmap) const { return Quals[cmap]; }
inline const char* GetName(ImPlotColormap cmap) const { return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] : NULL; } inline const char* GetName(ImPlotColormap cmap) const { return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] : nullptr; }
inline ImPlotColormap GetIndex(const char* name) const { ImGuiID key = ImHashStr(name); return Map.GetInt(key,-1); } inline ImPlotColormap GetIndex(const char* name) const { ImGuiID key = ImHashStr(name); return Map.GetInt(key,-1); }
inline const ImU32* GetKeys(ImPlotColormap cmap) const { return &Keys[KeyOffsets[cmap]]; } inline const ImU32* GetKeys(ImPlotColormap cmap) const { return &Keys[KeyOffsets[cmap]]; }
inline int GetKeyCount(ImPlotColormap cmap) const { return KeyCounts[cmap]; } inline int GetKeyCount(ImPlotColormap cmap) const { return KeyCounts[cmap]; }
inline ImU32 GetKeyColor(ImPlotColormap cmap, int idx) const { return Keys[KeyOffsets[cmap]+idx]; } inline ImU32 GetKeyColor(ImPlotColormap cmap, int idx) const { return Keys[KeyOffsets[cmap]+idx]; }
inline void SetKeyColor(ImPlotColormap cmap, int idx, ImU32 value) { Keys[KeyOffsets[cmap]+idx] = value; RebuildTables(); } inline void SetKeyColor(ImPlotColormap cmap, int idx, ImU32 value) { Keys[KeyOffsets[cmap]+idx] = value; RebuildTables(); }
inline const ImU32* GetTable(ImPlotColormap cmap) const { return &Tables[TableOffsets[cmap]]; } inline const ImU32* GetTable(ImPlotColormap cmap) const { return &Tables[TableOffsets[cmap]]; }
inline int GetTableSize(ImPlotColormap cmap) const { return TableSizes[cmap]; } inline int GetTableSize(ImPlotColormap cmap) const { return TableSizes[cmap]; }
inline ImU32 GetTableColor(ImPlotColormap cmap, int idx) const { return Tables[TableOffsets[cmap]+idx]; } inline ImU32 GetTableColor(ImPlotColormap cmap, int idx) const { return Tables[TableOffsets[cmap]+idx]; }
inline ImU32 LerpTable(ImPlotColormap cmap, float t) const { inline ImU32 LerpTable(ImPlotColormap cmap, float t) const {
int off = TableOffsets[cmap]; int off = TableOffsets[cmap];
@ -564,7 +564,7 @@ struct ImPlotTicker {
ImPlotTick& AddTick(double value, bool major, int level, bool show_label, const char* label) { ImPlotTick& AddTick(double value, bool major, int level, bool show_label, const char* label) {
ImPlotTick tick(value, major, level, show_label); ImPlotTick tick(value, major, level, show_label);
if (show_label && label != NULL) { if (show_label && label != nullptr) {
tick.TextOffset = TextBuffer.size(); tick.TextOffset = TextBuffer.size();
TextBuffer.append(label, label + strlen(label) + 1); TextBuffer.append(label, label + strlen(label) + 1);
tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset); tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);
@ -574,7 +574,7 @@ struct ImPlotTicker {
ImPlotTick& AddTick(double value, bool major, int level, bool show_label, ImPlotFormatter formatter, void* data) { ImPlotTick& AddTick(double value, bool major, int level, bool show_label, ImPlotFormatter formatter, void* data) {
ImPlotTick tick(value, major, level, show_label); ImPlotTick tick(value, major, level, show_label);
if (show_label && formatter != NULL) { if (show_label && formatter != nullptr) {
char buff[IMPLOT_LABEL_MAX_SIZE]; char buff[IMPLOT_LABEL_MAX_SIZE];
tick.TextOffset = TextBuffer.size(); tick.TextOffset = TextBuffer.size();
formatter(tick.PlotPos, buff, sizeof(buff), data); formatter(tick.PlotPos, buff, sizeof(buff), data);
@ -673,23 +673,23 @@ struct ImPlotAxis
Range.Min = 0; Range.Min = 0;
Range.Max = 1; Range.Max = 1;
Scale = ImPlotScale_Linear; Scale = ImPlotScale_Linear;
TransformForward = TransformInverse = NULL; TransformForward = TransformInverse = nullptr;
TransformData = NULL; TransformData = nullptr;
FitExtents.Min = HUGE_VAL; FitExtents.Min = HUGE_VAL;
FitExtents.Max = -HUGE_VAL; FitExtents.Max = -HUGE_VAL;
OrthoAxis = NULL; OrthoAxis = nullptr;
ConstraintRange = ImPlotRange(-INFINITY,INFINITY); ConstraintRange = ImPlotRange(-INFINITY,INFINITY);
ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY); ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY);
LinkedMin = LinkedMax = NULL; LinkedMin = LinkedMax = nullptr;
PickerLevel = 0; PickerLevel = 0;
Datum1 = Datum2 = 0; Datum1 = Datum2 = 0;
PixelMin = PixelMax = 0; PixelMin = PixelMax = 0;
LabelOffset = -1; LabelOffset = -1;
ColorMaj = ColorMin = ColorTick = ColorTxt = ColorBg = ColorHov = ColorAct = 0; ColorMaj = ColorMin = ColorTick = ColorTxt = ColorBg = ColorHov = ColorAct = 0;
ColorHiLi = IM_COL32_BLACK_TRANS; ColorHiLi = IM_COL32_BLACK_TRANS;
Formatter = NULL; Formatter = nullptr;
FormatterData = NULL; FormatterData = nullptr;
Locator = NULL; Locator = nullptr;
Enabled = Hovered = Held = FitThisFrame = HasRange = HasFormatSpec = false; Enabled = Hovered = Held = FitThisFrame = HasRange = HasFormatSpec = false;
ShowDefaultTicks = true; ShowDefaultTicks = true;
} }
@ -697,18 +697,18 @@ struct ImPlotAxis
inline void Reset() { inline void Reset() {
Enabled = false; Enabled = false;
Scale = ImPlotScale_Linear; Scale = ImPlotScale_Linear;
TransformForward = TransformInverse = NULL; TransformForward = TransformInverse = nullptr;
TransformData = NULL; TransformData = nullptr;
LabelOffset = -1; LabelOffset = -1;
HasFormatSpec = false; HasFormatSpec = false;
Formatter = NULL; Formatter = nullptr;
FormatterData = NULL; FormatterData = nullptr;
Locator = NULL; Locator = nullptr;
ShowDefaultTicks = true; ShowDefaultTicks = true;
FitThisFrame = false; FitThisFrame = false;
FitExtents.Min = HUGE_VAL; FitExtents.Min = HUGE_VAL;
FitExtents.Max = -HUGE_VAL; FitExtents.Max = -HUGE_VAL;
OrthoAxis = NULL; OrthoAxis = nullptr;
ConstraintRange = ImPlotRange(-INFINITY,INFINITY); ConstraintRange = ImPlotRange(-INFINITY,INFINITY);
ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY); ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY);
Ticker.Reset(); Ticker.Reset();
@ -806,7 +806,7 @@ struct ImPlotAxis
inline void UpdateTransformCache() { inline void UpdateTransformCache() {
ScaleToPixel = (PixelMax - PixelMin) / Range.Size(); ScaleToPixel = (PixelMax - PixelMin) / Range.Size();
if (TransformForward != NULL) { if (TransformForward != nullptr) {
ScaleMin = TransformForward(Range.Min, TransformData); ScaleMin = TransformForward(Range.Min, TransformData);
ScaleMax = TransformForward(Range.Max, TransformData); ScaleMax = TransformForward(Range.Max, TransformData);
} }
@ -817,7 +817,7 @@ struct ImPlotAxis
} }
inline float PlotToPixels(double plt) const { inline float PlotToPixels(double plt) const {
if (TransformForward != NULL) { if (TransformForward != nullptr) {
double s = TransformForward(plt, TransformData); double s = TransformForward(plt, TransformData);
double t = (s - ScaleMin) / (ScaleMax - ScaleMin); double t = (s - ScaleMin) / (ScaleMax - ScaleMin);
plt = Range.Min + Range.Size() * t; plt = Range.Min + Range.Size() * t;
@ -828,7 +828,7 @@ struct ImPlotAxis
inline double PixelsToPlot(float pix) const { inline double PixelsToPlot(float pix) const {
double plt = (pix - PixelMin) / ScaleToPixel + Range.Min; double plt = (pix - PixelMin) / ScaleToPixel + Range.Min;
if (TransformInverse != NULL) { if (TransformInverse != nullptr) {
double t = (plt - Range.Min) / Range.Size(); double t = (plt - Range.Min) / Range.Size();
double s = t * (ScaleMax - ScaleMin) + ScaleMin; double s = t * (ScaleMax - ScaleMin) + ScaleMin;
plt = TransformInverse(s, TransformData); plt = TransformInverse(s, TransformData);
@ -1067,7 +1067,7 @@ struct ImPlotPlot
inline void ClearTextBuffer() { TextBuffer.Buf.shrink(0); } inline void ClearTextBuffer() { TextBuffer.Buf.shrink(0); }
inline void SetTitle(const char* title) { inline void SetTitle(const char* title) {
if (title && ImGui::FindRenderedTextEnd(title, NULL) != title) { if (title && ImGui::FindRenderedTextEnd(title, nullptr) != title) {
TitleOffset = TextBuffer.size(); TitleOffset = TextBuffer.size();
TextBuffer.append(title, title + strlen(title) + 1); TextBuffer.append(title, title + strlen(title) + 1);
} }
@ -1098,7 +1098,7 @@ struct ImPlotPlot
} }
inline void SetAxisLabel(ImPlotAxis& axis, const char* label) { inline void SetAxisLabel(ImPlotAxis& axis, const char* label) {
if (label && ImGui::FindRenderedTextEnd(label, NULL) != label) { if (label && ImGui::FindRenderedTextEnd(label, nullptr) != label) {
axis.LabelOffset = TextBuffer.size(); axis.LabelOffset = TextBuffer.size();
TextBuffer.append(label, label + strlen(label) + 1); TextBuffer.append(label, label + strlen(label) + 1);
} }
@ -1162,7 +1162,7 @@ struct ImPlotNextPlotData
for (int i = 0; i < ImAxis_COUNT; ++i) { for (int i = 0; i < ImAxis_COUNT; ++i) {
HasRange[i] = false; HasRange[i] = false;
Fit[i] = false; Fit[i] = false;
LinkedMin[i] = LinkedMax[i] = NULL; LinkedMin[i] = LinkedMax[i] = nullptr;
} }
} }
@ -1288,9 +1288,10 @@ IMPLOT_API void ShowPlotContextMenu(ImPlotPlot& plot);
// Lock Setup and call SetupFinish if necessary. // Lock Setup and call SetupFinish if necessary.
static inline void SetupLock() { static inline void SetupLock() {
if (!GImPlot->CurrentPlot->SetupLocked) ImPlotContext& gp = *GImPlot;
if (!gp.CurrentPlot->SetupLocked)
SetupFinish(); SetupFinish();
GImPlot->CurrentPlot->SetupLocked = true; gp.CurrentPlot->SetupLocked = true;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1326,7 +1327,7 @@ bool BeginItemEx(const char* label_id, const _Fitter& fitter, ImPlotItemFlags fl
IMPLOT_API void EndItem(); IMPLOT_API void EndItem();
// Register or get an existing item from the current plot. // Register or get an existing item from the current plot.
IMPLOT_API ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool* just_created = NULL); IMPLOT_API ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool* just_created = nullptr);
// Get a plot item from the current plot. // Get a plot item from the current plot.
IMPLOT_API ImPlotItem* GetItem(const char* label_id); IMPLOT_API ImPlotItem* GetItem(const char* label_id);
// Gets the current item. // Gets the current item.
@ -1438,7 +1439,7 @@ static inline const ImPlotNextItemData& GetItemData() { return GImPlot->NextItem
// Returns true if a color is set to be automatically determined // Returns true if a color is set to be automatically determined
static inline bool IsColorAuto(const ImVec4& col) { return col.w == -1; } static inline bool IsColorAuto(const ImVec4& col) { return col.w == -1; }
// Returns true if a style color is set to be automaticaly determined // Returns true if a style color is set to be automatically determined
static inline bool IsColorAuto(ImPlotCol idx) { return IsColorAuto(GImPlot->Style.Colors[idx]); } static inline bool IsColorAuto(ImPlotCol idx) { return IsColorAuto(GImPlot->Style.Colors[idx]); }
// Returns the automatically deduced style color // Returns the automatically deduced style color
IMPLOT_API ImVec4 GetAutoColor(ImPlotCol idx); IMPLOT_API ImVec4 GetAutoColor(ImPlotCol idx);
@ -1448,9 +1449,9 @@ static inline ImVec4 GetStyleColorVec4(ImPlotCol idx) { return IsColorAuto(idx)
static inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); } static inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); }
// Draws vertical text. The position is the bottom left of the text rect. // Draws vertical text. The position is the bottom left of the text rect.
IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = NULL); IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = nullptr);
// Draws multiline horizontal text centered. // Draws multiline horizontal text centered.
IMPLOT_API void AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end = NULL); IMPLOT_API void AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end = nullptr);
// Calculates the size of vertical text // Calculates the size of vertical text
static inline ImVec2 CalcTextSizeVertical(const char *text) { static inline ImVec2 CalcTextSizeVertical(const char *text) {
ImVec2 sz = ImGui::CalcTextSize(text); ImVec2 sz = ImGui::CalcTextSize(text);
@ -1589,7 +1590,7 @@ IMPLOT_API int FormatDateTime(const ImPlotTime& t, char* buffer, int size, ImPlo
// #level = 0 for day, 1 for month, 2 for year. Modified by user interaction. // #level = 0 for day, 1 for month, 2 for year. Modified by user interaction.
// #t will be set when a day is clicked and the function will return true. // #t will be set when a day is clicked and the function will return true.
// #t1 and #t2 are optional dates to highlight. // #t1 and #t2 are optional dates to highlight.
IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = NULL, const ImPlotTime* t2 = NULL); IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = nullptr, const ImPlotTime* t2 = nullptr);
// Shows a time picker widget block (hour/min/sec). // Shows a time picker widget block (hour/min/sec).
// #t will be set when a new hour, minute, or sec is selected or am/pm is toggled, and the function will return true. // #t will be set when a new hour, minute, or sec is selected or am/pm is toggled, and the function will return true.
IMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t); IMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t);

View File

@ -285,15 +285,15 @@ ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool*
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
ImPlotItemGroup& Items = *gp.CurrentItems; ImPlotItemGroup& Items = *gp.CurrentItems;
ImGuiID id = Items.GetItemID(label_id); ImGuiID id = Items.GetItemID(label_id);
if (just_created != NULL) if (just_created != nullptr)
*just_created = Items.GetItem(id) == NULL; *just_created = Items.GetItem(id) == nullptr;
ImPlotItem* item = Items.GetOrAddItem(id); ImPlotItem* item = Items.GetOrAddItem(id);
if (item->SeenThisFrame) if (item->SeenThisFrame)
return item; return item;
item->SeenThisFrame = true; item->SeenThisFrame = true;
int idx = Items.GetItemIndex(item); int idx = Items.GetItemIndex(item);
item->ID = id; item->ID = id;
if (!ImHasFlag(flags, ImPlotItemFlags_NoLegend) && ImGui::FindRenderedTextEnd(label_id, NULL) != label_id) { if (!ImHasFlag(flags, ImPlotItemFlags_NoLegend) && ImGui::FindRenderedTextEnd(label_id, nullptr) != label_id) {
Items.Legend.Indices.push_back(idx); Items.Legend.Indices.push_back(idx);
item->NameOffset = Items.Legend.Labels.size(); item->NameOffset = Items.Legend.Labels.size();
Items.Legend.Labels.append(label_id, label_id + strlen(label_id) + 1); Items.Legend.Labels.append(label_id, label_id + strlen(label_id) + 1);
@ -311,7 +311,7 @@ ImPlotItem* GetItem(const char* label_id) {
bool IsItemHidden(const char* label_id) { bool IsItemHidden(const char* label_id) {
ImPlotItem* item = GetItem(label_id); ImPlotItem* item = GetItem(label_id);
return item != NULL && !item->Show; return item != nullptr && !item->Show;
} }
ImPlotItem* GetCurrentItem() { ImPlotItem* GetCurrentItem() {
@ -368,17 +368,17 @@ void BustItemCache() {
void BustColorCache(const char* plot_title_id) { void BustColorCache(const char* plot_title_id) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
if (plot_title_id == NULL) { if (plot_title_id == nullptr) {
BustItemCache(); BustItemCache();
} }
else { else {
ImGuiID id = ImGui::GetCurrentWindow()->GetID(plot_title_id); ImGuiID id = ImGui::GetCurrentWindow()->GetID(plot_title_id);
ImPlotPlot* plot = gp.Plots.GetByKey(id); ImPlotPlot* plot = gp.Plots.GetByKey(id);
if (plot != NULL) if (plot != nullptr)
plot->Items.Reset(); plot->Items.Reset();
else { else {
ImPlotSubplot* subplot = gp.Subplots.GetByKey(id); ImPlotSubplot* subplot = gp.Subplots.GetByKey(id);
if (subplot != NULL) if (subplot != nullptr)
subplot->Items.Reset(); subplot->Items.Reset();
} }
} }
@ -394,7 +394,7 @@ static const float ITEM_HIGHLIGHT_MARK_SCALE = 1.25f;
// Begins a new item. Returns false if the item should not be plotted. // Begins a new item. Returns false if the item should not be plotted.
bool BeginItem(const char* label_id, ImPlotItemFlags flags, ImPlotCol recolor_from) { bool BeginItem(const char* label_id, ImPlotItemFlags flags, ImPlotCol recolor_from) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotX() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "PlotX() needs to be called between BeginPlot() and EndPlot()!");
SetupLock(); SetupLock();
bool just_created; bool just_created;
ImPlotItem* item = RegisterOrGetItem(label_id, flags, &just_created); ImPlotItem* item = RegisterOrGetItem(label_id, flags, &just_created);
@ -422,7 +422,7 @@ bool BeginItem(const char* label_id, ImPlotItemFlags flags, ImPlotCol recolor_fr
// reset next item data // reset next item data
gp.NextItemData.Reset(); gp.NextItemData.Reset();
gp.PreviousItem = item; gp.PreviousItem = item;
gp.CurrentItem = NULL; gp.CurrentItem = nullptr;
return false; return false;
} }
else { else {
@ -481,7 +481,7 @@ void EndItem() {
gp.NextItemData.Reset(); gp.NextItemData.Reset();
// set current item // set current item
gp.PreviousItem = gp.CurrentItem; gp.PreviousItem = gp.CurrentItem;
gp.CurrentItem = NULL; gp.CurrentItem = nullptr;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -785,7 +785,7 @@ struct Transformer1 {
{ } { }
template <typename T> IMPLOT_INLINE float operator()(T p) const { template <typename T> IMPLOT_INLINE float operator()(T p) const {
if (TransformFwd != NULL) { if (TransformFwd != nullptr) {
double s = TransformFwd(p, TransformData); double s = TransformFwd(p, TransformData);
double t = (s - ScaMin) / (ScaMax - ScaMin); double t = (s - ScaMin) / (ScaMax - ScaMin);
p = PltMin + (PltMax - PltMin) * t; p = PltMin + (PltMax - PltMin) * t;
@ -1900,8 +1900,9 @@ void PlotBarGroups(const char* const label_ids[], const T* values, int item_coun
const bool stack = ImHasFlag(flags, ImPlotBarGroupsFlags_Stacked); const bool stack = ImHasFlag(flags, ImPlotBarGroupsFlags_Stacked);
if (stack) { if (stack) {
SetupLock(); SetupLock();
GImPlot->TempDouble1.resize(4*group_count); ImPlotContext& gp = *GImPlot;
double* temp = GImPlot->TempDouble1.Data; gp.TempDouble1.resize(4*group_count);
double* temp = gp.TempDouble1.Data;
double* neg = &temp[0]; double* neg = &temp[0];
double* pos = &temp[group_count]; double* pos = &temp[group_count];
double* curr_min = &temp[group_count*2]; double* curr_min = &temp[group_count*2];
@ -2172,7 +2173,7 @@ IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& cent
template <typename T> template <typename T>
void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) { void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
ImDrawList & draw_list = *GetPlotDrawList(); ImDrawList & draw_list = *GetPlotDrawList();
double sum = 0; double sum = 0;
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
@ -2200,7 +2201,7 @@ void PlotPieChart(const char* const label_ids[], const T* values, int count, dou
} }
a0 = a1; a0 = a1;
} }
if (fmt != NULL) { if (fmt != nullptr) {
a0 = angle0 * 2 * IM_PI / 360.0; a0 = angle0 * 2 * IM_PI / 360.0;
a1 = angle0 * 2 * IM_PI / 360.0; a1 = angle0 * 2 * IM_PI / 360.0;
char buffer[32]; char buffer[32];
@ -2254,7 +2255,8 @@ struct GetterHeatmapRowMaj {
rect.Pos = p; rect.Pos = p;
rect.HalfSize = HalfSize; rect.HalfSize = HalfSize;
const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f); const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f);
rect.Color = GImPlot->ColormapData.LerpTable(GImPlot->Style.Colormap, t); ImPlotContext& gp = *GImPlot;
rect.Color = gp.ColormapData.LerpTable(gp.Style.Colormap, t);
return rect; return rect;
} }
const T* const Values; const T* const Values;
@ -2288,7 +2290,8 @@ struct GetterHeatmapColMaj {
rect.Pos = p; rect.Pos = p;
rect.HalfSize = HalfSize; rect.HalfSize = HalfSize;
const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f); const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f);
rect.Color = GImPlot->ColormapData.LerpTable(GImPlot->Style.Colormap, t); ImPlotContext& gp = *GImPlot;
rect.Color = gp.ColormapData.LerpTable(gp.Style.Colormap, t);
return rect; return rect;
} }
const T* const Values; const T* const Values;
@ -2325,7 +2328,7 @@ void RenderHeatmap(ImDrawList& draw_list, const T* values, int rows, int cols, d
RenderPrimitives1<RendererRectC>(getter); RenderPrimitives1<RendererRectC>(getter);
} }
// labels // labels
if (fmt != NULL) { if (fmt != nullptr) {
const double w = (bounds_max.x - bounds_min.x) / cols; const double w = (bounds_max.x - bounds_min.x) / cols;
const double h = (bounds_max.y - bounds_min.y) / rows; const double h = (bounds_max.y - bounds_min.y) / rows;
const ImPlotPoint half_size(w*0.5,h*0.5); const ImPlotPoint half_size(w*0.5,h*0.5);
@ -2409,8 +2412,9 @@ double PlotHistogram(const char* label_id, const T* values, int count, int bins,
else else
width = range.Size() / bins; width = range.Size() / bins;
ImVector<double>& bin_centers = GImPlot->TempDouble1; ImPlotContext& gp = *GImPlot;
ImVector<double>& bin_counts = GImPlot->TempDouble2; ImVector<double>& bin_centers = gp.TempDouble1;
ImVector<double>& bin_counts = gp.TempDouble2;
bin_centers.resize(bins); bin_centers.resize(bins);
bin_counts.resize(bins); bin_counts.resize(bins);
int below = 0; int below = 0;
@ -2507,7 +2511,8 @@ double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count
const int bins = x_bins * y_bins; const int bins = x_bins * y_bins;
ImVector<double>& bin_counts = GImPlot->TempDouble1; ImPlotContext& gp = *GImPlot;
ImVector<double>& bin_counts = gp.TempDouble1;
bin_counts.resize(bins); bin_counts.resize(bins);
for (int b = 0; b < bins; ++b) for (int b = 0; b < bins; ++b)
@ -2535,7 +2540,7 @@ double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count
if (BeginItemEx(label_id, FitterRect(range))) { if (BeginItemEx(label_id, FitterRect(range))) {
ImDrawList& draw_list = *GetPlotDrawList(); ImDrawList& draw_list = *GetPlotDrawList();
RenderHeatmap(draw_list, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, NULL, range.Min(), range.Max(), false, col_maj); RenderHeatmap(draw_list, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, nullptr, range.Min(), range.Max(), false, col_maj);
EndItem(); EndItem();
} }
return max_count; return max_count;
@ -2648,7 +2653,7 @@ void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPo
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void PlotText(const char* text, double x, double y, const ImVec2& pixel_offset, ImPlotTextFlags flags) { void PlotText(const char* text, double x, double y, const ImVec2& pixel_offset, ImPlotTextFlags flags) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotText() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotText() needs to be called between BeginPlot() and EndPlot()!");
SetupLock(); SetupLock();
ImDrawList & draw_list = *GetPlotDrawList(); ImDrawList & draw_list = *GetPlotDrawList();
PushPlotClipRect(); PushPlotClipRect();

View File

@ -1,4 +1,18 @@
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
//
// Zig bindings for 'dear imgui' library. Easy to use, hand-crafted API with default arguments,
// named parameters and Zig style text formatting.
//
//--------------------------------------------------------------------------------------------------
pub const version = @import("std").SemanticVersion{ .major = 1, .minor = 89, .patch = 6 };
pub const plot = @import("plot.zig");
pub const backend = switch (@import("zgui_options").backend) {
.glfw_wgpu => @import("backend_glfw_wgpu.zig"),
.win32_dx12 => .{}, // TODO:
.no_backend => .{},
};
//--------------------------------------------------------------------------------------------------
const std = @import("std"); const std = @import("std");
const assert = std.debug.assert; const assert = std.debug.assert;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -175,7 +189,13 @@ pub const io = struct {
config: ?FontConfig, config: ?FontConfig,
ranges: ?[*]const Wchar, ranges: ?[*]const Wchar,
) Font { ) Font {
return zguiIoAddFontFromMemoryWithConfig(fontdata.ptr, @intCast(i32, fontdata.len), size_pixels, if (config) |c| &c else null, ranges); return zguiIoAddFontFromMemoryWithConfig(
fontdata.ptr,
@intCast(i32, fontdata.len),
size_pixels,
if (config) |c| &c else null,
ranges,
);
} }
extern fn zguiIoAddFontFromMemoryWithConfig( extern fn zguiIoAddFontFromMemoryWithConfig(
font_data: *const anyopaque, font_data: *const anyopaque,
@ -3025,6 +3045,16 @@ extern fn zguiColorConvertRGBtoHSV(r: f32, g: f32, b: f32, out_h: *f32, out_s: *
extern fn zguiColorConvertHSVtoRGB(h: f32, s: f32, v: f32, out_r: *f32, out_g: *f32, out_b: *f32) void; extern fn zguiColorConvertHSVtoRGB(h: f32, s: f32, v: f32, out_r: *f32, out_g: *f32, out_b: *f32) void;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// //
// Inputs Utilities: Keyboard
//
//--------------------------------------------------------------------------------------------------
pub fn isKeyDown(key: Key) bool {
return zguiIsKeyDown(key);
}
extern fn zguiIsKeyDown(key: Key) bool;
//--------------------------------------------------------------------------------------------------
//
// Helpers // Helpers
// //
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -3053,7 +3083,14 @@ pub fn typeToDataTypeEnum(comptime T: type) DataType {
u64 => .U64, u64 => .U64,
f32 => .F32, f32 => .F32,
f64 => .F64, f64 => .F64,
else => @compileError("Only fundamental scalar types allowed"), usize => switch (@sizeOf(usize)) {
1 => .U8,
2 => .U16,
4 => .U32,
8 => .U64,
else => @compileError("Unsupported usize length"),
},
else => @compileError("Only fundamental scalar types allowed: " ++ @typeName(T)),
}; };
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -497,6 +497,50 @@ extern fn zguiPlot_PlotScatter(
offset: i32, offset: i32,
stride: i32, stride: i32,
) void; ) void;
pub const ShadedFlags = packed struct(u32) {
_padding: u32 = 0,
};
fn PlotShadedGen(comptime T: type) type {
return struct {
xv: []const T,
yv: []const T,
yref: f64 = 0.0,
flags: ShadedFlags = .{},
offset: i32 = 0,
stride: i32 = @sizeOf(T),
};
}
pub fn plotShaded(label_id: [:0]const u8, comptime T: type, args: PlotShadedGen(T)) void {
assert(args.xv.len == args.yv.len);
zguiPlot_PlotShaded(
label_id,
gui.typeToDataTypeEnum(T),
args.xv.ptr,
args.yv.ptr,
@intCast(i32, args.xv.len),
args.yref,
args.flags,
args.offset,
args.stride,
);
}
extern fn zguiPlot_PlotShaded(
label_id: [*:0]const u8,
data_type: gui.DataType,
xv: *const anyopaque,
yv: *const anyopaque,
count: i32,
yref: f64,
flags: ShadedFlags,
offset: i32,
stride: i32,
) void;
//----------------------------------------------------------------------------------------------
/// `pub fn showDemoWindow(popen: ?*bool) void`
pub const showDemoWindow = zguiPlot_ShowDemoWindow;
extern fn zguiPlot_ShowDemoWindow(popen: ?*bool) void;
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------
/// `pub fn endPlot() void` /// `pub fn endPlot() void`
pub const endPlot = zguiPlot_EndPlot; pub const endPlot = zguiPlot_EndPlot;

View File

@ -1579,6 +1579,14 @@ ZGUI_API void zguiColorConvertHSVtoRGB(float h, float s, float v, float* out_r,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// //
// Inputs Utilities: Keyboard
//
//--------------------------------------------------------------------------------------------------
ZGUI_API bool zguiIsKeyDown(ImGuiKey key) {
return ImGui::IsKeyDown(key);
}
//--------------------------------------------------------------------------------------------------
//
// DrawList // DrawList
// //
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -2308,6 +2316,41 @@ ZGUI_API void zguiPlot_PlotScatterValues(
assert(false); assert(false);
} }
ZGUI_API void zguiPlot_PlotShaded(
const char* label_id,
ImGuiDataType data_type,
const void* xv,
const void* yv,
int count,
double yref,
ImPlotShadedFlags flags,
int offset,
int stride
) {
if (data_type == ImGuiDataType_S8)
ImPlot::PlotShaded(label_id, (const ImS8*)xv, (const ImS8*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_U8)
ImPlot::PlotShaded(label_id, (const ImU8*)xv, (const ImU8*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_S16)
ImPlot::PlotShaded(label_id, (const ImS16*)xv, (const ImS16*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_U16)
ImPlot::PlotShaded(label_id, (const ImU16*)xv, (const ImU16*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_S32)
ImPlot::PlotShaded(label_id, (const ImS32*)xv, (const ImS32*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_U32)
ImPlot::PlotShaded(label_id, (const ImU32*)xv, (const ImU32*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_Float)
ImPlot::PlotShaded(label_id, (const float*)xv, (const float*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_Double)
ImPlot::PlotShaded(label_id, (const double*)xv, (const double*)yv, count, yref, flags, offset, stride);
else
assert(false);
}
ZGUI_API void zguiPlot_ShowDemoWindow(bool* p_open) {
ImPlot::ShowDemoWindow(p_open);
}
ZGUI_API void zguiPlot_EndPlot(void) { ZGUI_API void zguiPlot_EndPlot(void) {
ImPlot::EndPlot(); ImPlot::EndPlot();
} }