mirror of
https://github.com/kevinporetti/UnrealImGui.git
synced 2025-02-23 04:30:32 +00:00
Enabled experimental ImGui gamepad navigation feature:
- Updated InputNavigation CVar to support 1: keyboard navigation, 2: gamepad navigation and 3: keyboard + gamepad navigation simultaneously. - Added ImGui interoperability utilities mapping gamepad input events to values in ImGui navigation inputs array. - Added to ImGui Input State support for gamepad navigation inputs. - Refactored ImGui Input State to keep consistent interface for keyboard, mouse and gamepad updates.
This commit is contained in:
parent
e83f37d518
commit
82729a12c8
@ -82,7 +82,7 @@ void FImGuiInputState::SetMouseDown(uint32 MouseIndex, bool bIsDown)
|
||||
}
|
||||
}
|
||||
|
||||
void FImGuiInputState::Reset(bool bKeyboard, bool bMouse)
|
||||
void FImGuiInputState::Reset(bool bKeyboard, bool bMouse, bool bNavigation)
|
||||
{
|
||||
if (bKeyboard)
|
||||
{
|
||||
@ -100,6 +100,11 @@ void FImGuiInputState::Reset(bool bKeyboard, bool bMouse)
|
||||
{
|
||||
ClearModifierKeys();
|
||||
}
|
||||
|
||||
if (bNavigation)
|
||||
{
|
||||
ClearNavigationInputs();
|
||||
}
|
||||
}
|
||||
|
||||
void FImGuiInputState::ClearUpdateState()
|
||||
@ -152,3 +157,10 @@ void FImGuiInputState::ClearModifierKeys()
|
||||
bIsShiftDown = false;
|
||||
bIsAltDown = false;
|
||||
}
|
||||
|
||||
void FImGuiInputState::ClearNavigationInputs()
|
||||
{
|
||||
using std::fill;
|
||||
fill(NavigationInputs, &NavigationInputs[Utilities::GetArraySize(NavigationInputs)], 0.f);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,9 @@ public:
|
||||
// Array for key states.
|
||||
using FKeysArray = ImGuiInterops::ImGuiTypes::FKeysArray;
|
||||
|
||||
// Array for navigation input states.
|
||||
using FNavInputArray = ImGuiInterops::ImGuiTypes::FNavInputArray;
|
||||
|
||||
// Pair of indices defining range in mouse buttons array.
|
||||
using FMouseButtonsIndexRange = Utilities::TArrayIndexRange<FMouseButtonsArray, uint32>;
|
||||
|
||||
@ -47,9 +50,14 @@ public:
|
||||
const FKeysIndexRange& GetKeysUpdateRange() const { return KeysUpdateRange; }
|
||||
|
||||
// Change state of the key in the keys array and expand range bounding dirty part of the array.
|
||||
// @param KeyIndex - Index of the key
|
||||
// @param KeyEvent - Key event representing the key
|
||||
// @param bIsDown - True, if key is down
|
||||
void SetKeyDown(uint32 KeyIndex, bool bIsDown);
|
||||
void SetKeyDown(const FKeyEvent& KeyEvent, bool bIsDown) { SetKeyDown(ImGuiInterops::GetKeyIndex(KeyEvent), bIsDown); }
|
||||
|
||||
// Change state of the key in the keys array and expand range bounding dirty part of the array.
|
||||
// @param Key - Keyboard key
|
||||
// @param bIsDown - True, if key is down
|
||||
void SetKeyDown(const FKey& Key, bool bIsDown) { SetKeyDown(ImGuiInterops::GetKeyIndex(Key), bIsDown); }
|
||||
|
||||
// Get reference to the array with mouse button down states.
|
||||
const FMouseButtonsArray& GetMouseButtons() const { return MouseButtonsDown; }
|
||||
@ -58,9 +66,14 @@ public:
|
||||
const FMouseButtonsIndexRange& GetMouseButtonsUpdateRange() const { return MouseButtonsUpdateRange; }
|
||||
|
||||
// Change state of the button in the mouse buttons array and expand range bounding dirty part of the array.
|
||||
// @param MouseIndex - Index of the mouse button
|
||||
// @param MouseEvent - Mouse event representing mouse button
|
||||
// @param bIsDown - True, if button is down
|
||||
void SetMouseDown(uint32 MouseIndex, bool IsDown);
|
||||
void SetMouseDown(const FPointerEvent& MouseEvent, bool bIsDown) { SetMouseDown(ImGuiInterops::GetMouseIndex(MouseEvent), bIsDown); }
|
||||
|
||||
// Change state of the button in the mouse buttons array and expand range bounding dirty part of the array.
|
||||
// @param MouseButton - Mouse button key
|
||||
// @param bIsDown - True, if button is down
|
||||
void SetMouseDown(const FKey& MouseButton, bool bIsDown) { SetMouseDown(ImGuiInterops::GetMouseIndex(MouseButton), bIsDown); }
|
||||
|
||||
// Get mouse wheel delta accumulated during the last frame.
|
||||
float GetMouseWheelDelta() const { return MouseWheelDelta; }
|
||||
@ -81,7 +94,7 @@ public:
|
||||
|
||||
// Set whether input has active mouse pointer.
|
||||
// @param bHasPointer - True, if input has active mouse pointer
|
||||
void SetMousePointer(bool bHasPointer) { bHasMousePointer = bHasPointer; }
|
||||
void SetMousePointer(bool bInHasMousePointer) { bHasMousePointer = bInHasMousePointer; }
|
||||
|
||||
// Get Control down state.
|
||||
bool IsControlDown() const { return bIsControlDown; }
|
||||
@ -104,18 +117,18 @@ public:
|
||||
// @param bIsDown - True, if Alt is down
|
||||
void SetAltDown(bool bIsDown) { bIsAltDown = bIsDown; }
|
||||
|
||||
// Reset state and mark as dirty.
|
||||
void ResetState() { Reset(true, true); }
|
||||
// Get reference to the array with navigation input states.
|
||||
const FNavInputArray& GetNavigationInputs() const { return NavigationInputs; }
|
||||
|
||||
// Reset keyboard state and mark as dirty.
|
||||
void ResetKeyboardState() { Reset(true, false); }
|
||||
// Change state of the navigation input associated with this gamepad key.
|
||||
// @param KeyEvent - Key event with gamepad key input
|
||||
// @param bIsDown - True, if key is down
|
||||
void SetGamepadNavigationKey(const FKeyEvent& KeyEvent, bool bIsDown) { ImGuiInterops::SetGamepadNavigationKey(NavigationInputs, KeyEvent.GetKey(), bIsDown); }
|
||||
|
||||
// Reset mouse state and mark as dirty.
|
||||
void ResetMouseState() { Reset(false, true); }
|
||||
|
||||
// Clear part of the state that is meant to be updated in every frame like: accumulators, buffers and information
|
||||
// about dirty parts of keys or mouse buttons arrays.
|
||||
void ClearUpdateState();
|
||||
// Change state of the navigation input associated with this gamepad axis.
|
||||
// @param AnalogInputEvent - Analogue input event with gamepad axis input
|
||||
// @param Value - Analogue value that should be set for this axis
|
||||
void SetGamepadNavigationAxis(const FAnalogInputEvent& AnalogInputEvent, float Value) { ImGuiInterops::SetGamepadNavigationAxis(NavigationInputs, AnalogInputEvent.GetKey(), Value); }
|
||||
|
||||
// Check whether keyboard navigation is enabled.
|
||||
bool IsKeyboardNavigationEnabled() const { return bKeyboardNavigationEnabled; }
|
||||
@ -124,15 +137,49 @@ public:
|
||||
// @param bEnabled - True, if navigation is enabled
|
||||
void SetKeyboardNavigationEnabled(bool bEnabled) { bKeyboardNavigationEnabled = bEnabled; }
|
||||
|
||||
// Check whether gamepad navigation is enabled.
|
||||
bool IsGamepadNavigationEnabled() const { return bGamepadNavigationEnabled; }
|
||||
|
||||
// Set whether gamepad navigation is enabled.
|
||||
// @param bEnabled - True, if navigation is enabled
|
||||
void SetGamepadNavigationEnabled(bool bEnabled) { bGamepadNavigationEnabled = bEnabled; }
|
||||
|
||||
// Check whether gamepad is attached.
|
||||
bool HasGamepad() const { return bHasGamepad; }
|
||||
|
||||
// Set whether gamepad is attached.
|
||||
// @param bInHasGamepad - True, if gamepad is attached
|
||||
void SetGamepad(bool bInHasGamepad) { bHasGamepad = bInHasGamepad; }
|
||||
|
||||
// Reset the whole state and mark as dirty.
|
||||
void ResetState() { Reset(true, true, true); }
|
||||
|
||||
// Reset keyboard state and mark as dirty.
|
||||
void ResetKeyboardState() { Reset(true, false, false); }
|
||||
|
||||
// Reset mouse state and mark as dirty.
|
||||
void ResetMouseState() { Reset(false, true, false); }
|
||||
|
||||
// Reset navigation state.
|
||||
void ResetNavigationState() { Reset(false, false, true); }
|
||||
|
||||
// Clear part of the state that is meant to be updated in every frame like: accumulators, buffers, navigation data
|
||||
// and information about dirty parts of keys or mouse buttons arrays.
|
||||
void ClearUpdateState();
|
||||
|
||||
private:
|
||||
|
||||
void Reset(bool bKeyboard, bool bMouse);
|
||||
void SetKeyDown(uint32 KeyIndex, bool bIsDown);
|
||||
void SetMouseDown(uint32 MouseIndex, bool IsDown);
|
||||
|
||||
void Reset(bool bKeyboard, bool bMouse, bool bNavigation);
|
||||
|
||||
void ClearCharacters();
|
||||
void ClearKeys();
|
||||
void ClearMouseButtons();
|
||||
void ClearMouseAnalogue();
|
||||
void ClearModifierKeys();
|
||||
void ClearNavigationInputs();
|
||||
|
||||
FVector2D MousePosition = FVector2D::ZeroVector;
|
||||
float MouseWheelDelta = 0.f;
|
||||
@ -146,6 +193,8 @@ private:
|
||||
FKeysArray KeysDown;
|
||||
FKeysIndexRange KeysUpdateRange;
|
||||
|
||||
FNavInputArray NavigationInputs;
|
||||
|
||||
bool bHasMousePointer = false;
|
||||
|
||||
bool bIsControlDown = false;
|
||||
@ -153,4 +202,6 @@ private:
|
||||
bool bIsAltDown = false;
|
||||
|
||||
bool bKeyboardNavigationEnabled = false;
|
||||
bool bGamepadNavigationEnabled = false;
|
||||
bool bHasGamepad = false;
|
||||
};
|
||||
|
@ -159,6 +159,77 @@ namespace ImGuiInterops
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
inline void UpdateKey(const FKey& Key, const FKey& KeyCondition, float& Value, bool bIsDown)
|
||||
{
|
||||
if (Key == KeyCondition)
|
||||
{
|
||||
Value = (bIsDown) ? 1.f : 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
inline void UpdateAxisValues(float& Axis, float& Opposite, float Value)
|
||||
{
|
||||
constexpr float AxisInputThreshold = 0.166f;
|
||||
|
||||
// Filter out small values to avoid false positives (helpful in case of worn controllers).
|
||||
Axis = FMath::Max(0.f, Value - AxisInputThreshold);
|
||||
Opposite = 0.f;
|
||||
}
|
||||
|
||||
inline void UpdateSymmetricAxis(const FKey& Key, const FKey& KeyCondition, float& Negative, float& Positive, float Value)
|
||||
{
|
||||
if (Key == KeyCondition)
|
||||
{
|
||||
if (Value < 0.f)
|
||||
{
|
||||
UpdateAxisValues(Negative, Positive, -Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateAxisValues(Positive, Negative, Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetGamepadNavigationKey(ImGuiTypes::FNavInputArray& NavInputs, const FKey& Key, bool bIsDown)
|
||||
{
|
||||
#define MAP_KEY(KeyCondition, NavIndex) UpdateKey(Key, KeyCondition, NavInputs[NavIndex], bIsDown)
|
||||
|
||||
if (Key.IsGamepadKey())
|
||||
{
|
||||
MAP_KEY(EKeys::Gamepad_FaceButton_Bottom, ImGuiNavInput_Activate);
|
||||
MAP_KEY(EKeys::Gamepad_FaceButton_Right, ImGuiNavInput_Cancel);
|
||||
MAP_KEY(EKeys::Gamepad_FaceButton_Top, ImGuiNavInput_Input);
|
||||
MAP_KEY(EKeys::Gamepad_FaceButton_Left, ImGuiNavInput_Menu);
|
||||
MAP_KEY(EKeys::Gamepad_DPad_Left, ImGuiNavInput_DpadLeft);
|
||||
MAP_KEY(EKeys::Gamepad_DPad_Right, ImGuiNavInput_DpadRight);
|
||||
MAP_KEY(EKeys::Gamepad_DPad_Up, ImGuiNavInput_DpadUp);
|
||||
MAP_KEY(EKeys::Gamepad_DPad_Down, ImGuiNavInput_DpadDown);
|
||||
MAP_KEY(EKeys::Gamepad_LeftShoulder, ImGuiNavInput_FocusPrev);
|
||||
MAP_KEY(EKeys::Gamepad_RightShoulder, ImGuiNavInput_FocusNext);
|
||||
MAP_KEY(EKeys::Gamepad_LeftShoulder, ImGuiNavInput_TweakSlow);
|
||||
MAP_KEY(EKeys::Gamepad_RightShoulder, ImGuiNavInput_TweakFast);
|
||||
}
|
||||
|
||||
#undef MAP_KEY
|
||||
}
|
||||
|
||||
void SetGamepadNavigationAxis(ImGuiTypes::FNavInputArray& NavInputs, const FKey& Key, float Value)
|
||||
{
|
||||
#define MAP_SYMMETRIC_AXIS(KeyCondition, NegNavIndex, PosNavIndex) UpdateSymmetricAxis(Key, KeyCondition, NavInputs[NegNavIndex], NavInputs[PosNavIndex], Value)
|
||||
|
||||
if (Key.IsGamepadKey())
|
||||
{
|
||||
MAP_SYMMETRIC_AXIS(EKeys::Gamepad_LeftX, ImGuiNavInput_LStickLeft, ImGuiNavInput_LStickRight);
|
||||
MAP_SYMMETRIC_AXIS(EKeys::Gamepad_LeftY, ImGuiNavInput_LStickDown, ImGuiNavInput_LStickUp);
|
||||
}
|
||||
|
||||
#undef MAP_SYMMETRIC_AXIS
|
||||
}
|
||||
|
||||
//====================================================================================================
|
||||
// Input State Copying
|
||||
//====================================================================================================
|
||||
@ -210,6 +281,13 @@ namespace ImGuiInterops
|
||||
Copy(InputState.GetCharacters(), IO.InputCharacters);
|
||||
}
|
||||
|
||||
if (InputState.IsGamepadNavigationEnabled() && InputState.HasGamepad())
|
||||
{
|
||||
Copy(InputState.GetNavigationInputs(), IO.NavInputs);
|
||||
}
|
||||
|
||||
SetFlag(IO.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard, InputState.IsKeyboardNavigationEnabled());
|
||||
SetFlag(IO.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad, InputState.IsGamepadNavigationEnabled());
|
||||
SetFlag(IO.BackendFlags, ImGuiBackendFlags_HasGamepad, InputState.HasGamepad());
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ namespace ImGuiInterops
|
||||
{
|
||||
using FMouseButtonsArray = decltype(ImGuiIO::MouseDown);
|
||||
using FKeysArray = decltype(ImGuiIO::KeysDown);
|
||||
using FNavInputArray = decltype(ImGuiIO::NavInputs);
|
||||
|
||||
using FInputCharactersBuffer = decltype(ImGuiIO::InputCharacters);
|
||||
|
||||
@ -54,8 +55,21 @@ namespace ImGuiInterops
|
||||
return GetMouseIndex(MouseEvent.GetEffectingButton());
|
||||
}
|
||||
|
||||
// Convert from ImGuiMouseCursor type to EMouseCursor.
|
||||
EMouseCursor::Type ToSlateMouseCursor(ImGuiMouseCursor MouseCursor);
|
||||
|
||||
// Set in the target array navigation input corresponding to gamepad key.
|
||||
// @param NavInputs - Target array
|
||||
// @param Key - Gamepad key mapped to navigation input (non-mapped keys will be ignored)
|
||||
// @param bIsDown - True, if key is down
|
||||
void SetGamepadNavigationKey(ImGuiTypes::FNavInputArray& NavInputs, const FKey& Key, bool bIsDown);
|
||||
|
||||
// Set in the target array navigation input corresponding to gamepad axis.
|
||||
// @param NavInputs - Target array
|
||||
// @param Key - Gamepad axis key mapped to navigation input (non-axis or non-mapped inputs will be ignored)
|
||||
// @param Value - Axis value (-1..1 values from Unreal are mapped to separate ImGui axes with values in range 0..1)
|
||||
void SetGamepadNavigationAxis(ImGuiTypes::FNavInputArray& NavInputs, const FKey& Key, float Value);
|
||||
|
||||
|
||||
//====================================================================================================
|
||||
// Input State Copying
|
||||
|
@ -25,7 +25,7 @@ constexpr int32 IMGUI_WIDGET_Z_ORDER = 10000;
|
||||
DEFINE_LOG_CATEGORY_STATIC(LogImGuiWidget, Warning, All);
|
||||
|
||||
#define TEXT_INPUT_MODE(Val) (\
|
||||
(Val) == EInputMode::MouseAndKeyboard ? TEXT("MouseAndKeyboard") :\
|
||||
(Val) == EInputMode::Full ? TEXT("Full") :\
|
||||
(Val) == EInputMode::MousePointerOnly ? TEXT("MousePointerOnly") :\
|
||||
TEXT("None"))
|
||||
|
||||
@ -52,9 +52,11 @@ namespace CVars
|
||||
ECVF_Default);
|
||||
|
||||
TAutoConsoleVariable<int> InputNavigation(TEXT("ImGui.InputNavigation"), 0,
|
||||
TEXT("[EXPERIMENTAL, WIP] Set ImGui navigation mode.\n")
|
||||
TEXT("EXPERIMENTAL Set ImGui navigation mode.\n")
|
||||
TEXT("0: navigation is disabled\n")
|
||||
TEXT("1: keyboard navigation"),
|
||||
TEXT("1: keyboard navigation\n")
|
||||
TEXT("2: gamepad navigation (gamepad input is consumed)\n")
|
||||
TEXT("3: keyboard and gamepad navigation (gamepad input is consumed)"),
|
||||
ECVF_Default);
|
||||
|
||||
TAutoConsoleVariable<int> DrawMouseCursor(TEXT("ImGui.DrawMouseCursor"), 0,
|
||||
@ -154,35 +156,81 @@ FReply SImGuiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterEven
|
||||
|
||||
FReply SImGuiWidget::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent)
|
||||
{
|
||||
if (KeyEvent.GetKey().IsGamepadKey())
|
||||
{
|
||||
if (InputState.IsGamepadNavigationEnabled())
|
||||
{
|
||||
InputState.SetGamepadNavigationKey(KeyEvent, true);
|
||||
|
||||
return FReply::Handled();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Super::OnKeyDown(MyGeometry, KeyEvent);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsConsoleOpened() || IgnoreKeyEvent(KeyEvent))
|
||||
{
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
InputState.SetKeyDown(ImGuiInterops::GetKeyIndex(KeyEvent), true);
|
||||
InputState.SetKeyDown(KeyEvent, true);
|
||||
CopyModifierKeys(KeyEvent);
|
||||
|
||||
UpdateCanvasMapMode(KeyEvent);
|
||||
|
||||
return WithMouseLockRequests(FReply::Handled());
|
||||
}
|
||||
}
|
||||
|
||||
FReply SImGuiWidget::OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent)
|
||||
{
|
||||
if (KeyEvent.GetKey().IsGamepadKey())
|
||||
{
|
||||
if (InputState.IsGamepadNavigationEnabled())
|
||||
{
|
||||
InputState.SetGamepadNavigationKey(KeyEvent, false);
|
||||
|
||||
return FReply::Handled();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Super::OnKeyUp(MyGeometry, KeyEvent);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Even if we don't send new keystrokes to ImGui, we still handle key up events, to make sure that we clear keys
|
||||
// pressed before suppressing keyboard input.
|
||||
InputState.SetKeyDown(ImGuiInterops::GetKeyIndex(KeyEvent), false);
|
||||
InputState.SetKeyDown(KeyEvent, false);
|
||||
CopyModifierKeys(KeyEvent);
|
||||
|
||||
UpdateCanvasMapMode(KeyEvent);
|
||||
|
||||
// If console is opened we notify key change but we also let event trough, so it can be handled by console.
|
||||
return IsConsoleOpened() ? FReply::Unhandled() : WithMouseLockRequests(FReply::Handled());
|
||||
}
|
||||
}
|
||||
|
||||
FReply SImGuiWidget::OnAnalogValueChanged(const FGeometry& MyGeometry, const FAnalogInputEvent& AnalogInputEvent)
|
||||
{
|
||||
if (AnalogInputEvent.GetKey().IsGamepadKey() && InputState.IsGamepadNavigationEnabled())
|
||||
{
|
||||
InputState.SetGamepadNavigationAxis(AnalogInputEvent, AnalogInputEvent.GetAnalogValue());
|
||||
|
||||
return FReply::Handled();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Super::OnAnalogValueChanged(MyGeometry, AnalogInputEvent);
|
||||
}
|
||||
}
|
||||
|
||||
FReply SImGuiWidget::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||||
{
|
||||
InputState.SetMouseDown(ImGuiInterops::GetMouseIndex(MouseEvent), true);
|
||||
InputState.SetMouseDown(MouseEvent, true);
|
||||
CopyModifierKeys(MouseEvent);
|
||||
|
||||
UpdateCanvasMapMode(MouseEvent);
|
||||
@ -193,7 +241,7 @@ FReply SImGuiWidget::OnMouseButtonDown(const FGeometry& MyGeometry, const FPoint
|
||||
|
||||
FReply SImGuiWidget::OnMouseButtonDoubleClick(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||||
{
|
||||
InputState.SetMouseDown(ImGuiInterops::GetMouseIndex(MouseEvent), true);
|
||||
InputState.SetMouseDown(MouseEvent, true);
|
||||
CopyModifierKeys(MouseEvent);
|
||||
|
||||
UpdateCanvasMapMode(MouseEvent);
|
||||
@ -204,7 +252,7 @@ FReply SImGuiWidget::OnMouseButtonDoubleClick(const FGeometry& MyGeometry, const
|
||||
|
||||
FReply SImGuiWidget::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||||
{
|
||||
InputState.SetMouseDown(ImGuiInterops::GetMouseIndex(MouseEvent), false);
|
||||
InputState.SetMouseDown(MouseEvent, false);
|
||||
CopyModifierKeys(MouseEvent);
|
||||
|
||||
UpdateCanvasMapMode(MouseEvent);
|
||||
@ -299,7 +347,7 @@ void SImGuiWidget::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent
|
||||
{
|
||||
for (const FKey& Button : { EKeys::LeftMouseButton, EKeys::MiddleMouseButton, EKeys::RightMouseButton, EKeys::ThumbMouseButton, EKeys::ThumbMouseButton2 })
|
||||
{
|
||||
InputState.SetMouseDown(ImGuiInterops::GetMouseIndex(Button), MouseEvent.IsMouseButtonDown(Button));
|
||||
InputState.SetMouseDown(Button, MouseEvent.IsMouseButtonDown(Button));
|
||||
}
|
||||
}
|
||||
|
||||
@ -440,18 +488,24 @@ void SImGuiWidget::UpdateInputEnabled()
|
||||
// We don't get any events when application loses focus (we get OnMouseLeave but not always) but we fix it with
|
||||
// this manual check. We still allow the above code to run, even if we need to suppress keyboard input right after
|
||||
// that.
|
||||
if (bInputEnabled && !GameViewport->Viewport->IsForegroundWindow() && InputMode == EInputMode::MouseAndKeyboard)
|
||||
if (bInputEnabled && !GameViewport->Viewport->IsForegroundWindow() && InputMode == EInputMode::Full)
|
||||
{
|
||||
UpdateInputMode(false, IsDirectlyHovered());
|
||||
}
|
||||
|
||||
InputState.SetKeyboardNavigationEnabled(CVars::InputNavigation.GetValueOnGameThread() > 0);
|
||||
if (bInputEnabled)
|
||||
{
|
||||
InputState.SetKeyboardNavigationEnabled(CVars::InputNavigation.GetValueOnGameThread() & 1);
|
||||
InputState.SetGamepadNavigationEnabled(CVars::InputNavigation.GetValueOnGameThread() & 2);
|
||||
const auto& Application = FSlateApplication::Get().GetPlatformApplication();
|
||||
InputState.SetGamepad(Application.IsValid() && Application->IsGamepadAttached());
|
||||
}
|
||||
}
|
||||
|
||||
void SImGuiWidget::UpdateInputMode(bool bHasKeyboardFocus, bool bHasMousePointer)
|
||||
{
|
||||
const EInputMode NewInputMode =
|
||||
bHasKeyboardFocus ? EInputMode::MouseAndKeyboard :
|
||||
bHasKeyboardFocus ? EInputMode::Full :
|
||||
bHasMousePointer ? EInputMode::MousePointerOnly :
|
||||
EInputMode::None;
|
||||
|
||||
@ -466,16 +520,17 @@ void SImGuiWidget::UpdateInputMode(bool bHasKeyboardFocus, bool bHasMousePointer
|
||||
{
|
||||
InputState.ResetState();
|
||||
}
|
||||
else if (InputMode == EInputMode::MouseAndKeyboard)
|
||||
else if (InputMode == EInputMode::Full)
|
||||
{
|
||||
InputState.ResetKeyboardState();
|
||||
InputState.ResetNavigationState();
|
||||
}
|
||||
|
||||
InputMode = NewInputMode;
|
||||
|
||||
ClearMouseEventNotification();
|
||||
|
||||
if (InputMode != EInputMode::MouseAndKeyboard)
|
||||
if (InputMode != EInputMode::Full)
|
||||
{
|
||||
SetCanvasMapMode(false);
|
||||
}
|
||||
|
@ -53,6 +53,8 @@ public:
|
||||
|
||||
virtual FReply OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) override;
|
||||
|
||||
virtual FReply OnAnalogValueChanged(const FGeometry& MyGeometry, const FAnalogInputEvent& AnalogInputEvent) override;
|
||||
|
||||
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
|
||||
|
||||
virtual FReply OnMouseButtonDoubleClick(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
|
||||
@ -80,8 +82,8 @@ private:
|
||||
None,
|
||||
// Mouse pointer only without user focus
|
||||
MousePointerOnly,
|
||||
// Full input with user focus
|
||||
MouseAndKeyboard
|
||||
// Full input with user focus (mouse, keyboard and depending on navigation mode gamepad)
|
||||
Full
|
||||
};
|
||||
|
||||
// If needed, add to event reply a mouse lock or unlock request.
|
||||
|
Loading…
Reference in New Issue
Block a user