Add Dead Zone to virtual input action for better usage with gamepad sticks/triggers
#3660
This commit is contained in:
@@ -2,6 +2,71 @@
|
||||
|
||||
#include "Gamepad.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
GamepadAxis GetButtonAxis(GamepadButton button, bool& positive)
|
||||
{
|
||||
positive = true;
|
||||
switch (button)
|
||||
{
|
||||
case GamepadButton::LeftTrigger:
|
||||
return GamepadAxis::LeftTrigger;
|
||||
case GamepadButton::RightTrigger:
|
||||
return GamepadAxis::RightTrigger;
|
||||
case GamepadButton::LeftStickUp:
|
||||
return GamepadAxis::LeftStickY;
|
||||
case GamepadButton::LeftStickDown:
|
||||
positive = false;
|
||||
return GamepadAxis::LeftStickY;
|
||||
case GamepadButton::LeftStickLeft:
|
||||
positive = false;
|
||||
return GamepadAxis::LeftStickX;
|
||||
case GamepadButton::LeftStickRight:
|
||||
return GamepadAxis::LeftStickX;
|
||||
case GamepadButton::RightStickUp:
|
||||
return GamepadAxis::RightStickY;
|
||||
case GamepadButton::RightStickDown:
|
||||
positive = false;
|
||||
return GamepadAxis::RightStickY;
|
||||
case GamepadButton::RightStickLeft:
|
||||
positive = false;
|
||||
return GamepadAxis::RightStickX;
|
||||
case GamepadButton::RightStickRight:
|
||||
return GamepadAxis::RightStickX;
|
||||
default:
|
||||
return GamepadAxis::None;
|
||||
}
|
||||
}
|
||||
|
||||
bool GetButtonState(const Gamepad::State& state, GamepadButton button, float deadZone)
|
||||
{
|
||||
if (deadZone > 0.01f)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case GamepadButton::LeftTrigger:
|
||||
case GamepadButton::RightTrigger:
|
||||
case GamepadButton::LeftStickUp:
|
||||
case GamepadButton::LeftStickDown:
|
||||
case GamepadButton::LeftStickLeft:
|
||||
case GamepadButton::LeftStickRight:
|
||||
case GamepadButton::RightStickUp:
|
||||
case GamepadButton::RightStickDown:
|
||||
case GamepadButton::RightStickLeft:
|
||||
case GamepadButton::RightStickRight:
|
||||
{
|
||||
bool positive;
|
||||
float axis = state.Axis[(int32)GetButtonAxis(button, positive)];
|
||||
return positive ? axis >= deadZone : axis <= -deadZone;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return state.Buttons[(int32)button];
|
||||
}
|
||||
}
|
||||
|
||||
void GamepadLayout::Init()
|
||||
{
|
||||
for (int32 i = 0; i < (int32)GamepadButton::MAX; i++)
|
||||
@@ -31,6 +96,21 @@ void Gamepad::ResetState()
|
||||
_mappedPrevState.Clear();
|
||||
}
|
||||
|
||||
bool Gamepad::GetButton(GamepadButton button, float deadZone) const
|
||||
{
|
||||
return GetButtonState(_mappedState, button, deadZone);
|
||||
}
|
||||
|
||||
bool Gamepad::GetButtonDown(GamepadButton button, float deadZone) const
|
||||
{
|
||||
return GetButtonState(_mappedState, button, deadZone) && !GetButtonState(_mappedPrevState, button, deadZone);
|
||||
}
|
||||
|
||||
bool Gamepad::GetButtonUp(GamepadButton button, float deadZone) const
|
||||
{
|
||||
return !GetButtonState(_mappedState, button, deadZone) && GetButtonState(_mappedPrevState, button, deadZone);
|
||||
}
|
||||
|
||||
bool Gamepad::IsAnyButtonDown() const
|
||||
{
|
||||
// TODO: optimize with SIMD
|
||||
|
||||
@@ -148,36 +148,30 @@ public:
|
||||
/// Gets the gamepad button state (true if being pressed during the current frame).
|
||||
/// </summary>
|
||||
/// <param name="button">Gamepad button to check</param>
|
||||
/// <param name="deadZone">Custom dead-zone value to detect gamepad button usage for non-binary buttons such as left/right thumbs that can move freely. By default, any movement is registered.</param>
|
||||
/// <returns>True if user holds down the button, otherwise false.</returns>
|
||||
API_FUNCTION() FORCE_INLINE bool GetButton(const GamepadButton button) const
|
||||
{
|
||||
return _mappedState.Buttons[static_cast<int32>(button)];
|
||||
}
|
||||
API_FUNCTION() bool GetButton(GamepadButton button, float deadZone = 0.0f) const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gamepad button down state (true if was pressed during the current frame).
|
||||
/// </summary>
|
||||
/// <param name="button">Gamepad button to check</param>
|
||||
/// <param name="deadZone">Custom dead-zone value to detect gamepad button usage for non-binary buttons such as left/right thumbs that can move freely. By default, any movement is registered.</param>
|
||||
/// <returns>True if user starts pressing down the button, otherwise false.</returns>
|
||||
API_FUNCTION() FORCE_INLINE bool GetButtonDown(const GamepadButton button) const
|
||||
{
|
||||
return _mappedState.Buttons[static_cast<int32>(button)] && !_mappedPrevState.Buttons[static_cast<int32>(button)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if any gamepad button is currently pressed.
|
||||
/// </summary>
|
||||
API_PROPERTY() bool IsAnyButtonDown() const;
|
||||
API_FUNCTION() bool GetButtonDown(GamepadButton button, float deadZone = 0.0f) const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gamepad button up state (true if was released during the current frame).
|
||||
/// </summary>
|
||||
/// <param name="button">Gamepad button to check</param>
|
||||
/// <param name="deadZone">Custom dead-zone value to detect gamepad button usage for non-binary buttons such as left/right thumbs that can move freely. By default, any movement is registered.</param>
|
||||
/// <returns>True if user releases the button, otherwise false.</returns>
|
||||
API_FUNCTION() FORCE_INLINE bool GetButtonUp(const GamepadButton button) const
|
||||
{
|
||||
return !_mappedState.Buttons[static_cast<int32>(button)] && _mappedPrevState.Buttons[static_cast<int32>(button)];
|
||||
}
|
||||
API_FUNCTION() bool GetButtonUp(GamepadButton button, float deadZone = 0.0f) const;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if any gamepad button is currently pressed.
|
||||
/// </summary>
|
||||
API_PROPERTY() bool IsAnyButtonDown() const;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -120,6 +120,7 @@ void InputSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* m
|
||||
config.MouseButton = JsonTools::GetEnum(v, "MouseButton", MouseButton::None);
|
||||
config.GamepadButton = JsonTools::GetEnum(v, "GamepadButton", GamepadButton::None);
|
||||
config.Gamepad = JsonTools::GetEnum(v, "Gamepad", InputGamepadIndex::All);
|
||||
config.DeadZone = JsonTools::GetFloat(v, "DeadZone", 0.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -499,24 +500,24 @@ float Input::GetGamepadAxis(int32 gamepadIndex, GamepadAxis axis)
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
bool Input::GetGamepadButton(int32 gamepadIndex, GamepadButton button)
|
||||
bool Input::GetGamepadButton(int32 gamepadIndex, GamepadButton button, float deadZone)
|
||||
{
|
||||
if (gamepadIndex >= 0 && gamepadIndex < Gamepads.Count())
|
||||
return Gamepads[gamepadIndex]->GetButton(button);
|
||||
return Gamepads[gamepadIndex]->GetButton(button, deadZone);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Input::GetGamepadButtonDown(int32 gamepadIndex, GamepadButton button)
|
||||
bool Input::GetGamepadButtonDown(int32 gamepadIndex, GamepadButton button, float deadZone)
|
||||
{
|
||||
if (gamepadIndex >= 0 && gamepadIndex < Gamepads.Count())
|
||||
return Gamepads[gamepadIndex]->GetButtonDown(button);
|
||||
return Gamepads[gamepadIndex]->GetButtonDown(button, deadZone);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Input::GetGamepadButtonUp(int32 gamepadIndex, GamepadButton button)
|
||||
bool Input::GetGamepadButtonUp(int32 gamepadIndex, GamepadButton button, float deadZone)
|
||||
{
|
||||
if (gamepadIndex >= 0 && gamepadIndex < Gamepads.Count())
|
||||
return Gamepads[gamepadIndex]->GetButtonUp(button);
|
||||
return Gamepads[gamepadIndex]->GetButtonUp(button, deadZone);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -542,13 +543,13 @@ float Input::GetGamepadAxis(InputGamepadIndex gamepad, GamepadAxis axis)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Input::GetGamepadButton(InputGamepadIndex gamepad, GamepadButton button)
|
||||
bool Input::GetGamepadButton(InputGamepadIndex gamepad, GamepadButton button, float deadZone)
|
||||
{
|
||||
if (gamepad == InputGamepadIndex::All)
|
||||
{
|
||||
for (auto g : Gamepads)
|
||||
{
|
||||
if (g->GetButton(button))
|
||||
if (g->GetButton(button, deadZone))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -556,18 +557,18 @@ bool Input::GetGamepadButton(InputGamepadIndex gamepad, GamepadButton button)
|
||||
{
|
||||
const auto index = static_cast<int32>(gamepad);
|
||||
if (index < Gamepads.Count())
|
||||
return Gamepads[index]->GetButton(button);
|
||||
return Gamepads[index]->GetButton(button, deadZone);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Input::GetGamepadButtonDown(InputGamepadIndex gamepad, GamepadButton button)
|
||||
bool Input::GetGamepadButtonDown(InputGamepadIndex gamepad, GamepadButton button, float deadZone)
|
||||
{
|
||||
if (gamepad == InputGamepadIndex::All)
|
||||
{
|
||||
for (auto g : Gamepads)
|
||||
{
|
||||
if (g->GetButtonDown(button))
|
||||
if (g->GetButtonDown(button, deadZone))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -575,18 +576,18 @@ bool Input::GetGamepadButtonDown(InputGamepadIndex gamepad, GamepadButton button
|
||||
{
|
||||
const auto index = static_cast<int32>(gamepad);
|
||||
if (index < Gamepads.Count())
|
||||
return Gamepads[index]->GetButtonDown(button);
|
||||
return Gamepads[index]->GetButtonDown(button, deadZone);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Input::GetGamepadButtonUp(InputGamepadIndex gamepad, GamepadButton button)
|
||||
bool Input::GetGamepadButtonUp(InputGamepadIndex gamepad, GamepadButton button, float deadZone)
|
||||
{
|
||||
if (gamepad == InputGamepadIndex::All)
|
||||
{
|
||||
for (auto g : Gamepads)
|
||||
{
|
||||
if (g->GetButtonUp(button))
|
||||
if (g->GetButtonUp(button, deadZone))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -594,7 +595,7 @@ bool Input::GetGamepadButtonUp(InputGamepadIndex gamepad, GamepadButton button)
|
||||
{
|
||||
const auto index = static_cast<int32>(gamepad);
|
||||
if (index < Gamepads.Count())
|
||||
return Gamepads[index]->GetButtonUp(button);
|
||||
return Gamepads[index]->GetButtonUp(button, deadZone);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1065,26 +1066,26 @@ void InputService::Update()
|
||||
bool isActive;
|
||||
if (config.Mode == InputActionMode::Pressing)
|
||||
{
|
||||
isActive = Input::GetKey(config.Key) || Input::GetMouseButton(config.MouseButton) || Input::GetGamepadButton(config.Gamepad, config.GamepadButton);
|
||||
isActive = Input::GetKey(config.Key) || Input::GetMouseButton(config.MouseButton) || Input::GetGamepadButton(config.Gamepad, config.GamepadButton, config.DeadZone);
|
||||
}
|
||||
else if (config.Mode == InputActionMode::Press)
|
||||
{
|
||||
isActive = Input::GetKeyDown(config.Key) || Input::GetMouseButtonDown(config.MouseButton) || Input::GetGamepadButtonDown(config.Gamepad, config.GamepadButton);
|
||||
isActive = Input::GetKeyDown(config.Key) || Input::GetMouseButtonDown(config.MouseButton) || Input::GetGamepadButtonDown(config.Gamepad, config.GamepadButton, config.DeadZone);
|
||||
}
|
||||
else
|
||||
{
|
||||
isActive = Input::GetKeyUp(config.Key) || Input::GetMouseButtonUp(config.MouseButton) || Input::GetGamepadButtonUp(config.Gamepad, config.GamepadButton);
|
||||
isActive = Input::GetKeyUp(config.Key) || Input::GetMouseButtonUp(config.MouseButton) || Input::GetGamepadButtonUp(config.Gamepad, config.GamepadButton, config.DeadZone);
|
||||
}
|
||||
|
||||
if (Input::GetKeyDown(config.Key) || Input::GetMouseButtonDown(config.MouseButton) || Input::GetGamepadButtonDown(config.Gamepad, config.GamepadButton))
|
||||
if (Input::GetKeyDown(config.Key) || Input::GetMouseButtonDown(config.MouseButton) || Input::GetGamepadButtonDown(config.Gamepad, config.GamepadButton, config.DeadZone))
|
||||
{
|
||||
data.State = InputActionState::Press;
|
||||
}
|
||||
else if (Input::GetKey(config.Key) || Input::GetMouseButton(config.MouseButton) || Input::GetGamepadButton(config.Gamepad, config.GamepadButton))
|
||||
else if (Input::GetKey(config.Key) || Input::GetMouseButton(config.MouseButton) || Input::GetGamepadButton(config.Gamepad, config.GamepadButton, config.DeadZone))
|
||||
{
|
||||
data.State = InputActionState::Pressing;
|
||||
}
|
||||
else if (Input::GetKeyUp(config.Key) || Input::GetMouseButtonUp(config.MouseButton) || Input::GetGamepadButtonUp(config.Gamepad, config.GamepadButton))
|
||||
else if (Input::GetKeyUp(config.Key) || Input::GetMouseButtonUp(config.MouseButton) || Input::GetGamepadButtonUp(config.Gamepad, config.GamepadButton, config.DeadZone))
|
||||
{
|
||||
data.State = InputActionState::Release;
|
||||
}
|
||||
|
||||
@@ -238,24 +238,27 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="gamepadIndex">The gamepad index</param>
|
||||
/// <param name="button">Gamepad button to check</param>
|
||||
/// <param name="deadZone">Custom dead-zone value to detect gamepad button usage for non-binary buttons such as left/right thumbs that can move freely. By default, any movement is registered.</param>
|
||||
/// <returns>True if user holds down the button, otherwise false.</returns>
|
||||
API_FUNCTION() static bool GetGamepadButton(int32 gamepadIndex, GamepadButton button);
|
||||
API_FUNCTION() static bool GetGamepadButton(int32 gamepadIndex, GamepadButton button, float deadZone = 0.0f);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gamepad button down state (true if was pressed during the current frame).
|
||||
/// </summary>
|
||||
/// <param name="gamepadIndex">The gamepad index</param>
|
||||
/// <param name="button">Gamepad button to check</param>
|
||||
/// <param name="deadZone">Custom dead-zone value to detect gamepad button usage for non-binary buttons such as left/right thumbs that can move freely. By default, any movement is registered.</param>
|
||||
/// <returns>True if user starts pressing down the button, otherwise false.</returns>
|
||||
API_FUNCTION() static bool GetGamepadButtonDown(int32 gamepadIndex, GamepadButton button);
|
||||
API_FUNCTION() static bool GetGamepadButtonDown(int32 gamepadIndex, GamepadButton button, float deadZone = 0.0f);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gamepad button up state (true if was released during the current frame).
|
||||
/// </summary>
|
||||
/// <param name="gamepadIndex">The gamepad index</param>
|
||||
/// <param name="button">Gamepad button to check</param>
|
||||
/// <param name="deadZone">Custom dead-zone value to detect gamepad button usage for non-binary buttons such as left/right thumbs that can move freely. By default, any movement is registered.</param>
|
||||
/// <returns>True if user releases the button, otherwise false.</returns>
|
||||
API_FUNCTION() static bool GetGamepadButtonUp(int32 gamepadIndex, GamepadButton button);
|
||||
API_FUNCTION() static bool GetGamepadButtonUp(int32 gamepadIndex, GamepadButton button, float deadZone = 0.0f);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gamepad axis value.
|
||||
@@ -270,24 +273,27 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="gamepad">The gamepad</param>
|
||||
/// <param name="button">Gamepad button to check</param>
|
||||
/// <param name="deadZone">Custom dead-zone value to detect gamepad button usage for non-binary buttons such as left/right thumbs that can move freely. By default, any movement is registered.</param>
|
||||
/// <returns>True if user holds down the button, otherwise false.</returns>
|
||||
API_FUNCTION() static bool GetGamepadButton(InputGamepadIndex gamepad, GamepadButton button);
|
||||
API_FUNCTION() static bool GetGamepadButton(InputGamepadIndex gamepad, GamepadButton button, float deadZone = 0.0f);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gamepad button down state (true if was pressed during the current frame).
|
||||
/// </summary>
|
||||
/// <param name="gamepad">The gamepad</param>
|
||||
/// <param name="button">Gamepad button to check</param>
|
||||
/// <param name="deadZone">Custom dead-zone value to detect gamepad button usage for non-binary buttons such as left/right thumbs that can move freely. By default, any movement is registered.</param>
|
||||
/// <returns>True if user starts pressing down the button, otherwise false.</returns>
|
||||
API_FUNCTION() static bool GetGamepadButtonDown(InputGamepadIndex gamepad, GamepadButton button);
|
||||
API_FUNCTION() static bool GetGamepadButtonDown(InputGamepadIndex gamepad, GamepadButton button, float deadZone = 0.0f);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gamepad button up state (true if was released during the current frame).
|
||||
/// </summary>
|
||||
/// <param name="gamepad">The gamepad</param>
|
||||
/// <param name="button">Gamepad button to check</param>
|
||||
/// <param name="deadZone">Custom dead-zone value to detect gamepad button usage for non-binary buttons such as left/right thumbs that can move freely. By default, any movement is registered.</param>
|
||||
/// <returns>True if user releases the button, otherwise false.</returns>
|
||||
API_FUNCTION() static bool GetGamepadButtonUp(InputGamepadIndex gamepad, GamepadButton button);
|
||||
API_FUNCTION() static bool GetGamepadButtonUp(InputGamepadIndex gamepad, GamepadButton button, float deadZone = 0.0f);
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -48,6 +48,12 @@ API_STRUCT() struct ActionConfig
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(40)")
|
||||
InputGamepadIndex Gamepad;
|
||||
|
||||
/// <summary>
|
||||
/// Threshold for non-binary value inputs such as gamepad stick position to decide if action was triggered. Can be sued to activate action only if input value is higher than specified number.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes = "EditorOrder(50)")
|
||||
float DeadZone = 0.5f;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user