mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-28 09:30:56 +01:00
Internals: refactor: mouse input functions into their own section.
This commit is contained in:
parent
206b9ead8f
commit
28eabcb099
474
imgui.cpp
474
imgui.cpp
@ -70,6 +70,7 @@ CODE
|
|||||||
// [SECTION] STYLING
|
// [SECTION] STYLING
|
||||||
// [SECTION] RENDER HELPERS
|
// [SECTION] RENDER HELPERS
|
||||||
// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
|
// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
|
||||||
|
// [SECTION] INPUTS
|
||||||
// [SECTION] ERROR CHECKING
|
// [SECTION] ERROR CHECKING
|
||||||
// [SECTION] LAYOUT
|
// [SECTION] LAYOUT
|
||||||
// [SECTION] SCROLLING
|
// [SECTION] SCROLLING
|
||||||
@ -4767,238 +4768,6 @@ static void FindHoveredWindow()
|
|||||||
g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window;
|
g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if mouse cursor is hovering given rectangle
|
|
||||||
// NB- Rectangle is clipped by our current clip setting
|
|
||||||
// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding)
|
|
||||||
bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
|
|
||||||
// Clip
|
|
||||||
ImRect rect_clipped(r_min, r_max);
|
|
||||||
if (clip)
|
|
||||||
rect_clipped.ClipWith(g.CurrentWindow->ClipRect);
|
|
||||||
|
|
||||||
// Expand for touch input
|
|
||||||
const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding);
|
|
||||||
if (!rect_for_touch.Contains(g.IO.MousePos))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ImGui::GetKeyIndex(ImGuiKey imgui_key)
|
|
||||||
{
|
|
||||||
IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT);
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
return g.IO.KeyMap[imgui_key];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that dear imgui doesn't know the semantic of each entry of io.KeysDown[]!
|
|
||||||
// Use your own indices/enums according to how your backend/engine stored them into io.KeysDown[]!
|
|
||||||
bool ImGui::IsKeyDown(int user_key_index)
|
|
||||||
{
|
|
||||||
if (user_key_index < 0)
|
|
||||||
return false;
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
|
|
||||||
return g.IO.KeysDown[user_key_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
// t0 = previous time (e.g.: g.Time - g.IO.DeltaTime)
|
|
||||||
// t1 = current time (e.g.: g.Time)
|
|
||||||
// An event is triggered at:
|
|
||||||
// t = 0.0f t = repeat_delay, t = repeat_delay + repeat_rate*N
|
|
||||||
int ImGui::CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate)
|
|
||||||
{
|
|
||||||
if (t1 == 0.0f)
|
|
||||||
return 1;
|
|
||||||
if (t0 >= t1)
|
|
||||||
return 0;
|
|
||||||
if (repeat_rate <= 0.0f)
|
|
||||||
return (t0 < repeat_delay) && (t1 >= repeat_delay);
|
|
||||||
const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / repeat_rate);
|
|
||||||
const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / repeat_rate);
|
|
||||||
const int count = count_t1 - count_t0;
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
if (key_index < 0)
|
|
||||||
return 0;
|
|
||||||
IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown));
|
|
||||||
const float t = g.IO.KeysDownDuration[key_index];
|
|
||||||
return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, repeat_delay, repeat_rate);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui::IsKeyPressed(int user_key_index, bool repeat)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
if (user_key_index < 0)
|
|
||||||
return false;
|
|
||||||
IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
|
|
||||||
const float t = g.IO.KeysDownDuration[user_key_index];
|
|
||||||
if (t == 0.0f)
|
|
||||||
return true;
|
|
||||||
if (repeat && t > g.IO.KeyRepeatDelay)
|
|
||||||
return GetKeyPressedAmount(user_key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui::IsKeyReleased(int user_key_index)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
if (user_key_index < 0) return false;
|
|
||||||
IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
|
|
||||||
return g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui::IsMouseDown(ImGuiMouseButton button)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
|
||||||
return g.IO.MouseDown[button];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
|
||||||
const float t = g.IO.MouseDownDuration[button];
|
|
||||||
if (t == 0.0f)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (repeat && t > g.IO.KeyRepeatDelay)
|
|
||||||
{
|
|
||||||
// FIXME: 2019/05/03: Our old repeat code was wrong here and led to doubling the repeat rate, which made it an ok rate for repeat on mouse hold.
|
|
||||||
int amount = CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate * 0.50f);
|
|
||||||
if (amount > 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui::IsMouseReleased(ImGuiMouseButton button)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
|
||||||
return g.IO.MouseReleased[button];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
|
||||||
return g.IO.MouseClickedCount[button] == 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ImGui::GetMouseClickedCount(ImGuiMouseButton button)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
|
||||||
return g.IO.MouseClickedCount[button];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return if a mouse click/drag went past the given threshold. Valid to call during the MouseReleased frame.
|
|
||||||
// [Internal] This doesn't test if the button is pressed
|
|
||||||
bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
|
||||||
if (lock_threshold < 0.0f)
|
|
||||||
lock_threshold = g.IO.MouseDragThreshold;
|
|
||||||
return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui::IsMouseDragging(ImGuiMouseButton button, float lock_threshold)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
|
||||||
if (!g.IO.MouseDown[button])
|
|
||||||
return false;
|
|
||||||
return IsMouseDragPastThreshold(button, lock_threshold);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImVec2 ImGui::GetMousePos()
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
return g.IO.MousePos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed!
|
|
||||||
ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
if (g.BeginPopupStack.Size > 0)
|
|
||||||
return g.OpenPopupStack[g.BeginPopupStack.Size - 1].OpenMousePos;
|
|
||||||
return g.IO.MousePos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position.
|
|
||||||
bool ImGui::IsMousePosValid(const ImVec2* mouse_pos)
|
|
||||||
{
|
|
||||||
// The assert is only to silence a false-positive in XCode Static Analysis.
|
|
||||||
// Because GImGui is not dereferenced in every code path, the static analyzer assume that it may be NULL (which it doesn't for other functions).
|
|
||||||
IM_ASSERT(GImGui != NULL);
|
|
||||||
const float MOUSE_INVALID = -256000.0f;
|
|
||||||
ImVec2 p = mouse_pos ? *mouse_pos : GImGui->IO.MousePos;
|
|
||||||
return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui::IsAnyMouseDown()
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++)
|
|
||||||
if (g.IO.MouseDown[n])
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the delta from the initial clicking position while the mouse button is clicked or was just released.
|
|
||||||
// This is locked and return 0.0f until the mouse moves past a distance threshold at least once.
|
|
||||||
// NB: This is only valid if IsMousePosValid(). backends in theory should always keep mouse position valid when dragging even outside the client window.
|
|
||||||
ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button, float lock_threshold)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
|
||||||
if (lock_threshold < 0.0f)
|
|
||||||
lock_threshold = g.IO.MouseDragThreshold;
|
|
||||||
if (g.IO.MouseDown[button] || g.IO.MouseReleased[button])
|
|
||||||
if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold)
|
|
||||||
if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MouseClickedPos[button]))
|
|
||||||
return g.IO.MousePos - g.IO.MouseClickedPos[button];
|
|
||||||
return ImVec2(0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui::ResetMouseDragDelta(ImGuiMouseButton button)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
|
||||||
// NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr
|
|
||||||
g.IO.MouseClickedPos[button] = g.IO.MousePos;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGuiMouseCursor ImGui::GetMouseCursor()
|
|
||||||
{
|
|
||||||
return GImGui->MouseCursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
|
|
||||||
{
|
|
||||||
GImGui->MouseCursor = cursor_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui::CaptureKeyboardFromApp(bool capture)
|
|
||||||
{
|
|
||||||
GImGui->WantCaptureKeyboardNextFrame = capture ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui::CaptureMouseFromApp(bool capture)
|
|
||||||
{
|
|
||||||
GImGui->WantCaptureMouseNextFrame = capture ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui::IsItemActive()
|
bool ImGui::IsItemActive()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
@ -7460,6 +7229,247 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// [SECTION] INPUTS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Test if mouse cursor is hovering given rectangle
|
||||||
|
// NB- Rectangle is clipped by our current clip setting
|
||||||
|
// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding)
|
||||||
|
bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
|
||||||
|
// Clip
|
||||||
|
ImRect rect_clipped(r_min, r_max);
|
||||||
|
if (clip)
|
||||||
|
rect_clipped.ClipWith(g.CurrentWindow->ClipRect);
|
||||||
|
|
||||||
|
// Expand for touch input
|
||||||
|
const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding);
|
||||||
|
if (!rect_for_touch.Contains(g.IO.MousePos))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ImGui::GetKeyIndex(ImGuiKey imgui_key)
|
||||||
|
{
|
||||||
|
IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT);
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
return g.IO.KeyMap[imgui_key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that dear imgui doesn't know the semantic of each entry of io.KeysDown[]!
|
||||||
|
// Use your own indices/enums according to how your backend/engine stored them into io.KeysDown[]!
|
||||||
|
bool ImGui::IsKeyDown(int user_key_index)
|
||||||
|
{
|
||||||
|
if (user_key_index < 0)
|
||||||
|
return false;
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
|
||||||
|
return g.IO.KeysDown[user_key_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// t0 = previous time (e.g.: g.Time - g.IO.DeltaTime)
|
||||||
|
// t1 = current time (e.g.: g.Time)
|
||||||
|
// An event is triggered at:
|
||||||
|
// t = 0.0f t = repeat_delay, t = repeat_delay + repeat_rate*N
|
||||||
|
int ImGui::CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate)
|
||||||
|
{
|
||||||
|
if (t1 == 0.0f)
|
||||||
|
return 1;
|
||||||
|
if (t0 >= t1)
|
||||||
|
return 0;
|
||||||
|
if (repeat_rate <= 0.0f)
|
||||||
|
return (t0 < repeat_delay) && (t1 >= repeat_delay);
|
||||||
|
const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / repeat_rate);
|
||||||
|
const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / repeat_rate);
|
||||||
|
const int count = count_t1 - count_t0;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
if (key_index < 0)
|
||||||
|
return 0;
|
||||||
|
IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown));
|
||||||
|
const float t = g.IO.KeysDownDuration[key_index];
|
||||||
|
return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, repeat_delay, repeat_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::IsKeyPressed(int user_key_index, bool repeat)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
if (user_key_index < 0)
|
||||||
|
return false;
|
||||||
|
IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
|
||||||
|
const float t = g.IO.KeysDownDuration[user_key_index];
|
||||||
|
if (t == 0.0f)
|
||||||
|
return true;
|
||||||
|
if (repeat && t > g.IO.KeyRepeatDelay)
|
||||||
|
return GetKeyPressedAmount(user_key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::IsKeyReleased(int user_key_index)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
if (user_key_index < 0) return false;
|
||||||
|
IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
|
||||||
|
return g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::IsMouseDown(ImGuiMouseButton button)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||||
|
return g.IO.MouseDown[button];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||||
|
const float t = g.IO.MouseDownDuration[button];
|
||||||
|
if (t == 0.0f)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (repeat && t > g.IO.KeyRepeatDelay)
|
||||||
|
{
|
||||||
|
// FIXME: 2019/05/03: Our old repeat code was wrong here and led to doubling the repeat rate, which made it an ok rate for repeat on mouse hold.
|
||||||
|
int amount = CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate * 0.50f);
|
||||||
|
if (amount > 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::IsMouseReleased(ImGuiMouseButton button)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||||
|
return g.IO.MouseReleased[button];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||||
|
return g.IO.MouseClickedCount[button] == 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ImGui::GetMouseClickedCount(ImGuiMouseButton button)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||||
|
return g.IO.MouseClickedCount[button];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return if a mouse click/drag went past the given threshold. Valid to call during the MouseReleased frame.
|
||||||
|
// [Internal] This doesn't test if the button is pressed
|
||||||
|
bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||||
|
if (lock_threshold < 0.0f)
|
||||||
|
lock_threshold = g.IO.MouseDragThreshold;
|
||||||
|
return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::IsMouseDragging(ImGuiMouseButton button, float lock_threshold)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||||
|
if (!g.IO.MouseDown[button])
|
||||||
|
return false;
|
||||||
|
return IsMouseDragPastThreshold(button, lock_threshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec2 ImGui::GetMousePos()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
return g.IO.MousePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed!
|
||||||
|
ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
if (g.BeginPopupStack.Size > 0)
|
||||||
|
return g.OpenPopupStack[g.BeginPopupStack.Size - 1].OpenMousePos;
|
||||||
|
return g.IO.MousePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position.
|
||||||
|
bool ImGui::IsMousePosValid(const ImVec2* mouse_pos)
|
||||||
|
{
|
||||||
|
// The assert is only to silence a false-positive in XCode Static Analysis.
|
||||||
|
// Because GImGui is not dereferenced in every code path, the static analyzer assume that it may be NULL (which it doesn't for other functions).
|
||||||
|
IM_ASSERT(GImGui != NULL);
|
||||||
|
const float MOUSE_INVALID = -256000.0f;
|
||||||
|
ImVec2 p = mouse_pos ? *mouse_pos : GImGui->IO.MousePos;
|
||||||
|
return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::IsAnyMouseDown()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++)
|
||||||
|
if (g.IO.MouseDown[n])
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the delta from the initial clicking position while the mouse button is clicked or was just released.
|
||||||
|
// This is locked and return 0.0f until the mouse moves past a distance threshold at least once.
|
||||||
|
// NB: This is only valid if IsMousePosValid(). backends in theory should always keep mouse position valid when dragging even outside the client window.
|
||||||
|
ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button, float lock_threshold)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||||
|
if (lock_threshold < 0.0f)
|
||||||
|
lock_threshold = g.IO.MouseDragThreshold;
|
||||||
|
if (g.IO.MouseDown[button] || g.IO.MouseReleased[button])
|
||||||
|
if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold)
|
||||||
|
if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MouseClickedPos[button]))
|
||||||
|
return g.IO.MousePos - g.IO.MouseClickedPos[button];
|
||||||
|
return ImVec2(0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui::ResetMouseDragDelta(ImGuiMouseButton button)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||||
|
// NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr
|
||||||
|
g.IO.MouseClickedPos[button] = g.IO.MousePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGuiMouseCursor ImGui::GetMouseCursor()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
return g.MouseCursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
g.MouseCursor = cursor_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui::CaptureKeyboardFromApp(bool capture)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
g.WantCaptureKeyboardNextFrame = capture ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui::CaptureMouseFromApp(bool capture)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
g.WantCaptureMouseNextFrame = capture ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] ERROR CHECKING
|
// [SECTION] ERROR CHECKING
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user