From 5f9dce430360d5f1c7079ae8fe5263b27af1d531 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 24 Nov 2015 10:37:50 +0100 Subject: [PATCH] Added Input --- include/Engine/Core/.gitkeep | 0 include/Engine/Core/EGamepadAxis.h | 37 ++++ include/Engine/Core/EGamepadButton.h | 52 +++++ include/Engine/Core/EKeyDown.h | 18 ++ include/Engine/Core/EKeyUp.h | 18 ++ include/Engine/Core/ELockMouse.h | 16 ++ include/Engine/Core/EMouseMove.h | 20 ++ include/Engine/Core/EMousePress.h | 20 ++ include/Engine/Core/EMouseRelease.h | 20 ++ include/Engine/Core/InputController.h | 35 ++++ include/Engine/Core/InputManager.h | 67 +++++++ include/Engine/Input/.gitkeep | 0 include/Engine/Input/EBindGamepadAxis.h | 24 +++ include/Engine/Input/EBindGamepadButton.h | 26 +++ include/Engine/Input/EBindKey.h | 25 +++ include/Engine/Input/EBindMouseButton.h | 25 +++ include/Engine/Input/EInputCommand.h | 21 ++ include/Engine/Input/InputSystem.h | 78 ++++++++ src/Engine/Core/.gitkeep | 0 src/Engine/Core/InputManager.cpp | 214 +++++++++++++++++++++ src/Engine/Input/.gitkeep | 0 src/Engine/Input/InputSystem.cpp | 221 ++++++++++++++++++++++ 22 files changed, 937 insertions(+) delete mode 100644 include/Engine/Core/.gitkeep create mode 100644 include/Engine/Core/EGamepadAxis.h create mode 100644 include/Engine/Core/EGamepadButton.h create mode 100644 include/Engine/Core/EKeyDown.h create mode 100644 include/Engine/Core/EKeyUp.h create mode 100644 include/Engine/Core/ELockMouse.h create mode 100644 include/Engine/Core/EMouseMove.h create mode 100644 include/Engine/Core/EMousePress.h create mode 100644 include/Engine/Core/EMouseRelease.h create mode 100644 include/Engine/Core/InputController.h create mode 100644 include/Engine/Core/InputManager.h delete mode 100755 include/Engine/Input/.gitkeep create mode 100644 include/Engine/Input/EBindGamepadAxis.h create mode 100644 include/Engine/Input/EBindGamepadButton.h create mode 100644 include/Engine/Input/EBindKey.h create mode 100644 include/Engine/Input/EBindMouseButton.h create mode 100644 include/Engine/Input/EInputCommand.h create mode 100644 include/Engine/Input/InputSystem.h delete mode 100755 src/Engine/Core/.gitkeep create mode 100644 src/Engine/Core/InputManager.cpp delete mode 100755 src/Engine/Input/.gitkeep create mode 100644 src/Engine/Input/InputSystem.cpp diff --git a/include/Engine/Core/.gitkeep b/include/Engine/Core/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/include/Engine/Core/EGamepadAxis.h b/include/Engine/Core/EGamepadAxis.h new file mode 100644 index 00000000..0c94d7ca --- /dev/null +++ b/include/Engine/Core/EGamepadAxis.h @@ -0,0 +1,37 @@ +#ifndef Events_GamepadAxis_h__ +#define Events_GamepadAxis_h__ + +#include "Core/EventBroker.h" + +namespace Gamepad +{ + /** Gamepad axis type */ + enum class Axis + { + LeftX, + LeftY, + RightX, + RightY, + LeftTrigger, + RightTrigger, + LAST = RightTrigger + }; +} + +namespace Events +{ + +/** Thrown when a gamepad axis changes value */ +struct GamepadAxis : Event +{ + /** ID of the gamepad. */ + int GamepadID; + /** The axis type. */ + Gamepad::Axis Axis; + /** The new value of the axis. */ + float Value; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Core/EGamepadButton.h b/include/Engine/Core/EGamepadButton.h new file mode 100644 index 00000000..e3612196 --- /dev/null +++ b/include/Engine/Core/EGamepadButton.h @@ -0,0 +1,52 @@ +#ifndef Events_GamepadButton_h__ +#define Events_GamepadButton_h__ + +#include "Core/EventBroker.h" + +namespace Gamepad +{ + /** Gamepad button type */ + enum class Button + { + Up, + Down, + Left, + Right, + Start, + Back, + LeftThumb, + RightThumb, + LeftShoulder, + RightShoulder, + A, + B, + X, + Y, + LAST = Y + }; +} + +namespace Events +{ + +/** Thrown on gamepad button press. */ +struct GamepadButtonDown : Event +{ + /** ID of the gamepad. */ + int GamepadID; + /** The button that was pressed. */ + Gamepad::Button Button; +}; + +/** Thrown on gamepad button release. */ +struct GamepadButtonUp : Event +{ + /** ID of the gamepad. */ + int GamepadID; + /** The button that was released. */ + Gamepad::Button Button; +}; + +} + +#endif diff --git a/include/Engine/Core/EKeyDown.h b/include/Engine/Core/EKeyDown.h new file mode 100644 index 00000000..fb576ec0 --- /dev/null +++ b/include/Engine/Core/EKeyDown.h @@ -0,0 +1,18 @@ +#ifndef Events_KeyDown_h__ +#define Events_KeyDown_h__ + +#include "Core/EventBroker.h" + +namespace Events +{ + +/** Thrown on key press. */ +struct KeyDown : Event +{ + /** GLFW key code */ + int KeyCode; +}; + +} + +#endif diff --git a/include/Engine/Core/EKeyUp.h b/include/Engine/Core/EKeyUp.h new file mode 100644 index 00000000..d446dbbf --- /dev/null +++ b/include/Engine/Core/EKeyUp.h @@ -0,0 +1,18 @@ +#ifndef Events_KeyUp_h__ +#define Events_KeyUp_h__ + +#include "Core/EventBroker.h" + +namespace Events +{ + +/** Thrown on key release. */ +struct KeyUp : Event +{ + /** GLFW key code */ + int KeyCode; +}; + +} + +#endif diff --git a/include/Engine/Core/ELockMouse.h b/include/Engine/Core/ELockMouse.h new file mode 100644 index 00000000..1c47c01a --- /dev/null +++ b/include/Engine/Core/ELockMouse.h @@ -0,0 +1,16 @@ +#ifndef Events_LockMouse_h__ +#define Events_LockMouse_h__ + +#include "Core/EventBroker.h" + +namespace Events +{ + +/** Called to lock mouse to the middle of the window. */ +struct LockMouse : Event { }; +/** Called to unlock mouse from the middle of the window. */ +struct UnlockMouse : Event { }; + +} + +#endif diff --git a/include/Engine/Core/EMouseMove.h b/include/Engine/Core/EMouseMove.h new file mode 100644 index 00000000..5bc9402c --- /dev/null +++ b/include/Engine/Core/EMouseMove.h @@ -0,0 +1,20 @@ +#ifndef Events_MouseMove_h__ +#define Events_MouseMove_h__ + +#include "Core/EventBroker.h" + +namespace Events +{ + +/** Thrown on mouse movement */ +struct MouseMove : Event +{ + /** The new position of the cursor in window coordinates. */ + double X, Y; + /** The delta movement of the mouse. */ + double DeltaX, DeltaY; +}; + +} + +#endif diff --git a/include/Engine/Core/EMousePress.h b/include/Engine/Core/EMousePress.h new file mode 100644 index 00000000..36a8d1f3 --- /dev/null +++ b/include/Engine/Core/EMousePress.h @@ -0,0 +1,20 @@ +#ifndef Events_MousePress_h__ +#define Events_MousePress_h__ + +#include "Core/EventBroker.h" + +namespace Events +{ + +/** Thrown on mouse button press. */ +struct MousePress : Event +{ + /** GLFW mouse button code */ + int Button; + /** The click position in window coordinates. */ + double X, Y; +}; + +} + +#endif diff --git a/include/Engine/Core/EMouseRelease.h b/include/Engine/Core/EMouseRelease.h new file mode 100644 index 00000000..6b347985 --- /dev/null +++ b/include/Engine/Core/EMouseRelease.h @@ -0,0 +1,20 @@ +#ifndef Events_MouseRelease_h__ +#define Events_MouseRelease_h__ + +#include "Core/EventBroker.h" + +namespace Events +{ + +/** Thrown on mouse button release. */ +struct MouseRelease : Event +{ + /** GLFW mouse button code */ + int Button; + /** The mouse position in window coordinates. */ + double X, Y; +}; + +} + +#endif diff --git a/include/Engine/Core/InputController.h b/include/Engine/Core/InputController.h new file mode 100644 index 00000000..28563f38 --- /dev/null +++ b/include/Engine/Core/InputController.h @@ -0,0 +1,35 @@ +#ifndef InputController_h__ +#define InputController_h__ + +#include + +#include "EventBroker.h" +#include "EMouseMove.h" +#include "Input/EInputCommand.h" + +template +class InputController +{ +public: + InputController(std::shared_ptr eventBroker) + : EventBroker(eventBroker) + { Initialize(); } + + virtual void Initialize() + { + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &InputController::OnCommand); + EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &InputController::OnMouseMove); + } + + virtual bool OnCommand(const Events::InputCommand &event) { return false; } + virtual bool OnMouseMove(const Events::MouseMove &event) { return false; } + +protected: + std::shared_ptr EventBroker; + +private: + EventRelay m_EInputCommand; + EventRelay m_EMouseMove; +}; + +#endif diff --git a/include/Engine/Core/InputManager.h b/include/Engine/Core/InputManager.h new file mode 100644 index 00000000..cd960e6f --- /dev/null +++ b/include/Engine/Core/InputManager.h @@ -0,0 +1,67 @@ +#ifndef InputManager_h__ +#define InputManager_h__ + +#include + +#include "Core/EventBroker.h" +#include "EKeyDown.h" +#include "EKeyUp.h" +#include "EMousePress.h" +#include "EMouseRelease.h" +#include "EMouseMove.h" +#include "ELockMouse.h" +#include "EGamepadAxis.h" +#include "EGamepadButton.h" + +class InputManager +{ +public: + InputManager(GLFWwindow* window, std::shared_ptr eventBroker) + : m_GLFWWindow(window) + , EventBroker(eventBroker) + , m_CurrentKeyState() + , m_LastKeyState() + , m_CurrentMouseState() + , m_LastMouseState() + , m_CurrentMouseX(0), m_CurrentMouseY(0) + , m_LastMouseX(0), m_LastMouseY(0) + , m_CurrentMouseDeltaX(0), m_CurrentMouseDeltaY(0) + , m_MouseLocked(false) + { Initialize(); } + + void Initialize(); + + static const short MAX_GAMEPADS = 4; + + void Update(double dt); + +private: + GLFWwindow* m_GLFWWindow; + std::shared_ptr EventBroker; + + EventRelay m_ELockMouse; + bool OnLockMouse(const Events::LockMouse &event); + EventRelay m_EUnlockMouse; + bool OnUnlockMouse(const Events::UnlockMouse &event); + + std::array m_CurrentKeyState; + std::array m_LastKeyState; + std::array m_CurrentMouseState; + std::array m_LastMouseState; + typedef std::array(Gamepad::Axis::LAST) + 1> GamepadAxisState; + std::array m_CurrentGamepadAxisState; + std::array m_LastGamepadAxisState; + typedef std::array(Gamepad::Button::LAST) + 1> GamepadButtonState; + std::array m_CurrentGamepadButtonState; + std::array m_LastGamepadButtonState; + + double m_CurrentMouseX, m_CurrentMouseY; + double m_LastMouseX, m_LastMouseY; + double m_CurrentMouseDeltaX, m_CurrentMouseDeltaY; + bool m_MouseLocked; + + void PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis); + void PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button); +}; + +#endif diff --git a/include/Engine/Input/.gitkeep b/include/Engine/Input/.gitkeep deleted file mode 100755 index e69de29b..00000000 diff --git a/include/Engine/Input/EBindGamepadAxis.h b/include/Engine/Input/EBindGamepadAxis.h new file mode 100644 index 00000000..1f2665ad --- /dev/null +++ b/include/Engine/Input/EBindGamepadAxis.h @@ -0,0 +1,24 @@ +#ifndef Events_BindGamepadAxis_h__ +#define Events_BindGamepadAxis_h__ + +#include "Core/EventBroker.h" +#include "Core/EGamepadAxis.h" + +namespace Events +{ + +/** Called to bind a gamepad axis to an input command. */ +struct BindGamepadAxis : Event +{ + /** The axis to bind. */ + Gamepad::Axis Axis; + /** The command to send. */ + std::string Command; + /** The value to send for positive stimulation. + + Multiplied by the 0-1 clamped value of the axis. + */ + float Value; +}; + +} diff --git a/include/Engine/Input/EBindGamepadButton.h b/include/Engine/Input/EBindGamepadButton.h new file mode 100644 index 00000000..47dddf31 --- /dev/null +++ b/include/Engine/Input/EBindGamepadButton.h @@ -0,0 +1,26 @@ +#ifndef Events_BindGamepadButton_h__ +#define Events_BindGamepadButton_h__ + +#include "Core/EventBroker.h" +#include "Core/EGamepadButton.h" + +namespace Events +{ + +/** Called to bind a gamepad button to an input command. */ +struct BindGamepadButton : Event +{ + /** The gamepad button to bind. */ + Gamepad::Button Button; + /** The command to send. */ + std::string Command; + /** The value to send for positive stimulation. + + Multiplied by the 0-1 clamped value of the button. + */ + float Value; +}; + +} + +#endif diff --git a/include/Engine/Input/EBindKey.h b/include/Engine/Input/EBindKey.h new file mode 100644 index 00000000..fb1c199a --- /dev/null +++ b/include/Engine/Input/EBindKey.h @@ -0,0 +1,25 @@ +#ifndef Events_BindKey_h__ +#define Events_BindKey_h__ + +#include "Core/EventBroker.h" + +namespace Events +{ + +/** Called to bind a keyboard key to an input command. */ +struct BindKey : Event +{ + /** The GLFW key code to bind. */ + int KeyCode; + /** The command to send. */ + std::string Command; + /** The value to send for positive stimulation. + + Multiplied by the 0-1 clamped value of the key. + */ + float Value; +}; + +} + +#endif diff --git a/include/Engine/Input/EBindMouseButton.h b/include/Engine/Input/EBindMouseButton.h new file mode 100644 index 00000000..78b5dfa3 --- /dev/null +++ b/include/Engine/Input/EBindMouseButton.h @@ -0,0 +1,25 @@ +#ifndef Events_BindMouseButton_h__ +#define Events_BindMouseButton_h__ + +#include "Core/EventBroker.h" + +namespace Events +{ + +/** Called to bind a mouse button to an input command. */ +struct BindMouseButton : Event +{ + /** The GLFW mouse button code to bind. */ + int Button; + /** The command to send. */ + std::string Command; + /** The value to send for positive stimulation. + + Multiplied by the 0-1 clamped value of the button. + */ + float Value; +}; + +} + +#endif diff --git a/include/Engine/Input/EInputCommand.h b/include/Engine/Input/EInputCommand.h new file mode 100644 index 00000000..9c190a1e --- /dev/null +++ b/include/Engine/Input/EInputCommand.h @@ -0,0 +1,21 @@ +#ifndef Events_InputCommand_h__ +#define Events_InputCommand_h__ + +#include "Core/EventBroker.h" + +namespace Events +{ +/** Thrown when an input command is sent. */ +struct InputCommand : Event +{ + /** Numerical ID of the player. */ + unsigned int PlayerID; + /** The command that was sent. */ + std::string Command; + /** The value of the command. */ + float Value; +}; + +} + +#endif diff --git a/include/Engine/Input/InputSystem.h b/include/Engine/Input/InputSystem.h new file mode 100644 index 00000000..2023880b --- /dev/null +++ b/include/Engine/Input/InputSystem.h @@ -0,0 +1,78 @@ +#ifndef InputSystem_h__ +#define InputSystem_h__ + +#include +#include + +#include "Core/System.h" +#include "Core/EKeyUp.h" +#include "Core/EKeyDown.h" +#include "Core/EMousePress.h" +#include "Core/EMouseRelease.h" +#include "Core/EGamepadAxis.h" +#include "Core/EGamepadButton.h" +#include "Core/Util/EnumClassHash.h" +#include "EBindKey.h" +#include "EBindMouseButton.h" +#include "EBindGamepadAxis.h" +#include "EBindGamepadButton.h" +#include "EInputCommand.h" + +namespace Systems +{ + +class InputSystem : public System +{ +public: + InputSystem(World* world, std::shared_ptr eventBroker) + : System(world, eventBroker) + { } + + void RegisterComponents(ComponentFactory* cf) override; + void Initialize() override; + + void Update(double dt) override; + +private: + std::unordered_map> m_CommandKeyboardValues; // command string -> keyboard key value for command + std::unordered_map> m_CommandMouseButtonValues; // command string -> mouse button value for command + std::unordered_map> m_CommandGamepadAxisValues; // command string -> gamepad axis value for command + std::unordered_map> m_CommandGamepadButtonValues; // command string -> gamepad button value for command + // Input binding tables + std::unordered_multimap> m_KeyBindings; // GLFW_KEY... -> command string & value + std::unordered_multimap> m_MouseButtonBindings; // GLFW_MOUSE_BUTTON... -> command string + std::unordered_multimap, EnumClassHash> m_GamepadAxisBindings; // Gamepad::Axis -> command string & value + std::unordered_multimap, EnumClassHash> m_GamepadButtonBindings; // Gamepad::Button -> command string + + // Input events + EventRelay m_EKeyDown; + bool OnKeyDown(const Events::KeyDown &event); + EventRelay m_EKeyUp; + bool OnKeyUp(const Events::KeyUp &event); + EventRelay m_EMousePress; + bool OnMousePress(const Events::MousePress &event); + EventRelay m_EMouseRelease; + bool OnMouseRelease(const Events::MouseRelease &event); + EventRelay m_EGamepadAxis; + bool OnGamepadAxis(const Events::GamepadAxis &event); + EventRelay m_EGamepadButtonDown; + bool OnGamepadButtonDown(const Events::GamepadButtonDown &event); + EventRelay m_EGamepadButtonUp; + bool OnGamepadButtonUp(const Events::GamepadButtonUp &event); + // Input binding events + EventRelay m_EBindKey; + bool OnBindKey(const Events::BindKey &event); + EventRelay m_EBindMouseButton; + bool OnBindMouseButton(const Events::BindMouseButton &event); + EventRelay m_EBindGamepadAxis; + bool OnBindGamepadAxis(const Events::BindGamepadAxis &event); + EventRelay m_EBindGamepadButton; + bool OnBindGamepadButton(const Events::BindGamepadButton &event); + + float GetCommandTotalValue(std::string command); + void PublishCommand(int playerID, std::string command, float value); +}; + +} + +#endif diff --git a/src/Engine/Core/.gitkeep b/src/Engine/Core/.gitkeep deleted file mode 100755 index e69de29b..00000000 diff --git a/src/Engine/Core/InputManager.cpp b/src/Engine/Core/InputManager.cpp new file mode 100644 index 00000000..8a6a0615 --- /dev/null +++ b/src/Engine/Core/InputManager.cpp @@ -0,0 +1,214 @@ +#include "PrecompiledHeader.h" +#include "Core/InputManager.h" + +void InputManager::Initialize() +{ + // TODO: Gamepad + //m_LastGamepadAxisState = std::array(); + //m_LastGamepadButtonState = std::array(); + + EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &InputManager::OnLockMouse); + EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &InputManager::OnUnlockMouse); +} + +void InputManager::Update(double dt) +{ + EventBroker->Process(); + + m_LastKeyState = m_CurrentKeyState; + m_LastMouseState = m_CurrentMouseState; + m_LastMouseX = m_CurrentMouseX; + m_LastMouseY = m_CurrentMouseY; + + // Keyboard input + for (int i = 0; i <= GLFW_KEY_LAST; ++i) { + m_CurrentKeyState[i] = glfwGetKey(m_GLFWWindow, i); + if (m_CurrentKeyState[i] != m_LastKeyState[i]) { + // Publish key events + if (m_CurrentKeyState[i]) { + Events::KeyDown e; + e.KeyCode = i; + EventBroker->Publish(e); + } else { + Events::KeyUp e; + e.KeyCode = i; + EventBroker->Publish(e); + } + } + } + + // Mouse buttons + for (int i = 0; i <= GLFW_MOUSE_BUTTON_LAST; ++i) { + m_CurrentMouseState[i] = glfwGetMouseButton(m_GLFWWindow, i); + if (m_CurrentMouseState[i] != m_LastMouseState[i]) { + double x, y; + glfwGetCursorPos(m_GLFWWindow, &x, &y); + // Publish mouse button events + if (m_CurrentMouseState[i]) { + Events::MousePress e; + e.Button = i; + e.X = x; + e.Y = y; + EventBroker->Publish(e); + } else { + Events::MouseRelease e; + e.Button = i; + e.X = x; + e.Y = y; + EventBroker->Publish(e); + } + } + } + + // Mouse movement + glfwGetCursorPos(m_GLFWWindow, &m_CurrentMouseX, &m_CurrentMouseY); + m_CurrentMouseDeltaX = m_CurrentMouseX - m_LastMouseX; + m_CurrentMouseDeltaY = m_CurrentMouseY - m_LastMouseY; + if (m_CurrentMouseDeltaX != 0 || m_CurrentMouseDeltaY != 0) { + // Publish mouse move events + Events::MouseMove e; + e.X = m_CurrentMouseX; + e.Y = m_CurrentMouseY; + e.DeltaX = m_CurrentMouseDeltaX; + e.DeltaY = m_CurrentMouseDeltaY; + EventBroker->Publish(e); + } + + // // Lock mouse while holding LMB + // if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT]) + // { + // m_LastMouseX = m_Renderer->Width() / 2.f; // xpos; + // m_LastMouseY = m_Renderer->Height() / 2.f; // ypos; + // glfwSetCursorPos(m_GLFWWindow, m_LastMouseX, m_LastMouseY); + // } + // // Hide/show cursor with LMB + // if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT] && !m_LastMouseState[GLFW_MOUSE_BUTTON_LEFT]) + // { + // glfwSetInputMode(m_GLFWWindow, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + // } + // if (!m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT] && m_LastMouseState[GLFW_MOUSE_BUTTON_LEFT]) + // { + // glfwSetInputMode(m_GLFWWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + // } + + // TODO: Xbox360 controller + /*DWORD dwResult; + for (int i = 0; i < MAX_GAMEPADS; i++) + { + XINPUT_STATE state = { 0 }; + // Simply get the state of the controller from XInput. + dwResult = XInputGetState(i, &state); + if (dwResult == 0) + { + if(std::abs(state.Gamepad.sThumbLX) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) + state.Gamepad.sThumbLX = 0; + if(std::abs(state.Gamepad.sThumbLY) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) + state.Gamepad.sThumbLY = 0; + if(std::abs(state.Gamepad.sThumbRX) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) + state.Gamepad.sThumbRX = 0; + if(std::abs(state.Gamepad.sThumbRY) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) + state.Gamepad.sThumbRY = 0; + if(std::abs(state.Gamepad.bLeftTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD) + state.Gamepad.bLeftTrigger = 0; + if(std::abs(state.Gamepad.bRightTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD) + state.Gamepad.bRightTrigger = 0; + + m_CurrentGamepadAxisState[i][static_cast(Gamepad::Axis::LeftX)] = state.Gamepad.sThumbLX / 32767.f; + m_CurrentGamepadAxisState[i][static_cast(Gamepad::Axis::LeftY)] = state.Gamepad.sThumbLY / 32767.f; + m_CurrentGamepadAxisState[i][static_cast(Gamepad::Axis::RightX)] = state.Gamepad.sThumbRX / 32767.f; + m_CurrentGamepadAxisState[i][static_cast(Gamepad::Axis::RightY)] = state.Gamepad.sThumbRY / 32767.f; + m_CurrentGamepadAxisState[i][static_cast(Gamepad::Axis::LeftTrigger)] = state.Gamepad.bLeftTrigger / 255.f; + m_CurrentGamepadAxisState[i][static_cast(Gamepad::Axis::RightTrigger)] = state.Gamepad.bRightTrigger / 255.f; + PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftX); + PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftY); + PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightX); + PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightY); + PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftTrigger); + PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightTrigger); + + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Up)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Down)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Left)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Right)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Start)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_START); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Back)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::LeftThumb)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::RightThumb)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::LeftShoulder)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::RightShoulder)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::A)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_A); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::B)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_B); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::X)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_X); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Y)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Up); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Down); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Left); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Right); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Start); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Back); + PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftThumb); + PublishGamepadButtonIfChanged(i, Gamepad::Button::RightThumb); + PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftShoulder); + PublishGamepadButtonIfChanged(i, Gamepad::Button::RightShoulder); + PublishGamepadButtonIfChanged(i, Gamepad::Button::A); + PublishGamepadButtonIfChanged(i, Gamepad::Button::B); + PublishGamepadButtonIfChanged(i, Gamepad::Button::X); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Y); + } + }*/ + + m_LastKeyState = m_CurrentKeyState; + m_LastMouseState = m_CurrentMouseState; + m_LastMouseX = m_CurrentMouseX; + m_LastMouseY = m_CurrentMouseY; + m_LastGamepadAxisState = m_CurrentGamepadAxisState; + m_LastGamepadButtonState = m_CurrentGamepadButtonState; +} + +void InputManager::PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis) +{ + float currentValue = m_CurrentGamepadAxisState[gamepadID][static_cast(axis)]; + float lastValue = m_LastGamepadAxisState[gamepadID][static_cast(axis)]; + if (currentValue != lastValue) { + Events::GamepadAxis e; + e.GamepadID = gamepadID; + e.Axis = axis; + e.Value = currentValue; + EventBroker->Publish(e); + } +} + +void InputManager::PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button) +{ + bool currentState = m_CurrentGamepadButtonState[gamepadID][static_cast(button)]; + float lastState = m_LastGamepadButtonState[gamepadID][static_cast(button)]; + if (currentState != lastState) { + if (currentState == true) { + Events::GamepadButtonDown e; + e.GamepadID = gamepadID; + e.Button = button; + EventBroker->Publish(e); + } else { + Events::GamepadButtonUp e; + e.GamepadID = gamepadID; + e.Button = button; + EventBroker->Publish(e); + } + } +} + +bool InputManager::OnLockMouse(const Events::LockMouse &event) +{ + m_MouseLocked = true; + glfwSetInputMode(m_GLFWWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + + return true; +} + +bool InputManager::OnUnlockMouse(const Events::UnlockMouse &event) +{ + m_MouseLocked = false; + glfwSetInputMode(m_GLFWWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + + return true; +} diff --git a/src/Engine/Input/.gitkeep b/src/Engine/Input/.gitkeep deleted file mode 100755 index e69de29b..00000000 diff --git a/src/Engine/Input/InputSystem.cpp b/src/Engine/Input/InputSystem.cpp new file mode 100644 index 00000000..d11cd73d --- /dev/null +++ b/src/Engine/Input/InputSystem.cpp @@ -0,0 +1,221 @@ +#include "PrecompiledHeader.h" +#include "Input/InputSystem.h" +#include "Core/World.h" + +void Systems::InputSystem::RegisterComponents(ComponentFactory* cf) +{ + +} + +void Systems::InputSystem::Initialize() +{ + // Subscribe to events + EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &Systems::InputSystem::OnKeyDown); + EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &Systems::InputSystem::OnKeyUp); + EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &Systems::InputSystem::OnMousePress); + EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &Systems::InputSystem::OnMouseRelease); + EVENT_SUBSCRIBE_MEMBER(m_EGamepadAxis, &Systems::InputSystem::OnGamepadAxis); + EVENT_SUBSCRIBE_MEMBER(m_EGamepadButtonDown, &Systems::InputSystem::OnGamepadButtonDown); + EVENT_SUBSCRIBE_MEMBER(m_EGamepadButtonUp, &Systems::InputSystem::OnGamepadButtonUp); + EVENT_SUBSCRIBE_MEMBER(m_EBindKey, &Systems::InputSystem::OnBindKey); + EVENT_SUBSCRIBE_MEMBER(m_EBindMouseButton, &Systems::InputSystem::OnBindMouseButton); + EVENT_SUBSCRIBE_MEMBER(m_EBindGamepadAxis, &Systems::InputSystem::OnBindGamepadAxis); + EVENT_SUBSCRIBE_MEMBER(m_EBindGamepadButton, &Systems::InputSystem::OnBindGamepadButton); +} + +void Systems::InputSystem::Update(double dt) +{ + +} + +bool Systems::InputSystem::OnKeyDown(const Events::KeyDown &event) +{ + auto range = m_KeyBindings.equal_range(event.KeyCode); + for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) { + std::string command; + float value; + std::tie(command, value) = bindingIt->second; + m_CommandKeyboardValues[command][event.KeyCode] = value; + PublishCommand(1, command, GetCommandTotalValue(command)); + } + + return true; +} + +bool Systems::InputSystem::OnKeyUp(const Events::KeyUp &event) +{ + auto range = m_KeyBindings.equal_range(event.KeyCode); + for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) { + std::string command; + float value; + std::tie(command, value) = bindingIt->second; + m_CommandKeyboardValues[command][event.KeyCode] = 0; + PublishCommand(1, command, GetCommandTotalValue(command));; + } + + return true; +} + +bool Systems::InputSystem::OnMousePress(const Events::MousePress &event) +{ + auto range = m_MouseButtonBindings.equal_range(event.Button); + for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) { + std::string command; + float value; + std::tie(command, value) = bindingIt->second; + m_CommandMouseButtonValues[command][event.Button] = value; + PublishCommand(1, command, GetCommandTotalValue(command)); + } + + return true; +} + +bool Systems::InputSystem::OnMouseRelease(const Events::MouseRelease &event) +{ + auto range = m_MouseButtonBindings.equal_range(event.Button); + for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) { + std::string command; + float value; + std::tie(command, value) = bindingIt->second; + m_CommandMouseButtonValues[command][event.Button] = 0; + PublishCommand(1, command, GetCommandTotalValue(command)); + } + + return true; +} + +bool Systems::InputSystem::OnGamepadAxis(const Events::GamepadAxis &event) +{ + auto range = m_GamepadAxisBindings.equal_range(event.Axis); + for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) { + std::string command; + float value; + std::tie(command, value) = bindingIt->second; + m_CommandGamepadAxisValues[command][event.Axis] = event.Value * value; + PublishCommand(event.GamepadID + 1, command, GetCommandTotalValue(command)); + } + + return true; +} + +bool Systems::InputSystem::OnGamepadButtonDown(const Events::GamepadButtonDown &event) +{ + auto range = m_GamepadButtonBindings.equal_range(event.Button); + for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) { + std::string command; + float value; + std::tie(command, value) = bindingIt->second; + m_CommandGamepadButtonValues[command][event.Button] = value; + PublishCommand(event.GamepadID + 1, command, GetCommandTotalValue(command)); + } + + return true; +} + +bool Systems::InputSystem::OnGamepadButtonUp(const Events::GamepadButtonUp &event) +{ + auto range = m_GamepadButtonBindings.equal_range(event.Button); + for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) { + std::string command; + float value; + std::tie(command, value) = bindingIt->second; + m_CommandGamepadButtonValues[command][event.Button] = 0; + PublishCommand(event.GamepadID + 1, command, GetCommandTotalValue(command)); + } + + return true; +} + +bool Systems::InputSystem::OnBindKey(const Events::BindKey &event) +{ + if (event.Command.empty()) { + return false; + } + + m_KeyBindings.insert(std::make_pair(event.KeyCode, std::make_tuple(event.Command, event.Value))); + LOG_DEBUG("Input: Bound key %i to %s", event.KeyCode, event.Command.c_str()); + + return true; +} + +bool Systems::InputSystem::OnBindMouseButton(const Events::BindMouseButton &event) +{ + if (event.Command.empty()) { + return false; + } + + m_MouseButtonBindings.insert(std::make_pair(event.Button, std::make_tuple(event.Command, event.Value))); + LOG_DEBUG("Input: Bound mouse button %i to %s", event.Button, event.Command.c_str()); + + return true; +} + +bool Systems::InputSystem::OnBindGamepadAxis(const Events::BindGamepadAxis &event) +{ + if (event.Command.empty()) { + return false; + } + + m_GamepadAxisBindings.insert(std::make_pair(event.Axis, std::make_tuple(event.Command, event.Value))); + LOG_DEBUG("Input: Bound gamepad axis %i to %s", event.Axis, event.Command.c_str()); + + return true; +} + +bool Systems::InputSystem::OnBindGamepadButton(const Events::BindGamepadButton &event) +{ + if (event.Command.empty()) { + return false; + } + + m_GamepadButtonBindings.insert(std::make_pair(event.Button, std::make_tuple(event.Command, event.Value))); + LOG_DEBUG("Input: Bound gamepad axis %i to %s", event.Button, event.Command.c_str()); + + return true; +} + +float Systems::InputSystem::GetCommandTotalValue(std::string command) +{ + float value = 0.f; + + auto keyboardIt = m_CommandKeyboardValues.find(command); + if (keyboardIt != m_CommandKeyboardValues.end()) { + for (auto &key : keyboardIt->second) { + value += key.second; + } + } + + auto mouseButtonIt = m_CommandMouseButtonValues.find(command); + if (mouseButtonIt != m_CommandMouseButtonValues.end()) { + for (auto &button : mouseButtonIt->second) { + value += button.second; + } + } + + auto gamepadAxisIt = m_CommandGamepadAxisValues.find(command); + if (gamepadAxisIt != m_CommandGamepadAxisValues.end()) { + for (auto &axis : gamepadAxisIt->second) { + value += axis.second; + } + } + + auto gamepadButtonIt = m_CommandGamepadButtonValues.find(command); + if (gamepadButtonIt != m_CommandGamepadButtonValues.end()) { + for (auto &button : gamepadButtonIt->second) { + value += button.second; + } + } + + return std::max(-1.f, std::min(value, 1.f)); +} + +void Systems::InputSystem::PublishCommand(int playerID, std::string command, float value) +{ + Events::InputCommand e; + e.PlayerID = playerID; + e.Command = command; + e.Value = value; + EventBroker->Publish(e); + + LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, playerID); +}