From bffc97f31029b501fd49a7189228a7526d56bf9a Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Fri, 11 Dec 2015 00:37:48 +0100 Subject: [PATCH] Groundwork for input command proxy --- include/Engine/Input/EBindOrigin.h | 22 ++ include/Engine/Input/EInputCommand.h | 2 +- include/Engine/Input/InputProxy.h | 146 +++++++++++++ include/Engine/Input/InputSystem.h | 78 ------- include/Engine/Input/KeyboardInputHandler.h | 67 ++++++ include/Game/Game.h | 3 + src/Engine/CMakeLists.txt | 2 +- src/Engine/Input/InputProxy.cpp | 221 ++++++++++++++++++++ src/Engine/Input/InputSystem.cpp | 221 -------------------- src/Game/Game.cpp | 8 + 10 files changed, 469 insertions(+), 301 deletions(-) create mode 100644 include/Engine/Input/EBindOrigin.h create mode 100644 include/Engine/Input/InputProxy.h delete mode 100644 include/Engine/Input/InputSystem.h create mode 100644 include/Engine/Input/KeyboardInputHandler.h create mode 100644 src/Engine/Input/InputProxy.cpp delete mode 100644 src/Engine/Input/InputSystem.cpp diff --git a/include/Engine/Input/EBindOrigin.h b/include/Engine/Input/EBindOrigin.h new file mode 100644 index 00000000..e39a6023 --- /dev/null +++ b/include/Engine/Input/EBindOrigin.h @@ -0,0 +1,22 @@ +#ifndef Events_BindOrigin_h__ +#define Events_BindOrigin_h__ + +#include "Core/EventBroker.h" + +namespace Events +{ + +/** Called to bind an input origin to an input command. */ +struct BindOrigin : Event +{ + /** The input origin to bind. */ + std::string Origin; + /** The command to send. */ + std::string Command; + /** The value to send for positive stimulation. */ + float Value = 1.f; +}; + +} + +#endif diff --git a/include/Engine/Input/EInputCommand.h b/include/Engine/Input/EInputCommand.h index 9c190a1e..9ec897d3 100644 --- a/include/Engine/Input/EInputCommand.h +++ b/include/Engine/Input/EInputCommand.h @@ -13,7 +13,7 @@ struct InputCommand : Event /** The command that was sent. */ std::string Command; /** The value of the command. */ - float Value; + float Value = 0; }; } diff --git a/include/Engine/Input/InputProxy.h b/include/Engine/Input/InputProxy.h new file mode 100644 index 00000000..1b0e213e --- /dev/null +++ b/include/Engine/Input/InputProxy.h @@ -0,0 +1,146 @@ +#ifndef InputSystem_h__ +#define InputSystem_h__ + +#include +#include + +#include + +#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" +#include "EBindOrigin.h" + +class InputProxy; + +class InputHandler +{ +public: + InputHandler(EventBroker* eventBroker, InputProxy* inputProxy) + : m_EventBroker(eventBroker) + , m_InputProxy(inputProxy) + { } + + virtual void Update(double dt) { } + virtual bool BindOrigin(std::string origin, std::string command, float value) = 0; + +protected: + EventBroker* m_EventBroker; + InputProxy* m_InputProxy; +}; + +class InputProxy +{ +public: + InputProxy(EventBroker* eventBroker) + : m_EventBroker(eventBroker) + { + EVENT_SUBSCRIBE_MEMBER(m_EBindOrigin, &InputProxy::OnBindOrigin); + } + + void Update(double dt) + { + m_EventBroker->Process(); + m_EventBroker->Process(); + for (auto& handler : m_Handlers) { + handler->Update(dt); + } + } + + void Process() + { + // Accumulate the input values of all unique commands published by input handlers + for (auto& pair : m_CommandQueue) { + Events::InputCommand e; + e.PlayerID = pair.first.first; + e.Command = pair.first.second; + e.Value = 0; + for (auto& value : pair.second) { + e.Value += value; + } + e.Value = std::max(-1.f, std::min(e.Value, 1.f)); + m_EventBroker->Publish(e); + LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + } + m_CommandQueue.clear(); + } + + template + void AddHandler() + { + m_Handlers.push_back(new T(m_EventBroker, this)); + } + + void Publish(const Events::InputCommand& e) + { + auto key = std::make_pair(e.PlayerID, e.Command); + m_CommandQueue[key].push_back(e.Value); + } + +protected: + EventBroker* m_EventBroker; + std::vector m_Handlers; + // Represents every unique command (has of PlayerID & Command) and all values reported for that command + std::map, std::vector> m_CommandQueue; + + EventRelay m_EBindOrigin; + bool OnBindOrigin(const Events::BindOrigin& e) + { + bool originBound = false; + for (auto& handler : m_Handlers) { + bool result = handler->BindOrigin(e.Origin, e.Command, e.Value); + if (result) { + if (originBound) { + LOG_WARNING("Multiple handlers responded to binding input origin \"%s\"!", e.Origin.c_str()); + } + originBound = true; + } + } + + if (!originBound) { + LOG_ERROR("No input handler responded to binding input origin \"%s\"!", e.Origin.c_str()); + } + + return originBound; + } + //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_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_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_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/include/Engine/Input/InputSystem.h b/include/Engine/Input/InputSystem.h deleted file mode 100644 index 2023880b..00000000 --- a/include/Engine/Input/InputSystem.h +++ /dev/null @@ -1,78 +0,0 @@ -#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/include/Engine/Input/KeyboardInputHandler.h b/include/Engine/Input/KeyboardInputHandler.h new file mode 100644 index 00000000..1ffaa067 --- /dev/null +++ b/include/Engine/Input/KeyboardInputHandler.h @@ -0,0 +1,67 @@ +#include +#include "InputProxy.h" +#include "Core/EKeyDown.h" +#include "Core/EKeyUp.h" + +class KeyboardInputHandler : public InputHandler +{ +public: + KeyboardInputHandler(EventBroker* eventBroker, InputProxy* inputProxy) + : InputHandler(eventBroker, inputProxy) + { + EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &KeyboardInputHandler::OnKeyDown); + EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &KeyboardInputHandler::OnKeyUp); + + m_OriginKeyCodes["R"] = GLFW_KEY_R; + } + + bool BindOrigin(std::string origin, std::string command, float value) override + { + auto originIt = m_OriginKeyCodes.find(origin); + if (originIt == m_OriginKeyCodes.end()) { + return false; + } + + int keyCode = originIt->second; + m_KeyBindings[keyCode] = std::make_tuple(command, value); + return true; + } + +private: + std::unordered_map m_OriginKeyCodes; + std::unordered_map> m_KeyBindings; // GLFW_KEY... -> command string & value + + EventRelay m_EKeyDown; + bool OnKeyDown(const Events::KeyDown& e) + { + auto it = m_KeyBindings.find(e.KeyCode); + if (it == m_KeyBindings.end()) { + return false; + } + + Events::InputCommand ic; + ic.PlayerID = 0; + std::tie(ic.Command, ic.Value) = it->second; + m_InputProxy->Publish(ic); + + return true; + } + + EventRelay m_EKeyUp; + bool OnKeyUp(const Events::KeyUp& e) + { + auto it = m_KeyBindings.find(e.KeyCode); + if (it == m_KeyBindings.end()) { + return false; + } + + Events::InputCommand ic; + ic.PlayerID = 0; + std::tie(ic.Command, std::ignore) = it->second; + ic.Value = 0; + m_InputProxy->Publish(ic); + + return true; + } + +}; \ No newline at end of file diff --git a/include/Game/Game.h b/include/Game/Game.h index bc66d62f..04d14be0 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -9,6 +9,8 @@ #include "GUI/Frame.h" #include "Core/World.h" #include "Rendering/RenderQueueFactory.h" +#include "Input/InputProxy.h" +#include "Input/KeyboardInputHandler.h" #include "Core/EKeyDown.h" #include "Core/EntityXMLFile.h" #include "Core/SystemPipeline.h" @@ -30,6 +32,7 @@ private: EventBroker* m_EventBroker; IRenderer* m_Renderer; InputManager* m_InputManager; + InputProxy* m_InputProxy; GUI::Frame* m_FrameStack; World* m_World; SystemPipeline* m_SystemPipeline; diff --git a/src/Engine/CMakeLists.txt b/src/Engine/CMakeLists.txt index de24b9cf..97ed3e68 100644 --- a/src/Engine/CMakeLists.txt +++ b/src/Engine/CMakeLists.txt @@ -73,7 +73,7 @@ source_group(GUI FILES ${SOURCE_FILES_GUI}) set(SOURCE_FILES ${SOURCE_FILES_Core} ${SOURCE_FILES_Core_Util} - #${SOURCE_FILES_Input} + ${SOURCE_FILES_Input} ${SOURCE_FILES_Network} ${SOURCE_FILES_GUI} ${SOURCE_FILES_Rendering} diff --git a/src/Engine/Input/InputProxy.cpp b/src/Engine/Input/InputProxy.cpp new file mode 100644 index 00000000..3a6626df --- /dev/null +++ b/src/Engine/Input/InputProxy.cpp @@ -0,0 +1,221 @@ +#include "Input/InputProxy.h" +#include "Core/World.h" + +//InputProxy::InputProxy(EventBroker* eventBroker) +// : m_EventBroker(eventBroker) +//{ +// // Subscribe to events +// EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &InputProxy::OnMousePress); +// EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &InputProxy::OnMouseRelease); +// EVENT_SUBSCRIBE_MEMBER(m_EGamepadAxis, &InputProxy::OnGamepadAxis); +// EVENT_SUBSCRIBE_MEMBER(m_EGamepadButtonDown, &InputProxy::OnGamepadButtonDown); +// EVENT_SUBSCRIBE_MEMBER(m_EGamepadButtonUp, &InputProxy::OnGamepadButtonUp); +// EVENT_SUBSCRIBE_MEMBER(m_EBindKey, &InputProxy::OnBindKey); +// EVENT_SUBSCRIBE_MEMBER(m_EBindMouseButton, &InputProxy::OnBindMouseButton); +// EVENT_SUBSCRIBE_MEMBER(m_EBindGamepadAxis, &InputProxy::OnBindGamepadAxis); +// EVENT_SUBSCRIBE_MEMBER(m_EBindGamepadButton, &InputProxy::OnBindGamepadButton); +// +// SteamController()->Init(); +// +//} +// +//void InputProxy::Update(double dt) +//{ +// std::array controllers; +// int numControllers = SteamController()->GetConnectedControllers(controllers.data()); +// +// ControllerDigitalActionHandle_t debug_reload_handle = SteamController()->GetDigitalActionHandle("debug_reload"); +// SteamController()-> +//} +// +//bool InputProxy::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 InputProxy::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 InputProxy::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 InputProxy::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 InputProxy::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 InputProxy::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 InputProxy::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 InputProxy::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 InputProxy::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 InputProxy::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 InputProxy::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 InputProxy::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 InputProxy::PublishCommand(int playerID, std::string command, float value) +//{ +// Events::InputCommand e; +// e.PlayerID = playerID; +// e.Command = command; +// e.Value = value; +// m_EventBroker->Publish(e); +// +// LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, playerID); +//} diff --git a/src/Engine/Input/InputSystem.cpp b/src/Engine/Input/InputSystem.cpp deleted file mode 100644 index d11cd73d..00000000 --- a/src/Engine/Input/InputSystem.cpp +++ /dev/null @@ -1,221 +0,0 @@ -#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); -} diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index fa12bbc6..5451289e 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -29,6 +29,9 @@ Game::Game(int argc, char* argv[]) // Create input manager m_InputManager = new InputManager(m_Renderer->Window(), m_EventBroker); + m_InputProxy = new InputProxy(m_EventBroker); + m_InputProxy->AddHandler(); + m_InputProxy->AddHandler(); // Create the root level GUI frame m_FrameStack = new GUI::Frame(m_EventBroker); @@ -66,9 +69,14 @@ void Game::Tick() double dt = currentTime - m_LastTime; m_LastTime = currentTime; + // Handle input in a weird looking but responsive way m_EventBroker->Swap(); m_InputManager->Update(dt); m_EventBroker->Swap(); + m_InputProxy->Update(dt); + m_EventBroker->Swap(); + m_InputProxy->Process(); + m_EventBroker->Swap(); // Iterate through systems and update world! m_SystemPipeline->Update(m_World, dt);