mirror of
https://github.com/Drezil/imgui.git
synced 2024-12-22 15:46:35 +00:00
Nav: Fixed moving window with gamepad or keyboard when running at very high framerate + removed ImGuiNavDirSourceFlags_RawKeyboard.
This commit is contained in:
parent
82e10f1b61
commit
93f02ee0c6
@ -41,6 +41,7 @@ Other Changes:
|
||||
|
||||
- InputText: added experimental io.ConfigInputTextEnterKeepActive feature to make pressing
|
||||
Enter keep the input active and select all text.
|
||||
- Nav: Fixed moving/resizing window with gamepad or keyboard when running at very high framerate.
|
||||
- Misc: io.Framerate moving average now converge in 60 frames instead of 120. (#5236, #4138)
|
||||
- Backends: Metal: Use __bridge for ARC based systems. (#5403) [@stack]
|
||||
- Backends: Metal: Add dispatch synchronization. (#5447) [@luigifcruz]
|
||||
|
69
imgui.cpp
69
imgui.cpp
@ -5713,23 +5713,31 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
|
||||
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
|
||||
|
||||
// Navigation resize (keyboard/gamepad)
|
||||
// FIXME: This cannot be moved to NavUpdateWindowing() because CalcWindowSizeAfterConstraint() need to callback into user.
|
||||
// Not even sure the callback works here.
|
||||
if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow == window)
|
||||
{
|
||||
ImVec2 nav_resize_delta;
|
||||
ImVec2 nav_resize_dir;
|
||||
if (g.NavInputSource == ImGuiInputSource_Keyboard && g.IO.KeyShift)
|
||||
nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_RawKeyboard, ImGuiNavReadMode_Down);
|
||||
nav_resize_dir = ImVec2((float)IsKeyDown(ImGuiKey_RightArrow) - (float)IsKeyDown(ImGuiKey_LeftArrow), (float)IsKeyDown(ImGuiKey_DownArrow) - (float)IsKeyDown(ImGuiKey_UpArrow));
|
||||
if (g.NavInputSource == ImGuiInputSource_Gamepad)
|
||||
nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiNavReadMode_Down);
|
||||
if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f)
|
||||
nav_resize_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiNavReadMode_Down);
|
||||
if (nav_resize_dir.x != 0.0f || nav_resize_dir.y != 0.0f)
|
||||
{
|
||||
const float NAV_RESIZE_SPEED = 600.0f;
|
||||
nav_resize_delta *= ImFloor(NAV_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y));
|
||||
nav_resize_delta = ImMax(nav_resize_delta, visibility_rect.Min - window->Pos - window->Size);
|
||||
const float resize_step = NAV_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y);
|
||||
g.NavWindowingAccumDeltaSize += nav_resize_dir * resize_step;
|
||||
g.NavWindowingAccumDeltaSize = ImMax(g.NavWindowingAccumDeltaSize, visibility_rect.Min - window->Pos - window->Size); // We need Pos+Size >= visibility_rect.Min, so Size >= visibility_rect.Min - Pos, so size_delta >= visibility_rect.Min - window->Pos - window->Size
|
||||
g.NavWindowingToggleLayer = false;
|
||||
g.NavDisableMouseHover = true;
|
||||
resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive);
|
||||
// FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck.
|
||||
size_target = CalcWindowSizeAfterConstraint(window, window->SizeFull + nav_resize_delta);
|
||||
ImVec2 accum_floored = ImFloor(g.NavWindowingAccumDeltaSize);
|
||||
if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
|
||||
{
|
||||
// FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck.
|
||||
size_target = CalcWindowSizeAfterConstraint(window, window->SizeFull + accum_floored);
|
||||
g.NavWindowingAccumDeltaSize -= accum_floored;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10125,31 +10133,30 @@ const char* ImGui::GetNavInputName(ImGuiNavInput n)
|
||||
float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiNavReadMode mode)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (mode == ImGuiNavReadMode_Down)
|
||||
return g.IO.NavInputs[n]; // Instant, read analog input (0.0f..1.0f, as provided by user)
|
||||
ImGuiIO& io = g.IO;
|
||||
if (mode == ImGuiNavReadMode_Down) // Instant, read analog input (0.0f..1.0f, as provided by user)
|
||||
return io.NavInputs[n];
|
||||
|
||||
const float t = g.IO.NavInputsDownDuration[n];
|
||||
const float t = io.NavInputsDownDuration[n];
|
||||
if (t < 0.0f && mode == ImGuiNavReadMode_Released) // Return 1.0f when just released, no repeat, ignore analog input.
|
||||
return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f);
|
||||
return (io.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f);
|
||||
if (t < 0.0f)
|
||||
return 0.0f;
|
||||
if (mode == ImGuiNavReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input.
|
||||
return (t == 0.0f) ? 1.0f : 0.0f;
|
||||
if (mode == ImGuiNavReadMode_Repeat)
|
||||
return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.80f);
|
||||
return (float)CalcTypematicRepeatAmount(t - io.DeltaTime, t, io.KeyRepeatDelay * 0.72f, io.KeyRepeatRate * 0.80f);
|
||||
if (mode == ImGuiNavReadMode_RepeatSlow)
|
||||
return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 1.25f, g.IO.KeyRepeatRate * 2.00f);
|
||||
return (float)CalcTypematicRepeatAmount(t - io.DeltaTime, t, io.KeyRepeatDelay * 1.25f, io.KeyRepeatRate * 2.00f);
|
||||
if (mode == ImGuiNavReadMode_RepeatFast)
|
||||
return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.30f);
|
||||
return (float)CalcTypematicRepeatAmount(t - io.DeltaTime, t, io.KeyRepeatDelay * 0.72f, io.KeyRepeatRate * 0.30f);
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiNavReadMode mode, float slow_factor, float fast_factor)
|
||||
{
|
||||
ImVec2 delta(0.0f, 0.0f);
|
||||
if (dir_sources & ImGuiNavDirSourceFlags_RawKeyboard)
|
||||
delta += ImVec2((float)IsKeyDown(ImGuiKey_RightArrow) - (float)IsKeyDown(ImGuiKey_LeftArrow), (float)IsKeyDown(ImGuiKey_DownArrow) - (float)IsKeyDown(ImGuiKey_UpArrow));
|
||||
if (dir_sources & ImGuiNavDirSourceFlags_Keyboard)
|
||||
if (dir_sources & ImGuiNavDirSourceFlags_Keyboard) // Number of presses during the frame, according to repeat rate
|
||||
delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight_, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft_, mode), GetNavInputAmount(ImGuiNavInput_KeyDown_, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp_, mode));
|
||||
if (dir_sources & ImGuiNavDirSourceFlags_PadDPad)
|
||||
delta += ImVec2(GetNavInputAmount(ImGuiNavInput_DpadRight, mode) - GetNavInputAmount(ImGuiNavInput_DpadLeft, mode), GetNavInputAmount(ImGuiNavInput_DpadDown, mode) - GetNavInputAmount(ImGuiNavInput_DpadUp, mode));
|
||||
@ -10825,7 +10832,10 @@ static void NavUpdateWindowingHighlightWindow(int focus_change_dir)
|
||||
if (!window_target)
|
||||
window_target = FindWindowNavFocusable((focus_change_dir < 0) ? (g.WindowsFocusOrder.Size - 1) : 0, i_current, focus_change_dir);
|
||||
if (window_target) // Don't reset windowing target if there's a single window in the list
|
||||
{
|
||||
g.NavWindowingTarget = g.NavWindowingTargetAnim = window_target;
|
||||
g.NavWindowingAccumDeltaPos = g.NavWindowingAccumDeltaSize = ImVec2(0.0f, 0.0f);
|
||||
}
|
||||
g.NavWindowingToggleLayer = false;
|
||||
}
|
||||
|
||||
@ -10859,8 +10869,9 @@ static void ImGui::NavUpdateWindowing()
|
||||
if (start_windowing_with_gamepad || start_windowing_with_keyboard)
|
||||
if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
|
||||
{
|
||||
g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow;
|
||||
g.NavWindowingTarget = g.NavWindowingTargetAnim = window;
|
||||
g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f;
|
||||
g.NavWindowingAccumDeltaPos = g.NavWindowingAccumDeltaSize = ImVec2(0.0f, 0.0f);
|
||||
g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true : false; // Gamepad starts toggling layer
|
||||
g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
|
||||
}
|
||||
@ -10932,18 +10943,24 @@ static void ImGui::NavUpdateWindowing()
|
||||
// Move window
|
||||
if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
ImVec2 move_delta;
|
||||
ImVec2 nav_move_dir;
|
||||
if (g.NavInputSource == ImGuiInputSource_Keyboard && !io.KeyShift)
|
||||
move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_RawKeyboard, ImGuiNavReadMode_Down);
|
||||
nav_move_dir = ImVec2((float)IsKeyDown(ImGuiKey_RightArrow) - (float)IsKeyDown(ImGuiKey_LeftArrow), (float)IsKeyDown(ImGuiKey_DownArrow) - (float)IsKeyDown(ImGuiKey_UpArrow));
|
||||
if (g.NavInputSource == ImGuiInputSource_Gamepad)
|
||||
move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiNavReadMode_Down);
|
||||
if (move_delta.x != 0.0f || move_delta.y != 0.0f)
|
||||
nav_move_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiNavReadMode_Down);
|
||||
if (nav_move_dir.x != 0.0f || nav_move_dir.y != 0.0f)
|
||||
{
|
||||
const float NAV_MOVE_SPEED = 800.0f;
|
||||
const float move_speed = ImFloor(NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, 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);
|
||||
const float move_step = NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
|
||||
g.NavWindowingAccumDeltaPos += nav_move_dir * move_step;
|
||||
g.NavDisableMouseHover = true;
|
||||
ImVec2 accum_floored = ImFloor(g.NavWindowingAccumDeltaPos);
|
||||
if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
|
||||
{
|
||||
ImGuiWindow* moving_window = g.NavWindowingTarget->RootWindow;
|
||||
SetWindowPos(moving_window, moving_window->Pos + accum_floored, ImGuiCond_Always);
|
||||
g.NavWindowingAccumDeltaPos -= accum_floored;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1171,6 +1171,7 @@ struct ImGuiPtrOrIndex
|
||||
|
||||
typedef ImBitArray<ImGuiKey_NamedKey_COUNT, -ImGuiKey_NamedKey_BEGIN> ImBitArrayForNamedKeys;
|
||||
|
||||
// Extend ImGuiKey_
|
||||
enum ImGuiKeyPrivate_
|
||||
{
|
||||
ImGuiKey_LegacyNativeKey_BEGIN = 0,
|
||||
@ -1308,10 +1309,9 @@ enum ImGuiNavHighlightFlags_
|
||||
enum ImGuiNavDirSourceFlags_
|
||||
{
|
||||
ImGuiNavDirSourceFlags_None = 0,
|
||||
ImGuiNavDirSourceFlags_RawKeyboard = 1 << 0, // Raw keyboard (not pulled from nav), facilitate use of some functions before we can unify nav and keys
|
||||
ImGuiNavDirSourceFlags_Keyboard = 1 << 1,
|
||||
ImGuiNavDirSourceFlags_PadDPad = 1 << 2,
|
||||
ImGuiNavDirSourceFlags_PadLStick = 1 << 3
|
||||
ImGuiNavDirSourceFlags_Keyboard = 1 << 0,
|
||||
ImGuiNavDirSourceFlags_PadDPad = 1 << 1,
|
||||
ImGuiNavDirSourceFlags_PadLStick = 1 << 2
|
||||
};
|
||||
|
||||
enum ImGuiNavMoveFlags_
|
||||
@ -1724,6 +1724,8 @@ struct ImGuiContext
|
||||
float NavWindowingTimer;
|
||||
float NavWindowingHighlightAlpha;
|
||||
bool NavWindowingToggleLayer;
|
||||
ImVec2 NavWindowingAccumDeltaPos;
|
||||
ImVec2 NavWindowingAccumDeltaSize;
|
||||
|
||||
// Render
|
||||
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
|
||||
@ -2699,13 +2701,15 @@ namespace ImGui
|
||||
inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; return g.ActiveIdUsingKeyInputMask[key]; }
|
||||
inline void SetActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; g.ActiveIdUsingKeyInputMask.SetBit(key); }
|
||||
IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f);
|
||||
inline bool IsNavInputDown(ImGuiNavInput n) { ImGuiContext& g = *GImGui; return g.IO.NavInputs[n] > 0.0f; }
|
||||
inline bool IsNavInputTest(ImGuiNavInput n, ImGuiNavReadMode rm) { return (GetNavInputAmount(n, rm) > 0.0f); }
|
||||
IMGUI_API ImGuiModFlags GetMergedModFlags();
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
|
||||
inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // [removed in 1.87]
|
||||
#endif
|
||||
|
||||
// Inputs: Navigation
|
||||
inline bool IsNavInputDown(ImGuiNavInput n) { ImGuiContext& g = *GImGui; return g.IO.NavInputs[n] > 0.0f; }
|
||||
inline bool IsNavInputTest(ImGuiNavInput n, ImGuiNavReadMode read_mode) { return (GetNavInputAmount(n, read_mode) > 0.0f); }
|
||||
|
||||
// Drag and Drop
|
||||
IMGUI_API bool IsDragDropActive();
|
||||
IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id);
|
||||
|
Loading…
Reference in New Issue
Block a user