|
|
@@ -1,4 +1,4 @@
|
|
|
-// dear imgui, v1.90.7
|
|
|
+// dear imgui, v1.90.9 WIP
|
|
|
// (main code and documentation)
|
|
|
|
|
|
// Help:
|
|
|
@@ -430,6 +430,9 @@ CODE
|
|
|
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
|
|
|
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
|
|
|
|
|
|
+ - 2024/06/10 (1.90.9) - removed old nested structure: renaming ImGuiStorage::ImGuiStoragePair type to ImGuiStoragePair (simpler for many languages).
|
|
|
+ - 2024/06/06 (1.90.8) - reordered ImGuiInputTextFlags values. This should not be breaking unless you are using generated headers that have values not matching the main library.
|
|
|
+ - 2024/06/06 (1.90.8) - removed 'ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft', was mostly unused and misleading.
|
|
|
- 2024/05/27 (1.90.7) - commented out obsolete symbols marked obsolete in 1.88 (May 2022):
|
|
|
- old: CaptureKeyboardFromApp(bool)
|
|
|
- new: SetNextFrameWantCaptureKeyboard(bool)
|
|
|
@@ -2502,18 +2505,16 @@ void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float&
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
// std::lower_bound but without the bullshit
|
|
|
-static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector<ImGuiStorage::ImGuiStoragePair>& data, ImGuiID key)
|
|
|
+ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_end, ImGuiID key)
|
|
|
{
|
|
|
- ImGuiStorage::ImGuiStoragePair* first = data.Data;
|
|
|
- ImGuiStorage::ImGuiStoragePair* last = data.Data + data.Size;
|
|
|
- size_t count = (size_t)(last - first);
|
|
|
- while (count > 0)
|
|
|
+ ImGuiStoragePair* in_p = in_begin;
|
|
|
+ for (size_t count = (size_t)(in_end - in_p); count > 0; )
|
|
|
{
|
|
|
size_t count2 = count >> 1;
|
|
|
- ImGuiStorage::ImGuiStoragePair* mid = first + count2;
|
|
|
+ ImGuiStoragePair* mid = in_p + count2;
|
|
|
if (mid->key < key)
|
|
|
{
|
|
|
- first = ++mid;
|
|
|
+ in_p = ++mid;
|
|
|
count -= count2 + 1;
|
|
|
}
|
|
|
else
|
|
|
@@ -2521,7 +2522,7 @@ static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector<ImGuiStorage::ImGuiSt
|
|
|
count = count2;
|
|
|
}
|
|
|
}
|
|
|
- return first;
|
|
|
+ return in_p;
|
|
|
}
|
|
|
|
|
|
// For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once.
|
|
|
@@ -2542,7 +2543,7 @@ void ImGuiStorage::BuildSortByKey()
|
|
|
|
|
|
int ImGuiStorage::GetInt(ImGuiID key, int default_val) const
|
|
|
{
|
|
|
- ImGuiStoragePair* it = LowerBound(const_cast<ImVector<ImGuiStoragePair>&>(Data), key);
|
|
|
+ ImGuiStoragePair* it = ImLowerBound(const_cast<ImGuiStoragePair*>(Data.Data), const_cast<ImGuiStoragePair*>(Data.Data + Data.Size), key);
|
|
|
if (it == Data.end() || it->key != key)
|
|
|
return default_val;
|
|
|
return it->val_i;
|
|
|
@@ -2555,7 +2556,7 @@ bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const
|
|
|
|
|
|
float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const
|
|
|
{
|
|
|
- ImGuiStoragePair* it = LowerBound(const_cast<ImVector<ImGuiStoragePair>&>(Data), key);
|
|
|
+ ImGuiStoragePair* it = ImLowerBound(const_cast<ImGuiStoragePair*>(Data.Data), const_cast<ImGuiStoragePair*>(Data.Data + Data.Size), key);
|
|
|
if (it == Data.end() || it->key != key)
|
|
|
return default_val;
|
|
|
return it->val_f;
|
|
|
@@ -2563,7 +2564,7 @@ float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const
|
|
|
|
|
|
void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
|
|
|
{
|
|
|
- ImGuiStoragePair* it = LowerBound(const_cast<ImVector<ImGuiStoragePair>&>(Data), key);
|
|
|
+ ImGuiStoragePair* it = ImLowerBound(const_cast<ImGuiStoragePair*>(Data.Data), const_cast<ImGuiStoragePair*>(Data.Data + Data.Size), key);
|
|
|
if (it == Data.end() || it->key != key)
|
|
|
return NULL;
|
|
|
return it->val_p;
|
|
|
@@ -2572,7 +2573,7 @@ void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
|
|
|
// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
|
|
|
int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
|
|
|
{
|
|
|
- ImGuiStoragePair* it = LowerBound(Data, key);
|
|
|
+ ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
|
|
|
if (it == Data.end() || it->key != key)
|
|
|
it = Data.insert(it, ImGuiStoragePair(key, default_val));
|
|
|
return &it->val_i;
|
|
|
@@ -2585,7 +2586,7 @@ bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val)
|
|
|
|
|
|
float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
|
|
|
{
|
|
|
- ImGuiStoragePair* it = LowerBound(Data, key);
|
|
|
+ ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
|
|
|
if (it == Data.end() || it->key != key)
|
|
|
it = Data.insert(it, ImGuiStoragePair(key, default_val));
|
|
|
return &it->val_f;
|
|
|
@@ -2593,7 +2594,7 @@ float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
|
|
|
|
|
|
void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
|
|
|
{
|
|
|
- ImGuiStoragePair* it = LowerBound(Data, key);
|
|
|
+ ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
|
|
|
if (it == Data.end() || it->key != key)
|
|
|
it = Data.insert(it, ImGuiStoragePair(key, default_val));
|
|
|
return &it->val_p;
|
|
|
@@ -2602,7 +2603,7 @@ void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
|
|
|
// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame)
|
|
|
void ImGuiStorage::SetInt(ImGuiID key, int val)
|
|
|
{
|
|
|
- ImGuiStoragePair* it = LowerBound(Data, key);
|
|
|
+ ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
|
|
|
if (it == Data.end() || it->key != key)
|
|
|
Data.insert(it, ImGuiStoragePair(key, val));
|
|
|
else
|
|
|
@@ -2616,7 +2617,7 @@ void ImGuiStorage::SetBool(ImGuiID key, bool val)
|
|
|
|
|
|
void ImGuiStorage::SetFloat(ImGuiID key, float val)
|
|
|
{
|
|
|
- ImGuiStoragePair* it = LowerBound(Data, key);
|
|
|
+ ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
|
|
|
if (it == Data.end() || it->key != key)
|
|
|
Data.insert(it, ImGuiStoragePair(key, val));
|
|
|
else
|
|
|
@@ -2625,7 +2626,7 @@ void ImGuiStorage::SetFloat(ImGuiID key, float val)
|
|
|
|
|
|
void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val)
|
|
|
{
|
|
|
- ImGuiStoragePair* it = LowerBound(Data, key);
|
|
|
+ ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
|
|
|
if (it == Data.end() || it->key != key)
|
|
|
Data.insert(it, ImGuiStoragePair(key, val));
|
|
|
else
|
|
|
@@ -4172,7 +4173,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
|
|
|
// Done with rectangle culling so we can perform heavier checks now.
|
|
|
if (!(item_flags & ImGuiItemFlags_NoWindowHoverableCheck) && !IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
|
|
|
{
|
|
|
- g.HoveredIdDisabled = true;
|
|
|
+ g.HoveredIdIsDisabled = true;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -4207,7 +4208,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
|
|
|
// Release active id if turning disabled
|
|
|
if (g.ActiveId == id && id != 0)
|
|
|
ClearActiveID();
|
|
|
- g.HoveredIdDisabled = true;
|
|
|
+ g.HoveredIdIsDisabled = true;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -4239,7 +4240,7 @@ bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id)
|
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
if (!bb.Overlaps(window->ClipRect))
|
|
|
if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId))
|
|
|
- if (!g.LogEnabled)
|
|
|
+ if (!g.ItemUnclipByLog)
|
|
|
return true;
|
|
|
return false;
|
|
|
}
|
|
|
@@ -4510,7 +4511,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
|
|
|
g.MovingWindow = NULL;
|
|
|
|
|
|
// Cancel moving if clicked over an item which was disabled or inhibited by popups (note that we know HoveredId == 0 already)
|
|
|
- if (g.HoveredIdDisabled)
|
|
|
+ if (g.HoveredIdIsDisabled)
|
|
|
g.MovingWindow = NULL;
|
|
|
}
|
|
|
else if (root_window == NULL && g.NavWindow != NULL)
|
|
|
@@ -4704,7 +4705,7 @@ void ImGui::NewFrame()
|
|
|
g.HoveredIdPreviousFrame = g.HoveredId;
|
|
|
g.HoveredId = 0;
|
|
|
g.HoveredIdAllowOverlap = false;
|
|
|
- g.HoveredIdDisabled = false;
|
|
|
+ g.HoveredIdIsDisabled = false;
|
|
|
|
|
|
// Clear ActiveID if the item is not alive anymore.
|
|
|
// In 1.87, the common most call to KeepAliveID() was moved from GetID() to ItemAdd().
|
|
|
@@ -5779,7 +5780,7 @@ static inline ImVec2 CalcWindowMinSize(ImGuiWindow* window)
|
|
|
|
|
|
// Reduce artifacts with very small windows
|
|
|
ImGuiWindow* window_for_height = window;
|
|
|
- size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight() + window_for_height->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f));
|
|
|
+ size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight + window_for_height->MenuBarHeight + ImMax(0.0f, g.Style.WindowRounding - 1.0f));
|
|
|
return size_min;
|
|
|
}
|
|
|
|
|
|
@@ -5990,7 +5991,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
|
|
|
ImRect clamp_rect = visibility_rect;
|
|
|
const bool window_move_from_title_bar = g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar);
|
|
|
if (window_move_from_title_bar)
|
|
|
- clamp_rect.Min.y -= window->TitleBarHeight();
|
|
|
+ clamp_rect.Min.y -= window->TitleBarHeight;
|
|
|
|
|
|
ImVec2 pos_target(FLT_MAX, FLT_MAX);
|
|
|
ImVec2 size_target(FLT_MAX, FLT_MAX);
|
|
|
@@ -6189,7 +6190,7 @@ static inline void ClampWindowPos(ImGuiWindow* window, const ImRect& visibility_
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImVec2 size_for_clamping = window->Size;
|
|
|
if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
|
|
|
- size_for_clamping.y = window->TitleBarHeight();
|
|
|
+ size_for_clamping.y = window->TitleBarHeight;
|
|
|
window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max);
|
|
|
}
|
|
|
|
|
|
@@ -6225,7 +6226,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
|
|
|
}
|
|
|
if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
|
|
|
{
|
|
|
- float y = window->Pos.y + window->TitleBarHeight() - 1;
|
|
|
+ float y = window->Pos.y + window->TitleBarHeight - 1;
|
|
|
window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), border_col, g.Style.FrameBorderSize);
|
|
|
}
|
|
|
}
|
|
|
@@ -6270,7 +6271,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
|
|
}
|
|
|
if (override_alpha)
|
|
|
bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
|
|
|
- window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
|
|
|
+ window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
|
|
|
}
|
|
|
|
|
|
// Title bar
|
|
|
@@ -6564,6 +6565,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
window_stack_data.Window = window;
|
|
|
window_stack_data.ParentLastItemDataBackup = g.LastItemData;
|
|
|
window_stack_data.StackSizesOnBegin.SetToContextState(&g);
|
|
|
+ window_stack_data.DisabledOverrideReenable = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
|
|
|
g.CurrentWindowStack.push_back(window_stack_data);
|
|
|
if (flags & ImGuiWindowFlags_ChildMenu)
|
|
|
g.BeginMenuDepth++;
|
|
|
@@ -6650,6 +6652,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
// [EXPERIMENTAL] Skip Refresh mode
|
|
|
UpdateWindowSkipRefresh(window);
|
|
|
|
|
|
+ // Nested root windows (typically tooltips) override disabled state
|
|
|
+ if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window)
|
|
|
+ BeginDisabledOverrideReenable();
|
|
|
+
|
|
|
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
|
|
|
g.CurrentWindow = NULL;
|
|
|
|
|
|
@@ -6732,6 +6738,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
// Lock menu offset so size calculation can use it as menu-bar windows need a minimum size.
|
|
|
window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x);
|
|
|
window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y;
|
|
|
+ window->TitleBarHeight = (flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : g.FontSize + g.Style.FramePadding.y * 2.0f;
|
|
|
+ window->MenuBarHeight = (flags & ImGuiWindowFlags_MenuBar) ? window->DC.MenuBarOffset.y + g.FontSize + g.Style.FramePadding.y * 2.0f : 0.0f;
|
|
|
|
|
|
// Depending on condition we use previous or current window size to compare against contents size to decide if a scrollbar should be visible.
|
|
|
// Those flags will be altered further down in the function depending on more conditions.
|
|
|
@@ -6772,7 +6780,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
const ImVec2 scrollbar_sizes_from_last_frame = window->ScrollbarSizes;
|
|
|
window->DecoOuterSizeX1 = 0.0f;
|
|
|
window->DecoOuterSizeX2 = 0.0f;
|
|
|
- window->DecoOuterSizeY1 = window->TitleBarHeight() + window->MenuBarHeight();
|
|
|
+ window->DecoOuterSizeY1 = window->TitleBarHeight + window->MenuBarHeight;
|
|
|
window->DecoOuterSizeY2 = 0.0f;
|
|
|
window->ScrollbarSizes = ImVec2(0.0f, 0.0f);
|
|
|
|
|
|
@@ -6921,7 +6929,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
|
|
|
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
|
|
|
if (window->ScrollbarX && !window->ScrollbarY)
|
|
|
- window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar);
|
|
|
+ window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
|
|
|
window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
|
|
|
|
|
|
// Amend the partially filled window->DecorationXXX values.
|
|
|
@@ -7247,7 +7255,7 @@ void ImGui::End()
|
|
|
IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size > 1, "Calling End() too many times!");
|
|
|
return;
|
|
|
}
|
|
|
- IM_ASSERT(g.CurrentWindowStack.Size > 0);
|
|
|
+ ImGuiWindowStackData& window_stack_data = g.CurrentWindowStack.back();
|
|
|
|
|
|
// Error checking: verify that user doesn't directly call End() on a child window.
|
|
|
if (window->Flags & ImGuiWindowFlags_ChildWindow)
|
|
|
@@ -7259,6 +7267,8 @@ void ImGui::End()
|
|
|
if (!window->SkipRefresh)
|
|
|
PopClipRect(); // Inner window clip rectangle
|
|
|
PopFocusScope();
|
|
|
+ if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window)
|
|
|
+ EndDisabledOverrideReenable();
|
|
|
|
|
|
if (window->SkipRefresh)
|
|
|
{
|
|
|
@@ -7274,12 +7284,12 @@ void ImGui::End()
|
|
|
ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
|
|
|
|
|
|
// Pop from window stack
|
|
|
- g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup;
|
|
|
+ g.LastItemData = window_stack_data.ParentLastItemDataBackup;
|
|
|
if (window->Flags & ImGuiWindowFlags_ChildMenu)
|
|
|
g.BeginMenuDepth--;
|
|
|
if (window->Flags & ImGuiWindowFlags_Popup)
|
|
|
g.BeginPopupStack.pop_back();
|
|
|
- g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithContextState(&g);
|
|
|
+ window_stack_data.StackSizesOnBegin.CompareWithContextState(&g);
|
|
|
g.CurrentWindowStack.pop_back();
|
|
|
SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
|
|
|
}
|
|
|
@@ -7371,9 +7381,13 @@ void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags)
|
|
|
if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (g.NavWindow != window)) // Early out in common case.
|
|
|
if (ImGuiWindow* blocking_modal = FindBlockingModal(window))
|
|
|
{
|
|
|
+ // This block would typically be reached in two situations:
|
|
|
+ // - API call to FocusWindow() with a window under a modal and ImGuiFocusRequestFlags_UnlessBelowModal flag.
|
|
|
+ // - User clicking on void or anything behind a modal while a modal is open (window == NULL)
|
|
|
IMGUI_DEBUG_LOG_FOCUS("[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name : "<NULL>", blocking_modal->Name);
|
|
|
if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
|
|
|
- BringWindowToDisplayBehind(window, blocking_modal); // Still bring to right below modal.
|
|
|
+ BringWindowToDisplayBehind(window, blocking_modal); // Still bring right under modal. (FIXME: Could move in focus list too?)
|
|
|
+ ClosePopupsOverWindow(GetTopMostPopupModal(), false); // Note how we need to use GetTopMostPopupModal() aad NOT blocking_modal, to handle nested modals
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -7523,7 +7537,7 @@ void ImGui::BeginDisabled(bool disabled)
|
|
|
}
|
|
|
if (was_disabled || disabled)
|
|
|
g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
|
|
|
- g.ItemFlagsStack.push_back(g.CurrentItemFlags);
|
|
|
+ g.ItemFlagsStack.push_back(g.CurrentItemFlags); // FIXME-OPT: can we simply skip this and use DisabledStackSize?
|
|
|
g.DisabledStackSize++;
|
|
|
}
|
|
|
|
|
|
@@ -7540,6 +7554,29 @@ void ImGui::EndDisabled()
|
|
|
g.Style.Alpha = g.DisabledAlphaBackup; //PopStyleVar();
|
|
|
}
|
|
|
|
|
|
+// Could have been called BeginDisabledDisable() but it didn't want to be award nominated for most awkward function name.
|
|
|
+// Ideally we would use a shared e.g. BeginDisabled()->BeginDisabledEx() but earlier needs to be optimal.
|
|
|
+// The whole code for this is awkward, will reevaluate if we find a way to implement SetNextItemDisabled().
|
|
|
+void ImGui::BeginDisabledOverrideReenable()
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ IM_ASSERT(g.CurrentItemFlags & ImGuiItemFlags_Disabled);
|
|
|
+ g.Style.Alpha = g.DisabledAlphaBackup;
|
|
|
+ g.CurrentItemFlags &= ~ImGuiItemFlags_Disabled;
|
|
|
+ g.ItemFlagsStack.push_back(g.CurrentItemFlags);
|
|
|
+ g.DisabledStackSize++;
|
|
|
+}
|
|
|
+
|
|
|
+void ImGui::EndDisabledOverrideReenable()
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ g.DisabledStackSize--;
|
|
|
+ IM_ASSERT(g.DisabledStackSize > 0);
|
|
|
+ g.ItemFlagsStack.pop_back();
|
|
|
+ g.CurrentItemFlags = g.ItemFlagsStack.back();
|
|
|
+ g.Style.Alpha = g.DisabledAlphaBackup * g.Style.DisabledAlpha;
|
|
|
+}
|
|
|
+
|
|
|
void ImGui::PushTabStop(bool tab_stop)
|
|
|
{
|
|
|
PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop);
|
|
|
@@ -8870,7 +8907,7 @@ bool ImGui::IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id)
|
|
|
|
|
|
bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat)
|
|
|
{
|
|
|
- return IsMouseClicked(button, ImGuiKeyOwner_Any, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None);
|
|
|
+ return IsMouseClicked(button, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None, ImGuiKeyOwner_Any);
|
|
|
}
|
|
|
|
|
|
bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiInputFlags flags, ImGuiID owner_id)
|
|
|
@@ -9695,7 +9732,7 @@ void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
|
|
|
// This is the only public API until we expose owner_id versions of the API as replacements.
|
|
|
bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord)
|
|
|
{
|
|
|
- return IsKeyChordPressed(key_chord, 0, ImGuiInputFlags_None);
|
|
|
+ return IsKeyChordPressed(key_chord, ImGuiInputFlags_None, ImGuiKeyOwner_Any);
|
|
|
}
|
|
|
|
|
|
// This is equivalent to comparing KeyMods + doing a IsKeyPressed()
|
|
|
@@ -9884,10 +9921,6 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
|
|
|
if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && g.IO.BackendUsingLegacyKeyArrays == 1)
|
|
|
IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation.");
|
|
|
#endif
|
|
|
-
|
|
|
- // Check: the io.ConfigWindowsResizeFromEdges option requires backend to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly.
|
|
|
- if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors))
|
|
|
- g.IO.ConfigWindowsResizeFromEdges = false;
|
|
|
}
|
|
|
|
|
|
static void ImGui::ErrorCheckEndFrameSanityChecks()
|
|
|
@@ -9995,7 +10028,13 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
|
|
|
while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044
|
|
|
{
|
|
|
if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name);
|
|
|
- EndDisabled();
|
|
|
+ if (g.CurrentItemFlags & ImGuiItemFlags_Disabled)
|
|
|
+ EndDisabled();
|
|
|
+ else
|
|
|
+ {
|
|
|
+ EndDisabledOverrideReenable();
|
|
|
+ g.CurrentWindowStack.back().DisabledOverrideReenable = false;
|
|
|
+ }
|
|
|
}
|
|
|
while (g.ColorStack.Size > stack_sizes->SizeOfColorStack)
|
|
|
{
|
|
|
@@ -10084,6 +10123,7 @@ void ImGui::KeepAliveID(ImGuiID id)
|
|
|
// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
|
|
|
// declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction.
|
|
|
// THIS IS IN THE PERFORMANCE CRITICAL PATH (UNTIL THE CLIPPING TEST AND EARLY-RETURN)
|
|
|
+IM_MSVC_RUNTIME_CHECKS_OFF
|
|
|
bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
@@ -10136,15 +10176,12 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
|
|
|
#endif
|
|
|
|
|
|
// Clipping test
|
|
|
- // (this is a modified copy of IsClippedEx() so we can reuse the is_rect_visible value)
|
|
|
- //const bool is_clipped = IsClippedEx(bb, id);
|
|
|
- //if (is_clipped)
|
|
|
- // return false;
|
|
|
+ // (this is an inline copy of IsClippedEx() so we can reuse the is_rect_visible value, otherwise we'd do 'if (IsClippedEx(bb, id)) return false')
|
|
|
// g.NavActivateId is not necessarily == g.NavId, in the case of remote activation (e.g. shortcuts)
|
|
|
const bool is_rect_visible = bb.Overlaps(window->ClipRect);
|
|
|
if (!is_rect_visible)
|
|
|
if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId))
|
|
|
- if (!g.LogEnabled)
|
|
|
+ if (!g.ItemUnclipByLog)
|
|
|
return false;
|
|
|
|
|
|
// [DEBUG]
|
|
|
@@ -10171,7 +10208,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
|
|
|
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
|
|
|
return true;
|
|
|
}
|
|
|
-
|
|
|
+IM_MSVC_RUNTIME_CHECKS_RESTORE
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
// [SECTION] LAYOUT
|
|
|
@@ -10208,6 +10245,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
|
|
|
// Register minimum needed size so it can extend the bounding box used for auto-fit calculation.
|
|
|
// See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different.
|
|
|
// THIS IS IN THE PERFORMANCE CRITICAL PATH.
|
|
|
+IM_MSVC_RUNTIME_CHECKS_OFF
|
|
|
void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
@@ -10243,6 +10281,7 @@ void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
|
|
|
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
|
|
SameLine();
|
|
|
}
|
|
|
+IM_MSVC_RUNTIME_CHECKS_RESTORE
|
|
|
|
|
|
// Gets back to previous line and continue with horizontal layout
|
|
|
// offset_from_start_x == 0 : follow right after previous item
|
|
|
@@ -11196,8 +11235,8 @@ void ImGui::CloseCurrentPopup()
|
|
|
window->DC.NavHideHighlightOneFrame = true;
|
|
|
}
|
|
|
|
|
|
-// Attention! BeginPopup() adds default flags which BeginPopupEx()!
|
|
|
-bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags)
|
|
|
+// Attention! BeginPopup() adds default flags when calling BeginPopupEx()!
|
|
|
+bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
if (!IsPopupOpen(id, ImGuiPopupFlags_None))
|
|
|
@@ -11207,13 +11246,12 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags)
|
|
|
}
|
|
|
|
|
|
char name[20];
|
|
|
- if (flags & ImGuiWindowFlags_ChildMenu)
|
|
|
+ if (extra_window_flags & ImGuiWindowFlags_ChildMenu)
|
|
|
ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginMenuDepth); // Recycle windows based on depth
|
|
|
else
|
|
|
ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame
|
|
|
|
|
|
- flags |= ImGuiWindowFlags_Popup;
|
|
|
- bool is_open = Begin(name, NULL, flags);
|
|
|
+ bool is_open = Begin(name, NULL, extra_window_flags | ImGuiWindowFlags_Popup);
|
|
|
if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display)
|
|
|
EndPopup();
|
|
|
|
|
|
@@ -13096,6 +13134,8 @@ bool ImGui::IsDragDropActive()
|
|
|
void ImGui::ClearDragDrop()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
+ if (g.DragDropActive)
|
|
|
+ IMGUI_DEBUG_LOG_ACTIVEID("[dragdrop] ClearDragDrop()\n");
|
|
|
g.DragDropActive = false;
|
|
|
g.DragDropPayload.Clear();
|
|
|
g.DragDropAcceptFlags = ImGuiDragDropFlags_None;
|
|
|
@@ -13134,7 +13174,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
|
|
|
bool source_drag_active = false;
|
|
|
ImGuiID source_id = 0;
|
|
|
ImGuiID source_parent_id = 0;
|
|
|
- if (!(flags & ImGuiDragDropFlags_SourceExtern))
|
|
|
+ if ((flags & ImGuiDragDropFlags_SourceExtern) == 0)
|
|
|
{
|
|
|
source_id = g.LastItemData.ID;
|
|
|
if (source_id != 0)
|
|
|
@@ -13196,43 +13236,44 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
|
|
|
}
|
|
|
|
|
|
IM_ASSERT(g.DragDropWithinTarget == false); // Can't nest BeginDragDropSource() and BeginDragDropTarget()
|
|
|
- if (source_drag_active)
|
|
|
- {
|
|
|
- if (!g.DragDropActive)
|
|
|
- {
|
|
|
- IM_ASSERT(source_id != 0);
|
|
|
- ClearDragDrop();
|
|
|
- ImGuiPayload& payload = g.DragDropPayload;
|
|
|
- payload.SourceId = source_id;
|
|
|
- payload.SourceParentId = source_parent_id;
|
|
|
- g.DragDropActive = true;
|
|
|
- g.DragDropSourceFlags = flags;
|
|
|
- g.DragDropMouseButton = mouse_button;
|
|
|
- if (payload.SourceId == g.ActiveId)
|
|
|
- g.ActiveIdNoClearOnFocusLoss = true;
|
|
|
- }
|
|
|
- g.DragDropSourceFrameCount = g.FrameCount;
|
|
|
- g.DragDropWithinSource = true;
|
|
|
+ if (!source_drag_active)
|
|
|
+ return false;
|
|
|
|
|
|
- if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
|
|
|
- {
|
|
|
- // Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit)
|
|
|
- // We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents.
|
|
|
- bool ret;
|
|
|
- if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
|
|
|
- ret = BeginTooltipHidden();
|
|
|
- else
|
|
|
- ret = BeginTooltip();
|
|
|
- IM_ASSERT(ret); // FIXME-NEWBEGIN: If this ever becomes false, we need to Begin("##Hidden", NULL, ImGuiWindowFlags_NoSavedSettings) + SetWindowHiddendAndSkipItemsForCurrentFrame().
|
|
|
- IM_UNUSED(ret);
|
|
|
- }
|
|
|
+ // Activate drag and drop
|
|
|
+ if (!g.DragDropActive)
|
|
|
+ {
|
|
|
+ IM_ASSERT(source_id != 0);
|
|
|
+ ClearDragDrop();
|
|
|
+ IMGUI_DEBUG_LOG_ACTIVEID("[dragdrop] BeginDragDropSource() DragDropActive = true, source_id = %08X\n", source_id);
|
|
|
+ ImGuiPayload& payload = g.DragDropPayload;
|
|
|
+ payload.SourceId = source_id;
|
|
|
+ payload.SourceParentId = source_parent_id;
|
|
|
+ g.DragDropActive = true;
|
|
|
+ g.DragDropSourceFlags = flags;
|
|
|
+ g.DragDropMouseButton = mouse_button;
|
|
|
+ if (payload.SourceId == g.ActiveId)
|
|
|
+ g.ActiveIdNoClearOnFocusLoss = true;
|
|
|
+ }
|
|
|
+ g.DragDropSourceFrameCount = g.FrameCount;
|
|
|
+ g.DragDropWithinSource = true;
|
|
|
+
|
|
|
+ if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
|
|
|
+ {
|
|
|
+ // Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit)
|
|
|
+ // We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents.
|
|
|
+ bool ret;
|
|
|
+ if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
|
|
|
+ ret = BeginTooltipHidden();
|
|
|
+ else
|
|
|
+ ret = BeginTooltip();
|
|
|
+ IM_ASSERT(ret); // FIXME-NEWBEGIN: If this ever becomes false, we need to Begin("##Hidden", NULL, ImGuiWindowFlags_NoSavedSettings) + SetWindowHiddendAndSkipItemsForCurrentFrame().
|
|
|
+ IM_UNUSED(ret);
|
|
|
+ }
|
|
|
|
|
|
- if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
|
|
|
- g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
|
|
|
+ if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
|
|
|
+ g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
|
|
|
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
void ImGui::EndDragDropSource()
|
|
|
@@ -13543,7 +13584,7 @@ void ImGui::LogBegin(ImGuiLogType type, int auto_open_depth)
|
|
|
IM_ASSERT(g.LogEnabled == false);
|
|
|
IM_ASSERT(g.LogFile == NULL);
|
|
|
IM_ASSERT(g.LogBuffer.empty());
|
|
|
- g.LogEnabled = true;
|
|
|
+ g.LogEnabled = g.ItemUnclipByLog = true;
|
|
|
g.LogType = type;
|
|
|
g.LogNextPrefix = g.LogNextSuffix = NULL;
|
|
|
g.LogDepthRef = window->DC.TreeDepth;
|
|
|
@@ -13642,7 +13683,7 @@ void ImGui::LogFinish()
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- g.LogEnabled = false;
|
|
|
+ g.LogEnabled = g.ItemUnclipByLog = false;
|
|
|
g.LogType = ImGuiLogType_None;
|
|
|
g.LogFile = NULL;
|
|
|
g.LogBuffer.clear();
|
|
|
@@ -15374,7 +15415,7 @@ void ImGui::DebugNodeStorage(ImGuiStorage* storage, const char* label)
|
|
|
{
|
|
|
if (!TreeNode(label, "%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes()))
|
|
|
return;
|
|
|
- for (const ImGuiStorage::ImGuiStoragePair& p : storage->Data)
|
|
|
+ for (const ImGuiStoragePair& p : storage->Data)
|
|
|
BulletText("Key 0x%08X Value { i: %d }", p.key, p.val_i); // Important: we currently don't store a type, real value may not be integer.
|
|
|
TreePop();
|
|
|
}
|
|
|
@@ -15568,8 +15609,11 @@ void ImGui::DebugLogV(const char* fmt, va_list args)
|
|
|
if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY)
|
|
|
IMGUI_DEBUG_PRINTF("%s", g.DebugLogBuf.begin() + old_size);
|
|
|
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
|
|
+ // IMGUI_TEST_ENGINE_LOG() adds a trailing \n automatically
|
|
|
+ const int new_size = g.DebugLogBuf.size();
|
|
|
+ const bool trailing_carriage_return = (g.DebugLogBuf[new_size - 1] == '\n');
|
|
|
if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTestEngine)
|
|
|
- IMGUI_TEST_ENGINE_LOG("%s", g.DebugLogBuf.begin() + old_size);
|
|
|
+ IMGUI_TEST_ENGINE_LOG("%.*s", new_size - old_size - (trailing_carriage_return ? 1 : 0), g.DebugLogBuf.begin() + old_size);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
@@ -15637,25 +15681,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
|
|
|
clipper.Begin(g.DebugLogIndex.size());
|
|
|
while (clipper.Step())
|
|
|
for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
|
|
|
- {
|
|
|
- const char* line_begin = g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no);
|
|
|
- const char* line_end = g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no);
|
|
|
- TextUnformatted(line_begin, line_end); // Display line
|
|
|
- ImRect text_rect = g.LastItemData.Rect;
|
|
|
- if (IsItemHovered())
|
|
|
- for (const char* p = line_begin; p <= line_end - 10; p++) // Search for 0x???????? identifiers
|
|
|
- {
|
|
|
- ImGuiID id = 0;
|
|
|
- if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1)
|
|
|
- continue;
|
|
|
- ImVec2 p0 = CalcTextSize(line_begin, p);
|
|
|
- ImVec2 p1 = CalcTextSize(p, p + 10);
|
|
|
- g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y));
|
|
|
- if (IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true))
|
|
|
- DebugLocateItemOnHover(id);
|
|
|
- p += 10;
|
|
|
- }
|
|
|
- }
|
|
|
+ DebugTextUnformattedWithLocateItem(g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no), g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no));
|
|
|
g.DebugLogFlags = backup_log_flags;
|
|
|
if (GetScrollY() >= GetScrollMaxY())
|
|
|
SetScrollHereY(1.0f);
|
|
|
@@ -15664,6 +15690,28 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
|
|
|
End();
|
|
|
}
|
|
|
|
|
|
+// Display line, search for 0xXXXXXXXX identifiers and call DebugLocateItemOnHover() when hovered.
|
|
|
+void ImGui::DebugTextUnformattedWithLocateItem(const char* line_begin, const char* line_end)
|
|
|
+{
|
|
|
+ TextUnformatted(line_begin, line_end);
|
|
|
+ if (!IsItemHovered())
|
|
|
+ return;
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ ImRect text_rect = g.LastItemData.Rect;
|
|
|
+ for (const char* p = line_begin; p <= line_end - 10; p++)
|
|
|
+ {
|
|
|
+ ImGuiID id = 0;
|
|
|
+ if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1)
|
|
|
+ continue;
|
|
|
+ ImVec2 p0 = CalcTextSize(line_begin, p);
|
|
|
+ ImVec2 p1 = CalcTextSize(p, p + 10);
|
|
|
+ g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y));
|
|
|
+ if (IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true))
|
|
|
+ DebugLocateItemOnHover(id);
|
|
|
+ p += 10;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
//-----------------------------------------------------------------------------
|
|
|
// [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL)
|
|
|
//-----------------------------------------------------------------------------
|