|
|
@@ -1,4 +1,4 @@
|
|
|
-// dear imgui, v1.78 WIP
|
|
|
+// dear imgui, v1.79 WIP
|
|
|
// (main code and documentation)
|
|
|
|
|
|
// Help:
|
|
|
@@ -372,6 +372,16 @@ CODE
|
|
|
When you are not sure about a 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.
|
|
|
|
|
|
+ - 2020/08/17 (1.78) - obsoleted use of the trailing 'float power=1.0f' parameter for DragFloat(), DragFloat2(), DragFloat3(), DragFloat4(), DragFloatRange2(), DragScalar(), DragScalarN(), SliderFloat(), SliderFloat2(), SliderFloat3(), SliderFloat4(), SliderScalar(), SliderScalarN(), VSliderFloat() and VSliderScalar().
|
|
|
+ replaced the 'float power=1.0f' argument with integer-based flags defaulting to 0 (as with all our flags).
|
|
|
+ worked out a backward-compatibility scheme so hopefully most C++ codebase should not be affected. in short, when calling those functions:
|
|
|
+ - if you omitted the 'power' parameter (likely!), you are not affected.
|
|
|
+ - if you set the 'power' parameter to 1.0f (same as previous default value): 1/ your compiler may warn on float>int conversion, 2/ everything else will work. 3/ you can replace the 1.0f value with 0 to fix the warning, and be technically correct.
|
|
|
+ - if you set the 'power' parameter to >1.0f (to enable non-linear editing): 1/ your compiler may warn on float>int conversion, 2/ code will assert at runtime, 3/ in case asserts are disabled, the code will not crash and enable the _Logarithmic flag. 4/ you can replace the >1.0f value with ImGuiSliderFlags_Logarithmic to fix the warning/assert and get a _similar_ effect as previous uses of power >1.0f.
|
|
|
+ see https://github.com/ocornut/imgui/issues/3361 for all details.
|
|
|
+ kept inline redirection functions (will obsolete) apart for: DragFloatRange2(), VSliderFloat(), VSliderScalar(). For those three the 'float power=1.0f' version were removed directly as they were most unlikely ever used.
|
|
|
+ for shared code, you can version check at compile-time with `#if IMGUI_VERSION_NUM >= 17704`.
|
|
|
+ - obsoleted use of v_min > v_max in DragInt, DragFloat, DragScalar to lock edits (introduced in 1.73, was not demoed nor documented very), will be replaced by a more generic ReadOnly feature. You may use the ImGuiSliderFlags_ReadOnly internal flag in the meantime.
|
|
|
- 2020/06/23 (1.77) - removed BeginPopupContextWindow(const char*, int mouse_button, bool also_over_items) in favor of BeginPopupContextWindow(const char*, ImGuiPopupFlags flags) with ImGuiPopupFlags_NoOverItems.
|
|
|
- 2020/06/15 (1.77) - renamed OpenPopupOnItemClick() to OpenPopupContextItem(). Kept inline redirection function (will obsolete).
|
|
|
- 2020/06/15 (1.77) - removed CalcItemRectClosestPoint() entry point which was made obsolete and asserting in December 2017.
|
|
|
@@ -648,9 +658,9 @@ CODE
|
|
|
Q&A: Usage
|
|
|
----------
|
|
|
|
|
|
+ Q: Why is my widget not reacting when I click on it?
|
|
|
Q: How can I have widgets with an empty label?
|
|
|
Q: How can I have multiple widgets with the same label?
|
|
|
- Q: Why are multiple widgets reacting when I interact with one?
|
|
|
Q: How can I display an image? What is ImTextureID, how does it works?
|
|
|
Q: How can I use my own math types instead of ImVec2/ImVec4?
|
|
|
Q: How can I interact with standard C++ types (such as std::string and std::vector)?
|
|
|
@@ -747,12 +757,12 @@ CODE
|
|
|
|
|
|
// Visual Studio warnings
|
|
|
#ifdef _MSC_VER
|
|
|
-#pragma warning (disable: 4127) // condition expression is constant
|
|
|
+#pragma warning (disable: 4127) // condition expression is constant
|
|
|
#pragma warning (disable: 4201) // nonstandard extension used: nameless struct/union
|
|
|
#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
|
|
|
-#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
|
|
-#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
|
|
|
-#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
|
|
|
+#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
|
|
+#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
|
|
|
+#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
|
|
|
#endif
|
|
|
#endif
|
|
|
|
|
|
@@ -927,6 +937,7 @@ ImGuiStyle::ImGuiStyle()
|
|
|
ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar
|
|
|
GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar
|
|
|
GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
|
|
|
+ LogSliderDeadzone = 4.0f; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero.
|
|
|
TabRounding = 4.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
|
|
|
TabBorderSize = 0.0f; // Thickness of border around tabs.
|
|
|
TabMinWidthForUnselectedCloseButton = 0.0f; // Minimum width for close button to appears on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected.
|
|
|
@@ -966,6 +977,7 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor)
|
|
|
ScrollbarRounding = ImFloor(ScrollbarRounding * scale_factor);
|
|
|
GrabMinSize = ImFloor(GrabMinSize * scale_factor);
|
|
|
GrabRounding = ImFloor(GrabRounding * scale_factor);
|
|
|
+ LogSliderDeadzone = ImFloor(LogSliderDeadzone * scale_factor);
|
|
|
TabRounding = ImFloor(TabRounding * scale_factor);
|
|
|
if (TabMinWidthForUnselectedCloseButton != FLT_MAX)
|
|
|
TabMinWidthForUnselectedCloseButton = ImFloor(TabMinWidthForUnselectedCloseButton * scale_factor);
|
|
|
@@ -3613,16 +3625,17 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
|
|
|
// - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow.
|
|
|
// - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame.
|
|
|
// - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms.
|
|
|
+ bool clear_hovered_windows = false;
|
|
|
FindHoveredWindow();
|
|
|
|
|
|
// Modal windows prevents mouse from hovering behind them.
|
|
|
ImGuiWindow* modal_window = GetTopMostPopupModal();
|
|
|
if (modal_window && g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window))
|
|
|
- g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL;
|
|
|
+ clear_hovered_windows = true;
|
|
|
|
|
|
// Disabled mouse?
|
|
|
if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse)
|
|
|
- g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL;
|
|
|
+ clear_hovered_windows = true;
|
|
|
|
|
|
// We track click ownership. When clicked outside of a window the click is owned by the application and won't report hovering nor request capture even while dragging over our windows afterward.
|
|
|
int mouse_earliest_button_down = -1;
|
|
|
@@ -3642,6 +3655,9 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
|
|
|
// FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02)
|
|
|
const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0;
|
|
|
if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload)
|
|
|
+ clear_hovered_windows = true;
|
|
|
+
|
|
|
+ if (clear_hovered_windows)
|
|
|
g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL;
|
|
|
|
|
|
// Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to Dear ImGui + app)
|
|
|
@@ -5708,7 +5724,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
|
|
|
const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesCannotSkipItems == 0);
|
|
|
if (window_pos_with_pivot)
|
|
|
- SetWindowPos(window, window->SetWindowPosVal - window->SizeFull * window->SetWindowPosPivot, 0); // Position given a pivot (e.g. for centering)
|
|
|
+ SetWindowPos(window, window->SetWindowPosVal - window->Size * window->SetWindowPosPivot, 0); // Position given a pivot (e.g. for centering)
|
|
|
else if ((flags & ImGuiWindowFlags_ChildMenu) != 0)
|
|
|
window->Pos = FindBestWindowPosForPopup(window);
|
|
|
else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize)
|
|
|
@@ -7258,10 +7274,11 @@ float ImGui::GetWindowContentRegionWidth()
|
|
|
}
|
|
|
|
|
|
// Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)
|
|
|
+// Groups are currently a mishmash of functionalities which should perhaps be clarified and separated.
|
|
|
void ImGui::BeginGroup()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- ImGuiWindow* window = GetCurrentWindow();
|
|
|
+ ImGuiWindow* window = g.CurrentWindow;
|
|
|
|
|
|
window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1);
|
|
|
ImGuiGroupData& group_data = window->DC.GroupStack.back();
|
|
|
@@ -7286,8 +7303,8 @@ void ImGui::BeginGroup()
|
|
|
void ImGui::EndGroup()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- ImGuiWindow* window = GetCurrentWindow();
|
|
|
- IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls
|
|
|
+ ImGuiWindow* window = g.CurrentWindow;
|
|
|
+ IM_ASSERT(window->DC.GroupStack.Size > 0); // Mismatched BeginGroup()/EndGroup() calls
|
|
|
|
|
|
ImGuiGroupData& group_data = window->DC.GroupStack.back();
|
|
|
|
|
|
@@ -7315,9 +7332,9 @@ void ImGui::EndGroup()
|
|
|
// If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group.
|
|
|
// It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but would put a little more burden on individual widgets.
|
|
|
// Also if you grep for LastItemId you'll notice it is only used in that context.
|
|
|
- // (The tests not symmetrical because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.)
|
|
|
+ // (The two tests not the same because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.)
|
|
|
const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId;
|
|
|
- const bool group_contains_prev_active_id = !group_data.BackupActiveIdPreviousFrameIsAlive && g.ActiveIdPreviousFrameIsAlive;
|
|
|
+ const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive == false) && (g.ActiveIdPreviousFrameIsAlive == true);
|
|
|
if (group_contains_curr_active_id)
|
|
|
window->DC.LastItemId = g.ActiveId;
|
|
|
else if (group_contains_prev_active_id)
|
|
|
@@ -7379,7 +7396,7 @@ ImVec2 ImGui::ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_
|
|
|
if (!window_rect.Contains(item_rect))
|
|
|
{
|
|
|
if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x)
|
|
|
- SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x + g.Style.ItemSpacing.x, 0.0f);
|
|
|
+ SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x - g.Style.ItemSpacing.x, 0.0f);
|
|
|
else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x)
|
|
|
SetScrollFromPosX(window, item_rect.Max.x - window->Pos.x + g.Style.ItemSpacing.x, 1.0f);
|
|
|
if (item_rect.Min.y < window_rect.Min.y)
|
|
|
@@ -8502,7 +8519,9 @@ ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInput
|
|
|
static void ImGui::NavUpdate()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- g.IO.WantSetMousePos = false;
|
|
|
+ ImGuiIO& io = g.IO;
|
|
|
+
|
|
|
+ io.WantSetMousePos = false;
|
|
|
g.NavWrapRequestWindow = NULL;
|
|
|
g.NavWrapRequestFlags = ImGuiNavMoveFlags_None;
|
|
|
#if 0
|
|
|
@@ -8511,16 +8530,19 @@ static void ImGui::NavUpdate()
|
|
|
|
|
|
// Set input source as Gamepad when buttons are pressed (as some features differs when used with Gamepad vs Keyboard)
|
|
|
// (do it before we map Keyboard input!)
|
|
|
- bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
|
|
- bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
|
|
|
- if (nav_gamepad_active)
|
|
|
- if (g.IO.NavInputs[ImGuiNavInput_Activate] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Input] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Cancel] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Menu] > 0.0f)
|
|
|
+ bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
|
|
+ bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
|
|
|
+ if (nav_gamepad_active && g.NavInputSource != ImGuiInputSource_NavGamepad)
|
|
|
+ {
|
|
|
+ if (io.NavInputs[ImGuiNavInput_Activate] > 0.0f || io.NavInputs[ImGuiNavInput_Input] > 0.0f || io.NavInputs[ImGuiNavInput_Cancel] > 0.0f || io.NavInputs[ImGuiNavInput_Menu] > 0.0f
|
|
|
+ || io.NavInputs[ImGuiNavInput_DpadLeft] > 0.0f || io.NavInputs[ImGuiNavInput_DpadRight] > 0.0f || io.NavInputs[ImGuiNavInput_DpadUp] > 0.0f || io.NavInputs[ImGuiNavInput_DpadDown] > 0.0f)
|
|
|
g.NavInputSource = ImGuiInputSource_NavGamepad;
|
|
|
+ }
|
|
|
|
|
|
// Update Keyboard->Nav inputs mapping
|
|
|
if (nav_keyboard_active)
|
|
|
{
|
|
|
- #define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(g.IO.KeyMap[_KEY])) { g.IO.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_NavKeyboard; } } while (0)
|
|
|
+ #define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(io.KeyMap[_KEY])) { io.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_NavKeyboard; } } while (0)
|
|
|
NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate );
|
|
|
NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input );
|
|
|
NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel );
|
|
|
@@ -8528,17 +8550,17 @@ static void ImGui::NavUpdate()
|
|
|
NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_);
|
|
|
NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ );
|
|
|
NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ );
|
|
|
- if (g.IO.KeyCtrl)
|
|
|
- g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f;
|
|
|
- if (g.IO.KeyShift)
|
|
|
- g.IO.NavInputs[ImGuiNavInput_TweakFast] = 1.0f;
|
|
|
- if (g.IO.KeyAlt && !g.IO.KeyCtrl) // AltGR is Alt+Ctrl, also even on keyboards without AltGR we don't want Alt+Ctrl to open menu.
|
|
|
- g.IO.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f;
|
|
|
+ if (io.KeyCtrl)
|
|
|
+ io.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f;
|
|
|
+ if (io.KeyShift)
|
|
|
+ io.NavInputs[ImGuiNavInput_TweakFast] = 1.0f;
|
|
|
+ if (io.KeyAlt && !io.KeyCtrl) // AltGR is Alt+Ctrl, also even on keyboards without AltGR we don't want Alt+Ctrl to open menu.
|
|
|
+ io.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f;
|
|
|
#undef NAV_MAP_KEY
|
|
|
}
|
|
|
- memcpy(g.IO.NavInputsDownDurationPrev, g.IO.NavInputsDownDuration, sizeof(g.IO.NavInputsDownDuration));
|
|
|
- for (int i = 0; i < IM_ARRAYSIZE(g.IO.NavInputs); i++)
|
|
|
- g.IO.NavInputsDownDuration[i] = (g.IO.NavInputs[i] > 0.0f) ? (g.IO.NavInputsDownDuration[i] < 0.0f ? 0.0f : g.IO.NavInputsDownDuration[i] + g.IO.DeltaTime) : -1.0f;
|
|
|
+ memcpy(io.NavInputsDownDurationPrev, io.NavInputsDownDuration, sizeof(io.NavInputsDownDuration));
|
|
|
+ for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++)
|
|
|
+ io.NavInputsDownDuration[i] = (io.NavInputs[i] > 0.0f) ? (io.NavInputsDownDuration[i] < 0.0f ? 0.0f : io.NavInputsDownDuration[i] + io.DeltaTime) : -1.0f;
|
|
|
|
|
|
// Process navigation init request (select first/default focus)
|
|
|
// In very rare cases g.NavWindow may be null (e.g. clearing focus after requesting an init request, which does happen when releasing Alt while clicking on void)
|
|
|
@@ -8574,12 +8596,12 @@ static void ImGui::NavUpdate()
|
|
|
if (g.NavMousePosDirty && g.NavIdIsAlive)
|
|
|
{
|
|
|
// Set mouse position given our knowledge of the navigated item position from last frame
|
|
|
- if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (g.IO.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
|
|
|
+ if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
|
|
|
{
|
|
|
if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow)
|
|
|
{
|
|
|
- g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredRefPos();
|
|
|
- g.IO.WantSetMousePos = true;
|
|
|
+ io.MousePos = io.MousePosPrev = NavCalcPreferredRefPos();
|
|
|
+ io.WantSetMousePos = true;
|
|
|
}
|
|
|
}
|
|
|
g.NavMousePosDirty = false;
|
|
|
@@ -8598,8 +8620,8 @@ static void ImGui::NavUpdate()
|
|
|
NavUpdateWindowing();
|
|
|
|
|
|
// Set output flags for user application
|
|
|
- g.IO.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs);
|
|
|
- g.IO.NavVisible = (g.IO.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL);
|
|
|
+ io.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs);
|
|
|
+ io.NavVisible = (io.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL);
|
|
|
|
|
|
// Process NavCancel input (to close a popup, get back to parent, clear focus)
|
|
|
if (IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed))
|
|
|
@@ -8702,7 +8724,7 @@ static void ImGui::NavUpdate()
|
|
|
if (g.NavMoveDir != ImGuiDir_None)
|
|
|
{
|
|
|
g.NavMoveRequest = true;
|
|
|
- g.NavMoveRequestKeyMods = g.IO.KeyMods;
|
|
|
+ g.NavMoveRequestKeyMods = io.KeyMods;
|
|
|
g.NavMoveDirLast = g.NavMoveDir;
|
|
|
}
|
|
|
if (g.NavMoveRequest && g.NavId == 0)
|
|
|
@@ -8720,7 +8742,7 @@ static void ImGui::NavUpdate()
|
|
|
{
|
|
|
// *Fallback* manual-scroll with Nav directional keys when window has no navigable item
|
|
|
ImGuiWindow* window = g.NavWindow;
|
|
|
- const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * g.IO.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
|
|
|
+ const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
|
|
|
if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest)
|
|
|
{
|
|
|
if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right)
|
|
|
@@ -8733,15 +8755,9 @@ static void ImGui::NavUpdate()
|
|
|
// Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds.
|
|
|
ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f / 10.0f, 10.0f);
|
|
|
if (scroll_dir.x != 0.0f && window->ScrollbarX)
|
|
|
- {
|
|
|
SetScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed));
|
|
|
- g.NavMoveFromClampedRefRect = true;
|
|
|
- }
|
|
|
if (scroll_dir.y != 0.0f)
|
|
|
- {
|
|
|
SetScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed));
|
|
|
- g.NavMoveFromClampedRefRect = true;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
// Reset search results
|
|
|
@@ -8749,8 +8765,10 @@ static void ImGui::NavUpdate()
|
|
|
g.NavMoveResultLocalVisibleSet.Clear();
|
|
|
g.NavMoveResultOther.Clear();
|
|
|
|
|
|
- // When we have manually scrolled (without using navigation) and NavId becomes out of bounds, we project its bounding box to the visible area to restart navigation within visible items
|
|
|
- if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == ImGuiNavLayer_Main)
|
|
|
+ // When using gamepad, we project the reference nav bounding box into window visible area.
|
|
|
+ // This is to allow resuming navigation inside the visible area after doing a large amount of scrolling, since with gamepad every movements are relative
|
|
|
+ // (can't focus a visible object like we can with the mouse).
|
|
|
+ if (g.NavMoveRequest && g.NavInputSource == ImGuiInputSource_NavGamepad && g.NavLayer == ImGuiNavLayer_Main)
|
|
|
{
|
|
|
ImGuiWindow* window = g.NavWindow;
|
|
|
ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1, 1), window->InnerRect.Max - window->Pos + ImVec2(1, 1));
|
|
|
@@ -8758,14 +8776,13 @@ static void ImGui::NavUpdate()
|
|
|
{
|
|
|
float pad = window->CalcFontSize() * 0.5f;
|
|
|
window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intent of starting navigation from first fully visible item
|
|
|
- window->NavRectRel[g.NavLayer].ClipWith(window_rect_rel);
|
|
|
+ window->NavRectRel[g.NavLayer].ClipWithFull(window_rect_rel);
|
|
|
g.NavId = g.NavFocusScopeId = 0;
|
|
|
}
|
|
|
- g.NavMoveFromClampedRefRect = false;
|
|
|
}
|
|
|
|
|
|
// For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items)
|
|
|
- ImRect nav_rect_rel = (g.NavWindow && !g.NavWindow->NavRectRel[g.NavLayer].IsInverted()) ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0);
|
|
|
+ ImRect nav_rect_rel = g.NavWindow ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0);
|
|
|
g.NavScoringRect = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : GetViewportRect();
|
|
|
g.NavScoringRect.TranslateY(nav_scoring_rect_offset_y);
|
|
|
g.NavScoringRect.Min.x = ImMin(g.NavScoringRect.Min.x + 1.0f, g.NavScoringRect.Max.x);
|
|
|
@@ -8843,31 +8860,32 @@ static void ImGui::NavUpdateMoveResult()
|
|
|
g.NavJustMovedToKeyMods = g.NavMoveRequestKeyMods;
|
|
|
}
|
|
|
SetNavIDWithRectRel(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel);
|
|
|
- g.NavMoveFromClampedRefRect = false;
|
|
|
}
|
|
|
|
|
|
// Handle PageUp/PageDown/Home/End keys
|
|
|
static float ImGui::NavUpdatePageUpPageDown()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
+ ImGuiIO& io = g.IO;
|
|
|
+
|
|
|
if (g.NavMoveDir != ImGuiDir_None || g.NavWindow == NULL)
|
|
|
return 0.0f;
|
|
|
if ((g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget != NULL || g.NavLayer != ImGuiNavLayer_Main)
|
|
|
return 0.0f;
|
|
|
|
|
|
ImGuiWindow* window = g.NavWindow;
|
|
|
- const bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && !IsActiveIdUsingKey(ImGuiKey_PageUp);
|
|
|
- const bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && !IsActiveIdUsingKey(ImGuiKey_PageDown);
|
|
|
- const bool home_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_Home]) && !IsActiveIdUsingKey(ImGuiKey_Home);
|
|
|
- const bool end_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_End]) && !IsActiveIdUsingKey(ImGuiKey_End);
|
|
|
+ const bool page_up_held = IsKeyDown(io.KeyMap[ImGuiKey_PageUp]) && !IsActiveIdUsingKey(ImGuiKey_PageUp);
|
|
|
+ const bool page_down_held = IsKeyDown(io.KeyMap[ImGuiKey_PageDown]) && !IsActiveIdUsingKey(ImGuiKey_PageDown);
|
|
|
+ const bool home_pressed = IsKeyPressed(io.KeyMap[ImGuiKey_Home]) && !IsActiveIdUsingKey(ImGuiKey_Home);
|
|
|
+ const bool end_pressed = IsKeyPressed(io.KeyMap[ImGuiKey_End]) && !IsActiveIdUsingKey(ImGuiKey_End);
|
|
|
if (page_up_held != page_down_held || home_pressed != end_pressed) // If either (not both) are pressed
|
|
|
{
|
|
|
if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
|
|
|
{
|
|
|
// Fallback manual-scroll when window has no navigable item
|
|
|
- if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
|
|
|
+ if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true))
|
|
|
SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
|
|
|
- else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
|
|
|
+ else if (IsKeyPressed(io.KeyMap[ImGuiKey_PageDown], true))
|
|
|
SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
|
|
|
else if (home_pressed)
|
|
|
SetScrollY(window, 0.0f);
|
|
|
@@ -8879,14 +8897,14 @@ static float ImGui::NavUpdatePageUpPageDown()
|
|
|
ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
|
|
|
const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
|
|
|
float nav_scoring_rect_offset_y = 0.0f;
|
|
|
- if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
|
|
|
+ if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true))
|
|
|
{
|
|
|
nav_scoring_rect_offset_y = -page_offset_y;
|
|
|
g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item)
|
|
|
g.NavMoveClipDir = ImGuiDir_Up;
|
|
|
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
|
|
}
|
|
|
- else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
|
|
|
+ else if (IsKeyPressed(io.KeyMap[ImGuiKey_PageDown], true))
|
|
|
{
|
|
|
nav_scoring_rect_offset_y = +page_offset_y;
|
|
|
g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset down, we request the up direction (so we can always land on the last item)
|
|
|
@@ -9024,11 +9042,9 @@ static void ImGui::NavUpdateWindowing()
|
|
|
bool apply_toggle_layer = false;
|
|
|
|
|
|
ImGuiWindow* modal_window = GetTopMostPopupModal();
|
|
|
- if (modal_window != NULL)
|
|
|
- {
|
|
|
+ bool allow_windowing = (modal_window == NULL);
|
|
|
+ if (!allow_windowing)
|
|
|
g.NavWindowingTarget = NULL;
|
|
|
- return;
|
|
|
- }
|
|
|
|
|
|
// Fade out
|
|
|
if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL)
|
|
|
@@ -9039,8 +9055,8 @@ static void ImGui::NavUpdateWindowing()
|
|
|
}
|
|
|
|
|
|
// Start CTRL-TAB or Square+L/R window selection
|
|
|
- bool start_windowing_with_gamepad = !g.NavWindowingTarget && IsNavInputTest(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed);
|
|
|
- bool start_windowing_with_keyboard = !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard);
|
|
|
+ bool start_windowing_with_gamepad = allow_windowing && !g.NavWindowingTarget && IsNavInputTest(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed);
|
|
|
+ bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard);
|
|
|
if (start_windowing_with_gamepad || start_windowing_with_keyboard)
|
|
|
if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
|
|
|
{
|
|
|
@@ -9107,10 +9123,11 @@ static void ImGui::NavUpdateWindowing()
|
|
|
if (move_delta.x != 0.0f || move_delta.y != 0.0f)
|
|
|
{
|
|
|
const float NAV_MOVE_SPEED = 800.0f;
|
|
|
- const float move_speed = ImFloor(NAV_MOVE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); // FIXME: Doesn't code variable framerate very well
|
|
|
- SetWindowPos(g.NavWindowingTarget->RootWindow, g.NavWindowingTarget->RootWindow->Pos + move_delta * move_speed, ImGuiCond_Always);
|
|
|
+ const float move_speed = ImFloor(NAV_MOVE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); // FIXME: Doesn't handle variable framerate very well
|
|
|
+ ImGuiWindow* moving_window = g.NavWindowingTarget->RootWindow;
|
|
|
+ SetWindowPos(moving_window, moving_window->Pos + move_delta * move_speed, ImGuiCond_Always);
|
|
|
+ MarkIniSettingsDirty(moving_window);
|
|
|
g.NavDisableMouseHover = true;
|
|
|
- MarkIniSettingsDirty(g.NavWindowingTarget);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -10404,7 +10421,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
{
|
|
|
if (!ImGui::TreeNode(label, "%s (%d)", label, windows.Size))
|
|
|
return;
|
|
|
- for (int i = 0; i < windows.Size; i++)
|
|
|
+ ImGui::Text("(In front-to-back order:)");
|
|
|
+ for (int i = windows.Size - 1; i >= 0; i--) // Iterate front to back
|
|
|
{
|
|
|
ImGui::PushID(windows[i]);
|
|
|
Funcs::NodeWindow(windows[i], "Window");
|
|
|
@@ -10420,14 +10438,18 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
ImGui::BulletText("%s: NULL", label);
|
|
|
return;
|
|
|
}
|
|
|
- bool open = ImGui::TreeNode(label, "%s '%s', %d @ 0x%p", label, window->Name, (window->Active || window->WasActive), window);
|
|
|
- if (ImGui::IsItemHovered() && window->WasActive)
|
|
|
- ImGui::GetForegroundDrawList()->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
|
|
|
+
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ const bool is_active = window->WasActive;
|
|
|
+ ImGuiTreeNodeFlags tree_node_flags = (window == g.NavWindow) ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None;
|
|
|
+ if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
|
|
|
+ const bool open = ImGui::TreeNodeEx(label, tree_node_flags, "%s '%s'%s", label, window->Name, is_active ? "" : " *Inactive*");
|
|
|
+ if (!is_active) { PopStyleColor(); }
|
|
|
+ if (ImGui::IsItemHovered() && is_active)
|
|
|
+ ImGui::GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
|
|
|
if (!open)
|
|
|
return;
|
|
|
|
|
|
- if (!window->WasActive)
|
|
|
- ImGui::TextDisabled("Note: window is not currently visible.");
|
|
|
if (window->MemoryCompacted)
|
|
|
ImGui::TextDisabled("Note: some memory buffers have been compacted/freed.");
|
|
|
|
|
|
@@ -10472,9 +10494,13 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
char buf[256];
|
|
|
char* p = buf;
|
|
|
const char* buf_end = buf + IM_ARRAYSIZE(buf);
|
|
|
- p += ImFormatString(p, buf_end - p, "TabBar (%d tabs)%s", tab_bar->Tabs.Size, (tab_bar->PrevFrameVisible < ImGui::GetFrameCount() - 2) ? " *Inactive*" : "");
|
|
|
+ const bool is_active = (tab_bar->PrevFrameVisible >= ImGui::GetFrameCount() - 2);
|
|
|
+ p += ImFormatString(p, buf_end - p, "Tab Bar 0x%08X (%d tabs)%s", tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*");
|
|
|
IM_UNUSED(p);
|
|
|
- if (ImGui::TreeNode(tab_bar, "%s", buf))
|
|
|
+ if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
|
|
|
+ bool open = ImGui::TreeNode(tab_bar, "%s", buf);
|
|
|
+ if (!is_active) { PopStyleColor(); }
|
|
|
+ if (open)
|
|
|
{
|
|
|
for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
|
|
|
{
|
|
|
@@ -10626,8 +10652,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
|
|
|
if (ImGui::TreeNode("SettingsIniData", "Settings unpacked data (.ini): %d bytes", g.SettingsIniData.size()))
|
|
|
{
|
|
|
- char* buf = (char*)(void*)(g.SettingsIniData.Buf.Data ? g.SettingsIniData.Buf.Data : "");
|
|
|
- ImGui::InputTextMultiline("##Ini", buf, g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, 0.0f), ImGuiInputTextFlags_ReadOnly);
|
|
|
+ ImGui::InputTextMultiline("##Ini", (char*)(void*)g.SettingsIniData.c_str(), g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, 0.0f), ImGuiInputTextFlags_ReadOnly);
|
|
|
ImGui::TreePop();
|
|
|
}
|
|
|
ImGui::TreePop();
|
|
|
@@ -10637,21 +10662,35 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
if (ImGui::TreeNode("Internal state"))
|
|
|
{
|
|
|
const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT);
|
|
|
+
|
|
|
+ ImGui::Text("WINDOWING");
|
|
|
+ ImGui::Indent();
|
|
|
ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL");
|
|
|
ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL");
|
|
|
ImGui::Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name : "NULL");
|
|
|
- ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not
|
|
|
+ ImGui::Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL");
|
|
|
+ ImGui::Unindent();
|
|
|
+
|
|
|
+ ImGui::Text("ITEMS");
|
|
|
+ ImGui::Indent();
|
|
|
ImGui::Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]);
|
|
|
ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL");
|
|
|
- ImGui::Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL");
|
|
|
+ ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not
|
|
|
+ ImGui::Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
|
|
|
+ ImGui::Unindent();
|
|
|
+
|
|
|
+ ImGui::Text("NAV,FOCUS");
|
|
|
+ ImGui::Indent();
|
|
|
ImGui::Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL");
|
|
|
ImGui::Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer);
|
|
|
ImGui::Text("NavInputSource: %s", input_source_names[g.NavInputSource]);
|
|
|
ImGui::Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible);
|
|
|
ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId);
|
|
|
ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover);
|
|
|
+ ImGui::Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId);
|
|
|
ImGui::Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name : "NULL");
|
|
|
- ImGui::Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
|
|
|
+ ImGui::Unindent();
|
|
|
+
|
|
|
ImGui::TreePop();
|
|
|
}
|
|
|
|