|
@@ -2538,11 +2538,9 @@ void ImGuiStorage::SetInt(ImGuiID key, int val)
|
|
|
{
|
|
|
ImGuiStoragePair* it = LowerBound(Data, key);
|
|
|
if (it == Data.end() || it->key != key)
|
|
|
- {
|
|
|
Data.insert(it, ImGuiStoragePair(key, val));
|
|
|
- return;
|
|
|
- }
|
|
|
- it->val_i = val;
|
|
|
+ else
|
|
|
+ it->val_i = val;
|
|
|
}
|
|
|
|
|
|
void ImGuiStorage::SetBool(ImGuiID key, bool val)
|
|
@@ -2554,22 +2552,18 @@ void ImGuiStorage::SetFloat(ImGuiID key, float val)
|
|
|
{
|
|
|
ImGuiStoragePair* it = LowerBound(Data, key);
|
|
|
if (it == Data.end() || it->key != key)
|
|
|
- {
|
|
|
Data.insert(it, ImGuiStoragePair(key, val));
|
|
|
- return;
|
|
|
- }
|
|
|
- it->val_f = val;
|
|
|
+ else
|
|
|
+ it->val_f = val;
|
|
|
}
|
|
|
|
|
|
void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val)
|
|
|
{
|
|
|
ImGuiStoragePair* it = LowerBound(Data, key);
|
|
|
if (it == Data.end() || it->key != key)
|
|
|
- {
|
|
|
Data.insert(it, ImGuiStoragePair(key, val));
|
|
|
- return;
|
|
|
- }
|
|
|
- it->val_p = val;
|
|
|
+ else
|
|
|
+ it->val_p = val;
|
|
|
}
|
|
|
|
|
|
void ImGuiStorage::SetAllInt(int v)
|
|
@@ -4098,13 +4092,21 @@ bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flag
|
|
|
static inline float CalcDelayFromHoveredFlags(ImGuiHoveredFlags flags)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- if (flags & ImGuiHoveredFlags_DelayShort)
|
|
|
- return g.Style.HoverDelayShort;
|
|
|
if (flags & ImGuiHoveredFlags_DelayNormal)
|
|
|
return g.Style.HoverDelayNormal;
|
|
|
+ if (flags & ImGuiHoveredFlags_DelayShort)
|
|
|
+ return g.Style.HoverDelayShort;
|
|
|
return 0.0f;
|
|
|
}
|
|
|
|
|
|
+static ImGuiHoveredFlags ApplyHoverFlagsForTooltip(ImGuiHoveredFlags user_flags, ImGuiHoveredFlags shared_flags)
|
|
|
+{
|
|
|
+ // Allow instance flags to override shared flags
|
|
|
+ if (user_flags & (ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal))
|
|
|
+ shared_flags &= ~(ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal);
|
|
|
+ return user_flags | shared_flags;
|
|
|
+}
|
|
|
+
|
|
|
// This is roughly matching the behavior of internal-facing ItemHoverable()
|
|
|
// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()
|
|
|
// - this should work even for non-interactive items that have no ID, so we cannot use LastItemId
|
|
@@ -4122,7 +4124,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
|
|
|
return false;
|
|
|
|
|
|
if (flags & ImGuiHoveredFlags_ForTooltip)
|
|
|
- flags |= g.Style.HoverFlagsForTooltipNav;
|
|
|
+ flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipNav);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -4132,7 +4134,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
|
|
|
return false;
|
|
|
|
|
|
if (flags & ImGuiHoveredFlags_ForTooltip)
|
|
|
- flags |= g.Style.HoverFlagsForTooltipMouse;
|
|
|
+ flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipMouse);
|
|
|
|
|
|
IM_ASSERT((flags & (ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy | ImGuiHoveredFlags_DockHierarchy)) == 0); // Flags not supported by this function
|
|
|
|
|
@@ -5686,18 +5688,28 @@ ImVec2 ImGui::GetItemRectSize()
|
|
|
return g.LastItemData.Rect.GetSize();
|
|
|
}
|
|
|
|
|
|
-bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags)
|
|
|
+bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags)
|
|
|
+{
|
|
|
+ ImGuiID id = GetCurrentWindow()->GetID(str_id);
|
|
|
+ return BeginChildEx(str_id, id, size_arg, border, window_flags);
|
|
|
+}
|
|
|
+
|
|
|
+bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags)
|
|
|
+{
|
|
|
+ IM_ASSERT(id != 0);
|
|
|
+ return BeginChildEx(NULL, id, size_arg, border, window_flags);
|
|
|
+}
|
|
|
+
|
|
|
+bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiWindow* parent_window = g.CurrentWindow;
|
|
|
-
|
|
|
- flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoDocking;
|
|
|
- flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
|
|
|
+ window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoDocking;
|
|
|
+ window_flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
|
|
|
|
|
|
// Size
|
|
|
const ImVec2 content_avail = GetContentRegionAvail();
|
|
|
ImVec2 size = ImTrunc(size_arg);
|
|
|
- const int auto_fit_axises = ((size.x == 0.0f) ? (1 << ImGuiAxis_X) : 0x00) | ((size.y == 0.0f) ? (1 << ImGuiAxis_Y) : 0x00);
|
|
|
if (size.x <= 0.0f)
|
|
|
size.x = ImMax(content_avail.x + size.x, 4.0f); // Arbitrary minimum child size (0.0f causing too many issues)
|
|
|
if (size.y <= 0.0f)
|
|
@@ -5714,12 +5726,13 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
|
|
|
const float backup_border_size = g.Style.ChildBorderSize;
|
|
|
if (!border)
|
|
|
g.Style.ChildBorderSize = 0.0f;
|
|
|
- bool ret = Begin(temp_window_name, NULL, flags);
|
|
|
+
|
|
|
+ // Begin into window
|
|
|
+ const bool ret = Begin(temp_window_name, NULL, window_flags);
|
|
|
g.Style.ChildBorderSize = backup_border_size;
|
|
|
|
|
|
ImGuiWindow* child_window = g.CurrentWindow;
|
|
|
child_window->ChildId = id;
|
|
|
- child_window->AutoFitChildAxises = (ImS8)auto_fit_axises;
|
|
|
|
|
|
// Set the cursor to handle case where the user called SetNextWindowPos()+BeginChild() manually.
|
|
|
// While this is not really documented/defined, it seems that the expected thing to do.
|
|
@@ -5727,11 +5740,11 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
|
|
|
parent_window->DC.CursorPos = child_window->Pos;
|
|
|
|
|
|
// Process navigation-in immediately so NavInit can run on first frame
|
|
|
- // Can enter a child if (A) it has navigatable items or (B) it can be scrolled.
|
|
|
+ // Can enter a child if (A) it has navigable items or (B) it can be scrolled.
|
|
|
const ImGuiID temp_id_for_activation = ImHashStr("##Child", 0, id);
|
|
|
if (g.ActiveId == temp_id_for_activation)
|
|
|
ClearActiveID();
|
|
|
- if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY))
|
|
|
+ if (g.NavActivateId == id && !(window_flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY))
|
|
|
{
|
|
|
FocusWindow(child_window);
|
|
|
NavInitWindow(child_window, false);
|
|
@@ -5741,50 +5754,29 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
|
|
|
-{
|
|
|
- ImGuiWindow* window = GetCurrentWindow();
|
|
|
- return BeginChildEx(str_id, window->GetID(str_id), size_arg, border, extra_flags);
|
|
|
-}
|
|
|
-
|
|
|
-bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
|
|
|
-{
|
|
|
- IM_ASSERT(id != 0);
|
|
|
- return BeginChildEx(NULL, id, size_arg, border, extra_flags);
|
|
|
-}
|
|
|
-
|
|
|
void ImGui::EndChild()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- ImGuiWindow* window = g.CurrentWindow;
|
|
|
+ ImGuiWindow* child_window = g.CurrentWindow;
|
|
|
|
|
|
IM_ASSERT(g.WithinEndChild == false);
|
|
|
- IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() calls
|
|
|
+ IM_ASSERT(child_window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() calls
|
|
|
|
|
|
g.WithinEndChild = true;
|
|
|
- if (window->BeginCount > 1)
|
|
|
- {
|
|
|
- End();
|
|
|
- }
|
|
|
- else
|
|
|
+ ImVec2 child_size = child_window->Size;
|
|
|
+ End();
|
|
|
+ if (child_window->BeginCount == 1)
|
|
|
{
|
|
|
- ImVec2 sz = window->Size;
|
|
|
- if (window->AutoFitChildAxises & (1 << ImGuiAxis_X)) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f
|
|
|
- sz.x = ImMax(4.0f, sz.x);
|
|
|
- if (window->AutoFitChildAxises & (1 << ImGuiAxis_Y))
|
|
|
- sz.y = ImMax(4.0f, sz.y);
|
|
|
- End();
|
|
|
-
|
|
|
ImGuiWindow* parent_window = g.CurrentWindow;
|
|
|
- ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz);
|
|
|
- ItemSize(sz);
|
|
|
- if ((window->DC.NavLayersActiveMask != 0 || window->DC.NavWindowHasScrollY) && !(window->Flags & ImGuiWindowFlags_NavFlattened))
|
|
|
+ ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + child_size);
|
|
|
+ ItemSize(child_size);
|
|
|
+ if ((child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY) && !(child_window->Flags & ImGuiWindowFlags_NavFlattened))
|
|
|
{
|
|
|
- ItemAdd(bb, window->ChildId);
|
|
|
- RenderNavHighlight(bb, window->ChildId);
|
|
|
+ ItemAdd(bb, child_window->ChildId);
|
|
|
+ RenderNavHighlight(bb, child_window->ChildId);
|
|
|
|
|
|
// When browsing a window that has no activable items (scroll only) we keep a highlight on the child (pass g.NavId to trick into always displaying)
|
|
|
- if (window->DC.NavLayersActiveMask == 0 && window == g.NavWindow)
|
|
|
+ if (child_window->DC.NavLayersActiveMask == 0 && child_window == g.NavWindow)
|
|
|
RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_TypeThin);
|
|
|
}
|
|
|
else
|
|
@@ -5793,10 +5785,10 @@ void ImGui::EndChild()
|
|
|
ItemAdd(bb, 0);
|
|
|
|
|
|
// But when flattened we directly reach items, adjust active layer mask accordingly
|
|
|
- if (window->Flags & ImGuiWindowFlags_NavFlattened)
|
|
|
- parent_window->DC.NavLayersActiveMaskNext |= window->DC.NavLayersActiveMaskNext;
|
|
|
+ if (child_window->Flags & ImGuiWindowFlags_NavFlattened)
|
|
|
+ parent_window->DC.NavLayersActiveMaskNext |= child_window->DC.NavLayersActiveMaskNext;
|
|
|
}
|
|
|
- if (g.HoveredWindow == window)
|
|
|
+ if (g.HoveredWindow == child_window)
|
|
|
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
|
|
|
}
|
|
|
g.WithinEndChild = false;
|
|
@@ -6202,7 +6194,7 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
|
|
|
if (hovered || held)
|
|
|
g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;
|
|
|
|
|
|
- if (held && g.IO.MouseClickedCount[0] == 2 && resize_grip_n == 0)
|
|
|
+ if (held && g.IO.MouseClickedCount[0] == 2)
|
|
|
{
|
|
|
// Manual auto-fit when double-clicking
|
|
|
size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit);
|
|
@@ -6731,7 +6723,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
window->IDStack.push_back(window->ID);
|
|
|
|
|
|
// Add to stack
|
|
|
- // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
|
|
|
g.CurrentWindow = window;
|
|
|
ImGuiWindowStackData window_stack_data;
|
|
|
window_stack_data.Window = window;
|
|
@@ -6749,6 +6740,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
}
|
|
|
|
|
|
// Add to focus scope stack
|
|
|
+ // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
|
|
|
PushFocusScope(window->ID);
|
|
|
window->NavRootFocusScopeId = g.CurrentFocusScopeId;
|
|
|
g.CurrentWindow = NULL;
|
|
@@ -7934,7 +7926,7 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
|
|
|
// for different windows of the hierarchy. Possibly need a Hash(Current+Flags) ==> (Timer) cache.
|
|
|
// We can implement this for _Stationary because the data is linked to HoveredWindow rather than CurrentWindow.
|
|
|
if (flags & ImGuiHoveredFlags_ForTooltip)
|
|
|
- flags |= g.Style.HoverFlagsForTooltipMouse;
|
|
|
+ flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipMouse);
|
|
|
if ((flags & ImGuiHoveredFlags_Stationary) != 0 && g.HoverWindowUnlockedStationaryId != ref_window->ID)
|
|
|
return false;
|
|
|
|
|
@@ -9758,16 +9750,10 @@ void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
|
|
|
+// This is equivalent to comparing KeyMods + doing a IsKeyPressed()
|
|
|
+bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
-
|
|
|
- // When using (owner_id == 0/Any): SetShortcutRouting() will use CurrentFocusScopeId and filter with this, so IsKeyPressed() is fine with he 0/Any.
|
|
|
- if ((flags & ImGuiInputFlags_RouteMask_) == 0)
|
|
|
- flags |= ImGuiInputFlags_RouteFocused;
|
|
|
- if (!SetShortcutRouting(key_chord, owner_id, flags))
|
|
|
- return false;
|
|
|
-
|
|
|
if (key_chord & ImGuiMod_Shortcut)
|
|
|
key_chord = ConvertShortcutMod(key_chord);
|
|
|
ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
|
|
@@ -9778,11 +9764,22 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags
|
|
|
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
|
|
|
if (key == ImGuiKey_None)
|
|
|
key = ConvertSingleModFlagToKey(&g, mods);
|
|
|
-
|
|
|
if (!IsKeyPressed(key, owner_id, (flags & (ImGuiInputFlags_Repeat | (ImGuiInputFlags)ImGuiInputFlags_RepeatRateMask_))))
|
|
|
return false;
|
|
|
- IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0); // Passing flags not supported by this function!
|
|
|
+ return true;
|
|
|
+}
|
|
|
|
|
|
+bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
|
|
|
+{
|
|
|
+ // When using (owner_id == 0/Any): SetShortcutRouting() will use CurrentFocusScopeId and filter with this, so IsKeyPressed() is fine with he 0/Any.
|
|
|
+ if ((flags & ImGuiInputFlags_RouteMask_) == 0)
|
|
|
+ flags |= ImGuiInputFlags_RouteFocused;
|
|
|
+ if (!SetShortcutRouting(key_chord, owner_id, flags))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (!IsKeyChordPressed(key_chord, owner_id, flags))
|
|
|
+ return false;
|
|
|
+ IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0); // Passing flags not supported by this function!
|
|
|
return true;
|
|
|
}
|
|
|
|