Updated ImGui.

This commit is contained in:
Бранимир Караџић 2022-01-15 18:02:09 -08:00
parent 4581f14cd4
commit 84b33b3727
5 changed files with 481 additions and 129 deletions

View File

@ -348,7 +348,7 @@ CODE
- The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable.
- Keyboard:
- Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable.
NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
NewFrame() will automatically fill io.NavInputs[] based on your io.AddKeyEvent() calls.
- When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag
will be set. For more advanced uses, you may want to read from:
- io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
@ -386,6 +386,12 @@ 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.
- 2022/01/10 (1.87) - inputs: reworked keyboard IO. Removed io.KeyMap[], io.KeysDown[] in favor of calling io.AddKeyEvent(). Removed GetKeyIndex(), now unecessary. All IsKeyXXX() functions now take ImGuiKey values. All features are still functional until IMGUI_DISABLE_OBSOLETE_KEYIO is defined. Read Changelog and Release Notes for details.
- IsKeyPressed(MY_NATIVE_KEY_XXX) -> use IsKeyPressed(ImGuiKey_XXX)
- IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) -> use IsKeyPressed(ImGuiKey_XXX)
- Backend writing to io.KeyMap[],io.KeysDown[] -> backend should call io.AddKeyEvent()
- one case won't work with backward compatibility: if your custom backend used ImGuiKey as mock native indices (e.g. "io.KeyMap[ImGuiKey_A] = ImGuiKey_A") because those values are now larger than the legacy KeyDown[] array. Will assert.
- inputs: added io.AddKeyModsEvent() instead of writing directly to io.KeyCtrl, io.KeyShift, io.KeyAlt, io.KeySuper.
- 2022/01/05 (1.87) - inputs: renamed ImGuiKey_KeyPadEnter to ImGuiKey_KeypadEnter to align with new symbols. Kept redirection enum.
- 2022/01/05 (1.87) - removed io.ImeSetInputScreenPosFn() in favor of more flexible io.SetPlatformImeDataFn(). Removed 'void* io.ImeWindowHandle' in favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'.
- 2022/01/01 (1.87) - commented out redirecting functions/enums names that were marked obsolete in 1.69, 1.70, 1.71, 1.72 (March-July 2019)
@ -957,6 +963,7 @@ static void UpdateDebugToolStackQueries();
// Misc
static void UpdateSettings();
static void UpdateKeyboardInputs();
static void UpdateMouseInputs();
static void UpdateMouseWheel();
static bool UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect);
@ -1110,8 +1117,10 @@ ImGuiIO::ImGuiIO()
LogFilename = "imgui_log.txt";
MouseDoubleClickTime = 0.30f;
MouseDoubleClickMaxDist = 6.0f;
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
for (int i = 0; i < ImGuiKey_COUNT; i++)
KeyMap[i] = -1;
#endif
KeyRepeatDelay = 0.275f;
KeyRepeatRate = 0.050f;
UserData = NULL;
@ -1147,8 +1156,9 @@ ImGuiIO::ImGuiIO()
MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
MouseDragThreshold = 6.0f;
for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f;
for (int i = 0; i < IM_ARRAYSIZE(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; }
for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownDuration[i] = -1.0f;
BackendUsingLegacyKeyArrays = (ImS8)-1;
}
// Pass in translated ASCII characters for text input.
@ -1214,15 +1224,78 @@ void ImGuiIO::ClearInputCharacters()
void ImGuiIO::ClearInputKeys()
{
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
memset(KeysDown, 0, sizeof(KeysDown));
for (int n = 0; n < IM_ARRAYSIZE(KeysDownDuration); n++)
KeysDownDuration[n] = KeysDownDurationPrev[n] = -1.0f;
#endif
for (int n = 0; n < IM_ARRAYSIZE(KeysData); n++)
{
KeysData[n].Down = false;
KeysData[n].DownDuration = -1.0f;
KeysData[n].DownDurationPrev = -1.0f;
}
KeyCtrl = KeyShift = KeyAlt = KeySuper = false;
KeyMods = KeyModsPrev = ImGuiKeyModFlags_None;
for (int n = 0; n < IM_ARRAYSIZE(NavInputsDownDuration); n++)
NavInputsDownDuration[n] = NavInputsDownDurationPrev[n] = -1.0f;
}
// Queue a new key down/up event.
// - ImGuiKey key: Translated key (as in, generally ImGuiKey_A matches the key end-user would use to emit an 'A' character)
// - bool down: Is the key down? use false to signify a key release.
// FIXME: In the current version this is setting key data immediately. This will evolve into a trickling queue.
void ImGuiIO::AddKeyEvent(ImGuiKey key, bool down)
{
//if (e->Down) { IMGUI_DEBUG_LOG("AddKeyEvent() Key='%s' %d, NativeKeycode = %d, NativeScancode = %d\n", ImGui::GetKeyName(e->Key), e->Down, e->NativeKeycode, e->NativeScancode); }
if (key == ImGuiKey_None)
return;
IM_ASSERT(ImGui::IsNamedKey(key)); // Backend needs to pass a valid ImGuiKey_ constant. 0..511 values are legacy native key codes which are not accepted by this API.
// Verify that backend isn't mixing up using new io.AddKeyEvent() api and old io.KeysDown[] + io.KeyMap[] data.
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
IM_ASSERT((BackendUsingLegacyKeyArrays == -1 || BackendUsingLegacyKeyArrays == 0) && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
if (BackendUsingLegacyKeyArrays == -1)
for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
IM_ASSERT(KeyMap[n] == -1 && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
#endif
BackendUsingLegacyKeyArrays = 0;
// Write key
const int keydata_index = (key - ImGuiKey_KeysData_OFFSET);
KeysData[keydata_index].Down = down;
}
// [Optional] Call add AddKeyEvent().
// Specify native keycode, scancode + Specify index for legacy <1.87 IsKeyXXX() functions with native indices.
// If you are writing a backend in 2022 or don't use IsKeyXXX() with native values that are not ImGuiKey values, you can avoid calling this.
void ImGuiIO::SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native_scancode, int native_legacy_index)
{
if (key == ImGuiKey_None)
return;
IM_ASSERT(ImGui::IsNamedKey(key)); // >= 512
IM_ASSERT(native_legacy_index == -1 || ImGui::IsLegacyKey(native_legacy_index)); // >= 0 && <= 511
IM_UNUSED(native_keycode); // Yet unused
IM_UNUSED(native_scancode); // Yet unused
// Build native->imgui map so old user code can still call key functions with native 0..511 values.
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
const int legacy_key = (native_legacy_index != -1) ? native_legacy_index : native_keycode;
if (ImGui::IsLegacyKey(legacy_key))
KeyMap[legacy_key] = key;
#else
IM_UNUSED(key);
IM_UNUSED(native_legacy_index);
#endif
}
void ImGuiIO::AddKeyModsEvent(ImGuiKeyModFlags modifiers)
{
KeyMods = modifiers;
KeyCtrl = (modifiers & ImGuiKeyModFlags_Ctrl) != 0;
KeyShift = (modifiers & ImGuiKeyModFlags_Shift) != 0;
KeyAlt = (modifiers & ImGuiKeyModFlags_Alt) != 0;
KeySuper = (modifiers & ImGuiKeyModFlags_Super) != 0;
}
void ImGuiIO::AddFocusEvent(bool focused)
{
// We intentionally overwrite this and process in NewFrame(), in order to give a chance
@ -3222,7 +3295,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
g.ActiveIdUsingMouseWheel = false;
g.ActiveIdUsingNavDirMask = 0x00;
g.ActiveIdUsingNavInputMask = 0x00;
g.ActiveIdUsingKeyInputMask = 0x00;
g.ActiveIdUsingKeyInputMask.ClearAllBits();
}
void ImGui::ClearActiveID()
@ -3753,6 +3826,57 @@ static bool IsWindowActiveAndVisible(ImGuiWindow* window)
return (window->Active) && (!window->Hidden);
}
static void ImGui::UpdateKeyboardInputs()
{
ImGuiContext& g = *GImGui;
ImGuiIO& io = g.IO;
// Synchronize io.KeyMods with individual modifiers io.KeyXXX bools
io.KeyMods = GetMergedKeyModFlags();
// Import legacy keys or verify they are not used
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
if (io.BackendUsingLegacyKeyArrays == 0)
{
// Backend used new io.AddKeyEvent() API: Good! Verify that old arrays are never written too.
for (int n = 0; n < IM_ARRAYSIZE(io.KeysDown); n++)
IM_ASSERT(io.KeysDown[n] == false && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
}
else
{
if (g.FrameCount == 0)
for (int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKey_END; n++)
IM_ASSERT(g.IO.KeyMap[n] == -1 && "Backend is not allowed to write to io.KeyMap[0..511]!");
// Build reverse KeyMap (Named -> Legacy)
for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
if (io.KeyMap[n] != -1)
{
IM_ASSERT(IsLegacyKey((ImGuiKey)io.KeyMap[n]));
io.KeyMap[io.KeyMap[n]] = n;
}
// Import legacy keys into new ones
for (int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKey_END; n++)
if (io.KeysDown[n] || io.BackendUsingLegacyKeyArrays == 1)
{
const ImGuiKey key = (ImGuiKey)(io.KeyMap[n] != -1 ? io.KeyMap[n] : n);
IM_ASSERT(io.KeyMap[n] == -1 || IsNamedKey(key));
io.KeysData[key].Down = io.KeysDown[n];
io.BackendUsingLegacyKeyArrays = 1;
}
}
#endif
// Update keys
for (int i = 0; i < IM_ARRAYSIZE(io.KeysData); i++)
{
ImGuiKeyData& key_data = io.KeysData[i];
key_data.DownDurationPrev = key_data.DownDuration;
key_data.DownDuration = key_data.Down ? (key_data.DownDuration < 0.0f ? 0.0f : key_data.DownDuration + io.DeltaTime) : -1.0f;
}
}
static void ImGui::UpdateMouseInputs()
{
ImGuiContext& g = *GImGui;
@ -4098,7 +4222,7 @@ void ImGui::NewFrame()
{
g.ActiveIdUsingNavDirMask = 0x00;
g.ActiveIdUsingNavInputMask = 0x00;
g.ActiveIdUsingKeyInputMask = 0x00;
g.ActiveIdUsingKeyInputMask.ClearAllBits();
}
// Drag and drop
@ -4122,11 +4246,7 @@ void ImGui::NewFrame()
}
// Update keyboard input state
// Synchronize io.KeyMods with individual modifiers io.KeyXXX bools
g.IO.KeyMods = GetMergedKeyModFlags();
memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration));
for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++)
g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f;
UpdateKeyboardInputs();
// Update gamepad/keyboard navigation
NavUpdate();
@ -4893,7 +5013,7 @@ void ImGui::SetActiveIdUsingNavAndKeys()
IM_ASSERT(g.ActiveId != 0);
g.ActiveIdUsingNavDirMask = ~(ImU32)0;
g.ActiveIdUsingNavInputMask = ~(ImU32)0;
g.ActiveIdUsingKeyInputMask = ~(ImU64)0;
g.ActiveIdUsingKeyInputMask.SetAllBits();
NavMoveRequestCancel();
}
@ -7260,22 +7380,78 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c
return true;
}
int ImGui::GetKeyIndex(ImGuiKey imgui_key)
const ImGuiKeyData* ImGui::GetKeyData(ImGuiKey key)
{
IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT);
ImGuiContext& g = *GImGui;
return g.IO.KeyMap[imgui_key];
int index;
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
IM_ASSERT(key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_NamedKey_END);
if (IsLegacyKey(key))
index = (g.IO.KeyMap[key] != -1) ? g.IO.KeyMap[key] : key; // Remap native->imgui or imgui->native
else
index = key;
#else
IM_ASSERT(IsNamedKey(key) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend & user code.");
index = key - ImGuiKey_NamedKey_BEGIN;
#endif
return &g.IO.KeysData[index];
}
// 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)
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
int ImGui::GetKeyIndex(ImGuiKey key)
{
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];
IM_ASSERT(IsNamedKey(key));
const ImGuiKeyData* key_data = GetKeyData(key);
return (int)(key_data - g.IO.KeysData);
}
#endif
// Those names a provided for debugging purpose and are not meant to be saved persistently not compared.
static const char* const GKeyNames[] =
{
"Tab", "LeftArrow", "RightArrow", "UpArrow", "DownArrow", "PageUp", "PageDown",
"Home", "End", "Insert", "Delete", "Backspace", "Space", "Enter", "Escape",
"Apostrophe", "Comma", "Minus", "Period", "Slash", "Semicolon", "Equal", "LeftBracket",
"Backslash", "RightBracket", "GraveAccent", "CapsLock", "ScrollLock", "NumLock", "PrintScreen",
"Pause", "Keypad0", "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6",
"Keypad7", "Keypad8", "Keypad9", "KeypadDecimal", "KeypadDivide", "KeypadMultiply",
"KeypadSubtract", "KeypadAdd", "KeypadEnter", "KeypadEqual", "LeftShift", "LeftControl",
"LeftAlt", "LeftSuper", "RightShift", "RightControl", "RightAlt", "RightSuper", "Menu",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H",
"I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12"
};
IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT == IM_ARRAYSIZE(GKeyNames));
const char* ImGui::GetKeyName(ImGuiKey key)
{
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
IM_ASSERT(IsNamedKey(key) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code.");
#else
if (IsLegacyKey(key))
{
ImGuiIO& io = GetIO();
if (io.KeyMap[key] == -1)
return "N/A";
IM_ASSERT(IsNamedKey((ImGuiKey)io.KeyMap[key]));
key = (ImGuiKey)io.KeyMap[key];
}
#endif
if (key == ImGuiKey_None)
return "None";
if (!IsNamedKey(key))
return "Unknown";
return GKeyNames[key - ImGuiKey_NamedKey_BEGIN];
}
// Note that Dear ImGui doesn't know the meaning/semantic of ImGuiKey from 0..511: they are legacy native keycodes.
// Consider transitioning from 'IsKeyDown(MY_ENGINE_KEY_A)' (<1.87) to IsKeyDown(ImGuiKey_A) (>= 1.87)
bool ImGui::IsKeyDown(ImGuiKey key)
{
const ImGuiKeyData* key_data = GetKeyData(key);
return key_data->Down;
}
// t0 = previous time (e.g.: g.Time - g.IO.DeltaTime)
@ -7296,36 +7472,30 @@ int ImGui::CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, flo
return count;
}
int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate)
int ImGui::GetKeyPressedAmount(ImGuiKey key, 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];
const ImGuiKeyData* key_data = GetKeyData(key);
const float t = key_data->DownDuration;
return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, repeat_delay, repeat_rate);
}
bool ImGui::IsKeyPressed(int user_key_index, bool repeat)
bool ImGui::IsKeyPressed(ImGuiKey key, 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];
const ImGuiKeyData* key_data = GetKeyData(key);
const float t = key_data->DownDuration;
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 GetKeyPressedAmount(key, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
return false;
}
bool ImGui::IsKeyReleased(int user_key_index)
bool ImGui::IsKeyReleased(ImGuiKey key)
{
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];
const ImGuiKeyData* key_data = GetKeyData(key);
return key_data->DownDurationPrev >= 0.0f && !key_data->Down;
}
bool ImGui::IsMouseDown(ImGuiMouseButton button)
@ -7420,6 +7590,7 @@ bool ImGui::IsMousePosValid(const ImVec2* mouse_pos)
return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID;
}
// [WILL OBSOLETE] This was designed for backends, but prefer having backend maintain a mask of held mouse buttons, because upcoming input queue system will make this invalid.
bool ImGui::IsAnyMouseDown()
{
ImGuiContext& g = *GImGui;
@ -7477,6 +7648,13 @@ void ImGui::CaptureMouseFromApp(bool capture)
g.WantCaptureMouseNextFrame = capture ? 1 : 0;
}
static const char* GetInputSourceName(ImGuiInputSource source)
{
const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad", "Nav", "Clipboard" };
IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT && source >= 0 && source < ImGuiInputSource_COUNT);
return input_source_names[source];
}
//-----------------------------------------------------------------------------
// [SECTION] ERROR CHECKING
@ -7524,12 +7702,14 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting!"); // Allows us to avoid a few clamps in color computations
IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting.");
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
for (int n = 0; n < ImGuiKey_COUNT; n++)
IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)");
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_COUNT; n++)
IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..511, or -1 for unmapped key)");
// Check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only added in 1.60 WIP)
if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)
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))
@ -9552,6 +9732,18 @@ static ImVec2 ImGui::NavCalcPreferredRefPos()
}
}
const char* ImGui::GetNavInputName(ImGuiNavInput n)
{
static const char* names[] =
{
"Activate", "Cancel", "Input", "Menu", "DpadLeft", "DpadRight", "DpadUp", "DpadDown", "LStickLeft", "LStickRight", "LStickUp", "LStickDown",
"FocusPrev", "FocusNext", "TweakSlow", "TweakFast", "KeyLeft", "KeyRight", "KeyUp", "KeyDown"
};
IM_ASSERT(IM_ARRAYSIZE(names) == ImGuiNavInput_COUNT);
IM_ASSERT(n >= 0 && n < ImGuiNavInput_COUNT);
return names[n];
}
float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode)
{
ImGuiContext& g = *GImGui;
@ -9578,7 +9770,7 @@ ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInput
{
ImVec2 delta(0.0f, 0.0f);
if (dir_sources & ImGuiNavDirSourceFlags_RawKeyboard)
delta += ImVec2((float)IsKeyDown(GetKeyIndex(ImGuiKey_RightArrow)) - (float)IsKeyDown(GetKeyIndex(ImGuiKey_LeftArrow)), (float)IsKeyDown(GetKeyIndex(ImGuiKey_DownArrow)) - (float)IsKeyDown(GetKeyIndex(ImGuiKey_UpArrow)));
delta += ImVec2((float)IsKeyDown(ImGuiKey_RightArrow) - (float)IsKeyDown(ImGuiKey_LeftArrow), (float)IsKeyDown(ImGuiKey_DownArrow) - (float)IsKeyDown(ImGuiKey_UpArrow));
if (dir_sources & ImGuiNavDirSourceFlags_Keyboard)
delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight_, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft_, mode), GetNavInputAmount(ImGuiNavInput_KeyDown_, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp_, mode));
if (dir_sources & ImGuiNavDirSourceFlags_PadDPad)
@ -9614,7 +9806,7 @@ static void ImGui::NavUpdate()
// Update Keyboard->Nav inputs mapping
if (nav_keyboard_active)
{
#define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(io.KeyMap[_KEY])) { io.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_Keyboard; } } while (0)
#define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(_KEY)) { io.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_Keyboard; } } while (0)
NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate );
NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input );
NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel );
@ -9832,7 +10024,7 @@ void ImGui::NavUpdateCreateMoveRequest()
// [DEBUG] Always send a request
#if IMGUI_DEBUG_NAV_SCORING
if (io.KeyCtrl && IsKeyPressedMap(ImGuiKey_C))
if (io.KeyCtrl && IsKeyPressed(ImGuiKey_C))
g.NavMoveDirForDebug = (ImGuiDir)((g.NavMoveDirForDebug + 1) & 3);
if (io.KeyCtrl && g.NavMoveDir == ImGuiDir_None)
{
@ -9896,7 +10088,7 @@ void ImGui::NavUpdateCreateTabbingRequest()
if (window == NULL || g.NavWindowingTarget != NULL || (window->Flags & ImGuiWindowFlags_NoNavInputs))
return;
const bool tab_pressed = IsKeyPressedMap(ImGuiKey_Tab, true) && !IsActiveIdUsingKey(ImGuiKey_Tab) && !g.IO.KeyCtrl && !g.IO.KeyAlt;
const bool tab_pressed = IsKeyPressed(ImGuiKey_Tab, true) && !IsActiveIdUsingKey(ImGuiKey_Tab) && !g.IO.KeyCtrl && !g.IO.KeyAlt;
if (!tab_pressed)
return;
@ -10057,16 +10249,14 @@ static void ImGui::NavUpdateCancelRequest()
static float ImGui::NavUpdatePageUpPageDown()
{
ImGuiContext& g = *GImGui;
ImGuiIO& io = g.IO;
ImGuiWindow* window = g.NavWindow;
if ((window->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget != NULL)
return 0.0f;
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);
const bool page_up_held = IsKeyDown(ImGuiKey_PageUp) && !IsActiveIdUsingKey(ImGuiKey_PageUp);
const bool page_down_held = IsKeyDown(ImGuiKey_PageDown) && !IsActiveIdUsingKey(ImGuiKey_PageDown);
const bool home_pressed = IsKeyPressed(ImGuiKey_Home) && !IsActiveIdUsingKey(ImGuiKey_Home);
const bool end_pressed = IsKeyPressed(ImGuiKey_End) && !IsActiveIdUsingKey(ImGuiKey_End);
if (page_up_held == page_down_held && home_pressed == end_pressed) // Proceed if either (not both) are pressed, otherwise early out
return 0.0f;
@ -10076,9 +10266,9 @@ static float ImGui::NavUpdatePageUpPageDown()
if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll)
{
// Fallback manual-scroll when window has no navigable item
if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true))
if (IsKeyPressed(ImGuiKey_PageUp, true))
SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
else if (IsKeyPressed(io.KeyMap[ImGuiKey_PageDown], true))
else if (IsKeyPressed(ImGuiKey_PageDown, true))
SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
else if (home_pressed)
SetScrollY(window, 0.0f);
@ -10090,14 +10280,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(io.KeyMap[ImGuiKey_PageUp], true))
if (IsKeyPressed(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.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
}
else if (IsKeyPressed(io.KeyMap[ImGuiKey_PageDown], true))
else if (IsKeyPressed(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)
@ -10262,7 +10452,7 @@ static void ImGui::NavUpdateWindowing()
// Start CTRL+Tab or Square+L/R window selection
const bool start_windowing_with_gamepad = allow_windowing && !g.NavWindowingTarget && IsNavInputTest(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed);
const bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowingTarget && io.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab);
const bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowingTarget && io.KeyCtrl && IsKeyPressed(ImGuiKey_Tab);
if (start_windowing_with_gamepad || start_windowing_with_keyboard)
if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
{
@ -10304,7 +10494,7 @@ static void ImGui::NavUpdateWindowing()
{
// Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise
g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f
if (IsKeyPressedMap(ImGuiKey_Tab, true))
if (IsKeyPressed(ImGuiKey_Tab, true))
NavUpdateWindowingHighlightWindow(io.KeyShift ? +1 : -1);
if (!io.KeyCtrl)
apply_focus_window = g.NavWindowingTarget;
@ -11930,8 +12120,6 @@ void ImGui::ShowMetricsWindow(bool* p_open)
// Misc Details
if (TreeNode("Internal state"))
{
const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad", "Nav", "Clipboard" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT);
Text("WINDOWING");
Indent();
Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL");
@ -11942,9 +12130,13 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Text("ITEMS");
Indent();
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]);
Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, GetInputSourceName(g.ActiveIdSource));
Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL");
Text("ActiveIdUsing: Wheel: %d, NavDirMask: %X, NavInputMask: %X, KeyInputMask: %llX", g.ActiveIdUsingMouseWheel, g.ActiveIdUsingNavDirMask, g.ActiveIdUsingNavInputMask, g.ActiveIdUsingKeyInputMask);
int active_id_using_key_input_count = 0;
for (int n = 0; n < g.ActiveIdUsingKeyInputMask.Size; n++)
active_id_using_key_input_count += g.ActiveIdUsingKeyInputMask.TestBit(n) ? 1 : 0;
Text("ActiveIdUsing: Wheel: %d, NavDirMask: %X, NavInputMask: %X, KeyInputMask: %d key(s)", g.ActiveIdUsingMouseWheel, g.ActiveIdUsingNavDirMask, g.ActiveIdUsingNavInputMask, active_id_using_key_input_count);
Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Not displaying g.HoveredId as it is update mid-frame
Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
Unindent();
@ -11953,7 +12145,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Indent();
Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL");
Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer);
Text("NavInputSource: %s", input_source_names[g.NavInputSource]);
Text("NavInputSource: %s", GetInputSourceName(g.NavInputSource));
Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible);
Text("NavActivateId/DownId/PressedId/InputId: %08X/%08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId, g.NavActivatePressedId, g.NavActivateInputId);
Text("NavActivateFlags: %04X", g.NavActivateFlags);
@ -12462,7 +12654,7 @@ void ImGui::UpdateDebugToolItemPicker()
const ImGuiID hovered_id = g.HoveredIdPreviousFrame;
SetMouseCursor(ImGuiMouseCursor_Hand);
if (IsKeyPressedMap(ImGuiKey_Escape))
if (IsKeyPressed(ImGuiKey_Escape))
g.DebugItemPickerActive = false;
if (IsMouseClicked(0) && hovered_id)
{

View File

@ -65,7 +65,7 @@ Index of this file:
// Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.87 WIP"
#define IMGUI_VERSION_NUM 18603
#define IMGUI_VERSION_NUM 18605
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE
@ -152,6 +152,7 @@ struct ImColor; // Helper functions to create a color that c
struct ImGuiContext; // Dear ImGui context (opaque structure, unless including imgui_internal.h)
struct ImGuiIO; // Main configuration and I/O between your application and ImGui
struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use)
struct ImGuiKeyData; // Storage for ImGuiIO and IsKeyDown(), IsKeyPressed() etc functions.
struct ImGuiListClipper; // Helper to manually clip large list of items
struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame
struct ImGuiPayload; // User data payload for drag and drop operations
@ -173,7 +174,7 @@ typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A
typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions
typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type
typedef int ImGuiDir; // -> enum ImGuiDir_ // Enum: A cardinal direction
typedef int ImGuiKey; // -> enum ImGuiKey_ // Enum: A key identifier (ImGui-side enum)
typedef int ImGuiKey; // -> enum ImGuiKey_ // Enum: A key identifier
typedef int ImGuiNavInput; // -> enum ImGuiNavInput_ // Enum: An input identifier for navigation
typedef int ImGuiMouseButton; // -> enum ImGuiMouseButton_ // Enum: A mouse button identifier (0=left, 1=right, 2=middle)
typedef int ImGuiMouseCursor; // -> enum ImGuiMouseCursor_ // Enum: A mouse cursor identifier
@ -884,13 +885,16 @@ namespace ImGui
IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b);
// Inputs Utilities: Keyboard
// - For 'int user_key_index' you can use your own indices/enums according to how your backend/engine stored them in io.KeysDown[].
// - We don't know the meaning of those value. You can use GetKeyIndex() to map a ImGuiKey_ value into the user index.
IMGUI_API int GetKeyIndex(ImGuiKey imgui_key); // map ImGuiKey_* values into user's key index. == io.KeyMap[key]
IMGUI_API bool IsKeyDown(int user_key_index); // is key being held. == io.KeysDown[user_key_index].
IMGUI_API bool IsKeyPressed(int user_key_index, bool repeat = true); // was key pressed (went from !Down to Down)? if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate
IMGUI_API bool IsKeyReleased(int user_key_index); // was key released (went from Down to !Down)?
IMGUI_API int GetKeyPressedAmount(int key_index, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate
// Without IMGUI_DISABLE_OBSOLETE_KEYIO: (legacy support)
// - For 'ImGuiKey key' you can still use your legacy native/user indices according to how your backend/engine stored them in io.KeysDown[].
// With IMGUI_DISABLE_OBSOLETE_KEYIO: (this is the way forward)
// - Any use of 'ImGuiKey' will assert when key < 512 will be passed, previously reserved as native/user keys indices
// - GetKeyIndex() is pass-through and therefore deprecated (gone if IMGUI_DISABLE_OBSOLETE_KEYIO is defined)
IMGUI_API bool IsKeyDown(ImGuiKey key); // is key being held.
IMGUI_API bool IsKeyPressed(ImGuiKey key, bool repeat = true); // was key pressed (went from !Down to Down)? if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate
IMGUI_API bool IsKeyReleased(ImGuiKey key); // was key released (went from Down to !Down)?
IMGUI_API int GetKeyPressedAmount(ImGuiKey key, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate
IMGUI_API const char* GetKeyName(ImGuiKey key); // [DEBUG] returns English name of the key. Those names a provided for debugging purpose and are not meant to be saved persistently not compared.
IMGUI_API void CaptureKeyboardFromApp(bool want_capture_keyboard_value = true); // attention: misleading name! manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application to handle). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard_value"; after the next NewFrame() call.
// Inputs Utilities: Mouse
@ -904,7 +908,7 @@ namespace ImGui
IMGUI_API int GetMouseClickedCount(ImGuiMouseButton button); // return the number of successive mouse-clicks at the time where a click happen (otherwise 0).
IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block.
IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available
IMGUI_API bool IsAnyMouseDown(); // is any mouse button held?
IMGUI_API bool IsAnyMouseDown(); // [WILL OBSOLETE] is any mouse button held? This was designed for backends, but prefer having backend maintain a mask of held mouse buttons, because upcoming input queue system will make this invalid.
IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls
IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve mouse position at the time of opening popup we have BeginPopup() into (helper to avoid user backing that value themselves)
IMGUI_API bool IsMouseDragging(ImGuiMouseButton button, float lock_threshold = -1.0f); // is mouse dragging? (if lock_threshold < -1.0f, uses io.MouseDraggingThreshold)
@ -1349,10 +1353,10 @@ enum ImGuiSortDirection_
ImGuiSortDirection_Descending = 2 // Descending = 9->0, Z->A etc.
};
// User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array
enum ImGuiKey_
{
ImGuiKey_Tab,
ImGuiKey_None = 0,
ImGuiKey_Tab = 512, // == ImGuiKey_NamedKey_BEGIN
ImGuiKey_LeftArrow,
ImGuiKey_RightArrow,
ImGuiKey_UpArrow,
@ -1367,14 +1371,113 @@ enum ImGuiKey_
ImGuiKey_Space,
ImGuiKey_Enter,
ImGuiKey_Escape,
ImGuiKey_Apostrophe, // '
ImGuiKey_Comma, // ,
ImGuiKey_Minus, // -
ImGuiKey_Period, // .
ImGuiKey_Slash, // /
ImGuiKey_Semicolon, // ;
ImGuiKey_Equal, // =
ImGuiKey_LeftBracket, // [
ImGuiKey_Backslash, // \ (this text inhibit multiline comment caused by backlash)
ImGuiKey_RightBracket, // ]
ImGuiKey_GraveAccent, // `
ImGuiKey_CapsLock,
ImGuiKey_ScrollLock,
ImGuiKey_NumLock,
ImGuiKey_PrintScreen,
ImGuiKey_Pause,
ImGuiKey_Keypad0,
ImGuiKey_Keypad1,
ImGuiKey_Keypad2,
ImGuiKey_Keypad3,
ImGuiKey_Keypad4,
ImGuiKey_Keypad5,
ImGuiKey_Keypad6,
ImGuiKey_Keypad7,
ImGuiKey_Keypad8,
ImGuiKey_Keypad9,
ImGuiKey_KeypadDecimal,
ImGuiKey_KeypadDivide,
ImGuiKey_KeypadMultiply,
ImGuiKey_KeypadSubtract,
ImGuiKey_KeypadAdd,
ImGuiKey_KeypadEnter,
ImGuiKey_A, // for text edit CTRL+A: select all
ImGuiKey_C, // for text edit CTRL+C: copy
ImGuiKey_V, // for text edit CTRL+V: paste
ImGuiKey_X, // for text edit CTRL+X: cut
ImGuiKey_Y, // for text edit CTRL+Y: redo
ImGuiKey_Z, // for text edit CTRL+Z: undo
ImGuiKey_COUNT
ImGuiKey_KeypadEqual,
ImGuiKey_LeftShift,
ImGuiKey_LeftControl,
ImGuiKey_LeftAlt,
ImGuiKey_LeftSuper,
ImGuiKey_RightShift,
ImGuiKey_RightControl,
ImGuiKey_RightAlt,
ImGuiKey_RightSuper,
ImGuiKey_Menu,
ImGuiKey_0,
ImGuiKey_1,
ImGuiKey_2,
ImGuiKey_3,
ImGuiKey_4,
ImGuiKey_5,
ImGuiKey_6,
ImGuiKey_7,
ImGuiKey_8,
ImGuiKey_9,
ImGuiKey_A,
ImGuiKey_B,
ImGuiKey_C,
ImGuiKey_D,
ImGuiKey_E,
ImGuiKey_F,
ImGuiKey_G,
ImGuiKey_H,
ImGuiKey_I,
ImGuiKey_J,
ImGuiKey_K,
ImGuiKey_L,
ImGuiKey_M,
ImGuiKey_N,
ImGuiKey_O,
ImGuiKey_P,
ImGuiKey_Q,
ImGuiKey_R,
ImGuiKey_S,
ImGuiKey_T,
ImGuiKey_U,
ImGuiKey_V,
ImGuiKey_W,
ImGuiKey_X,
ImGuiKey_Y,
ImGuiKey_Z,
ImGuiKey_F1,
ImGuiKey_F2,
ImGuiKey_F3,
ImGuiKey_F4,
ImGuiKey_F5,
ImGuiKey_F6,
ImGuiKey_F7,
ImGuiKey_F8,
ImGuiKey_F9,
ImGuiKey_F10,
ImGuiKey_F11,
ImGuiKey_F12,
ImGuiKey_COUNT, // No valid ImGuiKey is ever greater than this value
// Legacy range used by legacy io.KeyMap[]. Prior to 1.87 we required user to fill io.KeysDown[512] using their own native index.
// We are ditching this method but keeping a legacy path for user code doing e.g. IsKeyPressed(MY_NATIVE_KEY_CODE)
ImGuiKey_LegacyNativeKey_BEGIN = 0,
ImGuiKey_LegacyNativeKey_END = 512, // First index after valid range
ImGuiKey_NamedKey_BEGIN = 512,
ImGuiKey_NamedKey_END = ImGuiKey_COUNT,
ImGuiKey_NamedKey_COUNT = ImGuiKey_NamedKey_END - ImGuiKey_NamedKey_BEGIN,
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
ImGuiKey_KeysData_SIZE = ImGuiKey_NamedKey_COUNT, // Size of KeysData[]: only hold named keys
ImGuiKey_KeysData_OFFSET = ImGuiKey_NamedKey_BEGIN // First key stored in KeysData[0]
#else
ImGuiKey_KeysData_SIZE = ImGuiKey_COUNT, // Size of KeysData[]: hold legacy 0..512 keycodes + named keys
ImGuiKey_KeysData_OFFSET = ImGuiKey_LegacyNativeKey_BEGIN // First key stored in KeysData[0]
#endif
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
, ImGuiKey_KeyPadEnter = ImGuiKey_KeypadEnter // Renamed in 1.87
#endif
@ -1391,7 +1494,7 @@ enum ImGuiKeyModFlags_
};
// Gamepad/Keyboard navigation
// Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
// Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.AddKeyEvent() calls.
// Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Backend: set ImGuiBackendFlags_HasGamepad and fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame().
// Read instructions in imgui.cpp for more details. Download PNG/PSD at http://dearimgui.org/controls_sheets.
enum ImGuiNavInput_
@ -1415,20 +1518,19 @@ enum ImGuiNavInput_
ImGuiNavInput_TweakFast, // Faster tweaks // e.g. R1 or R2 (PS4), RB or RT (Xbox), R or ZL (Switch)
// [Internal] Don't use directly! This is used internally to differentiate keyboard from gamepad inputs for behaviors that require to differentiate them.
// Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) will be directly reading from io.KeysDown[] instead of io.NavInputs[].
// Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) will be directly reading from keyboard keys instead of io.NavInputs[].
ImGuiNavInput_KeyLeft_, // Move left // = Arrow keys
ImGuiNavInput_KeyRight_, // Move right
ImGuiNavInput_KeyUp_, // Move up
ImGuiNavInput_KeyDown_, // Move down
ImGuiNavInput_COUNT,
ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyLeft_
ImGuiNavInput_COUNT
};
// Configuration flags stored in io.ConfigFlags. Set by user/application.
enum ImGuiConfigFlags_
{
ImGuiConfigFlags_None = 0,
ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeysDown[].
ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.AddKeyEvent() calls
ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui backend to fill io.NavInputs[]. Backend also needs to set ImGuiBackendFlags_HasGamepad.
ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your backend, otherwise ImGui will react as if the mouse is jumping around back and forth.
ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag when io.NavActive is set.
@ -1817,6 +1919,15 @@ struct ImGuiStyle
// Access via ImGui::GetIO(). Read 'Programmer guide' section in .cpp file for general usage.
//-----------------------------------------------------------------------------
// [Internal] Storage used by IsKeyDown(), IsKeyPressed() etc functions.
// If prior to 1.87 you used io.KeysDownDuration[] (which was marked as internal), you should use GetKeyData(key)->DownDuration and not io.KeysData[key]->DownDuration.
struct ImGuiKeyData
{
bool Down; // True for if key is down
float DownDuration; // Duration the key has been down (<0.0f: not pressed, 0.0f: just pressed, >0.0f: time held)
float DownDurationPrev; // Last frame duration the key has been down
};
struct ImGuiIO
{
//------------------------------------------------------------------
@ -1833,7 +1944,6 @@ struct ImGuiIO
float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds.
float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels.
float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging.
int KeyMap[ImGuiKey_COUNT]; // <unset> // Map of indices into the KeysDown[512] entries array which represent your "native" keyboard state.
float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.).
float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds.
void* UserData; // = NULL // Store your own data for retrieval by callbacks.
@ -1892,16 +2002,18 @@ struct ImGuiIO
bool KeyShift; // Keyboard modifier down: Shift
bool KeyAlt; // Keyboard modifier down: Alt
bool KeySuper; // Keyboard modifier down: Cmd/Super/Windows
bool KeysDown[512]; // Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys).
float NavInputs[ImGuiNavInput_COUNT]; // Gamepad inputs. Cleared back to zero by EndFrame(). Keyboard keys will be auto-mapped and be written here by NewFrame().
// Input Functions
IMGUI_API void AddKeyEvent(ImGuiKey key, bool down); // Queue a new key down/up event. Key should be "translated" (as in, generally ImGuiKey_A matches the key end-user would use to emit an 'A' character)
IMGUI_API void AddKeyModsEvent(ImGuiKeyModFlags modifiers);// Queue a change of Ctrl/Shift/Alt/Super modifiers
IMGUI_API void AddFocusEvent(bool focused); // Queue an hosting application/platform windows gain or loss of focus
IMGUI_API void AddInputCharacter(unsigned int c); // Queue new character input
IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue new character input from an UTF-16 character, it can be a surrogate
IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue new characters input from an UTF-8 string
IMGUI_API void ClearInputCharacters(); // [Internal] Clear the text input buffer manually
IMGUI_API void ClearInputKeys(); // [Internal] Release all keys
IMGUI_API void SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native_scancode, int native_legacy_index = -1); // [Optional] Specify index for legacy <1.87 IsKeyXXX() functions with native indices + specify native keycode, scancode.
//------------------------------------------------------------------
// Output - Updated by NewFrame() or EndFrame()/Render()
@ -1924,14 +2036,20 @@ struct ImGuiIO
int MetricsActiveAllocations; // Number of active allocations, updated by MemAlloc/MemFree based on current context. May be off if you have multiple imgui contexts.
ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta.
// Legacy: before 1.87, we required backend to fill io.KeyMap[] (imgui->native map) during initialization and io.KeysDown[] (native indices) every frame.
// This is still temporarily supported as a legacy feature. However the new preferred scheme is for backend to call io.AddKeyEvent().
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
int KeyMap[ImGuiKey_COUNT]; // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512.
bool KeysDown[512]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys).
#endif
//------------------------------------------------------------------
// [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed!
//------------------------------------------------------------------
ImGuiKeyModFlags KeyMods; // Key mods flags (same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags), updated by NewFrame()
ImGuiKeyModFlags KeyModsPrev; // Key mods flags (from previous frame)
float KeysDownDuration[512]; // Duration the key has been down (<0.0f: not pressed, 0.0f: just pressed, >0.0f: time held)
float KeysDownDurationPrev[512]; // Duration the key has been down (from previous frame)
ImGuiKeyData KeysData[ImGuiKey_KeysData_SIZE]; // Key state for all known keys. Use IsKeyXXX() functions to access this.
bool WantCaptureMouseUnlessPopupClose; // Alternative to WantCaptureMouse: (WantCaptureMouse == true && WantCaptureMouseUnlessPopupClose == false) when a click over void is expected to close a popup.
ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid)
@ -1951,6 +2069,7 @@ struct ImGuiIO
float NavInputsDownDurationPrev[ImGuiNavInput_COUNT];
float PenPressure; // Touch/Pen pressure (0.0f to 1.0f, should be >0.0f only when MouseDown[0] == true). Helper storage currently unused by Dear ImGui.
bool AppFocusLost;
ImS8 BackendUsingLegacyKeyArrays; // -1: unknown, 0: using AddKeyEvent(), 1: using legacy io.KeysDown[]
ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16()
ImVector<ImWchar> InputQueueCharacters; // Queue of _characters_ input (obtained by platform backend). Fill using AddInputCharacter() helper.
@ -2848,6 +2967,15 @@ struct ImGuiPlatformImeData
// Please keep your copy of dear imgui up to date! Occasionally set '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in imconfig.h to stay ahead.
//-----------------------------------------------------------------------------
namespace ImGui
{
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
IMGUI_API int GetKeyIndex(ImGuiKey key); // map ImGuiKey_* values into legacy native key index. == io.KeyMap[key]
#else
static inline int GetKeyIndex(ImGuiKey key) { IM_ASSERT(key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END && "ImGuiKey and native_index was merged together and native_index is disabled by IMGUI_DISABLE_OBSOLETE_KEYIO. Please switch to ImGuiKey."); return key; }
#endif
}
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
namespace ImGui
{

View File

@ -454,7 +454,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::SameLine();
ImGui::Text("<<PRESS SPACE TO DISABLE>>");
}
if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space)))
if (ImGui::IsKeyPressed(ImGuiKey_Space))
io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
}
ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
@ -5639,6 +5639,8 @@ static void ShowDemoWindowColumns()
ImGui::TreePop();
}
namespace ImGui { extern const ImGuiKeyData* GetKeyData(ImGuiKey key); }
static void ShowDemoWindowMisc()
{
IMGUI_DEMO_MARKER("Filtering");
@ -5695,15 +5697,26 @@ static void ShowDemoWindowMisc()
IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Keyboard & Navigation State");
if (ImGui::TreeNode("Keyboard & Navigation State"))
{
ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyDown(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X) (%.02f secs)", i, i, io.KeysDownDuration[i]); }
ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
// We iterate both legacy native range and named ImGuiKey ranges, which is a little odd but this allow displaying the data for old/new backends.
// User code should never have to go through such hoops: old code may use native keycodes, new code may use ImGuiKey codes.
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
struct funcs { static bool IsNativeDupe(ImGuiKey) { return false; } };
#else
struct funcs { static bool IsNativeDupe(ImGuiKey key) { return key < ImGuiKey_LegacyNativeKey_END && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array
#endif
ImGui::Text("Keys down:"); for (int i = 0; i < ImGuiKey_KeysData_SIZE; i++) { ImGuiKey key = (ImGuiKey)(i + ImGuiKey_KeysData_OFFSET); if (funcs::IsNativeDupe(key)) continue; if (ImGui::IsKeyDown(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d (0x%X) (%.02f secs)", ImGui::GetKeyName(key), key, key, ImGui::GetKeyData(key)->DownDuration); } }
ImGui::Text("Keys pressed:"); for (int i = 0; i < ImGuiKey_KeysData_SIZE; i++) { ImGuiKey key = (ImGuiKey)(i + ImGuiKey_KeysData_OFFSET); if (funcs::IsNativeDupe(key)) continue; if (ImGui::IsKeyPressed(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d (0x%X)", ImGui::GetKeyName(key), key, key); } }
ImGui::Text("Keys released:"); for (int i = 0; i < ImGuiKey_KeysData_SIZE; i++) { ImGuiKey key = (ImGuiKey)(i + ImGuiKey_KeysData_OFFSET); if (funcs::IsNativeDupe(key)) continue; if (ImGui::IsKeyReleased(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d (0x%X)", ImGui::GetKeyName(key), key, key); } }
ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f (%.02f secs)", i, io.NavInputs[i], io.NavInputsDownDuration[i]); }
ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); }
ImGui::TreePop();
}
if (ImGui::TreeNode("Capture override"))
{
ImGui::Button("Hovering me sets the\nkeyboard capture flag");
if (ImGui::IsItemHovered())
ImGui::CaptureKeyboardFromApp(true);
@ -5868,6 +5881,9 @@ void ImGui::ShowAboutWindow(bool* p_open)
#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS");
#endif
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_KEYIO");
#endif
#ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS");
#endif
@ -5981,7 +5997,7 @@ void ImGui::ShowAboutWindow(bool* p_open)
namespace ImGui { IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); }
// Demo helper function to select among loaded fonts.
// Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.
// Here we use the regular BeginCombo()/EndCombo() api which is the more flexible one.
void ImGui::ShowFontSelector(const char* label)
{
ImGuiIO& io = ImGui::GetIO();

View File

@ -441,7 +441,7 @@ static inline float ImLengthSqr(const ImVec2& lhs)
static inline float ImLengthSqr(const ImVec4& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y) + (lhs.z * lhs.z) + (lhs.w * lhs.w); }
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return ImRsqrt(d); return fail_value; }
static inline float ImFloor(float f) { return (float)(int)(f); }
static inline float ImFloorSigned(float f) { return (float)((f >= 0 || (int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
static inline float ImFloorSigned(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); }
static inline int ImModPositive(int a, int b) { return (a + b) % b; }
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
@ -543,6 +543,7 @@ inline void ImBitArraySetBitRange(ImU32* arr, int n, int n2) // Works on ran
template<int BITCOUNT>
struct IMGUI_API ImBitArray
{
static const int Size = BITCOUNT;
ImU32 Storage[(BITCOUNT + 31) >> 5];
ImBitArray() { ClearAllBits(); }
void ClearAllBits() { memset(Storage, 0, sizeof(Storage)); }
@ -552,6 +553,8 @@ struct IMGUI_API ImBitArray
void ClearBit(int n) { IM_ASSERT(n < BITCOUNT); ImBitArrayClearBit(Storage, n); }
void SetBitRange(int n, int n2) { ImBitArraySetBitRange(Storage, n, n2); } // Works on range [n..n2)
};
template<int BITCOUNT>
const int ImBitArray<BITCOUNT>::Size;
// Helper: ImBitVector
// Store 1-bit per value.
@ -1553,7 +1556,7 @@ struct ImGuiContext
bool ActiveIdUsingMouseWheel; // Active widget will want to read mouse wheel. Blocks scrolling the underlying window.
ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it)
ImU32 ActiveIdUsingNavInputMask; // Active widget will want to read those nav inputs.
ImU64 ActiveIdUsingKeyInputMask; // Active widget will want to read those key inputs. When we grow the ImGuiKey enum we'll need to either to order the enum to make useful keys come first, either redesign this into e.g. a small array.
ImBitArray<ImGuiKey_NamedKey_COUNT> ActiveIdUsingKeyInputMask; // Active widget will want to read those key inputs. When we grow the ImGuiKey enum we'll need to either to order the enum to make useful keys come first, either redesign this into e.g. a small array.
ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
ImGuiWindow* ActiveIdWindow;
ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard)
@ -1789,7 +1792,7 @@ struct ImGuiContext
ActiveIdUsingMouseWheel = false;
ActiveIdUsingNavDirMask = 0x00;
ActiveIdUsingNavInputMask = 0x00;
ActiveIdUsingKeyInputMask = 0x00;
ActiveIdUsingKeyInputMask.ClearAllBits();
ActiveIdClickOffset = ImVec2(-1, -1);
ActiveIdWindow = NULL;
ActiveIdSource = ImGuiInputSource_None;
@ -2574,6 +2577,7 @@ namespace ImGui
IMGUI_API void NavMoveRequestCancel();
IMGUI_API void NavMoveRequestApplyResult();
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
IMGUI_API const char* GetNavInputName(ImGuiNavInput n);
IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode);
IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f);
IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate);
@ -2590,16 +2594,22 @@ namespace ImGui
// Inputs
// FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
inline bool IsNamedKey(ImGuiKey key) { return key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END; }
inline bool IsLegacyKey(ImGuiKey key) { return key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_LegacyNativeKey_END; }
IMGUI_API const ImGuiKeyData* GetKeyData(ImGuiKey key);
IMGUI_API void SetItemUsingMouseWheel();
IMGUI_API void SetActiveIdUsingNavAndKeys();
inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; }
inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; }
inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; }
inline bool IsActiveIdUsingKey(ImGuiKey key) { IM_ASSERT(IsNamedKey(key)); ImGuiContext& g = *GImGui; return g.ActiveIdUsingKeyInputMask.TestBit(key - ImGuiKey_NamedKey_BEGIN); }
inline void SetActiveIdUsingKey(ImGuiKey key) { IM_ASSERT(IsNamedKey(key)); ImGuiContext& g = *GImGui; g.ActiveIdUsingKeyInputMask.SetBit(key - ImGuiKey_NamedKey_BEGIN); }
IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f);
inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { ImGuiContext& g = *GImGui; const int key_index = g.IO.KeyMap[key]; return (key_index >= 0) ? IsKeyPressed(key_index, repeat) : false; }
inline bool IsNavInputDown(ImGuiNavInput n) { ImGuiContext& g = *GImGui; return g.IO.NavInputs[n] > 0.0f; }
inline bool IsNavInputTest(ImGuiNavInput n, ImGuiInputReadMode rm) { return (GetNavInputAmount(n, rm) > 0.0f); }
IMGUI_API ImGuiKeyModFlags GetMergedKeyModFlags();
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); }
#endif
// Drag and Drop
IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id);

