diff --git a/Source/Engine/Input/Enums.h b/Source/Engine/Input/Enums.h
index 80e10786f..272231e41 100644
--- a/Source/Engine/Input/Enums.h
+++ b/Source/Engine/Input/Enums.h
@@ -263,6 +263,31 @@ API_ENUM() enum class InputActionMode
Release = 2,
};
+///
+/// The input action event trigger modes.
+///
+API_ENUM() enum class InputActionPhase
+{
+ ///
+ /// User is pressing the key/button.
+ ///
+ Pressing = 0,
+
+ ///
+ /// User pressed the key/button (but wasn't pressing it in the previous frame).
+ ///
+ Press = 1,
+
+ ///
+ /// User released the key/button (was pressing it in the previous frame).
+ ///
+ Release = 2,
+
+ Waiting = 3,
+
+ None = 4,
+};
+
///
/// The input gamepad index.
///
diff --git a/Source/Engine/Input/Input.cpp b/Source/Engine/Input/Input.cpp
index 7a4547c62..32a672635 100644
--- a/Source/Engine/Input/Input.cpp
+++ b/Source/Engine/Input/Input.cpp
@@ -29,11 +29,13 @@ struct ActionData
{
bool Active;
uint64 FrameIndex;
+ InputActionPhase Phase;
ActionData()
{
Active = false;
FrameIndex = 0;
+ Phase = InputActionPhase::None;
}
};
@@ -597,6 +599,16 @@ bool Input::GetAction(const StringView& name)
return e ? e->Active : false;
}
+InputActionPhase Input::GetActionPhase(const StringView& name)
+{
+ const auto e = Actions.TryGet(name);
+ if (e != nullptr)
+ {
+ return e->Phase;
+ }
+ return InputActionPhase::None;
+}
+
float Input::GetAxis(const StringView& name)
{
const auto e = Axes.TryGet(name);
@@ -806,6 +818,7 @@ void InputService::Update()
ActionData& data = Actions[name];
data.Active = false;
+ data.Phase = InputActionPhase::Waiting;
// Mark as updated in this frame
data.FrameIndex = frame;
@@ -830,6 +843,13 @@ void InputService::Update()
isActive = Input::GetKeyUp(config.Key) || Input::GetMouseButtonUp(config.MouseButton) || Input::GetGamepadButtonUp(config.Gamepad, config.GamepadButton);
}
+ if (Input::GetKeyDown(config.Key) || Input::GetMouseButtonDown(config.MouseButton) || Input::GetGamepadButtonDown(config.Gamepad, config.GamepadButton))
+ data.Phase = InputActionPhase::Press;
+ else if (Input::GetKey(config.Key) || Input::GetMouseButton(config.MouseButton) || Input::GetGamepadButton(config.Gamepad, config.GamepadButton))
+ data.Phase = InputActionPhase::Pressing;
+ else if (Input::GetKeyUp(config.Key) || Input::GetMouseButtonUp(config.MouseButton) || Input::GetGamepadButtonUp(config.Gamepad, config.GamepadButton))
+ data.Phase = InputActionPhase::Release;
+
data.Active |= isActive;
}
diff --git a/Source/Engine/Input/Input.h b/Source/Engine/Input/Input.h
index d9f86076b..dd40c485a 100644
--- a/Source/Engine/Input/Input.h
+++ b/Source/Engine/Input/Input.h
@@ -309,6 +309,14 @@ public:
///
API_FUNCTION() static bool GetAction(const StringView& name);
+ ///
+ /// Gets the value of the virtual action identified by name. Use to get the current config.
+ ///
+ /// The action name.
+ /// True if action has been triggered in the current frame (e.g. button pressed), otherwise false.
+ ///
+ API_FUNCTION() static InputActionPhase GetActionPhase(const StringView& name);
+
///
/// Gets the value of the virtual axis identified by name. Use to get the current config.
///
diff --git a/Source/Engine/Input/VirtualInput.h b/Source/Engine/Input/VirtualInput.h
index 8fd4efeb4..e8f669632 100644
--- a/Source/Engine/Input/VirtualInput.h
+++ b/Source/Engine/Input/VirtualInput.h
@@ -48,6 +48,9 @@ API_STRUCT() struct ActionConfig
///
API_FIELD(Attributes="EditorOrder(40)")
InputGamepadIndex Gamepad;
+
+ API_FIELD(Attributes = "EditorOrder(50)")
+ InputActionMode Phase;
};
///