@@ -1,3 +1,3 @@ | |||
Taken from https://github.com/ocornut/imgui master branch with commit ddddabdccfdafffd8664fb4e29230dc4f848137e | |||
Taken from https://github.com/ocornut/imgui master branch with tagged release 1.86 | |||
Files are used as-is except a few parts in the code disabled by a `#ifndef IMGUI_DPF_BACKEND` condition. |
@@ -27,13 +27,13 @@ | |||
//#define IMGUI_API __declspec( dllimport ) | |||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. | |||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS | |||
#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS | |||
//---- Disable all of Dear ImGui or don't implement standard windows. | |||
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp. | |||
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. | |||
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended. | |||
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty. | |||
#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended. | |||
#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger and other debug tools: ShowMetricsWindow() and ShowStackToolWindow() will be empty. | |||
//---- Don't implement some functions to reduce linkage requirements. | |||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) | |||
@@ -1,4 +1,4 @@ | |||
// dear imgui, v1.85 WIP | |||
// dear imgui, v1.86 | |||
// (headers) | |||
// Help: | |||
@@ -63,8 +63,8 @@ Index of this file: | |||
// Version | |||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) | |||
#define IMGUI_VERSION "1.85 WIP" | |||
#define IMGUI_VERSION_NUM 18416 | |||
#define IMGUI_VERSION "1.86" | |||
#define IMGUI_VERSION_NUM 18600 | |||
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) | |||
#define IMGUI_HAS_TABLE | |||
@@ -92,7 +92,7 @@ Index of this file: | |||
#endif | |||
// Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions. | |||
#if !defined(IMGUI_USE_STB_SPRINTF) && defined(__MINGW32__) | |||
#if !defined(IMGUI_USE_STB_SPRINTF) && defined(__MINGW32__) && !defined(__clang__) | |||
#define IM_FMTARGS(FMT) __attribute__((format(gnu_printf, FMT, FMT+1))) | |||
#define IM_FMTLIST(FMT) __attribute__((format(gnu_printf, FMT, 0))) | |||
#elif !defined(IMGUI_USE_STB_SPRINTF) && (defined(__clang__) || defined(__GNUC__)) | |||
@@ -152,7 +152,7 @@ struct ImGuiContext; // Dear ImGui context (opaque structure, unl | |||
struct ImGuiIO; // Main configuration and I/O between your application and ImGui | |||
struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use) | |||
struct ImGuiListClipper; // Helper to manually clip large list of items | |||
struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame, used by IMGUI_ONCE_UPON_A_FRAME macro | |||
struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame | |||
struct ImGuiPayload; // User data payload for drag and drop operations | |||
struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use) | |||
struct ImGuiStorage; // Helper for key->value storage | |||
@@ -307,6 +307,7 @@ namespace ImGui | |||
// Demo, Debug, Information | |||
IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create Demo window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! | |||
IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create Metrics/Debugger window. display Dear ImGui internals: windows, draw commands, various internal state, etc. | |||
IMGUI_API void ShowStackToolWindow(bool* p_open = NULL); // create Stack Tool window. hover items with mouse to query information about the source of their unique ID. | |||
IMGUI_API void ShowAboutWindow(bool* p_open = NULL); // create About window. display Dear ImGui version, credits and build/system information. | |||
IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) | |||
IMGUI_API bool ShowStyleSelector(const char* label); // add style selector block (not a window), essentially a combo listing the default styles. | |||
@@ -522,12 +523,12 @@ namespace ImGui | |||
IMGUI_API bool Combo(const char* label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int popup_max_height_in_items = -1); | |||
// Widgets: Drag Sliders | |||
// - CTRL+Click on any drag box to turn them into an input box. Manually input values aren't clamped and can go off-bounds. | |||
// - CTRL+Click on any drag box to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp. | |||
// - For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, note that a 'float v[X]' function argument is the same as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x | |||
// - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc. | |||
// - Format string may also be set to NULL or use the default format ("%f" or "%d"). | |||
// - Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For gamepad/keyboard navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision). | |||
// - Use v_min < v_max to clamp edits to given limits. Note that CTRL+Click manual input can override those limits. | |||
// - Use v_min < v_max to clamp edits to given limits. Note that CTRL+Click manual input can override those limits if ImGuiSliderFlags_AlwaysClamp is not used. | |||
// - Use v_max = FLT_MAX / INT_MAX etc to avoid clamping to a maximum, same with v_min = -FLT_MAX / INT_MIN to avoid clamping to a minimum. | |||
// - We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them. | |||
// - Legacy: Pre-1.78 there are DragXXX() function signatures that takes a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument. | |||
@@ -546,7 +547,7 @@ namespace ImGui | |||
IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0); | |||
// Widgets: Regular Sliders | |||
// - CTRL+Click on any slider to turn them into an input box. Manually input values aren't clamped and can go off-bounds. | |||
// - CTRL+Click on any slider to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp. | |||
// - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc. | |||
// - Format string may also be set to NULL or use the default format ("%f" or "%d"). | |||
// - Legacy: Pre-1.78 there are SliderXXX() function signatures that takes a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument. | |||
@@ -868,7 +869,6 @@ namespace ImGui | |||
IMGUI_API const char* GetStyleColorName(ImGuiCol idx); // get a string corresponding to the enum value (for display, saving, etc.). | |||
IMGUI_API void SetStateStorage(ImGuiStorage* storage); // replace current window storage with our own (if you want to manipulate it yourself, typically clear subsection of it) | |||
IMGUI_API ImGuiStorage* GetStateStorage(); | |||
IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. | |||
IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame | |||
IMGUI_API void EndChildFrame(); // always call EndChildFrame() regardless of BeginChildFrame() return values (which indicates a collapsed/clipped window) | |||
@@ -896,9 +896,10 @@ namespace ImGui | |||
// - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle. | |||
// - Dragging operations are only reported after mouse has moved a certain distance away from the initial clicking position (see 'lock_threshold' and 'io.MouseDraggingThreshold') | |||
IMGUI_API bool IsMouseDown(ImGuiMouseButton button); // is mouse button held? | |||
IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down) | |||
IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down). Same as GetMouseClickedCount() == 1. | |||
IMGUI_API bool IsMouseReleased(ImGuiMouseButton button); // did mouse button released? (went from Down to !Down) | |||
IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? (note that a double-click will also report IsMouseClicked() == true) | |||
IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? Same as GetMouseClickedCount() == 2. (note that a double-click will also report IsMouseClicked() == true) | |||
IMGUI_API int GetMouseClickedCount(ImGuiMouseButton button); // return the number of successive mouse-clicks at the time where a click happen (otherwise 0). | |||
IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block. | |||
IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available | |||
IMGUI_API bool IsAnyMouseDown(); // is any mouse button held? | |||
@@ -953,7 +954,7 @@ enum ImGuiWindowFlags_ | |||
ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window | |||
ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programmatically) | |||
ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel. On child window, mouse wheel will be forwarded to the parent unless NoScrollbar is also set. | |||
ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it | |||
ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it. Also referred to as Window Menu Button (e.g. within a docking node). | |||
ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame | |||
ImGuiWindowFlags_NoBackground = 1 << 7, // Disable drawing background color (WindowBg, etc.) and outside border. Similar as using SetNextWindowBgAlpha(0.0f). | |||
ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file | |||
@@ -973,7 +974,7 @@ enum ImGuiWindowFlags_ | |||
ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, | |||
// [Internal] | |||
ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) | |||
ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] On child window: allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. | |||
ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild() | |||
ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip() | |||
ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup() | |||
@@ -1267,7 +1268,8 @@ enum ImGuiFocusedFlags_ | |||
ImGuiFocusedFlags_ChildWindows = 1 << 0, // Return true if any children of the window is focused | |||
ImGuiFocusedFlags_RootWindow = 1 << 1, // Test from root window (top most parent of the current hierarchy) | |||
ImGuiFocusedFlags_AnyWindow = 1 << 2, // Return true if any window is focused. Important: If you are trying to tell how to dispatch your low-level inputs, do NOT use this. Use 'io.WantCaptureMouse' instead! Please read the FAQ! | |||
//ImGuiFocusedFlags_DockHierarchy = 1 << 3, // Consider docking hierarchy (treat dockspace host as parent of docked window) | |||
ImGuiFocusedFlags_NoPopupHierarchy = 1 << 3, // Do not consider popup hierarchy (do not treat popup emitter as parent of popup) (when used with _ChildWindows or _RootWindow) | |||
//ImGuiFocusedFlags_DockHierarchy = 1 << 4, // Consider docking hierarchy (treat dockspace host as parent of docked window) (when used with _ChildWindows or _RootWindow) | |||
ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows | |||
}; | |||
@@ -1280,12 +1282,13 @@ enum ImGuiHoveredFlags_ | |||
ImGuiHoveredFlags_ChildWindows = 1 << 0, // IsWindowHovered() only: Return true if any children of the window is hovered | |||
ImGuiHoveredFlags_RootWindow = 1 << 1, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) | |||
ImGuiHoveredFlags_AnyWindow = 1 << 2, // IsWindowHovered() only: Return true if any window is hovered | |||
//ImGuiHoveredFlags_DockHierarchy = 1 << 3, // IsWindowHovered() only: Consider docking hierarchy (treat dockspace host as parent of docked window) | |||
ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 4, // Return true even if a popup window is normally blocking access to this item/window | |||
//ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 4, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. | |||
ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 5, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. | |||
ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 6, // Return true even if the position is obstructed or overlapped by another window | |||
ImGuiHoveredFlags_AllowWhenDisabled = 1 << 7, // Return true even if the item is disabled | |||
ImGuiHoveredFlags_NoPopupHierarchy = 1 << 3, // IsWindowHovered() only: Do not consider popup hierarchy (do not treat popup emitter as parent of popup) (when used with _ChildWindows or _RootWindow) | |||
//ImGuiHoveredFlags_DockHierarchy = 1 << 4, // IsWindowHovered() only: Consider docking hierarchy (treat dockspace host as parent of docked window) (when used with _ChildWindows or _RootWindow) | |||
ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 5, // Return true even if a popup window is normally blocking access to this item/window | |||
//ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 6, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. | |||
ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 7, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. | |||
ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 8, // IsItemHovered() only: Return true even if the position is obstructed or overlapped by another window | |||
ImGuiHoveredFlags_AllowWhenDisabled = 1 << 9, // IsItemHovered() only: Return true even if the item is disabled | |||
ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped, | |||
ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows | |||
}; | |||
@@ -1739,7 +1742,7 @@ struct ImVector | |||
inline void pop_back() { IM_ASSERT(Size > 0); Size--; } | |||
inline void push_front(const T& v) { if (Size == 0) push_back(v); else insert(Data, v); } | |||
inline T* erase(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(T)); Size--; return Data + off; } | |||
inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data + Size && it_last > it && it_last <= Data + Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - count) * sizeof(T)); Size -= (int)count; return Data + off; } | |||
inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data + Size && it_last > it && it_last <= Data + Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - (size_t)count) * sizeof(T)); Size -= (int)count; return Data + off; } | |||
inline T* erase_unsorted(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; if (it < Data + Size - 1) memcpy(Data + off, Data + Size - 1, sizeof(T)); Size--; return Data + off; } | |||
inline T* insert(const T* it, const T& v) { IM_ASSERT(it >= Data && it <= Data + Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(T)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; } | |||
inline bool contains(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } | |||
@@ -1892,8 +1895,9 @@ struct ImGuiIO | |||
IMGUI_API void AddInputCharacter(unsigned int c); // Queue new character input | |||
IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue new character input from an UTF-16 character, it can be a surrogate | |||
IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue new characters input from an UTF-8 string | |||
IMGUI_API void ClearInputCharacters(); // Clear the text input buffer manually | |||
IMGUI_API void AddFocusEvent(bool focused); // Notifies Dear ImGui when hosting platform windows lose or gain input focus | |||
IMGUI_API void ClearInputCharacters(); // [Internal] Clear the text input buffer manually | |||
IMGUI_API void ClearInputKeys(); // [Internal] Release all keys | |||
//------------------------------------------------------------------ | |||
// Output - Updated by NewFrame() or EndFrame()/Render() | |||
@@ -1926,12 +1930,13 @@ struct ImGuiIO | |||
ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid) | |||
ImVec2 MouseClickedPos[5]; // Position at time of clicking | |||
double MouseClickedTime[5]; // Time of last click (used to figure out double-click) | |||
bool MouseClicked[5]; // Mouse button went from !Down to Down | |||
bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? | |||
bool MouseClicked[5]; // Mouse button went from !Down to Down (same as MouseClickedCount[x] != 0) | |||
bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? (same as MouseClickedCount[x] == 2) | |||
ImU16 MouseClickedCount[5]; // == 0 (not clicked), == 1 (same as MouseClicked[]), == 2 (double-clicked), == 3 (triple-clicked) etc. when going from !Down to Down | |||
ImU16 MouseClickedLastCount[5]; // Count successive number of clicks. Stays valid after mouse release. Reset after another click is done. | |||
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 MouseDownOwnedUnlessPopupClose[5];//Track if button was clicked inside a dear imgui window. | |||
bool MouseDownWasDoubleClick[5]; // Track if button down was a double-click | |||
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 | |||
ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point | |||
@@ -1941,6 +1946,7 @@ struct ImGuiIO | |||
float NavInputsDownDuration[ImGuiNavInput_COUNT]; | |||
float NavInputsDownDurationPrev[ImGuiNavInput_COUNT]; | |||
float PenPressure; // Touch/Pen pressure (0.0f to 1.0f, should be >0.0f only when MouseDown[0] == true). Helper storage currently unused by Dear ImGui. | |||
bool AppFocusLost; | |||
ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16 | |||
ImVector<ImWchar> InputQueueCharacters; // Queue of _characters_ input (obtained by platform backend). Fill using AddInputCharacter() helper. | |||
@@ -2165,10 +2171,12 @@ struct ImGuiStorage | |||
}; | |||
// Helper: Manually clip large list of items. | |||
// If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse | |||
// clipping based on visibility to save yourself from processing those items at all. | |||
// If you have lots evenly spaced items and you have a random access to the list, you can perform coarse | |||
// clipping based on visibility to only submit items that are in view. | |||
// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped. | |||
// (Dear ImGui already clip items based on their bounds but it needs to measure text size to do so, whereas manual coarse clipping before submission makes this cost and your own data fetching/submission cost almost null) | |||
// (Dear ImGui already clip items based on their bounds but: it needs to first layout the item to do so, and generally | |||
// fetching/submitting your own data incurs additional cost. Coarse clipping using ImGuiListClipper allows you to easily | |||
// scale using lists with tens of thousands of items without a problem) | |||
// Usage: | |||
// ImGuiListClipper clipper; | |||
// clipper.Begin(1000); // We have 1000 elements, evenly spaced. | |||
@@ -2177,30 +2185,30 @@ struct ImGuiStorage | |||
// ImGui::Text("line number %d", i); | |||
// Generally what happens is: | |||
// - Clipper lets you process the first element (DisplayStart = 0, DisplayEnd = 1) regardless of it being visible or not. | |||
// - User code submit one element. | |||
// - User code submit that one element. | |||
// - Clipper can measure the height of the first element | |||
// - Clipper calculate the actual range of elements to display based on the current clipping rectangle, position the cursor before the first visible element. | |||
// - User code submit visible elements. | |||
// - The clipper also handles various subtleties related to keyboard/gamepad navigation, wrapping etc. | |||
struct ImGuiListClipper | |||
{ | |||
int DisplayStart; | |||
int DisplayEnd; | |||
// [Internal] | |||
int ItemsCount; | |||
int StepNo; | |||
int ItemsFrozen; | |||
float ItemsHeight; | |||
float StartPosY; | |||
int DisplayStart; // First item to display, updated by each call to Step() | |||
int DisplayEnd; // End of items to display (exclusive) | |||
int ItemsCount; // [Internal] Number of items | |||
float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it | |||
float StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed | |||
void* TempData; // [Internal] Internal data | |||
// items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step) | |||
// items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing(). | |||
IMGUI_API ImGuiListClipper(); | |||
IMGUI_API ~ImGuiListClipper(); | |||
IMGUI_API void Begin(int items_count, float items_height = -1.0f); | |||
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. | |||
// items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step) | |||
// items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing(). | |||
IMGUI_API void Begin(int items_count, float items_height = -1.0f); // Automatically called by constructor if you passed 'items_count' or by Step() in Step 1. | |||
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. | |||
// Call ForceDisplayRangeByIndices() before first call to Step() if you need a range of items to be displayed regardless of 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. | |||
#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] | |||
@@ -2823,6 +2831,8 @@ struct ImGuiViewport | |||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS | |||
namespace ImGui | |||
{ | |||
// OBSOLETED in 1.86 (from November 2021) | |||
IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Calculate coarse clipping for large list of evenly sized items. Prefer using ImGuiListClipper. | |||
// OBSOLETED in 1.85 (from August 2021) | |||
static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; } | |||
// OBSOLETED in 1.81 (from February 2021) | |||
@@ -1,4 +1,4 @@ | |||
// dear imgui, v1.85 WIP | |||
// dear imgui, v1.86 | |||
// (drawing and font code) | |||
/* | |||
@@ -473,6 +473,7 @@ void ImDrawList::_PopUnusedDrawCmd() | |||
void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data) | |||
{ | |||
IM_ASSERT_PARANOID(CmdBuffer.Size > 0); | |||
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; | |||
IM_ASSERT(curr_cmd->UserCallback == NULL); | |||
if (curr_cmd->ElemCount != 0) | |||
@@ -494,6 +495,7 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data) | |||
// Try to merge two last draw commands | |||
void ImDrawList::_TryMergeDrawCmds() | |||
{ | |||
IM_ASSERT_PARANOID(CmdBuffer.Size > 0); | |||
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; | |||
ImDrawCmd* prev_cmd = curr_cmd - 1; | |||
if (ImDrawCmd_HeaderCompare(curr_cmd, prev_cmd) == 0 && curr_cmd->UserCallback == NULL && prev_cmd->UserCallback == NULL) | |||
@@ -508,6 +510,7 @@ void ImDrawList::_TryMergeDrawCmds() | |||
void ImDrawList::_OnChangedClipRect() | |||
{ | |||
// If current command is used with different settings we need to add a new command | |||
IM_ASSERT_PARANOID(CmdBuffer.Size > 0); | |||
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; | |||
if (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &_CmdHeader.ClipRect, sizeof(ImVec4)) != 0) | |||
{ | |||
@@ -530,6 +533,7 @@ void ImDrawList::_OnChangedClipRect() | |||
void ImDrawList::_OnChangedTextureID() | |||
{ | |||
// If current command is used with different settings we need to add a new command | |||
IM_ASSERT_PARANOID(CmdBuffer.Size > 0); | |||
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; | |||
if (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != _CmdHeader.TextureId) | |||
{ | |||
@@ -553,6 +557,7 @@ void ImDrawList::_OnChangedVtxOffset() | |||
{ | |||
// We don't need to compare curr_cmd->VtxOffset != _CmdHeader.VtxOffset because we know it'll be different at the time we call this. | |||
_VtxCurrentIdx = 0; | |||
IM_ASSERT_PARANOID(CmdBuffer.Size > 0); | |||
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; | |||
//IM_ASSERT(curr_cmd->VtxOffset != _CmdHeader.VtxOffset); // See #3349 | |||
if (curr_cmd->ElemCount != 0) | |||
@@ -1919,37 +1924,38 @@ ImFontConfig::ImFontConfig() | |||
// A work of art lies ahead! (. = white layer, X = black layer, others are blank) | |||
// The 2x2 white texels on the top left are the ones we'll use everywhere in Dear ImGui to render filled shapes. | |||
const int FONT_ATLAS_DEFAULT_TEX_DATA_W = 108; // Actual texture will be 2 times that + 1 spacing. | |||
// (This is used when io.MouseDrawCursor = true) | |||
const int FONT_ATLAS_DEFAULT_TEX_DATA_W = 122; // Actual texture will be 2 times that + 1 spacing. | |||
const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27; | |||
static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA_W * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1] = | |||
{ | |||
"..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX " | |||
"..- -X.....X- X.X - X.X -X.....X - X.....X- X..X " | |||
"--- -XXX.XXX- X...X - X...X -X....X - X....X- X..X " | |||
"X - X.X - X.....X - X.....X -X...X - X...X- X..X " | |||
"XX - X.X -X.......X- X.......X -X..X.X - X.X..X- X..X " | |||
"X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X- X..XXX " | |||
"X..X - X.X - X.X - X.X -XX X.X - X.X XX- X..X..XXX " | |||
"X...X - X.X - X.X - XX X.X XX - X.X - X.X - X..X..X..XX " | |||
"X....X - X.X - X.X - X.X X.X X.X - X.X - X.X - X..X..X..X.X " | |||
"X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X -XXX X..X..X..X..X" | |||
"X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X -X..XX........X..X" | |||
"X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X -X...X...........X" | |||
"X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X - X..............X" | |||
"X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X - X.............X" | |||
"X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X - X.............X" | |||
"X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X - X............X" | |||
"X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX - X...........X " | |||
"X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------- X..........X " | |||
"X.X X..X - -X.......X- X.......X - XX XX - - X..........X " | |||
"XX X..X - - X.....X - X.....X - X.X X.X - - X........X " | |||
" X..X - X...X - X...X - X..X X..X - - X........X " | |||
" XX - X.X - X.X - X...XXXXXXXXXXXXX...X - - XXXXXXXXXX " | |||
"------------ - X - X -X.....................X- ------------------" | |||
" ----------------------------------- X...XXXXXXXXXXXXX...X - " | |||
" - X..X X..X - " | |||
" - X.X X.X - " | |||
" - XX XX - " | |||
"..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX - XX XX " | |||
"..- -X.....X- X.X - X.X -X.....X - X.....X- X..X -X..X X..X" | |||
"--- -XXX.XXX- X...X - X...X -X....X - X....X- X..X -X...X X...X" | |||
"X - X.X - X.....X - X.....X -X...X - X...X- X..X - X...X X...X " | |||
"XX - X.X -X.......X- X.......X -X..X.X - X.X..X- X..X - X...X...X " | |||
"X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X- X..XXX - X.....X " | |||
"X..X - X.X - X.X - X.X -XX X.X - X.X XX- X..X..XXX - X...X " | |||
"X...X - X.X - X.X - XX X.X XX - X.X - X.X - X..X..X..XX - X.X " | |||
"X....X - X.X - X.X - X.X X.X X.X - X.X - X.X - X..X..X..X.X - X...X " | |||
"X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X -XXX X..X..X..X..X- X.....X " | |||
"X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X -X..XX........X..X- X...X...X " | |||
"X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X -X...X...........X- X...X X...X " | |||
"X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X - X..............X-X...X X...X" | |||
"X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X - X.............X-X..X X..X" | |||
"X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X - X.............X- XX XX " | |||
"X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X - X............X--------------" | |||
"X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX - X...........X - " | |||
"X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------- X..........X - " | |||
"X.X X..X - -X.......X- X.......X - XX XX - - X..........X - " | |||
"XX X..X - - X.....X - X.....X - X.X X.X - - X........X - " | |||
" X..X - - X...X - X...X - X..X X..X - - X........X - " | |||
" XX - - X.X - X.X - X...XXXXXXXXXXXXX...X - - XXXXXXXXXX - " | |||
"------------- - X - X -X.....................X- ------------------- " | |||
" ----------------------------------- X...XXXXXXXXXXXXX...X - " | |||
" - X..X X..X - " | |||
" - X.X X.X - " | |||
" - XX XX - " | |||
}; | |||
static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3] = | |||
@@ -1963,6 +1969,7 @@ static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3 | |||
{ ImVec2(73,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNESW | |||
{ ImVec2(55,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNWSE | |||
{ ImVec2(91,0), ImVec2(17,22), ImVec2( 5, 0) }, // ImGuiMouseCursor_Hand | |||
{ ImVec2(109,0),ImVec2(13,15), ImVec2( 6, 7) }, // ImGuiMouseCursor_NotAllowed | |||
}; | |||
ImFontAtlas::ImFontAtlas() | |||
@@ -3073,8 +3080,8 @@ void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end) | |||
void ImFontGlyphRangesBuilder::AddRanges(const ImWchar* ranges) | |||
{ | |||
for (; ranges[0]; ranges += 2) | |||
for (ImWchar c = ranges[0]; c <= ranges[1]; c++) | |||
AddChar(c); | |||
for (unsigned int c = ranges[0]; c <= ranges[1] && c <= IM_UNICODE_CODEPOINT_MAX; c++) //-V560 | |||
AddChar((ImWchar)c); | |||
} | |||
void ImFontGlyphRangesBuilder::BuildRanges(ImVector<ImWchar>* out_ranges) | |||
@@ -3899,10 +3906,10 @@ void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect | |||
const bool fill_R = (inner.Max.x < outer.Max.x); | |||
const bool fill_U = (inner.Min.y > outer.Min.y); | |||
const bool fill_D = (inner.Max.y < outer.Max.y); | |||
if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomLeft)); | |||
if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawFlags_RoundCornersTopRight) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomRight)); | |||
if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, (fill_L ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersTopRight)); | |||
if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, (fill_L ? 0 : ImDrawFlags_RoundCornersBottomLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersBottomRight)); | |||
if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_U ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomLeft)); | |||
if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_U ? 0 : ImDrawFlags_RoundCornersTopRight) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomRight)); | |||
if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_L ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersTopRight)); | |||
if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_L ? 0 : ImDrawFlags_RoundCornersBottomLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersBottomRight)); | |||
if (fill_L && fill_U) draw_list->AddRectFilled(ImVec2(outer.Min.x, outer.Min.y), ImVec2(inner.Min.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersTopLeft); | |||
if (fill_R && fill_U) draw_list->AddRectFilled(ImVec2(inner.Max.x, outer.Min.y), ImVec2(outer.Max.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersTopRight); | |||
if (fill_L && fill_D) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Max.y), ImVec2(inner.Min.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersBottomLeft); | |||
@@ -19,6 +19,7 @@ | |||
// CHANGELOG | |||
// (minor and older changes stripped away, please see git history for details) | |||
// 2021-12-08: OpenGL: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86. | |||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). | |||
// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | |||
// 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications. | |||
@@ -86,8 +87,9 @@ bool ImGui_ImplOpenGL2_Init() | |||
void ImGui_ImplOpenGL2_Shutdown() | |||
{ | |||
ImGuiIO& io = ImGui::GetIO(); | |||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); | |||
IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?"); | |||
ImGuiIO& io = ImGui::GetIO(); | |||
ImGui_ImplOpenGL2_DestroyDeviceObjects(); | |||
io.BackendRendererName = NULL; | |||
@@ -208,7 +210,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) | |||
// Project scissor/clipping rectangles into framebuffer space | |||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); | |||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); | |||
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y) | |||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) | |||
continue; | |||
// Apply scissor/clipping rectangle (Y is inverted in OpenGL) | |||
@@ -216,9 +218,8 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) | |||
// Bind texture, Draw | |||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()); | |||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer); | |||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset); | |||
} | |||
idx_buffer += pcmd->ElemCount; | |||
} | |||
} | |||
@@ -1,4 +1,4 @@ | |||
// dear imgui, v1.85 WIP | |||
// dear imgui, v1.86 | |||
// (internal structures/api) | |||
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! | |||
@@ -18,13 +18,14 @@ Index of this file: | |||
// [SECTION] Generic helpers | |||
// [SECTION] ImDrawList support | |||
// [SECTION] Widgets support: flags, enums, data structures | |||
// [SECTION] Clipper support | |||
// [SECTION] Navigation support | |||
// [SECTION] Columns support | |||
// [SECTION] Multi-select support | |||
// [SECTION] Docking support | |||
// [SECTION] Viewport support | |||
// [SECTION] Settings support | |||
// [SECTION] Metrics, Debug | |||
// [SECTION] Metrics, Debug tools | |||
// [SECTION] Generic context hooks | |||
// [SECTION] ImGuiContext (main imgui context) | |||
// [SECTION] ImGuiWindowTempData, ImGuiWindow | |||
@@ -152,6 +153,7 @@ typedef int ImGuiNavDirSourceFlags; // -> enum ImGuiNavDirSourceFlags_ // F | |||
typedef int ImGuiNavMoveFlags; // -> enum ImGuiNavMoveFlags_ // Flags: for navigation requests | |||
typedef int ImGuiNextItemDataFlags; // -> enum ImGuiNextItemDataFlags_ // Flags: for SetNextItemXXX() functions | |||
typedef int ImGuiNextWindowDataFlags; // -> enum ImGuiNextWindowDataFlags_// Flags: for SetNextWindowXXX() functions | |||
typedef int ImGuiScrollFlags; // -> enum ImGuiScrollFlags_ // Flags: for ScrollToItem() and navigation requests | |||
typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // Flags: for SeparatorEx() | |||
typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx() | |||
typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx() | |||
@@ -251,12 +253,19 @@ namespace ImStb | |||
#endif | |||
// Debug Tools | |||
// Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item. | |||
// Use 'Metrics/Debugger->Tools->Item Picker' to break into the call-stack of a specific item. | |||
// This will call IM_DEBUG_BREAK() which you may redefine yourself. See https://github.com/scottt/debugbreak for more reference. | |||
#ifndef IM_DEBUG_BREAK | |||
#if defined(__clang__) | |||
#define IM_DEBUG_BREAK() __builtin_debugtrap() | |||
#elif defined (_MSC_VER) | |||
#if defined (_MSC_VER) | |||
#define IM_DEBUG_BREAK() __debugbreak() | |||
#elif defined(__clang__) | |||
#define IM_DEBUG_BREAK() __builtin_debugtrap() | |||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) | |||
#define IM_DEBUG_BREAK() __asm__ volatile("int $0x03") | |||
#elif defined(__GNUC__) && defined(__thumb__) | |||
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xde01") | |||
#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) | |||
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0"); | |||
#else | |||
#define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger! | |||
#endif | |||
@@ -293,7 +302,9 @@ static inline ImGuiID ImHash(const void* data, int size, ImU32 seed = 0) { ret | |||
#endif | |||
// Helpers: Sorting | |||
#define ImQsort qsort | |||
#ifndef ImQsort | |||
static inline void ImQsort(void* base, size_t count, size_t size_of_element, int(IMGUI_CDECL *compare_func)(void const*, void const*)) { if (count > 1) qsort(base, count, size_of_element, compare_func); } | |||
#endif | |||
// Helpers: Color Blending | |||
IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b); | |||
@@ -400,8 +411,8 @@ static inline double ImLog(double x) { return log(x); } | |||
static inline int ImAbs(int x) { return x < 0 ? -x : x; } | |||
static inline float ImAbs(float x) { return fabsf(x); } | |||
static inline double ImAbs(double x) { return fabs(x); } | |||
static inline float ImSign(float x) { return (x < 0.0f) ? -1.0f : ((x > 0.0f) ? 1.0f : 0.0f); } // Sign operator - returns -1, 0 or 1 based on sign of argument | |||
static inline double ImSign(double x) { return (x < 0.0) ? -1.0 : ((x > 0.0) ? 1.0 : 0.0); } | |||
static inline float ImSign(float x) { return (x < 0.0f) ? -1.0f : (x > 0.0f) ? 1.0f : 0.0f; } // Sign operator - returns -1, 0 or 1 based on sign of argument | |||
static inline double ImSign(double x) { return (x < 0.0) ? -1.0 : (x > 0.0) ? 1.0 : 0.0; } | |||
#ifdef IMGUI_ENABLE_SSE | |||
static inline float ImRsqrt(float x) { return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); } | |||
#else | |||
@@ -437,6 +448,7 @@ static inline float ImDot(const ImVec2& a, const ImVec2& b) | |||
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } | |||
static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; } | |||
static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } | |||
static inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; } | |||
IM_MSVC_RUNTIME_CHECKS_RESTORE | |||
// Helpers: Geometry | |||
@@ -743,7 +755,7 @@ enum ImGuiItemFlags_ | |||
ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // Disable MenuItem/Selectable() automatically closing their popup window | |||
ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) | |||
ImGuiItemFlags_ReadOnly = 1 << 7, // false // [ALPHA] Allow hovering interactions but underlying value is not changed. | |||
ImGuiItemFlags_Inputable = 1 << 8 // false // [WIP] Auto-activate item when focused. Currently only used and supported by a few items before it becomes a generic feature. | |||
ImGuiItemFlags_Inputable = 1 << 8 // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature. | |||
}; | |||
// Storage for LastItem data | |||
@@ -758,9 +770,7 @@ enum ImGuiItemStatusFlags_ | |||
ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag. | |||
ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. | |||
ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing. | |||
ImGuiItemStatusFlags_FocusedByCode = 1 << 8, // Set when the Focusable item just got focused from code. | |||
ImGuiItemStatusFlags_FocusedByTabbing = 1 << 9, // Set when the Focusable item just got focused by Tabbing. | |||
ImGuiItemStatusFlags_Focused = ImGuiItemStatusFlags_FocusedByCode | ImGuiItemStatusFlags_FocusedByTabbing | |||
ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8 // Set when the Focusable item just got focused by Tabbing (FIXME: to be removed soon) | |||
#ifdef IMGUI_ENABLE_TEST_ENGINE | |||
, // [imgui_tests only] | |||
@@ -1020,8 +1030,6 @@ struct IMGUI_API ImGuiInputTextState | |||
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection | |||
bool Edited; // edited this frame | |||
ImGuiInputTextFlags Flags; // copy of InputText() flags | |||
ImGuiInputTextCallback UserCallback; // " | |||
void* UserCallbackData; // " | |||
ImGuiInputTextState() { memset(this, 0, sizeof(*this)); } | |||
void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); } | |||
@@ -1163,6 +1171,35 @@ struct ImGuiPtrOrIndex | |||
ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; } | |||
}; | |||
//----------------------------------------------------------------------------- | |||
// [SECTION] Clipper support | |||
//----------------------------------------------------------------------------- | |||
struct ImGuiListClipperRange | |||
{ | |||
int Min; | |||
int Max; | |||
bool PosToIndexConvert; // Begin/End are absolute position (will be converted to indices later) | |||
ImS8 PosToIndexOffsetMin; // Add to Min after converting to indices | |||
ImS8 PosToIndexOffsetMax; // Add to Min after converting to indices | |||
static ImGuiListClipperRange FromIndices(int min, int max) { ImGuiListClipperRange r = { min, max, false, 0, 0 }; return r; } | |||
static ImGuiListClipperRange FromPositions(float y1, float y2, int off_min, int off_max) { ImGuiListClipperRange r = { (int)y1, (int)y2, true, (ImS8)off_min, (ImS8)off_max }; return r; } | |||
}; | |||
// Temporary clipper data, buffers shared/reused between instances | |||
struct ImGuiListClipperData | |||
{ | |||
ImGuiListClipper* ListClipper; | |||
float LossynessOffset; | |||
int StepNo; | |||
int ItemsFrozen; | |||
ImVector<ImGuiListClipperRange> Ranges; | |||
ImGuiListClipperData() { memset(this, 0, sizeof(*this)); } | |||
void Reset(ImGuiListClipper* clipper) { ListClipper = clipper; StepNo = ItemsFrozen = 0; Ranges.resize(0); } | |||
}; | |||
//----------------------------------------------------------------------------- | |||
// [SECTION] Navigation support | |||
//----------------------------------------------------------------------------- | |||
@@ -1175,6 +1212,21 @@ enum ImGuiActivateFlags_ | |||
ImGuiActivateFlags_TryToPreserveState = 1 << 2 // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection) | |||
}; | |||
// Early work-in-progress API for ScrollToItem() | |||
enum ImGuiScrollFlags_ | |||
{ | |||
ImGuiScrollFlags_None = 0, | |||
ImGuiScrollFlags_KeepVisibleEdgeX = 1 << 0, // If item is not visible: scroll as little as possible on X axis to bring item back into view [default for X axis] | |||
ImGuiScrollFlags_KeepVisibleEdgeY = 1 << 1, // If item is not visible: scroll as little as possible on Y axis to bring item back into view [default for Y axis for windows that are already visible] | |||
ImGuiScrollFlags_KeepVisibleCenterX = 1 << 2, // If item is not visible: scroll to make the item centered on X axis [rarely used] | |||
ImGuiScrollFlags_KeepVisibleCenterY = 1 << 3, // If item is not visible: scroll to make the item centered on Y axis | |||
ImGuiScrollFlags_AlwaysCenterX = 1 << 4, // Always center the result item on X axis [rarely used] | |||
ImGuiScrollFlags_AlwaysCenterY = 1 << 5, // Always center the result item on Y axis [default for Y axis for appearing window) | |||
ImGuiScrollFlags_NoScrollParent = 1 << 6, // Disable forwarding scrolling to parent window if required to keep item/rect visible (only scroll window the function was applied to). | |||
ImGuiScrollFlags_MaskX_ = ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleCenterX | ImGuiScrollFlags_AlwaysCenterX, | |||
ImGuiScrollFlags_MaskY_ = ImGuiScrollFlags_KeepVisibleEdgeY | ImGuiScrollFlags_KeepVisibleCenterY | ImGuiScrollFlags_AlwaysCenterY | |||
}; | |||
enum ImGuiNavHighlightFlags_ | |||
{ | |||
ImGuiNavHighlightFlags_None = 0, | |||
@@ -1187,9 +1239,10 @@ enum ImGuiNavHighlightFlags_ | |||
enum ImGuiNavDirSourceFlags_ | |||
{ | |||
ImGuiNavDirSourceFlags_None = 0, | |||
ImGuiNavDirSourceFlags_Keyboard = 1 << 0, | |||
ImGuiNavDirSourceFlags_PadDPad = 1 << 1, | |||
ImGuiNavDirSourceFlags_PadLStick = 1 << 2 | |||
ImGuiNavDirSourceFlags_RawKeyboard = 1 << 0, // Raw keyboard (not pulled from nav), faciliate use of some functions before we can unify nav and keys | |||
ImGuiNavDirSourceFlags_Keyboard = 1 << 1, | |||
ImGuiNavDirSourceFlags_PadDPad = 1 << 2, | |||
ImGuiNavDirSourceFlags_PadLStick = 1 << 3 | |||
}; | |||
enum ImGuiNavMoveFlags_ | |||
@@ -1201,9 +1254,13 @@ enum ImGuiNavMoveFlags_ | |||
ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful but provided for completeness | |||
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_ScrollToEdge = 1 << 6, | |||
ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary | |||
ImGuiNavMoveFlags_Forwarded = 1 << 7, | |||
ImGuiNavMoveFlags_DebugNoResult = 1 << 8 | |||
ImGuiNavMoveFlags_DebugNoResult = 1 << 8, // Dummy scoring for debug purpose, don't apply result | |||
ImGuiNavMoveFlags_FocusApi = 1 << 9, | |||
ImGuiNavMoveFlags_Tabbing = 1 << 10, // == Focus + Activate if item is Inputable + DontChangeNavHighlight | |||
ImGuiNavMoveFlags_Activate = 1 << 11, | |||
ImGuiNavMoveFlags_DontSetNavHighlight = 1 << 12 // Do not alter the visible state of keyboard vs mouse nav highlight | |||
}; | |||
enum ImGuiNavLayer | |||
@@ -1219,12 +1276,13 @@ struct ImGuiNavItemData | |||
ImGuiID ID; // Init,Move // Best candidate item ID | |||
ImGuiID FocusScopeId; // Init,Move // Best candidate focus scope ID | |||
ImRect RectRel; // Init,Move // Best candidate bounding box in window relative space | |||
ImGuiItemFlags InFlags; // ????,Move // Best candidate item flags | |||
float DistBox; // Move // Best candidate box distance to current NavId | |||
float DistCenter; // Move // Best candidate center distance to current NavId | |||
float DistAxial; // Move // Best candidate axial distance to current NavId | |||
ImGuiNavItemData() { Clear(); } | |||
void Clear() { Window = NULL; ID = FocusScopeId = 0; RectRel = ImRect(); DistBox = DistCenter = DistAxial = FLT_MAX; } | |||
void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; DistBox = DistCenter = DistAxial = FLT_MAX; } | |||
}; | |||
//----------------------------------------------------------------------------- | |||
@@ -1366,11 +1424,12 @@ struct ImGuiSettingsHandler | |||
}; | |||
//----------------------------------------------------------------------------- | |||
// [SECTION] Metrics, Debug | |||
// [SECTION] Metrics, Debug Tools | |||
//----------------------------------------------------------------------------- | |||
struct ImGuiMetricsConfig | |||
{ | |||
bool ShowStackTool; | |||
bool ShowWindowsRects; | |||
bool ShowWindowsBeginOrder; | |||
bool ShowTablesRects; | |||
@@ -1381,6 +1440,7 @@ struct ImGuiMetricsConfig | |||
ImGuiMetricsConfig() | |||
{ | |||
ShowStackTool = false; | |||
ShowWindowsRects = false; | |||
ShowWindowsBeginOrder = false; | |||
ShowTablesRects = false; | |||
@@ -1391,6 +1451,27 @@ struct ImGuiMetricsConfig | |||
} | |||
}; | |||
struct ImGuiStackLevelInfo | |||
{ | |||
ImGuiID ID; | |||
ImS8 QueryFrameCount; // >= 1: Query in progress | |||
bool QuerySuccess; // Obtained result from DebugHookIdInfo() | |||
char Desc[58]; // Arbitrarily sized buffer to hold a result (FIXME: could replace Results[] with a chunk stream?) | |||
ImGuiStackLevelInfo() { memset(this, 0, sizeof(*this)); } | |||
}; | |||
// State for Stack tool queries | |||
struct ImGuiStackTool | |||
{ | |||
int LastActiveFrame; | |||
int StackLevel; // -1: query stack and resize Results, >= 0: individual stack level | |||
ImGuiID QueryId; // ID to query details for | |||
ImVector<ImGuiStackLevelInfo> Results; | |||
ImGuiStackTool() { memset(this, 0, sizeof(*this)); } | |||
}; | |||
//----------------------------------------------------------------------------- | |||
// [SECTION] Generic context hooks | |||
//----------------------------------------------------------------------------- | |||
@@ -1432,7 +1513,6 @@ struct ImGuiContext | |||
bool WithinEndChild; // Set within EndChild() | |||
bool GcCompactAll; // Request full GC | |||
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log() | |||
ImGuiID TestEngineHookIdInfo; // Will call test engine hooks: ImGuiTestEngineHook_IdInfo() from GetID() | |||
void* TestEngine; // Test engine user data | |||
// Windows state | |||
@@ -1452,6 +1532,7 @@ struct ImGuiContext | |||
float WheelingWindowTimer; | |||
// Item/widgets state and tracking information | |||
ImGuiID DebugHookIdInfo; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line] | |||
ImGuiID HoveredId; // Hovered widget, filled during the frame | |||
ImGuiID HoveredIdPreviousFrame; | |||
bool HoveredIdAllowOverlap; | |||
@@ -1499,6 +1580,7 @@ struct ImGuiContext | |||
ImVector<ImGuiGroupData>GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin() | |||
ImVector<ImGuiPopupData>OpenPopupStack; // Which popups are open (persistent) | |||
ImVector<ImGuiPopupData>BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) | |||
int BeginMenuCount; | |||
// Viewports | |||
ImVector<ImGuiViewportP*> Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData. | |||
@@ -1512,7 +1594,6 @@ struct ImGuiContext | |||
ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0 | |||
ImGuiID NavActivateInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0; ImGuiActivateFlags_PreferInput will be set and NavActivateId will be 0. | |||
ImGuiActivateFlags NavActivateFlags; | |||
ImGuiID NavJustTabbedId; // Just tabbed to this id. | |||
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest). | |||
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest). | |||
ImGuiKeyModFlags NavJustMovedToKeyMods; | |||
@@ -1520,7 +1601,6 @@ struct ImGuiContext | |||
ImGuiActivateFlags NavNextActivateFlags; | |||
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard. | |||
ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. | |||
int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing | |||
bool NavIdIsAlive; // Nav widget has been seen this frame ~~ 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 NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) | |||
@@ -1536,15 +1616,20 @@ struct ImGuiContext | |||
bool NavMoveScoringItems; // Move request submitted, still scoring incoming items | |||
bool NavMoveForwardToNextFrame; | |||
ImGuiNavMoveFlags NavMoveFlags; | |||
ImGuiScrollFlags NavMoveScrollFlags; | |||
ImGuiKeyModFlags NavMoveKeyMods; | |||
ImGuiDir NavMoveDir; // Direction of the move request (left/right/up/down) | |||
ImGuiDir NavMoveDirForDebug; | |||
ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename? | |||
ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring. | |||
ImRect NavScoringNoClipRect; // Some nav operations (such as PageUp/PageDown) enforce a region which clipper will attempt to always keep submitted | |||
int NavScoringDebugCount; // Metrics for debugging | |||
int NavTabbingDir; // Generally -1 or +1, 0 when tabbing without a nav id | |||
int NavTabbingCounter; // >0 when counting items for tabbing | |||
ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow | |||
ImGuiNavItemData NavMoveResultLocalVisible; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag) | |||
ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) | |||
ImGuiNavItemData NavTabbingResultFirst; // First tabbing request candidate within NavWindow and flattened hierarchy | |||
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize) | |||
ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most! | |||
@@ -1554,15 +1639,6 @@ struct ImGuiContext | |||
float NavWindowingHighlightAlpha; | |||
bool NavWindowingToggleLayer; | |||
// Legacy Focus/Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!) | |||
ImGuiWindow* TabFocusRequestCurrWindow; // | |||
ImGuiWindow* TabFocusRequestNextWindow; // | |||
int TabFocusRequestCurrCounterRegular; // Any item being requested for focus, stored as an index (we on layout to be stable between the frame pressing TAB and the next frame, semi-ouch) | |||
int TabFocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index | |||
int TabFocusRequestNextCounterRegular; // Stored for next frame | |||
int TabFocusRequestNextCounterTabStop; // " | |||
bool TabFocusPressed; // Set in NewFrame() when user pressed Tab | |||
// Render | |||
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list) | |||
ImGuiMouseCursor MouseCursor; | |||
@@ -1586,11 +1662,15 @@ struct ImGuiContext | |||
ImVector<unsigned char> DragDropPayloadBufHeap; // We don't expose the ImVector<> directly, ImGuiPayload only holds pointer+size | |||
unsigned char DragDropPayloadBufLocal[16]; // Local buffer for small payloads | |||
// Clipper | |||
int ClipperTempDataStacked; | |||
ImVector<ImGuiListClipperData> ClipperTempData; | |||
// Table | |||
ImGuiTable* CurrentTable; | |||
int CurrentTableStackIdx; | |||
ImPool<ImGuiTable> Tables; | |||
ImVector<ImGuiTableTempData> TablesTempDataStack; | |||
int TablesTempDataStacked; // Temporary table data size (because we leave previous instances undestructed, we generally don't use TablesTempData.Size) | |||
ImVector<ImGuiTableTempData> TablesTempData; // Temporary table data (buffers reused/shared across instances, support nesting) | |||
ImPool<ImGuiTable> Tables; // Persistent table data | |||
ImVector<float> TablesLastTimeActive; // Last used timestamp of each tables (SOA, for efficient GC) | |||
ImVector<ImDrawChannel> DrawChannelsTempMergeBuffer; | |||
@@ -1606,9 +1686,9 @@ struct ImGuiContext | |||
ImFont InputTextPasswordFont; | |||
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc. | |||
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets | |||
float ColorEditLastHue; // Backup of last Hue associated to LastColor[3], so we can restore Hue in lossy RGB<>HSV round trips | |||
float ColorEditLastSat; // Backup of last Saturation associated to LastColor[3], so we can restore Saturation in lossy RGB<>HSV round trips | |||
float ColorEditLastColor[3]; | |||
float ColorEditLastHue; // Backup of last Hue associated to LastColor, so we can restore Hue in lossy RGB<>HSV round trips | |||
float ColorEditLastSat; // Backup of last Saturation associated to LastColor, so we can restore Saturation in lossy RGB<>HSV round trips | |||
ImU32 ColorEditLastColor; // RGB value with alpha set to 0. | |||
ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker. | |||
ImGuiComboPreviewData ComboPreviewData; | |||
float SliderCurrentAccum; // Accumulated slider delta when using navigation controls. | |||
@@ -1654,8 +1734,9 @@ struct ImGuiContext | |||
// Debug Tools | |||
bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker()) | |||
ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this id | |||
ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID | |||
ImGuiMetricsConfig DebugMetricsConfig; | |||
ImGuiStackTool DebugStackTool; | |||
// Misc | |||
float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds. | |||
@@ -1680,7 +1761,6 @@ struct ImGuiContext | |||
WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild = false; | |||
GcCompactAll = false; | |||
TestEngineHookItems = false; | |||
TestEngineHookIdInfo = 0; | |||
TestEngine = NULL; | |||
WindowsActiveCount = 0; | |||
@@ -1691,6 +1771,7 @@ struct ImGuiContext | |||
WheelingWindow = NULL; | |||
WheelingWindowTimer = 0.0f; | |||
DebugHookIdInfo = 0; | |||
HoveredId = HoveredIdPreviousFrame = 0; | |||
HoveredIdAllowOverlap = false; | |||
HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false; | |||
@@ -1721,15 +1802,15 @@ struct ImGuiContext | |||
LastActiveIdTimer = 0.0f; | |||
CurrentItemFlags = ImGuiItemFlags_None; | |||
BeginMenuCount = 0; | |||
NavWindow = NULL; | |||
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0; | |||
NavJustTabbedId = NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; | |||
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; | |||
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None; | |||
NavJustMovedToKeyMods = ImGuiKeyModFlags_None; | |||
NavInputSource = ImGuiInputSource_None; | |||
NavLayer = ImGuiNavLayer_Main; | |||
NavIdTabCounter = INT_MAX; | |||
NavIdIsAlive = false; | |||
NavMousePosDirty = false; | |||
NavDisableHighlight = true; | |||
@@ -1742,19 +1823,17 @@ struct ImGuiContext | |||
NavMoveScoringItems = false; | |||
NavMoveForwardToNextFrame = false; | |||
NavMoveFlags = ImGuiNavMoveFlags_None; | |||
NavMoveScrollFlags = ImGuiScrollFlags_None; | |||
NavMoveKeyMods = ImGuiKeyModFlags_None; | |||
NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None; | |||
NavScoringDebugCount = 0; | |||
NavTabbingDir = 0; | |||
NavTabbingCounter = 0; | |||
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL; | |||
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; | |||
NavWindowingToggleLayer = false; | |||
TabFocusRequestCurrWindow = TabFocusRequestNextWindow = NULL; | |||
TabFocusRequestCurrCounterRegular = TabFocusRequestCurrCounterTabStop = INT_MAX; | |||
TabFocusRequestNextCounterRegular = TabFocusRequestNextCounterTabStop = INT_MAX; | |||
TabFocusPressed = false; | |||
DimBgRatio = 0.0f; | |||
MouseCursor = ImGuiMouseCursor_Arrow; | |||
@@ -1770,14 +1849,16 @@ struct ImGuiContext | |||
DragDropHoldJustPressedId = 0; | |||
memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal)); | |||
ClipperTempDataStacked = 0; | |||
CurrentTable = NULL; | |||
CurrentTableStackIdx = -1; | |||
TablesTempDataStacked = 0; | |||
CurrentTabBar = NULL; | |||
TempInputId = 0; | |||
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; | |||
ColorEditLastHue = ColorEditLastSat = 0.0f; | |||
ColorEditLastColor[0] = ColorEditLastColor[1] = ColorEditLastColor[2] = FLT_MAX; | |||
ColorEditLastColor = 0; | |||
SliderCurrentAccum = 0.0f; | |||
SliderCurrentAccumDirty = false; | |||
DragCurrentAccumDirty = false; | |||
@@ -1838,6 +1919,7 @@ struct IMGUI_API ImGuiWindowTempData | |||
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 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. | |||
// Keyboard/Gamepad navigation | |||
ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) | |||
@@ -1859,8 +1941,6 @@ struct IMGUI_API ImGuiWindowTempData | |||
int CurrentTableIdx; // Current table index (into g.Tables) | |||
ImGuiLayoutType LayoutType; | |||
ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin() | |||
int FocusCounterRegular; // (Legacy Focus/Tabbing system) Sequential counter, start at -1 and increase when ImGuiItemFlags_Inputable (FIXME-NAV: Needs redesign) | |||
int FocusCounterTabStop; // (Legacy Focus/Tabbing system) Same, but only count widgets which you can Tab through. | |||
// Local parameters stacks | |||
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. | |||
@@ -1904,6 +1984,7 @@ struct IMGUI_API ImGuiWindow | |||
bool Appearing; // Set during the frame where the window is appearing (or re-appearing) | |||
bool Hidden; // Do not display (== HiddenFrames*** > 0) | |||
bool IsFallbackWindow; // Set on the "Debug##Default" window. | |||
bool IsExplicitChild; // Set when passed _ChildWindow, left to false by BeginDocked() | |||
bool HasCloseButton; // Set when the window has a close button (p_open != NULL) | |||
signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3) | |||
short BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) | |||
@@ -1950,8 +2031,10 @@ struct IMGUI_API ImGuiWindow | |||
ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer) | |||
ImDrawList DrawListInst; | |||
ImGuiWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL. | |||
ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window == Top-level window. | |||
ImGuiWindow* ParentWindow; // If we are a child _or_ popup _or_ docked window, this is pointing to our parent. Otherwise NULL. | |||
ImGuiWindow* ParentWindowInBeginStack; | |||
ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window. Doesn't cross through popups/dock nodes. | |||
ImGuiWindow* RootWindowPopupTree; // Point to ourself or first ancestor that is not a child window. Cross through popups parent<>child. | |||
ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active. | |||
ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag. | |||
@@ -2023,7 +2106,7 @@ struct ImGuiTabItem | |||
}; | |||
// Storage for a tab bar (sizeof() 152 bytes) | |||
struct ImGuiTabBar | |||
struct IMGUI_API ImGuiTabBar | |||
{ | |||
ImVector<ImGuiTabItem> Tabs; | |||
ImGuiTabBarFlags Flags; | |||
@@ -2148,7 +2231,7 @@ struct ImGuiTableCellData | |||
}; | |||
// FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData | |||
struct ImGuiTable | |||
struct IMGUI_API ImGuiTable | |||
{ | |||
ImGuiID ID; | |||
ImGuiTableFlags Flags; | |||
@@ -2254,14 +2337,14 @@ struct ImGuiTable | |||
bool MemoryCompacted; | |||
bool HostSkipItems; // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis | |||
IMGUI_API ImGuiTable() { memset(this, 0, sizeof(*this)); LastFrameActive = -1; } | |||
IMGUI_API ~ImGuiTable() { IM_FREE(RawData); } | |||
ImGuiTable() { memset(this, 0, sizeof(*this)); LastFrameActive = -1; } | |||
~ImGuiTable() { IM_FREE(RawData); } | |||
}; | |||
// 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. | |||
// - We also leave out of this structure data that tend to be particularly useful for debugging/metrics. | |||
struct ImGuiTableTempData | |||
struct IMGUI_API ImGuiTableTempData | |||
{ | |||
int TableIndex; // Index in g.Tables.Buf[] pool | |||
float LastTimeActive; // Last timestamp this structure was used | |||
@@ -2278,7 +2361,7 @@ struct ImGuiTableTempData | |||
float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable() | |||
int HostBackupItemWidthStackSize;//Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable() | |||
IMGUI_API ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; } | |||
ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; } | |||
}; | |||
// sizeof() ~ 12 | |||
@@ -2337,13 +2420,16 @@ namespace ImGui | |||
IMGUI_API ImGuiWindow* FindWindowByName(const char* name); | |||
IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window); | |||
IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window); | |||
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); | |||
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy); | |||
IMGUI_API bool IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent); | |||
IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below); | |||
IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); | |||
IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0); | |||
IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); | |||
IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0); | |||
IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size); | |||
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); } | |||
// Windows: Display Order and Focus Order | |||
IMGUI_API void FocusWindow(ImGuiWindow* window); | |||
@@ -2351,6 +2437,9 @@ namespace ImGui | |||
IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window); | |||
IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window); | |||
IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window); | |||
IMGUI_API void BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* above_window); | |||
IMGUI_API int FindWindowDisplayIndex(ImGuiWindow* window); | |||
IMGUI_API ImGuiWindow* FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* window); | |||
// Fonts, drawing | |||
IMGUI_API void SetCurrentFont(ImFont* font); | |||
@@ -2389,7 +2478,14 @@ namespace ImGui | |||
IMGUI_API void SetScrollY(ImGuiWindow* window, float scroll_y); | |||
IMGUI_API void SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio); | |||
IMGUI_API void SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio); | |||
IMGUI_API ImVec2 ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect); | |||
// Early work-in-progress API (ScrollToItem() will become public) | |||
IMGUI_API void ScrollToItem(ImGuiScrollFlags flags = 0); | |||
IMGUI_API void ScrollToRect(ImGuiWindow* window, const ImRect& rect, ImGuiScrollFlags flags = 0); | |||
IMGUI_API ImVec2 ScrollToRectEx(ImGuiWindow* window, const ImRect& rect, ImGuiScrollFlags flags = 0); | |||
//#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS | |||
inline void ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& rect) { ScrollToRect(window, rect, ImGuiScrollFlags_KeepVisibleEdgeY); } | |||
//#endif | |||
// Basic Accessors | |||
inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.LastItemData.ID; } // Get ID of last item (~~ often same ImGui::GetID(label) beforehand) | |||
@@ -2412,8 +2508,8 @@ namespace ImGui | |||
IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f); | |||
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 void ItemInputable(ImGuiWindow* window, 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 ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); | |||
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); | |||
IMGUI_API void PushMultiItemsWidths(int components, float width_full); | |||
@@ -2428,9 +2524,9 @@ namespace ImGui | |||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS | |||
// Currently refactoring focus/nav/tabbing system | |||
// If you have old/custom copy-and-pasted widgets that used FocusableItemRegister(): | |||
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool focused = FocusableItemRegister(...)' | |||
// (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0' | |||
// (New) IMGUI_VERSION_NUM >= 18411: using 'ItemAdd(..., ImGuiItemAddFlags_Inputable)' and 'bool focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0' | |||
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)' | |||
// (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0' | |||
// (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_FocusedTabbing) != 0 || g.NavActivateInputId == id' (WIP) | |||
// Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText() | |||
inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd() | |||
inline void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem | |||
@@ -2447,16 +2543,18 @@ namespace ImGui | |||
IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None); | |||
IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup); | |||
IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup); | |||
IMGUI_API void ClosePopupsExceptModals(); | |||
IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags); | |||
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); | |||
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags); | |||
IMGUI_API void BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags); | |||
IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window); | |||
IMGUI_API ImGuiWindow* GetTopMostPopupModal(); | |||
IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal(); | |||
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 bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags); | |||
// Menus | |||
IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags); | |||
IMGUI_API bool BeginMenuEx(const char* label, const char* icon, bool enabled = true); | |||
IMGUI_API bool MenuItemEx(const char* label, const char* icon, const char* shortcut = NULL, bool selected = false, bool enabled = true); | |||
@@ -2469,8 +2567,9 @@ namespace ImGui | |||
IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit); | |||
IMGUI_API void NavInitRequestApplyResult(); | |||
IMGUI_API bool NavMoveRequestButNoResultYet(); | |||
IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags); | |||
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags); | |||
IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); | |||
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); | |||
IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result); | |||
IMGUI_API void NavMoveRequestCancel(); | |||
IMGUI_API void NavMoveRequestApplyResult(); | |||
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); | |||
@@ -2618,7 +2717,7 @@ namespace ImGui | |||
IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos); | |||
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); | |||
IMGUI_API void Scrollbar(ImGuiAxis axis); | |||
IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float avail_v, float contents_v, ImDrawFlags flags); | |||
IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 avail_v, ImS64 contents_v, ImDrawFlags flags); | |||
IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& padding, const ImVec4& bg_col, const ImVec4& tint_col); | |||
IMGUI_API ImRect GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis); | |||
IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis); | |||
@@ -2686,6 +2785,7 @@ namespace ImGui | |||
inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } | |||
IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); | |||
IMGUI_API void DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end); | |||
IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns); | |||
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label); | |||
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb); | |||
@@ -2697,6 +2797,7 @@ namespace ImGui | |||
IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label); | |||
IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings); | |||
IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label); | |||
IMGUI_API void DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows, int windows_size, ImGuiWindow* parent_in_begin_stack); | |||
IMGUI_API void DebugNodeViewport(ImGuiViewportP* viewport); | |||
IMGUI_API void DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb); | |||
@@ -2731,14 +2832,12 @@ IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table | |||
#ifdef IMGUI_ENABLE_TEST_ENGINE | |||
extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, const ImRect& bb, ImGuiID id); | |||
extern void ImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx, ImGuiID id, const char* label, ImGuiItemStatusFlags flags); | |||
extern void ImGuiTestEngineHook_IdInfo(ImGuiContext* ctx, ImGuiDataType data_type, ImGuiID id, const void* data_id); | |||
extern void ImGuiTestEngineHook_IdInfo(ImGuiContext* ctx, ImGuiDataType data_type, ImGuiID id, const void* data_id, const void* data_id_end); | |||
extern void ImGuiTestEngineHook_Log(ImGuiContext* ctx, const char* fmt, ...); | |||
extern const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx, ImGuiID id); | |||
#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _BB, _ID) // Register item bounding box | |||
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional) | |||
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log | |||
#define IMGUI_TEST_ENGINE_ID_INFO(_ID,_TYPE,_DATA) if (g.TestEngineHookIdInfo == _ID) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA)); | |||
#define IMGUI_TEST_ENGINE_ID_INFO2(_ID,_TYPE,_DATA,_DATA2) if (g.TestEngineHookIdInfo == _ID) ImGuiTestEngineHook_IdInfo(&g, _TYPE, _ID, (const void*)(_DATA), (const void*)(_DATA2)); | |||
#else | |||
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)0) | |||
#endif | |||
@@ -1,4 +1,4 @@ | |||
// dear imgui, v1.85 WIP | |||
// dear imgui, v1.86 | |||
// (tables and columns code) | |||
/* | |||
@@ -340,10 +340,9 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG | |||
// Acquire temporary buffers | |||
const int table_idx = g.Tables.GetIndex(table); | |||
g.CurrentTableStackIdx++; | |||
if (g.CurrentTableStackIdx + 1 > g.TablesTempDataStack.Size) | |||
g.TablesTempDataStack.resize(g.CurrentTableStackIdx + 1, ImGuiTableTempData()); | |||
ImGuiTableTempData* temp_data = table->TempData = &g.TablesTempDataStack[g.CurrentTableStackIdx]; | |||
if (++g.TablesTempDataStacked > g.TablesTempData.Size) | |||
g.TablesTempData.resize(g.TablesTempDataStacked, ImGuiTableTempData()); | |||
ImGuiTableTempData* temp_data = table->TempData = &g.TablesTempData[g.TablesTempDataStacked - 1]; | |||
temp_data->TableIndex = table_idx; | |||
table->DrawSplitter = &table->TempData->DrawSplitter; | |||
table->DrawSplitter->Clear(); | |||
@@ -564,6 +563,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG | |||
// + 0 (for ImGuiTable instance, we are pooling allocations in g.Tables) | |||
// + 1 (for table->RawData allocated below) | |||
// + 1 (for table->ColumnsNames, if names are used) | |||
// Shared allocations per number of nested tables | |||
// + 1 (for table->Splitter._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. | |||
@@ -1381,9 +1381,8 @@ void ImGui::EndTable() | |||
// Clear or restore current table, if any | |||
IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table); | |||
IM_ASSERT(g.CurrentTableStackIdx >= 0); | |||
g.CurrentTableStackIdx--; | |||
temp_data = g.CurrentTableStackIdx >= 0 ? &g.TablesTempDataStack[g.CurrentTableStackIdx] : NULL; | |||
IM_ASSERT(g.TablesTempDataStacked > 0); | |||
temp_data = (--g.TablesTempDataStacked > 0) ? &g.TablesTempData[g.TablesTempDataStacked - 1] : NULL; | |||
g.CurrentTable = temp_data ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL; | |||
if (g.CurrentTable) | |||
{ | |||
@@ -1,4 +1,4 @@ | |||
// dear imgui, v1.85 WIP | |||
// dear imgui, v1.86 | |||
// (widgets code) | |||
/* | |||
@@ -564,7 +564,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool | |||
SetFocusID(id, window); | |||
FocusWindow(window); | |||
} | |||
if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[mouse_button_clicked])) | |||
if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseClickedCount[mouse_button_clicked] == 2)) | |||
{ | |||
pressed = true; | |||
if (flags & ImGuiButtonFlags_NoHoldingActiveId) | |||
@@ -641,7 +641,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool | |||
if ((release_in || release_anywhere) && !g.DragDropActive) | |||
{ | |||
// Report as pressed when releasing the mouse (this is the most common path) | |||
bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDownWasDoubleClick[mouse_button]; | |||
bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseReleased[mouse_button] && g.IO.MouseClickedLastCount[mouse_button] == 2; | |||
bool is_repeating_already = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button] >= g.IO.KeyRepeatDelay; // Repeat mode trumps <on release> | |||
if (!is_double_click_release && !is_repeating_already) | |||
pressed = true; | |||
@@ -896,7 +896,9 @@ void ImGui::Scrollbar(ImGuiAxis axis) | |||
} | |||
float size_avail = window->InnerRect.Max[axis] - window->InnerRect.Min[axis]; | |||
float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f; | |||
ScrollbarEx(bb, id, axis, &window->Scroll[axis], size_avail, size_contents, rounding_corners); | |||
ImS64 scroll = (ImS64)window->Scroll[axis]; | |||
ScrollbarEx(bb, id, axis, &scroll, (ImS64)size_avail, (ImS64)size_contents, rounding_corners); | |||
window->Scroll[axis] = (float)scroll; | |||
} | |||
// Vertical/Horizontal scrollbar | |||
@@ -905,7 +907,7 @@ void ImGui::Scrollbar(ImGuiAxis axis) | |||
// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar | |||
// - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal. | |||
// Still, the code should probably be made simpler.. | |||
bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float size_avail_v, float size_contents_v, ImDrawFlags flags) | |||
bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 size_avail_v, ImS64 size_contents_v, ImDrawFlags flags) | |||
{ | |||
ImGuiContext& g = *GImGui; | |||
ImGuiWindow* window = g.CurrentWindow; | |||
@@ -936,8 +938,8 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa | |||
// Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount) | |||
// But we maintain a minimum size in pixel to allow for the user to still aim inside. | |||
IM_ASSERT(ImMax(size_contents_v, size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers. | |||
const float win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), 1.0f); | |||
const float grab_h_pixels = ImClamp(scrollbar_size_v * (size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v); | |||
const ImS64 win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), (ImS64)1); | |||
const float grab_h_pixels = ImClamp(scrollbar_size_v * ((float)size_avail_v / (float)win_size_v), style.GrabMinSize, scrollbar_size_v); | |||
const float grab_h_norm = grab_h_pixels / scrollbar_size_v; | |||
// Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). | |||
@@ -945,13 +947,13 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa | |||
bool hovered = false; | |||
ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); | |||
float scroll_max = ImMax(1.0f, size_contents_v - size_avail_v); | |||
float scroll_ratio = ImSaturate(*p_scroll_v / scroll_max); | |||
const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_avail_v); | |||
float scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max); | |||
float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; // Grab position in normalized space | |||
if (held && allow_interaction && grab_h_norm < 1.0f) | |||
{ | |||
float scrollbar_pos_v = bb.Min[axis]; | |||
float mouse_pos_v = g.IO.MousePos[axis]; | |||
const float scrollbar_pos_v = bb.Min[axis]; | |||
const float mouse_pos_v = g.IO.MousePos[axis]; | |||
// Click position in scrollbar normalized space (0.0f->1.0f) | |||
const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); | |||
@@ -971,10 +973,10 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa | |||
// Apply scroll (p_scroll_v will generally point on one member of window->Scroll) | |||
// It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position | |||
const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm)); | |||
*p_scroll_v = IM_ROUND(scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v)); | |||
*p_scroll_v = (ImS64)(scroll_v_norm * scroll_max); | |||
// Update values for rendering | |||
scroll_ratio = ImSaturate(*p_scroll_v / scroll_max); | |||
scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max); | |||
grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; | |||
// Update distance to grab now that we have seeked and saturated | |||
@@ -1391,11 +1393,20 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags) | |||
if (g.GroupStack.Size > 0 && g.GroupStack.back().WindowID == window->ID) | |||
x1 += window->DC.Indent.x; | |||
// FIXME-WORKRECT: In theory we should simply be using WorkRect.Min.x/Max.x everywhere but it isn't aesthetically what we want, | |||
// need to introduce a variant of WorkRect for that purpose. (#4787) | |||
if (ImGuiTable* table = g.CurrentTable) | |||
{ | |||
x1 = table->Columns[table->CurrentColumn].MinX; | |||
x2 = table->Columns[table->CurrentColumn].MaxX; | |||
} | |||
ImGuiOldColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL; | |||
if (columns) | |||
PushColumnsBackground(); | |||
// We don't provide our width to the layout so that it doesn't get feed back into AutoFit | |||
// FIXME: This prevents ->CursorMaxPos based bounding box evaluation from working (e.g. TableEndCell) | |||
const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness_draw)); | |||
ItemSize(ImVec2(0.0f, thickness_layout)); | |||
const bool item_visible = ItemAdd(bb, 0); | |||
@@ -1424,7 +1435,7 @@ void ImGui::Separator() | |||
// Those flags should eventually be overridable by the user | |||
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal; | |||
flags |= ImGuiSeparatorFlags_SpanAllColumns; | |||
flags |= ImGuiSeparatorFlags_SpanAllColumns; // NB: this only applies to legacy Columns() api as they relied on Separator() a lot. | |||
SeparatorEx(flags); | |||
} | |||
@@ -1799,7 +1810,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi | |||
bool value_changed = false; | |||
for (int i = 0; i < items_count; i++) | |||
{ | |||
PushID((void*)(intptr_t)i); | |||
PushID(i); | |||
const bool item_selected = (i == *current_item); | |||
const char* item_text; | |||
if (!items_getter(data, i, &item_text)) | |||
@@ -2407,17 +2418,17 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, | |||
bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); | |||
if (!temp_input_is_active) | |||
{ | |||
const bool focus_requested = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0; | |||
const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; | |||
const bool clicked = (hovered && g.IO.MouseClicked[0]); | |||
const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]); | |||
if (focus_requested || clicked || double_clicked || g.NavActivateId == id || g.NavActivateInputId == id) | |||
const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2); | |||
if (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id || g.NavActivateInputId == id) | |||
{ | |||
SetActiveID(id, window); | |||
SetFocusID(id, window); | |||
FocusWindow(window); | |||
g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); | |||
if (temp_input_allowed) | |||
if (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavActivateInputId == id) | |||
if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavActivateInputId == id) | |||
temp_input_is_active = true; | |||
} | |||
@@ -3025,15 +3036,15 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat | |||
bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); | |||
if (!temp_input_is_active) | |||
{ | |||
const bool focus_requested = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0; | |||
const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; | |||
const bool clicked = (hovered && g.IO.MouseClicked[0]); | |||
if (focus_requested || clicked || g.NavActivateId == id || g.NavActivateInputId == id) | |||
if (input_requested_by_tabbing || clicked || g.NavActivateId == id || g.NavActivateInputId == id) | |||
{ | |||
SetActiveID(id, window); | |||
SetFocusID(id, window); | |||
FocusWindow(window); | |||
g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); | |||
if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavActivateInputId == id)) | |||
if (temp_input_allowed && (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || g.NavActivateInputId == id)) | |||
temp_input_is_active = true; | |||
} | |||
} | |||
@@ -3679,17 +3690,18 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob | |||
} | |||
// 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) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || 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; } | |||
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 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; } | |||
#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h | |||
#ifdef __APPLE__ // FIXME: Move setting to IO structure | |||
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 STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(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; } | |||
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_MAC | |||
#else | |||
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(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; } | |||
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_WIN | |||
#endif | |||
#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h | |||
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL | |||
static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n) | |||
{ | |||
@@ -3881,11 +3893,12 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f | |||
// Generic named filters | |||
if (apply_named_filters && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific))) | |||
{ | |||
// The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf. | |||
// The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf to use e.g. ',' instead of '.'. | |||
// The standard mandate that programs starts in the "C" locale where the decimal point is '.'. | |||
// We don't really intend to provide widespread support for it, but out of empathy for people stuck with using odd API, we support the bare minimum aka overriding the decimal point. | |||
// Change the default decimal_point with: | |||
// ImGui::GetCurrentContext()->PlatformLocaleDecimalPoint = *localeconv()->decimal_point; | |||
// Users of non-default decimal point (in particular ',') may be affected by word-selection logic (is_word_boundary_from_right/is_word_boundary_from_left) functions. | |||
ImGuiContext& g = *GImGui; | |||
const unsigned c_decimal_point = (unsigned int)g.PlatformLocaleDecimalPoint; | |||
@@ -3964,7 +3977,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
if (is_resizable) | |||
IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag! | |||
if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope, | |||
if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope (including the scrollbar) | |||
BeginGroup(); | |||
const ImGuiID id = window->GetID(label); | |||
const ImVec2 label_size = CalcTextSize(label, NULL, true); | |||
@@ -3977,6 +3990,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
ImGuiWindow* draw_window = window; | |||
ImVec2 inner_size = frame_size; | |||
ImGuiItemStatusFlags item_status_flags = 0; | |||
ImGuiLastItemData item_data_backup; | |||
if (is_multiline) | |||
{ | |||
ImVec2 backup_pos = window->DC.CursorPos; | |||
@@ -3987,6 +4001,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
return false; | |||
} | |||
item_status_flags = g.LastItemData.StatusFlags; | |||
item_data_backup = g.LastItemData; | |||
window->DC.CursorPos = backup_pos; | |||
// We reproduce the contents of BeginChildFrame() in order to provide 'label' so our window internal data are easier to read/debug. | |||
@@ -3994,8 +4009,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]); | |||
PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding); | |||
PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize); | |||
PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); // Ensure no clip rect so mouse hover can reach FramePadding edges | |||
bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), true, ImGuiWindowFlags_NoMove); | |||
PopStyleVar(2); | |||
PopStyleVar(3); | |||
PopStyleColor(); | |||
if (!child_visible) | |||
{ | |||
@@ -4024,21 +4040,19 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
// We are only allowed to access the state if we are already the active widget. | |||
ImGuiInputTextState* state = GetInputTextState(id); | |||
const bool focus_requested_by_code = (item_status_flags & ImGuiItemStatusFlags_FocusedByCode) != 0; | |||
const bool focus_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; | |||
const bool input_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; | |||
const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard)); | |||
const bool user_clicked = hovered && io.MouseClicked[0]; | |||
const bool user_nav_input_start = (g.ActiveId != id) && (g.NavActivateInputId == id || g.NavActivateId == id); | |||
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y); | |||
const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y); | |||
bool clear_active_id = false; | |||
bool select_all = (g.ActiveId != id) && ((flags & ImGuiInputTextFlags_AutoSelectAll) != 0 || user_nav_input_start) && (!is_multiline); | |||
bool select_all = false; | |||
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_make_active = (user_clicked || user_scroll_finish || user_nav_input_start || focus_requested_by_code || focus_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); | |||
if ((init_state && g.ActiveId != id) || init_changed_specs) | |||
{ | |||
@@ -4074,13 +4088,20 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
state->ID = id; | |||
state->ScrollX = 0.0f; | |||
stb_textedit_initialize_state(&state->Stb, !is_multiline); | |||
if (!is_multiline && focus_requested_by_code) | |||
} | |||
if (!is_multiline) | |||
{ | |||
if (flags & ImGuiInputTextFlags_AutoSelectAll) | |||
select_all = true; | |||
if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState))) | |||
select_all = true; | |||
if (input_requested_by_tabbing || (user_clicked && io.KeyCtrl)) | |||
select_all = true; | |||
} | |||
if (flags & ImGuiInputTextFlags_AlwaysOverwrite) | |||
state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863) | |||
if (!is_multiline && (focus_requested_by_tabbing || (user_clicked && io.KeyCtrl))) | |||
select_all = true; | |||
} | |||
if (g.ActiveId != id && init_make_active) | |||
@@ -4113,7 +4134,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
// Lock the decision of whether we are going to take the path displaying the cursor or selection | |||
const bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active); | |||
bool render_selection = state && state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor); | |||
bool render_selection = state && (state->HasSelection() || select_all) && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor); | |||
bool value_changed = false; | |||
bool enter_pressed = false; | |||
@@ -4158,8 +4179,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
state->Edited = false; | |||
state->BufCapacityA = buf_size; | |||
state->Flags = flags; | |||
state->UserCallback = callback; | |||
state->UserCallbackData = callback_user_data; | |||
// 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. | |||
@@ -4171,19 +4190,49 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f)); | |||
const bool is_osx = io.ConfigMacOSXBehaviors; | |||
if (select_all || (hovered && !is_osx && io.MouseDoubleClicked[0])) | |||
if (select_all) | |||
{ | |||
state->SelectAll(); | |||
state->SelectedAllMouseLock = true; | |||
} | |||
else if (hovered && is_osx && io.MouseDoubleClicked[0]) | |||
else if (hovered && io.MouseClickedCount[0] >= 2 && !io.KeyShift) | |||
{ | |||
// Double-click select a word only, OS X style (by simulating keystrokes) | |||
state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT); | |||
state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT); | |||
stb_textedit_click(state, &state->Stb, mouse_x, mouse_y); | |||
const int multiclick_count = (io.MouseClickedCount[0] - 2); | |||
if ((multiclick_count % 2) == 0) | |||
{ | |||
// Double-click: Select word | |||
// We always use the "Mac" word advance for double-click select vs CTRL+Right which use the platform dependent variant: | |||
// FIXME: There are likely many ways to improve this behavior, but there's no "right" behavior (depends on use-case, software, OS) | |||
const bool is_bol = (state->Stb.cursor == 0) || ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor - 1) == '\n'; | |||
if (STB_TEXT_HAS_SELECTION(&state->Stb) || !is_bol) | |||
state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT); | |||
//state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT); | |||
if (!STB_TEXT_HAS_SELECTION(&state->Stb)) | |||
ImStb::stb_textedit_prep_selection_at_cursor(&state->Stb); | |||
state->Stb.cursor = ImStb::STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state->Stb.cursor); | |||
state->Stb.select_end = state->Stb.cursor; | |||
ImStb::stb_textedit_clamp(state, &state->Stb); | |||
} | |||
else | |||
{ | |||
// Triple-click: Select line | |||
const bool is_eol = ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor) == '\n'; | |||
state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART); | |||
state->OnKeyPressed(STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT); | |||
state->OnKeyPressed(STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT); | |||
if (!is_eol && is_multiline) | |||
{ | |||
ImSwap(state->Stb.select_start, state->Stb.select_end); | |||
state->Stb.cursor = state->Stb.select_end; | |||
} | |||
state->CursorFollow = false; | |||
} | |||
state->CursorAnimReset(); | |||
} | |||
else if (io.MouseClicked[0] && !state->SelectedAllMouseLock) | |||
{ | |||
// FIXME: unselect on late click could be done release? | |||
if (hovered) | |||
{ | |||
stb_textedit_click(state, &state->Stb, mouse_x, mouse_y); | |||
@@ -4214,7 +4263,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
// We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters. | |||
if (io.InputQueueCharacters.Size > 0) | |||
{ | |||
if (!ignore_char_inputs && !is_readonly && !user_nav_input_start) | |||
if (!ignore_char_inputs && !is_readonly && !input_requested_by_nav) | |||
for (int n = 0; n < io.InputQueueCharacters.Size; n++) | |||
{ | |||
// Insert character if they pass filtering | |||
@@ -4268,7 +4317,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
else if (IsKeyPressedMap(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; } | |||
else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); } | |||
else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); } | |||
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } | |||
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly && !is_cut) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } | |||
else if (IsKeyPressedMap(ImGuiKey_Backspace) && !is_readonly) | |||
{ | |||
if (!state->HasSelection()) | |||
@@ -4367,11 +4416,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
} | |||
// Process callbacks and apply result back to user's buffer. | |||
const char* apply_new_text = NULL; | |||
int apply_new_text_length = 0; | |||
if (g.ActiveId == id) | |||
{ | |||
IM_ASSERT(state != NULL); | |||
const char* apply_new_text = NULL; | |||
int apply_new_text_length = 0; | |||
if (cancel_edit) | |||
{ | |||
// Restore initial value. Only return true if restoring to the initial value changes the current buffer contents. | |||
@@ -4447,8 +4496,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
callback_data.Flags = flags; | |||
callback_data.UserData = callback_user_data; | |||
char* callback_buf = is_readonly ? buf : state->TextA.Data; | |||
callback_data.EventKey = event_key; | |||
callback_data.Buf = state->TextA.Data; | |||
callback_data.Buf = callback_buf; | |||
callback_data.BufTextLen = state->CurLenA; | |||
callback_data.BufSize = state->BufCapacityA; | |||
callback_data.BufDirty = false; | |||
@@ -4463,7 +4513,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
callback(&callback_data); | |||
// Read back what user may have modified | |||
IM_ASSERT(callback_data.Buf == state->TextA.Data); // Invalid to modify those fields | |||
callback_buf = is_readonly ? buf : state->TextA.Data; // Pointer may have been invalidated by a resize callback | |||
IM_ASSERT(callback_data.Buf == callback_buf); // Invalid to modify those fields | |||
IM_ASSERT(callback_data.BufSize == state->BufCapacityA); | |||
IM_ASSERT(callback_data.Flags == flags); | |||
const bool buf_dirty = callback_data.BufDirty; | |||
@@ -4490,39 +4541,37 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
} | |||
} | |||
// Copy result to user buffer | |||
if (apply_new_text) | |||
{ | |||
// We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size | |||
// of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used | |||
// without any storage on user's side. | |||
IM_ASSERT(apply_new_text_length >= 0); | |||
if (is_resizable) | |||
{ | |||
ImGuiInputTextCallbackData callback_data; | |||
callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize; | |||
callback_data.Flags = flags; | |||
callback_data.Buf = buf; | |||
callback_data.BufTextLen = apply_new_text_length; | |||
callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1); | |||
callback_data.UserData = callback_user_data; | |||
callback(&callback_data); | |||
buf = callback_data.Buf; | |||
buf_size = callback_data.BufSize; | |||
apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1); | |||
IM_ASSERT(apply_new_text_length <= buf_size); | |||
} | |||
//IMGUI_DEBUG_LOG("InputText(\"%s\"): apply_new_text length %d\n", label, apply_new_text_length); | |||
// Clear temporary user storage | |||
state->Flags = ImGuiInputTextFlags_None; | |||
} | |||
// 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)); | |||
value_changed = true; | |||
// Copy result to user buffer. This can currently only happen when (g.ActiveId == id) | |||
if (apply_new_text != NULL) | |||
{ | |||
// We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size | |||
// of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used | |||
// without any storage on user's side. | |||
IM_ASSERT(apply_new_text_length >= 0); | |||
if (is_resizable) | |||
{ | |||
ImGuiInputTextCallbackData callback_data; | |||
callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize; | |||
callback_data.Flags = flags; | |||
callback_data.Buf = buf; | |||
callback_data.BufTextLen = apply_new_text_length; | |||
callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1); | |||
callback_data.UserData = callback_user_data; | |||
callback(&callback_data); | |||
buf = callback_data.Buf; | |||
buf_size = callback_data.BufSize; | |||
apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1); | |||
IM_ASSERT(apply_new_text_length <= buf_size); | |||
} | |||
//IMGUI_DEBUG_LOG("InputText(\"%s\"): apply_new_text length %d\n", label, apply_new_text_length); | |||
// Clear temporary user storage | |||
state->Flags = ImGuiInputTextFlags_None; | |||
state->UserCallback = NULL; | |||
state->UserCallbackData = NULL; | |||
// 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)); | |||
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) | |||
@@ -4644,7 +4693,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
// Test if cursor is vertically visible | |||
if (cursor_offset.y - g.FontSize < scroll_y) | |||
scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); | |||
else if (cursor_offset.y - inner_size.y >= scroll_y) | |||
else if (cursor_offset.y - (inner_size.y - style.FramePadding.y * 2.0f) >= scroll_y) | |||
scroll_y = cursor_offset.y - inner_size.y + style.FramePadding.y * 2.0f; | |||
const float scroll_max_y = ImMax((text_size.y + style.FramePadding.y * 2.0f) - inner_size.y, 0.0f); | |||
scroll_y = ImClamp(scroll_y, 0.0f, scroll_max_y); | |||
@@ -4736,9 +4785,23 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||
if (is_multiline) | |||
{ | |||
// For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (ref issue #4761)... | |||
Dummy(ImVec2(text_size.x, text_size.y + style.FramePadding.y)); | |||
ImGuiItemFlags backup_item_flags = g.CurrentItemFlags; | |||
g.CurrentItemFlags |= ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop; | |||
EndChild(); | |||
item_data_backup.StatusFlags |= (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredWindow); | |||
g.CurrentItemFlags = backup_item_flags; | |||
// ...and then we need to undo the group overriding last item data, which gets a bit messy as EndGroup() tries to forward scrollbar being active... | |||
// FIXME: This quite messy/tricky, should attempt to get rid of the child window. | |||
EndGroup(); | |||
if (g.LastItemData.ID == 0) | |||
{ | |||
g.LastItemData.ID = id; | |||
g.LastItemData.InFlags = item_data_backup.InFlags; | |||
g.LastItemData.StatusFlags = item_data_backup.StatusFlags; | |||
} | |||
} | |||
// Log as text | |||
@@ -4781,6 +4844,30 @@ bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flag | |||
return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha); | |||
} | |||
// ColorEdit supports RGB and HSV inputs. In case of RGB input resulting color may have undefined hue and/or saturation. | |||
// Since widget displays both RGB and HSV values we must preserve hue and saturation to prevent these values resetting. | |||
static void ColorEditRestoreHS(const float* col, float* H, float* S, float* V) | |||
{ | |||
// This check is optional. Suppose we have two color widgets side by side, both widgets display different colors, but both colors have hue and/or saturation undefined. | |||
// With color check: hue/saturation is preserved in one widget. Editing color in one widget would reset hue/saturation in another one. | |||
// Without color check: common hue/saturation would be displayed in all widgets that have hue/saturation undefined. | |||
// g.ColorEditLastColor is stored as ImU32 RGB value: this essentially gives us color equality check with reduced precision. | |||
// Tiny external color changes would not be detected and this check would still pass. This is OK, since we only restore hue/saturation _only_ if they are undefined, | |||
// therefore this change flipping hue/saturation from undefined to a very tiny value would still be represented in color picker. | |||
ImGuiContext& g = *GImGui; | |||
if (g.ColorEditLastColor != ImGui::ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0))) | |||
return; | |||
// When S == 0, H is undefined. | |||
// When H == 1 it wraps around to 0. | |||
if (*S == 0.0f || (*H == 0.0f && g.ColorEditLastHue == 1)) | |||
*H = g.ColorEditLastHue; | |||
// When V == 0, S is undefined. | |||
if (*V == 0.0f) | |||
*S = g.ColorEditLastSat; | |||
} | |||
// Edit colors components (each component in 0.0f..1.0f range). | |||
// See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. | |||
// With typical options: Left-click on color square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item. | |||
@@ -4836,13 +4923,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag | |||
{ | |||
// Hue is lost when converting from greyscale rgb (saturation=0). Restore it. | |||
ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); | |||
if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) | |||
{ | |||
if (f[1] == 0) | |||
f[0] = g.ColorEditLastHue; | |||
if (f[2] == 0) | |||
f[1] = g.ColorEditLastSat; | |||
} | |||
ColorEditRestoreHS(col, &f[0], &f[1], &f[2]); | |||
} | |||
int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) }; | |||
@@ -4977,7 +5058,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag | |||
g.ColorEditLastHue = f[0]; | |||
g.ColorEditLastSat = f[1]; | |||
ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); | |||
memcpy(g.ColorEditLastColor, f, sizeof(float) * 3); | |||
g.ColorEditLastColor = ColorConvertFloat4ToU32(ImVec4(f[0], f[1], f[2], 0)); | |||
} | |||
if ((flags & ImGuiColorEditFlags_DisplayRGB) && (flags & ImGuiColorEditFlags_InputHSV)) | |||
ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); | |||
@@ -5112,13 +5193,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl | |||
{ | |||
// Hue is lost when converting from greyscale rgb (saturation=0). Restore it. | |||
ColorConvertRGBtoHSV(R, G, B, H, S, V); | |||
if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) | |||
{ | |||
if (S == 0) | |||
H = g.ColorEditLastHue; | |||
if (V == 0) | |||
S = g.ColorEditLastSat; | |||
} | |||
ColorEditRestoreHS(col, &H, &S, &V); | |||
} | |||
else if (flags & ImGuiColorEditFlags_InputHSV) | |||
{ | |||
@@ -5171,6 +5246,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl | |||
{ | |||
S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1)); | |||
V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1)); | |||
// Greatly reduces hue jitter and reset to 0 when hue == 255 and color is rapidly modified using SV square. | |||
if (g.ColorEditLastColor == ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0))) | |||
H = g.ColorEditLastHue; | |||
value_changed = value_changed_sv = true; | |||
} | |||
if (!(flags & ImGuiColorEditFlags_NoOptions)) | |||
@@ -5244,10 +5323,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl | |||
{ | |||
if (flags & ImGuiColorEditFlags_InputRGB) | |||
{ | |||
ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10 * 1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]); | |||
ColorConvertHSVtoRGB(H, S, V, col[0], col[1], col[2]); | |||
g.ColorEditLastHue = H; | |||
g.ColorEditLastSat = S; | |||
memcpy(g.ColorEditLastColor, col, sizeof(float) * 3); | |||
g.ColorEditLastColor = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)); | |||
} | |||
else if (flags & ImGuiColorEditFlags_InputHSV) | |||
{ | |||
@@ -5301,13 +5380,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl | |||
G = col[1]; | |||
B = col[2]; | |||
ColorConvertRGBtoHSV(R, G, B, H, S, V); | |||
if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) // Fix local Hue as display below will use it immediately. | |||
{ | |||
if (S == 0) | |||
H = g.ColorEditLastHue; | |||
if (V == 0) | |||
S = g.ColorEditLastSat; | |||
} | |||
ColorEditRestoreHS(col, &H, &S, &V); // Fix local Hue as display below will use it immediately. | |||
} | |||
else if (flags & ImGuiColorEditFlags_InputHSV) | |||
{ | |||
@@ -5533,7 +5606,7 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags | |||
{ | |||
ImGuiContext& g = *GImGui; | |||
BeginTooltipEx(0, ImGuiTooltipFlags_OverridePreviousTooltip); | |||
BeginTooltipEx(ImGuiTooltipFlags_OverridePreviousTooltip, ImGuiWindowFlags_None); | |||
const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text; | |||
if (text_end > text) | |||
{ | |||
@@ -5904,7 +5977,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l | |||
toggled = true; | |||
if (flags & ImGuiTreeNodeFlags_OpenOnArrow) | |||
toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job | |||
if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseDoubleClicked[0]) | |||
if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseClickedCount[0] == 2) | |||
toggled = true; | |||
} | |||
else if (pressed && g.DragDropHoldJustPressedId == id) | |||
@@ -6007,7 +6080,7 @@ void ImGui::TreePushOverrideID(ImGuiID id) | |||
ImGuiWindow* window = g.CurrentWindow; | |||
Indent(); | |||
window->DC.TreeDepth++; | |||
window->IDStack.push_back(id); | |||
PushOverrideID(id); | |||
} | |||
void ImGui::TreePop() | |||
@@ -6211,7 +6284,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl | |||
{ | |||
if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) | |||
{ | |||
SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, ImRect(bb.Min - window->Pos, bb.Max - window->Pos)); // (bb == NavRect) | |||
SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, WindowRectAbsToRel(window, bb)); // (bb == NavRect) | |||
g.NavDisableHighlight = true; | |||
} | |||
} | |||
@@ -6706,7 +6779,7 @@ void ImGui::EndMenuBar() | |||
SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]); | |||
g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. | |||
g.NavDisableMouseHover = g.NavMousePosDirty = true; | |||
NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags); // Repeat | |||
NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags); // Repeat | |||
} | |||
} | |||
@@ -6795,6 +6868,23 @@ void ImGui::EndMainMenuBar() | |||
End(); | |||
} | |||
static bool IsRootOfOpenMenuSet() | |||
{ | |||
ImGuiContext& g = *GImGui; | |||
ImGuiWindow* window = g.CurrentWindow; | |||
if ((g.OpenPopupStack.Size <= g.BeginPopupStack.Size) || (window->Flags & ImGuiWindowFlags_ChildMenu)) | |||
return false; | |||
// Initially we used 'OpenParentId' to differentiate multiple menu sets from each others (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. | |||
// 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. | |||
// 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 chilld menu. | |||
const ImGuiPopupData* upper_popup = &g.OpenPopupStack[g.BeginPopupStack.Size]; | |||
return (/*upper_popup->OpenParentId == window->IDStack.back() &&*/ upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu)); | |||
} | |||
bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) | |||
{ | |||
ImGuiWindow* window = GetCurrentWindow(); | |||
@@ -6807,8 +6897,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) | |||
bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None); | |||
// Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu) | |||
// The first menu in a hierarchy isn't so hovering doesn't get accross (otherwise e.g. resizing borders with ImGuiButtonFlags_FlattenChildren would react), but top-most BeginMenu() will bypass that limitation. | |||
ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; | |||
if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) | |||
if (window->Flags & ImGuiWindowFlags_ChildMenu) | |||
flags |= ImGuiWindowFlags_ChildWindow; | |||
// If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin(). | |||
@@ -6827,11 +6918,12 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) | |||
g.MenusIdSubmittedThisFrame.push_back(id); | |||
ImVec2 label_size = CalcTextSize(label, NULL, true); | |||
bool pressed; | |||
bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back()); | |||
// Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent without always being a Child window) | |||
const bool menuset_is_open = IsRootOfOpenMenuSet(); | |||
ImGuiWindow* backed_nav_window = g.NavWindow; | |||
if (menuset_is_open) | |||
g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent) | |||
g.NavWindow = window; | |||
// The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu, | |||
// However the final position is going to be different! It is chosen by FindBestWindowPosForPopup(). | |||
@@ -6841,6 +6933,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) | |||
if (!enabled) | |||
BeginDisabled(); | |||
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; | |||
bool pressed; | |||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) | |||
{ | |||
// Menu inside an horizontal menu bar | |||
@@ -6957,7 +7050,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) | |||
if (menu_is_open) | |||
{ | |||
SetNextWindowPos(popup_pos, ImGuiCond_Always); // Note: this is super misleading! The value will serve as reference for FindBestWindowPosForPopup(), not actual pos. | |||
PushStyleVar(ImGuiStyleVar_ChildRounding, style.PopupRounding); // First level will use _PopupRounding, subsequent will use _ChildRounding | |||
menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) | |||
PopStyleVar(); | |||
} | |||
else | |||
{ | |||
@@ -7000,13 +7095,19 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut | |||
ImVec2 pos = window->DC.CursorPos; | |||
ImVec2 label_size = CalcTextSize(label, NULL, true); | |||
const bool menuset_is_open = IsRootOfOpenMenuSet(); | |||
ImGuiWindow* backed_nav_window = g.NavWindow; | |||
if (menuset_is_open) | |||
g.NavWindow = window; | |||
// We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73), | |||
// but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only. | |||
bool pressed; | |||
PushID(label); | |||
if (!enabled) | |||
BeginDisabled(); | |||
const ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover; | |||
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover; | |||
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; | |||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) | |||
{ | |||
@@ -7016,7 +7117,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut | |||
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); | |||
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); | |||
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); | |||
pressed = Selectable("", selected, flags, ImVec2(w, 0.0f)); | |||
pressed = Selectable("", selected, selectable_flags, ImVec2(w, 0.0f)); | |||
PopStyleVar(); | |||
RenderText(text_pos, label); | |||
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). | |||
@@ -7031,7 +7132,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut | |||
float checkmark_w = IM_FLOOR(g.FontSize * 1.20f); | |||
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame | |||
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); | |||
pressed = Selectable("", false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f)); | |||
pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f)); | |||
RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label); | |||
if (icon_w > 0.0f) | |||
RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon); | |||
@@ -7048,6 +7149,8 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut | |||
if (!enabled) | |||
EndDisabled(); | |||
PopID(); | |||
if (menuset_is_open) | |||
g.NavWindow = backed_nav_window; | |||
return pressed; | |||
} | |||
@@ -7190,8 +7293,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG | |||
// Ensure correct ordering when toggling ImGuiTabBarFlags_Reorderable flag, or when a new tab was added while being not reorderable | |||
if ((flags & ImGuiTabBarFlags_Reorderable) != (tab_bar->Flags & ImGuiTabBarFlags_Reorderable) || (tab_bar->TabsAddedNew && !(flags & ImGuiTabBarFlags_Reorderable))) | |||
if (tab_bar->Tabs.Size > 1) | |||
ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder); | |||
ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder); | |||
tab_bar->TabsAddedNew = false; | |||
// Flags | |||
@@ -7864,9 +7966,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, | |||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); | |||
if (p_open && !*p_open) | |||
{ | |||
PushItemFlag(ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus, true); | |||
ItemAdd(ImRect(), id); | |||
PopItemFlag(); | |||
ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus); | |||
return false; | |||
} | |||
@@ -7933,9 +8033,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, | |||
// and then gets submitted again, the tabs will have 'tab_appearing=true' but 'tab_is_new=false'. | |||
if (tab_appearing && (!tab_bar_appearing || tab_is_new)) | |||
{ | |||
PushItemFlag(ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus, true); | |||
ItemAdd(ImRect(), id); | |||
PopItemFlag(); | |||
ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus); | |||
if (is_tab_button) | |||
return false; | |||
return tab_contents_visible; | |||
@@ -103,12 +103,15 @@ struct ImGuiWidget::PrivateData { | |||
{ | |||
#ifndef DGL_NO_SHARED_RESOURCES | |||
using namespace dpf_resources; | |||
static const ImWchar ranges[] = { 0x20, 0xFF, 0 }; /* FIXME unicode range not working.. */ | |||
ImFontConfig fc; | |||
fc.FontDataOwnedByAtlas = false; | |||
fc.OversampleH = 1; | |||
fc.OversampleV = 1; | |||
fc.PixelSnapH = true; | |||
io.Fonts->AddFontFromMemoryTTF((void*)dejavusans_ttf, dejavusans_ttf_size, 13.0f * scaleFactor, &fc); | |||
io.Fonts->AddFontFromMemoryTTF((void*)dejavusans_ttf, | |||
dejavusans_ttf_size, | |||
13.0f * scaleFactor, &fc, ranges); | |||
io.Fonts->Build(); | |||
#endif | |||
} | |||