mirror of
https://github.com/ocornut/imgui.git
synced 2026-05-08 14:52:20 +00:00
Merge branch 'master' into docking
This commit is contained in:
@@ -61,6 +61,12 @@ Other Changes:
|
||||
- Multi-Select:
|
||||
- Fixed an issue using Multi-Select within a Table causing column width measurement to
|
||||
be invalid when trailing column contents is not submitted in the last row. (#9341, #8250)
|
||||
- Fixed an issue using Multi-Select within a Table with the right-most column visible,
|
||||
which could lead to an extra vertical offset in the Header row. (#8250)
|
||||
- Box-Select: fixed an issue using ImGuiMultiSelectFlags_BoxSelect1d mode while scrolling.
|
||||
Notably, using mouse wheel while holding a box-selection could lead items close to windows
|
||||
edges from not being correctly unselected. (#7994, #8250, #7821, #7850, #7970)
|
||||
- Box-Select: improved dirty/unclip rectangle logic for ImGuiMultiSelectFlags_BoxSelect2d.
|
||||
- Box-Select: fixed an issue using ImGuiMultiSelectFlags_BoxSelect2d mode, where
|
||||
items out of view wouldn't be properly selected while scrolling while mouse cursor
|
||||
is hovering outside of selection scope. (#7994, #1861, #6518)
|
||||
@@ -74,7 +80,12 @@ Other Changes:
|
||||
and ImGuiSelectionUserData is technically opaque storage. (#7994, #1861)
|
||||
(we will probably bring this back as a minor optimization if we have a way to for
|
||||
user to tell us ImGuiSelectionUserData are indices)
|
||||
- Box-Select, Tables: fixed an issue when calling `BeginMultiSelect()` in a table
|
||||
- Box-Select: fixes for using accross nested child windows. (#8364)
|
||||
- Box-Select + Clipper: fixed an issue selecting items while scrolling while a clipper
|
||||
active. (#7994, #8250, #7821, #7850, #7970)
|
||||
- Box-Select + Tables: fixed an issue using box-selection in a tables with
|
||||
items straying out of columns boundaries. (#7994, #2221)
|
||||
- Box-Select + Tables: fixed an issue when calling `BeginMultiSelect()` in a table
|
||||
before layout has been locked (first row or headers row submitted). (#8250)
|
||||
- Style:
|
||||
- Fixed vertical scrollbar top coordinates when using thick borders on windows
|
||||
@@ -90,6 +101,7 @@ Other Changes:
|
||||
a better recoverable error. (#9350)
|
||||
- Misc:
|
||||
- Minor optimization: reduce redudant label scanning in common widgets.
|
||||
- Added missing Test Engine hooks for PlotXXX(), VSliderXXX(), TableHeader().
|
||||
- Backends:
|
||||
- Metal: avoid redundant vertex buffer bind in `SetupRenderState()`, which leads
|
||||
to validation issue. (#9343) [@Hunam6]
|
||||
|
||||
40
imgui.cpp
40
imgui.cpp
@@ -3521,12 +3521,14 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
|
||||
// FIXME: Selectable() use of half-ItemSpacing isn't consistent in matter of layout, as ItemAdd(bb) stray above ItemSize()'s CursorPos.
|
||||
// RangeSelect's BoxSelect relies on comparing overlap of previous and current rectangle and is sensitive to that.
|
||||
// As a workaround we currently half ItemSpacing worth on each side.
|
||||
min_y -= g.Style.ItemSpacing.y;
|
||||
max_y += g.Style.ItemSpacing.y;
|
||||
float pad_y = g.Style.ItemSpacing.y;
|
||||
min_y -= pad_y;
|
||||
max_y += pad_y;
|
||||
|
||||
// Box-select on 2D area requires different clipping.
|
||||
// (best adding pad_y here than in BeginBoxSelect() as we are closer to current state)
|
||||
if (bs->UnclipMode)
|
||||
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(bs->UnclipRect.Min.y, bs->UnclipRect.Max.y, 0, 0));
|
||||
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(bs->UnclipRect.Min.y - pad_y, bs->UnclipRect.Max.y + pad_y, 0, 0));
|
||||
}
|
||||
|
||||
// Add main visible range
|
||||
@@ -6095,14 +6097,6 @@ void ImGui::PopClipRect()
|
||||
window->ClipRect = window->DrawList->_ClipRectStack.back();
|
||||
}
|
||||
|
||||
static ImGuiWindow* FindFrontMostVisibleChildWindow(ImGuiWindow* window)
|
||||
{
|
||||
for (int n = window->DC.ChildWindows.Size - 1; n >= 0; n--)
|
||||
if (IsWindowActiveAndVisible(window->DC.ChildWindows[n]))
|
||||
return FindFrontMostVisibleChildWindow(window->DC.ChildWindows[n]);
|
||||
return window;
|
||||
}
|
||||
|
||||
static void ImGui::RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
@@ -6871,6 +6865,14 @@ void ImGui::EndChild()
|
||||
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
|
||||
}
|
||||
|
||||
ImGuiWindow* ImGui::FindFrontMostVisibleChildWindow(ImGuiWindow* window)
|
||||
{
|
||||
for (int n = window->DC.ChildWindows.Size - 1; n >= 0; n--)
|
||||
if (IsWindowActiveAndVisible(window->DC.ChildWindows[n]))
|
||||
return FindFrontMostVisibleChildWindow(window->DC.ChildWindows[n]);
|
||||
return window;
|
||||
}
|
||||
|
||||
static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled)
|
||||
{
|
||||
window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags);
|
||||
@@ -9381,6 +9383,17 @@ void ImGui::PopFocusScope()
|
||||
g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back().ID : 0;
|
||||
}
|
||||
|
||||
bool ImGui::IsInNavFocusRoute(ImGuiID focus_scope_id)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.NavFocusScopeId == focus_scope_id)
|
||||
return true;
|
||||
for (const ImGuiFocusScopeData& focus_scope : g.NavFocusRoute)
|
||||
if (focus_scope.ID == focus_scope_id)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImGui::SetNavFocusScope(ImGuiID focus_scope_id)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -11457,7 +11470,8 @@ bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, si
|
||||
// to extend contents size of our parent container (e.g. window contents size, which is used for auto-resizing
|
||||
// windows, table column contents size used for auto-resizing columns, group size).
|
||||
// This was causing issues and ambiguities and we needed to retire that.
|
||||
// From 1.89, extending contents size boundaries REQUIRES AN ITEM TO BE SUBMITTED.
|
||||
// 2022/08/05 (1.89): extending contents size boundaries REQUIRES AN ITEM TO BE SUBMITTED. However we gated the new logic behind a '#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS' block.
|
||||
// 2025/06/25 (1.92): removed the legacy path and turned into an assert. It was a mistake that there was a #ifndef before: our obsolescence schedule gets pushed back a bit more :(
|
||||
//
|
||||
// Previously this would make the window content size ~200x200:
|
||||
// Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + End(); // NOT OK ANYMORE
|
||||
@@ -14042,7 +14056,7 @@ static void ImGui::NavProcessItem()
|
||||
const ImGuiID id = g.LastItemData.ID;
|
||||
const ImGuiItemFlags item_flags = g.LastItemData.ItemFlags;
|
||||
|
||||
// When inside a container that isn't scrollable with Left<>Right, clip NavRect accordingly (#2221, #8816)
|
||||
// When inside a container that isn't scrollable with Left<>Right, clip NavRect accordingly (#2221, #8816, #7994)
|
||||
ImRect nav_bb = g.LastItemData.NavRect;
|
||||
if (window->DC.NavIsScrollPushableX == false)
|
||||
{
|
||||
|
||||
2
imgui.h
2
imgui.h
@@ -30,7 +30,7 @@
|
||||
// Library Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
||||
#define IMGUI_VERSION "1.92.8 WIP"
|
||||
#define IMGUI_VERSION_NUM 19272
|
||||
#define IMGUI_VERSION_NUM 19273
|
||||
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
|
||||
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
|
||||
#define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch.
|
||||
|
||||
@@ -11069,8 +11069,9 @@ struct ExampleAssetsBrowser
|
||||
bool AllowDragUnselected = false; // Will set ImGuiMultiSelectFlags_SelectOnClickRelease
|
||||
float IconSize = 0;
|
||||
int IconSpacing = 10;
|
||||
int IconHitSpacing = 4; // Increase hit-spacing if you want to make it possible to clear or box-select from gaps. Some spacing is required to able to amend with Shift+box-select. Value is small in Explorer.
|
||||
int IconHitSpacing = 4; // Increase hit-spacing if you want to make it possible to clear or box-select from gaps. Some spacing is required to able to amend with Shift+box-select. Value is small in Explorer.
|
||||
bool StretchSpacing = true;
|
||||
bool UseScrollX = false; // Debug: submit twice the number of items per line (overflow horizontally to exercise ScrollX + box-select)
|
||||
|
||||
// State
|
||||
ImVector<ExampleAsset> Items; // Our items
|
||||
@@ -11121,12 +11122,15 @@ struct ExampleAssetsBrowser
|
||||
// Layout: calculate number of icon per line and number of lines
|
||||
LayoutItemSize = ImVec2(floorf(IconSize), floorf(IconSize));
|
||||
LayoutColumnCount = IM_MAX((int)(avail_width / (LayoutItemSize.x + LayoutItemSpacing)), 1);
|
||||
LayoutLineCount = (Items.Size + LayoutColumnCount - 1) / LayoutColumnCount;
|
||||
|
||||
// Layout: when stretching: allocate remaining space to more spacing. Round before division, so item_spacing may be non-integer.
|
||||
if (StretchSpacing && LayoutColumnCount > 1)
|
||||
LayoutItemSpacing = floorf(avail_width - LayoutItemSize.x * LayoutColumnCount) / LayoutColumnCount;
|
||||
|
||||
if (UseScrollX)
|
||||
LayoutColumnCount *= 2;
|
||||
LayoutLineCount = (Items.Size + LayoutColumnCount - 1) / LayoutColumnCount;
|
||||
|
||||
LayoutItemStep = ImVec2(LayoutItemSize.x + LayoutItemSpacing, LayoutItemSize.y + LayoutItemSpacing);
|
||||
LayoutSelectableSpacing = IM_MAX(floorf(LayoutItemSpacing) - IconHitSpacing, 0.0f);
|
||||
LayoutOuterPadding = floorf(LayoutItemSpacing * 0.5f);
|
||||
@@ -11186,6 +11190,7 @@ struct ExampleAssetsBrowser
|
||||
ImGui::SliderInt("Icon Spacing", &IconSpacing, 0, 32);
|
||||
ImGui::SliderInt("Icon Hit Spacing", &IconHitSpacing, 0, 32);
|
||||
ImGui::Checkbox("Stretch Spacing", &StretchSpacing);
|
||||
ImGui::Checkbox("Use ScrollX", &UseScrollX);
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -11215,7 +11220,7 @@ struct ExampleAssetsBrowser
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui::SetNextWindowContentSize(ImVec2(0.0f, LayoutOuterPadding + LayoutLineCount * (LayoutItemSize.y + LayoutItemSpacing)));
|
||||
if (ImGui::BeginChild("Assets", ImVec2(0.0f, -ImGui::GetTextLineHeightWithSpacing()), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoMove))
|
||||
if (ImGui::BeginChild("Assets", ImVec2(0.0f, -ImGui::GetTextLineHeightWithSpacing()), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_HorizontalScrollbar))
|
||||
{
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
|
||||
@@ -11359,6 +11364,8 @@ struct ExampleAssetsBrowser
|
||||
}
|
||||
}
|
||||
clipper.End();
|
||||
if (Items.Size == 0)
|
||||
ImGui::Dummy(ImVec2(0, 0));
|
||||
ImGui::PopStyleVar(); // ImGuiStyleVar_ItemSpacing
|
||||
|
||||
// Context menu
|
||||
|
||||
@@ -617,6 +617,8 @@ struct IMGUI_API ImRect
|
||||
bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; }
|
||||
void Add(const ImVec2& p) { if (Min.x > p.x) Min.x = p.x; if (Min.y > p.y) Min.y = p.y; if (Max.x < p.x) Max.x = p.x; if (Max.y < p.y) Max.y = p.y; }
|
||||
void Add(const ImRect& r) { if (Min.x > r.Min.x) Min.x = r.Min.x; if (Min.y > r.Min.y) Min.y = r.Min.y; if (Max.x < r.Max.x) Max.x = r.Max.x; if (Max.y < r.Max.y) Max.y = r.Max.y; }
|
||||
void AddX(float x) { if (Min.x > x) Min.x = x; if (Max.x < x) Max.x = x; }
|
||||
void AddY(float y) { if (Min.y > y) Min.y = y; if (Max.y < y) Max.y = y; }
|
||||
void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; }
|
||||
void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
|
||||
void Translate(const ImVec2& d) { Min.x += d.x; Min.y += d.y; Max.x += d.x; Max.y += d.y; }
|
||||
@@ -1915,6 +1917,7 @@ struct ImGuiBoxSelectState
|
||||
// Temporary/Transient data
|
||||
bool UnclipMode; // (Temp/Transient, here in hot area). Set/cleared by the BeginMultiSelect()/EndMultiSelect() owning active box-select.
|
||||
ImRect UnclipRect; // Rectangle where ItemAdd() clipping may be temporarily disabled. Need support by multi-select supporting widgets.
|
||||
ImRect UnclipRects[2]; // Per-axis versions.
|
||||
ImRect BoxSelectRectPrev; // Selection rectangle in absolute coordinates (derived every frame from BoxSelectStartPosRel and MousePos)
|
||||
ImRect BoxSelectRectCurr;
|
||||
|
||||
@@ -3562,6 +3565,7 @@ namespace ImGui
|
||||
|
||||
// Childs
|
||||
IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags);
|
||||
IMGUI_API ImGuiWindow* FindFrontMostVisibleChildWindow(ImGuiWindow* window);
|
||||
|
||||
// Popups, Modals
|
||||
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags);
|
||||
@@ -3770,6 +3774,7 @@ namespace ImGui
|
||||
// We don't use the ID Stack for this as it is common to want them separate.
|
||||
IMGUI_API void PushFocusScope(ImGuiID id);
|
||||
IMGUI_API void PopFocusScope();
|
||||
IMGUI_API bool IsInNavFocusRoute(ImGuiID focus_scope_id);
|
||||
inline ImGuiID GetCurrentFocusScope() { ImGuiContext& g = *GImGui; return g.CurrentFocusScopeId; } // Focus scope we are outputting into, set by PushFocusScope()
|
||||
|
||||
// Drag and Drop
|
||||
|
||||
@@ -1330,6 +1330,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
// When starting a BeginMultiSelect() after table has been layout we update IsRequestOutput fields.
|
||||
void ImGui::TableApplyExternalUnclipRect(ImGuiTable* table, ImRect& rect)
|
||||
{
|
||||
if (rect.IsInverted())
|
||||
return;
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
{
|
||||
ImGuiTableColumn* column = &table->Columns[column_n];
|
||||
@@ -3311,6 +3313,8 @@ void ImGui::TableHeader(const char* label)
|
||||
// We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden
|
||||
if (IsPopupOpenRequestForItem(ImGuiPopupFlags_None, id))
|
||||
TableOpenContextMenu(column_n);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
}
|
||||
|
||||
// Unlike TableHeadersRow() it is not expected that you can reimplement or customize this with custom widgets.
|
||||
|
||||
@@ -1565,7 +1565,7 @@ bool ImGui::TextLink(const char* label)
|
||||
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf), 1.0f * (float)(int)g.Style._MainScale); // FIXME-TEXT: Underline mode // FIXME-DPI
|
||||
|
||||
PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf));
|
||||
RenderText(bb.Min, label, label_end);
|
||||
RenderText(bb.Min, label, label_end, false);
|
||||
PopStyleColor();
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
@@ -1957,7 +1957,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
|
||||
const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const float preview_width = ((flags & ImGuiComboFlags_WidthFitPreview) && (preview_value != NULL)) ? CalcTextSize(preview_value, NULL, true).x : 0.0f;
|
||||
const float preview_width = ((flags & ImGuiComboFlags_WidthFitPreview) && (preview_value != NULL)) ? CalcTextSize(preview_value, NULL, false).x : 0.0f;
|
||||
const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : ((flags & ImGuiComboFlags_WidthFitPreview) ? (arrow_size + preview_width + style.FramePadding.x * 2.0f) : CalcItemWidth());
|
||||
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
|
||||
const ImRect total_bb(bb.Min, bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
|
||||
@@ -3549,6 +3549,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@@ -7514,8 +7515,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
RenderTextClipped(pos, ImVec2(ImMin(pos.x + size.x, window->WorkRect.Max.x), pos.y + size.y), label, label_end, &label_size, style.SelectableTextAlign, &bb);
|
||||
|
||||
#ifdef IMGUI_DEBUG_BOXSELECT
|
||||
if (g.BoxSelectState.UnclipMode)
|
||||
GetForegroundDrawList()->AddText(pos, IM_COL32(255,255,0,200), label);
|
||||
if (g.BoxSelectState.UnclipMode) { GetForegroundDrawList()->AddText(pos, IM_COL32(255,255,0,200), label, label_end); }
|
||||
#endif
|
||||
|
||||
// Automatically close popups
|
||||
@@ -7833,7 +7833,7 @@ bool ImGui::BeginBoxSelect(const ImRect& scope_rect, ImGuiWindow* window, ImGuiI
|
||||
return false;
|
||||
|
||||
// Current frame absolute prev/current rectangles are used to toggle selection.
|
||||
// They are derived from positions relative to scrolling space.
|
||||
// They are derived from positions relative to scrolling space, so "previous" rectangle is reprojected for current frame coordinates.
|
||||
ImVec2 start_pos_abs = WindowPosRelToAbs(window, bs->StartPosRel);
|
||||
ImVec2 prev_end_pos_abs = WindowPosRelToAbs(window, bs->EndPosRel); // Clamped already
|
||||
ImVec2 curr_end_pos_abs = g.IO.MousePos;
|
||||
@@ -7843,26 +7843,68 @@ bool ImGui::BeginBoxSelect(const ImRect& scope_rect, ImGuiWindow* window, ImGuiI
|
||||
bs->BoxSelectRectPrev.Max = ImMax(start_pos_abs, prev_end_pos_abs);
|
||||
bs->BoxSelectRectCurr.Min = ImMin(start_pos_abs, curr_end_pos_abs);
|
||||
bs->BoxSelectRectCurr.Max = ImMax(start_pos_abs, curr_end_pos_abs);
|
||||
//IMGUI_DEBUG_LOG("StartPosRel (%.2f,%.2f) EndPosRel (%.2f,%.2f) -> (%.2f,%.2f)\n", bs->StartPosRel.x, bs->StartPosRel.y, bs->EndPosRel.x, bs->EndPosRel.y, WindowPosAbsToRel(window, g.IO.MousePos).x, WindowPosAbsToRel(window, g.IO.MousePos).y);
|
||||
|
||||
// Box-select 2D mode detects change of the rectangle.
|
||||
// Storing unclip rect used by widgets supporting box-select.
|
||||
if (ms_flags & ImGuiMultiSelectFlags_BoxSelect2d)
|
||||
// Storing unclip rects which will be tested by widgets supporting box-select. Always update rectangles when active (even if we don't use them).
|
||||
// To facilitate understanding this: enable IMGUI_DEBUG_BOXSELECT and visualize all geometry.
|
||||
if (ms_flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
||||
{
|
||||
if (bs->BoxSelectRectPrev.Min != bs->BoxSelectRectCurr.Min || bs->BoxSelectRectPrev.Max != bs->BoxSelectRectCurr.Max)
|
||||
bs->UnclipMode = true;
|
||||
// For both sides, compute the area differing between Prev and Curr rectangles.
|
||||
bs->UnclipRects[0] = bs->UnclipRects[1] = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
for (int side = 0; side < 2; side++)
|
||||
{
|
||||
ImVec2 d_min = (side == 0) ? ImMin(bs->BoxSelectRectCurr.Min, bs->BoxSelectRectPrev.Min) : ImMin(bs->BoxSelectRectCurr.Max, bs->BoxSelectRectPrev.Max);
|
||||
ImVec2 d_max = (side == 0) ? ImMax(bs->BoxSelectRectCurr.Min, bs->BoxSelectRectPrev.Min) : ImMax(bs->BoxSelectRectCurr.Max, bs->BoxSelectRectPrev.Max);
|
||||
if (d_min.x != d_max.x)
|
||||
{
|
||||
bs->UnclipRects[0].AddX(d_min.x);
|
||||
bs->UnclipRects[0].AddX(d_max.x);
|
||||
}
|
||||
if (d_min.y != d_max.y)
|
||||
{
|
||||
bs->UnclipRects[1].AddY(d_min.y);
|
||||
bs->UnclipRects[1].AddY(d_max.y);
|
||||
}
|
||||
}
|
||||
|
||||
// Always update rect even if we don't use it.
|
||||
bs->UnclipRect = bs->BoxSelectRectPrev; // FIXME-OPT: UnclipRect X coordinates could be intersection of Prev and Curr rect on X axis.
|
||||
bs->UnclipRect.Add(bs->BoxSelectRectCurr);
|
||||
ImRect box_select_intersection = bs->BoxSelectRectPrev;
|
||||
box_select_intersection.Add(bs->BoxSelectRectCurr);
|
||||
if (ms_flags & ImGuiMultiSelectFlags_BoxSelect2d)
|
||||
if (bs->BoxSelectRectPrev.Min.x != bs->BoxSelectRectCurr.Min.x || bs->BoxSelectRectPrev.Max.x != bs->BoxSelectRectCurr.Max.x)
|
||||
{
|
||||
bs->UnclipRects[0].AddY(box_select_intersection.Min.y);
|
||||
bs->UnclipRects[0].AddY(box_select_intersection.Max.y);
|
||||
}
|
||||
if (ms_flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
||||
if (bs->BoxSelectRectPrev.Min.y != bs->BoxSelectRectCurr.Min.y || bs->BoxSelectRectPrev.Max.y != bs->BoxSelectRectCurr.Max.y)
|
||||
{
|
||||
bs->UnclipRects[1].AddX(box_select_intersection.Min.x);
|
||||
bs->UnclipRects[1].AddX(box_select_intersection.Max.x);
|
||||
}
|
||||
|
||||
// Merge both rectangles into one.
|
||||
// FIXME-OPT: When UnclipRect.Area() is much larger than the sum of UnclipRects[0]/[1] Areas, widgets should
|
||||
// ideally first use UnclipRect as a first coarse cull layer + the individual ones as a second validation.
|
||||
bs->UnclipRect = bs->UnclipRects[0];
|
||||
bs->UnclipRect.Add(bs->UnclipRects[1]);
|
||||
if (!bs->UnclipRect.IsInverted() && (!window->ClipRect.Contains(bs->UnclipRect.Min) || !window->ClipRect.Contains(bs->UnclipRect.Max))) // !! Don't use Contains(ImRect)
|
||||
bs->UnclipMode = true;
|
||||
if (bs->UnclipMode && g.CurrentTable != NULL)
|
||||
TableApplyExternalUnclipRect(g.CurrentTable, bs->UnclipRect); // No need submitting both
|
||||
}
|
||||
if (bs->UnclipMode && g.CurrentTable != NULL)
|
||||
TableApplyExternalUnclipRect(g.CurrentTable, bs->UnclipRect);
|
||||
|
||||
#ifdef IMGUI_DEBUG_BOXSELECT
|
||||
if (ms_flags & ImGuiMultiSelectFlags_BoxSelect2d)
|
||||
GetForegroundDrawList()->AddRect(bs->UnclipRect.Min, bs->UnclipRect.Max, bs->UnclipMode ? IM_COL32(255,255,0,200) : IM_COL32(255,0,0,200), 0.0f, 0, 4.0f);
|
||||
//GetForegroundDrawList()->AddRect(scope_rect.Min, scope_rect.Max, IM_COL32(0, 255, 0, 200), 0.0f, 0, 4.0f);
|
||||
//GetForegroundDrawList()->AddRect(bs->BoxSelectRectPrev.Min, bs->BoxSelectRectPrev.Max, IM_COL32(255,0,0,200), 0.0f, 0, 3.0f);
|
||||
//GetForegroundDrawList()->AddRect(bs->BoxSelectRectCurr.Min, bs->BoxSelectRectCurr.Max, IM_COL32(0,255,0,200), 0.0f, 0, 1.0f);
|
||||
if (ms_flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
||||
{
|
||||
for (ImRect& unclip_r : bs->UnclipRects)
|
||||
if (!unclip_r.IsInverted())
|
||||
GetForegroundDrawList()->AddRect(unclip_r.Min, unclip_r.Max, bs->UnclipMode ? IM_COL32(255, 255, 0, 200) : IM_COL32(255, 0, 0, 200), 0.0f, 0, 4.0f);
|
||||
GetForegroundDrawList()->AddRect(bs->UnclipRect.Min, bs->UnclipRect.Max, bs->UnclipMode ? IM_COL32(255, 255, 0, 200) : IM_COL32(255, 0, 0, 200), 0.0f, 0, 2.0f);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@@ -7879,8 +7921,9 @@ void ImGui::EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flag
|
||||
bs->EndPosRel = WindowPosAbsToRel(window, ImClamp(g.IO.MousePos, scope_rect.Min, scope_rect.Max)); // Clamp stored position according to current scrolling view
|
||||
ImRect box_select_r = bs->BoxSelectRectCurr;
|
||||
box_select_r.ClipWith(scope_rect);
|
||||
window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
|
||||
window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT FIXME-DPI: Styling
|
||||
ImGuiWindow* draw_window = FindFrontMostVisibleChildWindow(window);
|
||||
draw_window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
|
||||
draw_window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT FIXME-DPI: Styling
|
||||
|
||||
// Scroll
|
||||
const bool enable_scroll = (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) && (ms_flags & ImGuiMultiSelectFlags_BoxSelectNoScroll) == 0;
|
||||
@@ -7920,7 +7963,6 @@ static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSe
|
||||
|
||||
static ImRect CalcScopeRect(ImGuiMultiSelectTempData* ms, ImGuiWindow* window)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (ms->Flags & ImGuiMultiSelectFlags_ScopeRect)
|
||||
{
|
||||
// Warning: this depends on CursorMaxPos so it means to be called by EndMultiSelect() only
|
||||
@@ -7929,10 +7971,10 @@ static ImRect CalcScopeRect(ImGuiMultiSelectTempData* ms, ImGuiWindow* window)
|
||||
}
|
||||
else
|
||||
{
|
||||
// When a table, pull HostClipRect, which allows us to predict ClipRect before first row/layout is performed. (#7970)
|
||||
//// When a table, pull HostClipRect, which allows us to predict ClipRect before first row/layout is performed. (#7970)
|
||||
ImRect scope_rect = window->InnerClipRect;
|
||||
if (g.CurrentTable != NULL)
|
||||
scope_rect = g.CurrentTable->HostClipRect;
|
||||
//if (g.CurrentTable != NULL)
|
||||
// scope_rect = g.CurrentTable->HostClipRect;
|
||||
|
||||
// Add inner table decoration (#7821) // FIXME: Why not baking in InnerClipRect?
|
||||
scope_rect.Min = ImMin(scope_rect.Min + ImVec2(window->DecoInnerSizeX1, window->DecoInnerSizeY1), scope_rect.Max);
|
||||
@@ -7980,10 +8022,12 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel
|
||||
ms->Clear();
|
||||
ms->FocusScopeId = id;
|
||||
ms->Flags = flags;
|
||||
ms->IsFocused = (ms->FocusScopeId == g.NavFocusScopeId);
|
||||
ms->BackupCursorMaxPos = window->DC.CursorMaxPos;
|
||||
ms->ScopeRectMin = window->DC.CursorMaxPos = window->DC.CursorPos; // CalcScopeRect() for ImGuiMultiSelectFlags_ScopeRect will measure in EndMultiSelect().
|
||||
ms->ScopeRectMin = window->DC.CursorPos;
|
||||
if (flags & ImGuiMultiSelectFlags_ScopeRect)
|
||||
window->DC.CursorMaxPos = ms->ScopeRectMin; // CalcScopeRect() for ImGuiMultiSelectFlags_ScopeRect will measure in EndMultiSelect().
|
||||
PushFocusScope(ms->FocusScopeId);
|
||||
ms->IsFocused = IsInNavFocusRoute(g.CurrentFocusScopeId);
|
||||
if (flags & ImGuiMultiSelectFlags_ScopeWindow) // Mark parent child window as navigable into, with highlight. Assume user will always submit interactive items.
|
||||
window->DC.NavLayersActiveMask |= 1 << ImGuiNavLayer_Main;
|
||||
|
||||
@@ -8111,7 +8155,7 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
|
||||
// Clear selection when clicking void?
|
||||
// We specifically test for IsMouseDragPastThreshold(0) == false to allow box-selection!
|
||||
// The InnerRect test is necessary for non-child/decorated windows.
|
||||
bool scope_hovered = IsWindowHovered() && window->InnerRect.Contains(g.IO.MousePos);
|
||||
bool scope_hovered = window->InnerRect.Contains(g.IO.MousePos) && IsWindowHovered(ImGuiHoveredFlags_ChildWindows);
|
||||
if (scope_hovered && (ms->Flags & ImGuiMultiSelectFlags_ScopeRect))
|
||||
scope_hovered &= scope_rect.Contains(g.IO.MousePos);
|
||||
if (scope_hovered && g.HoveredId == 0 && g.ActiveId == 0)
|
||||
@@ -8321,8 +8365,19 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
||||
if (ms->BoxSelectId != 0)
|
||||
if (ImGuiBoxSelectState* bs = GetBoxSelectState(ms->BoxSelectId))
|
||||
{
|
||||
const bool rect_overlap_curr = bs->BoxSelectRectCurr.Overlaps(g.LastItemData.Rect);
|
||||
const bool rect_overlap_prev = bs->BoxSelectRectPrev.Overlaps(g.LastItemData.Rect);
|
||||
ImRect item_rect = g.LastItemData.Rect;
|
||||
if (!window->DC.NavIsScrollPushableX) // FIXME: Rename to be more generic.
|
||||
if (ImGuiTable* table = g.CurrentTable)
|
||||
if (table->CurrentColumn != -1)
|
||||
{
|
||||
// FIXME: We cannot use current ClipRect as it includes HostClipRect.
|
||||
// A more generic version would be nice, but window->WorkRect.Min/Max exclude CellPadding. (#7994)
|
||||
ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];
|
||||
item_rect.Min.x = ImMax(item_rect.Min.x, column->MinX);
|
||||
item_rect.Max.x = ImMin(item_rect.Max.x, column->MaxX);
|
||||
}
|
||||
const bool rect_overlap_curr = bs->BoxSelectRectCurr.Overlaps(item_rect);
|
||||
const bool rect_overlap_prev = bs->BoxSelectRectPrev.Overlaps(item_rect);
|
||||
if ((rect_overlap_curr && !rect_overlap_prev && !selected) || (rect_overlap_prev && !rect_overlap_curr))
|
||||
{
|
||||
if (storage->LastSelectionSize <= 0 && bs->IsStartedSetNavIdOnce)
|
||||
@@ -8940,6 +8995,7 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
|
||||
|
||||
// Return hovered index or -1 if none are hovered.
|
||||
// This is currently not exposed in the public API because we need a larger redesign of the whole thing, but in the short-term we are making it available in PlotEx().
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
return idx_hovered;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user