Added ImGuiKey_MouseXXX aliases. (#4921) Reworked SetItemUsingMouseWheel() to use this for ActiveId. (#2891)

The rework of SetItemUsingMouseWheel() is half-complete since there's a HoveredIdUsingMouseWheel component. This will however be totally cleaned when we transtion to InputOwner system.
This commit is contained in:
ocornut 2022-07-08 18:32:25 +02:00
parent 105bb3ef8a
commit 1480bc5d4e
4 changed files with 41 additions and 17 deletions

View File

@ -56,7 +56,10 @@ Other Changes:
- InputText: added experimental io.ConfigInputTextEnterKeepActive feature to make pressing - InputText: added experimental io.ConfigInputTextEnterKeepActive feature to make pressing
Enter keep the input active and select all text. Enter keep the input active and select all text.
- IO: Added ImGuiKey_MouseXXX aliases for mouse buttons/wheel so all operations done on ImGuiKey
can apply to mouse data as well. (#4921)
- Nav: Fixed moving/resizing window with gamepad or keyboard when running at very high framerate. - Nav: Fixed moving/resizing window with gamepad or keyboard when running at very high framerate.
- Nav: Pressing Space/GamepadFaceDown on a repeating button uses the same repeating rate as a mouse hold.
- Misc: io.Framerate moving average now converge in 60 frames instead of 120. (#5236, #4138) - Misc: io.Framerate moving average now converge in 60 frames instead of 120. (#5236, #4138)
- Tools: Item Picker: Mouse button can be changed by holding Ctrl+Shift, making it easier - Tools: Item Picker: Mouse button can be changed by holding Ctrl+Shift, making it easier
to use the Item Picker in e.g. menus. (#2673) to use the Item Picker in e.g. menus. (#2673)

View File

@ -1278,6 +1278,7 @@ void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context."); IM_ASSERT(&g.IO == this && "Can only add events to current context.");
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. 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.
IM_ASSERT(!ImGui::IsAliasKey(key)); // Backend cannot submit ImGuiKey_MouseXXX values they are automatically inferred from AddMouseXXX() events.
// Verify that backend isn't mixing up using new io.AddKeyEvent() api and old io.KeysDown[] + io.KeyMap[] data. // Verify that backend isn't mixing up using new io.AddKeyEvent() api and old io.KeysDown[] + io.KeyMap[] data.
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
@ -3423,7 +3424,6 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
// Clear declaration of inputs claimed by the widget // Clear declaration of inputs claimed by the widget
// (Please note that this is WIP and not all keys/inputs are thoroughly declared by all widgets yet) // (Please note that this is WIP and not all keys/inputs are thoroughly declared by all widgets yet)
g.ActiveIdUsingMouseWheel = false;
g.ActiveIdUsingNavDirMask = 0x00; g.ActiveIdUsingNavDirMask = 0x00;
g.ActiveIdUsingKeyInputMask.ClearAllBits(); g.ActiveIdUsingKeyInputMask.ClearAllBits();
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
@ -3961,6 +3961,14 @@ static bool IsWindowActiveAndVisible(ImGuiWindow* window)
return (window->Active) && (!window->Hidden); return (window->Active) && (!window->Hidden);
} }
static void UpdateAliasKey(ImGuiKey key, bool v, float analog_value)
{
IM_ASSERT(ImGui::IsAliasKey(key));
ImGuiKeyData* key_data = ImGui::GetKeyData(key);
key_data->Down = v;
key_data->AnalogValue = analog_value;
}
static void ImGui::UpdateKeyboardInputs() static void ImGui::UpdateKeyboardInputs()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -4034,8 +4042,12 @@ static void ImGui::UpdateKeyboardInputs()
#endif #endif
// Synchronize io.KeyMods with individual modifiers io.KeyXXX bools // Synchronize io.KeyMods with individual modifiers io.KeyXXX bools, update aliases
io.KeyMods = GetMergedModFlags(); io.KeyMods = GetMergedModFlags();
for (int n = 0; n < ImGuiMouseButton_COUNT; n++)
UpdateAliasKey(MouseButtonToKey(n), io.MouseDown[n], io.MouseDown[n] ? 1.0f : 0.0f);
UpdateAliasKey(ImGuiKey_MouseWheelX, io.MouseWheelH != 0.0f, io.MouseWheelH);
UpdateAliasKey(ImGuiKey_MouseWheelY, io.MouseWheel != 0.0f, io.MouseWheel);
// Clear gamepad data if disabled // Clear gamepad data if disabled
if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0) if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0)
@ -4142,12 +4154,13 @@ void ImGui::UpdateMouseWheel()
} }
} }
float wheel_x = g.IO.MouseWheelH; const bool hovered_id_using_mouse_wheel = (g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrameUsingMouseWheel);
float wheel_y = g.IO.MouseWheel; const bool active_id_using_mouse_wheel_x = g.ActiveIdUsingKeyInputMask.TestBit(ImGuiKey_MouseWheelX);
if (wheel_x == 0.0f && wheel_y == 0.0f) const bool active_id_using_mouse_wheel_y = g.ActiveIdUsingKeyInputMask.TestBit(ImGuiKey_MouseWheelY);
return;
if ((g.ActiveId != 0 && g.ActiveIdUsingMouseWheel) || (g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrameUsingMouseWheel)) float wheel_x = (!hovered_id_using_mouse_wheel && !active_id_using_mouse_wheel_x) ? g.IO.MouseWheelH : 0.0f;
float wheel_y = (!hovered_id_using_mouse_wheel && !active_id_using_mouse_wheel_y) ? g.IO.MouseWheel : 0;
if (wheel_x == 0.0f && wheel_y == 0.0f)
return; return;
ImGuiWindow* window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow; ImGuiWindow* window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow;
@ -5206,7 +5219,10 @@ void ImGui::SetItemUsingMouseWheel()
if (g.HoveredId == id) if (g.HoveredId == id)
g.HoveredIdUsingMouseWheel = true; g.HoveredIdUsingMouseWheel = true;
if (g.ActiveId == id) if (g.ActiveId == id)
g.ActiveIdUsingMouseWheel = true; {
g.ActiveIdUsingKeyInputMask.SetBit(ImGuiKey_MouseWheelX);
g.ActiveIdUsingKeyInputMask.SetBit(ImGuiKey_MouseWheelY);
}
} }
void ImGui::SetActiveIdUsingNavAndKeys() void ImGui::SetActiveIdUsingNavAndKeys()
@ -7662,7 +7678,8 @@ static const char* const GKeyNames[] =
"GamepadL1", "GamepadR1", "GamepadL2", "GamepadR2", "GamepadL3", "GamepadR3", "GamepadL1", "GamepadR1", "GamepadL2", "GamepadR2", "GamepadL3", "GamepadR3",
"GamepadLStickLeft", "GamepadLStickRight", "GamepadLStickUp", "GamepadLStickDown", "GamepadLStickLeft", "GamepadLStickRight", "GamepadLStickUp", "GamepadLStickDown",
"GamepadRStickLeft", "GamepadRStickRight", "GamepadRStickUp", "GamepadRStickDown", "GamepadRStickLeft", "GamepadRStickRight", "GamepadRStickUp", "GamepadRStickDown",
"ModCtrl", "ModShift", "ModAlt", "ModSuper" "ModCtrl", "ModShift", "ModAlt", "ModSuper",
"MouseLeft", "MouseRight", "MouseMiddle", "MouseX1", "MouseX2", "MouseWheelX", "MouseWheelY",
}; };
IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT == IM_ARRAYSIZE(GKeyNames)); IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT == IM_ARRAYSIZE(GKeyNames));
@ -12691,7 +12708,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
int active_id_using_key_input_count = 0; int active_id_using_key_input_count = 0;
for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++) for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
active_id_using_key_input_count += g.ActiveIdUsingKeyInputMask[n] ? 1 : 0; active_id_using_key_input_count += g.ActiveIdUsingKeyInputMask[n] ? 1 : 0;
Text("ActiveIdUsing: Wheel: %d, NavDirMask: %X, KeyInputMask: %d key(s)", g.ActiveIdUsingMouseWheel, g.ActiveIdUsingNavDirMask, active_id_using_key_input_count); Text("ActiveIdUsing: NavDirMask: %X, KeyInputMask: %d key(s)", g.ActiveIdUsingNavDirMask, 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("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); Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
Unindent(); Unindent();

View File

@ -1432,6 +1432,10 @@ enum ImGuiKey_
// backends tend to interfere and break that equivalence. The safer decision is to relay that ambiguity down to the end-user... // backends tend to interfere and break that equivalence. The safer decision is to relay that ambiguity down to the end-user...
ImGuiKey_ModCtrl, ImGuiKey_ModShift, ImGuiKey_ModAlt, ImGuiKey_ModSuper, ImGuiKey_ModCtrl, ImGuiKey_ModShift, ImGuiKey_ModAlt, ImGuiKey_ModSuper,
// Mouse Buttons (auto-submitted from AddMouseButtonEvent() calls)
// - This is mirroring the data also written to io.MouseDown[], io.MouseWheel, in a format allowing them to be accessed via standard key API.
ImGuiKey_MouseLeft, ImGuiKey_MouseRight, ImGuiKey_MouseMiddle, ImGuiKey_MouseX1, ImGuiKey_MouseX2, ImGuiKey_MouseWheelX, ImGuiKey_MouseWheelY,
// End of list // End of list
ImGuiKey_COUNT, // No valid ImGuiKey is ever greater than this value ImGuiKey_COUNT, // No valid ImGuiKey is ever greater than this value

View File

@ -1177,6 +1177,8 @@ enum ImGuiKeyPrivate_
ImGuiKey_LegacyNativeKey_END = 512, ImGuiKey_LegacyNativeKey_END = 512,
ImGuiKey_Gamepad_BEGIN = ImGuiKey_GamepadStart, ImGuiKey_Gamepad_BEGIN = ImGuiKey_GamepadStart,
ImGuiKey_Gamepad_END = ImGuiKey_GamepadRStickDown + 1, ImGuiKey_Gamepad_END = ImGuiKey_GamepadRStickDown + 1,
ImGuiKey_Aliases_BEGIN = ImGuiKey_MouseLeft,
ImGuiKey_Aliases_END = ImGuiKey_COUNT,
// [Internal] Named shortcuts for Navigation // [Internal] Named shortcuts for Navigation
ImGuiKey_NavKeyboardTweakSlow = ImGuiKey_ModCtrl, ImGuiKey_NavKeyboardTweakSlow = ImGuiKey_ModCtrl,
@ -1246,11 +1248,9 @@ enum ImGuiInputReadFlags_
// Flags for IsKeyPressedEx() // Flags for IsKeyPressedEx()
ImGuiInputReadFlags_None = 0, ImGuiInputReadFlags_None = 0,
ImGuiInputReadFlags_Repeat = 1 << 0, // Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1. ImGuiInputReadFlags_Repeat = 1 << 0, // Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1.
ImGuiInputReadFlags_RepeatRateDefault = 1 << 1, // Repeat rate: Regular (default)
// Repeat rate ImGuiInputReadFlags_RepeatRateNavMove = 1 << 2, // Repeat rate: Fast
ImGuiInputReadFlags_RepeatRateDefault = 1 << 1, // Regular ImGuiInputReadFlags_RepeatRateNavTweak = 1 << 3, // Repeat rate: Faster
ImGuiInputReadFlags_RepeatRateNavMove = 1 << 2, // Fast
ImGuiInputReadFlags_RepeatRateNavTweak = 1 << 3, // Faster
ImGuiInputReadFlags_RepeatRateMask_ = ImGuiInputReadFlags_RepeatRateDefault | ImGuiInputReadFlags_RepeatRateNavMove | ImGuiInputReadFlags_RepeatRateNavTweak, ImGuiInputReadFlags_RepeatRateMask_ = ImGuiInputReadFlags_RepeatRateDefault | ImGuiInputReadFlags_RepeatRateNavMove | ImGuiInputReadFlags_RepeatRateNavTweak,
}; };
@ -1651,7 +1651,6 @@ struct ImGuiContext
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
// Input Ownership // Input Ownership
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 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it)
ImBitArrayForNamedKeys 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. ImBitArrayForNamedKeys 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.
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
@ -1896,7 +1895,6 @@ struct ImGuiContext
LastActiveId = 0; LastActiveId = 0;
LastActiveIdTimer = 0.0f; LastActiveIdTimer = 0.0f;
ActiveIdUsingMouseWheel = false;
ActiveIdUsingNavDirMask = 0x00; ActiveIdUsingNavDirMask = 0x00;
ActiveIdUsingKeyInputMask.ClearAllBits(); ActiveIdUsingKeyInputMask.ClearAllBits();
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
@ -2700,6 +2698,7 @@ namespace ImGui
inline bool IsNamedKey(ImGuiKey key) { return key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END; } 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; } inline bool IsLegacyKey(ImGuiKey key) { return key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_LegacyNativeKey_END; }
inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; } inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; }
inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; }
IMGUI_API ImGuiKeyData* GetKeyData(ImGuiKey key); IMGUI_API ImGuiKeyData* GetKeyData(ImGuiKey key);
IMGUI_API void GetKeyChordName(ImGuiModFlags mods, ImGuiKey key, char* out_buf, int out_buf_size); IMGUI_API void GetKeyChordName(ImGuiModFlags mods, ImGuiKey key, char* out_buf, int out_buf_size);
IMGUI_API void SetItemUsingMouseWheel(); IMGUI_API void SetItemUsingMouseWheel();
@ -2707,6 +2706,7 @@ namespace ImGui
inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; } inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; }
inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; return g.ActiveIdUsingKeyInputMask[key]; } inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; return g.ActiveIdUsingKeyInputMask[key]; }
inline void SetActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; g.ActiveIdUsingKeyInputMask.SetBit(key); } inline void SetActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; g.ActiveIdUsingKeyInputMask.SetBit(key); }
inline ImGuiKey MouseButtonToKey(ImGuiMouseButton button) { IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); return ImGuiKey_MouseLeft + button; }
IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f); IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f);
IMGUI_API ImGuiModFlags GetMergedModFlags(); IMGUI_API ImGuiModFlags GetMergedModFlags();
IMGUI_API ImVec2 GetKeyVector2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key_up, ImGuiKey key_down); IMGUI_API ImVec2 GetKeyVector2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key_up, ImGuiKey key_down);