View File

@ -4132,11 +4132,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory))
g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);
g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_Home) | ((ImU64)1 << ImGuiKey_End);
SetActiveIdUsingKey(ImGuiKey_Home);
SetActiveIdUsingKey(ImGuiKey_End);
if (is_multiline)
g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_PageUp) | ((ImU64)1 << ImGuiKey_PageDown);
if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character.
g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_Tab);
{
SetActiveIdUsingKey(ImGuiKey_PageUp);
SetActiveIdUsingKey(ImGuiKey_PageDown);
}
if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character.
{
SetActiveIdUsingKey(ImGuiKey_Tab);
}
}
// We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function)
@ -4266,7 +4272,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// It is ill-defined whether the backend needs to send a \t character when pressing the TAB keys.
// Win32 and GLFW naturally do it but not SDL.
const bool ignore_char_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper);
if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !ignore_char_inputs && !io.KeyShift && !is_readonly)
if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressed(ImGuiKey_Tab) && !ignore_char_inputs && !io.KeyShift && !is_readonly)
if (!io.InputQueueCharacters.contains('\t'))
{
unsigned int c = '\t'; // Insert TAB
@ -4313,27 +4319,27 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const bool is_shift_key_only = (io.KeyMods == ImGuiKeyModFlags_Shift);
const bool is_shortcut_key = g.IO.ConfigMacOSXBehaviors ? (io.KeyMods == ImGuiKeyModFlags_Super) : (io.KeyMods == ImGuiKeyModFlags_Ctrl);
const bool is_cut = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_X)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Delete))) && !is_readonly && !is_password && (!is_multiline || state->HasSelection());
const bool is_copy = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_C)) || (is_ctrl_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_password && (!is_multiline || state->HasSelection());
const bool is_paste = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_V)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_readonly;
const bool is_undo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Z)) && !is_readonly && is_undoable);
const bool is_redo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressedMap(ImGuiKey_Z))) && !is_readonly && is_undoable;
const bool is_cut = ((is_shortcut_key && IsKeyPressed(ImGuiKey_X)) || (is_shift_key_only && IsKeyPressed(ImGuiKey_Delete))) && !is_readonly && !is_password && (!is_multiline || state->HasSelection());
const bool is_copy = ((is_shortcut_key && IsKeyPressed(ImGuiKey_C)) || (is_ctrl_key_only && IsKeyPressed(ImGuiKey_Insert))) && !is_password && (!is_multiline || state->HasSelection());
const bool is_paste = ((is_shortcut_key && IsKeyPressed(ImGuiKey_V)) || (is_shift_key_only && IsKeyPressed(ImGuiKey_Insert))) && !is_readonly;
const bool is_undo = ((is_shortcut_key && IsKeyPressed(ImGuiKey_Z)) && !is_readonly && is_undoable);
const bool is_redo = ((is_shortcut_key && IsKeyPressed(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressed(ImGuiKey_Z))) && !is_readonly && is_undoable;
// We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful.
const bool is_validate_enter = IsKeyPressedMap(ImGuiKey_Enter) || IsKeyPressedMap(ImGuiKey_KeypadEnter);
const bool is_validate_nav = (IsNavInputTest(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed) && !IsKeyPressedMap(ImGuiKey_Space)) || IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed);
const bool is_cancel = IsKeyPressedMap(ImGuiKey_Escape) || IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed);
const bool is_validate_enter = IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_KeypadEnter);
const bool is_validate_nav = (IsNavInputTest(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed) && !IsKeyPressed(ImGuiKey_Space)) || IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed);
const bool is_cancel = IsKeyPressed(ImGuiKey_Escape) || IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed);
if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_PageUp) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGUP | k_mask); scroll_y -= row_count_per_page * g.FontSize; }
else if (IsKeyPressedMap(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly && !is_cut) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Backspace) && !is_readonly)
if (IsKeyPressed(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
else if (IsKeyPressed(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
else if (IsKeyPressed(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); }
else if (IsKeyPressed(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); }
else if (IsKeyPressed(ImGuiKey_PageUp) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGUP | k_mask); scroll_y -= row_count_per_page * g.FontSize; }
else if (IsKeyPressed(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
else if (IsKeyPressed(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
else if (IsKeyPressed(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
else if (IsKeyPressed(ImGuiKey_Delete) && !is_readonly && !is_cut) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
else if (IsKeyPressed(ImGuiKey_Backspace) && !is_readonly)
{
if (!state->HasSelection())
{
@ -4372,7 +4378,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state->OnKeyPressed(is_undo ? STB_TEXTEDIT_K_UNDO : STB_TEXTEDIT_K_REDO);
state->ClearSelection();
}
else if (is_shortcut_key && IsKeyPressedMap(ImGuiKey_A))
else if (is_shortcut_key && IsKeyPressed(ImGuiKey_A))
{
state->SelectAll();
state->CursorFollow = true;
@ -4478,18 +4484,18 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment.
ImGuiInputTextFlags event_flag = 0;
ImGuiKey event_key = ImGuiKey_COUNT;
if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && IsKeyPressedMap(ImGuiKey_Tab))
ImGuiKey event_key = ImGuiKey_None;
if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && IsKeyPressed(ImGuiKey_Tab))
{
event_flag = ImGuiInputTextFlags_CallbackCompletion;
event_key = ImGuiKey_Tab;
}
else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_UpArrow))
else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressed(ImGuiKey_UpArrow))
{
event_flag = ImGuiInputTextFlags_CallbackHistory;
event_key = ImGuiKey_UpArrow;
}
else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_DownArrow))
else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressed(ImGuiKey_DownArrow))
{
event_flag = ImGuiInputTextFlags_CallbackHistory;
event_key = ImGuiKey_DownArrow;