Refactored InputProxy to gracefully handle cases where multiple origins send the same command

This commit is contained in:
2015-12-11 17:15:33 +01:00
parent 2e7e8d3546
commit 03e226ffea
7 changed files with 104 additions and 44 deletions
@@ -3,6 +3,7 @@
#include "../GLM.h"
#include "../Core/InputController.h"
#include "../Core/ELockMouse.h"
template <typename EventContext>
class FirstPersonInputController : public InputController<EventContext>
@@ -11,9 +12,26 @@ public:
FirstPersonInputController(EventBroker* eventBroker, unsigned int playerID)
: InputController(eventBroker)
, m_PlayerID(playerID)
{ }
{
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &FirstPersonInputController::OnLockMouse);
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &FirstPersonInputController::OnUnlockMouse);
}
const glm::quat Orientation() const { return m_Orientation; }
void LockMouse()
{
Events::LockMouse e;
m_EventBroker->Publish(e);
m_MouseLocked = true;
}
void UnlockMouse()
{
Events::UnlockMouse e;
m_EventBroker->Publish(e);
m_MouseLocked = false;
}
virtual bool OnCommand(const Events::InputCommand& e) override
{
@@ -21,20 +39,32 @@ public:
return false;
}
if (e.Command == "Pitch") {
float val = glm::radians(e.Value);
m_Orientation = m_Orientation * glm::angleAxis<float>(-val, glm::vec3(1, 0, 0));
if (m_MouseLocked) {
if (e.Command == "Pitch") {
float val = glm::radians(e.Value);
m_Orientation = m_Orientation * glm::angleAxis<float>(-val, glm::vec3(1, 0, 0));
return true;
}
if (e.Command == "Yaw") {
float val = glm::radians(e.Value);
m_Orientation = glm::angleAxis<float>(-val, glm::vec3(0, 1, 0)) * m_Orientation;
return true;
}
}
if (e.Command == "Yaw") {
float val = glm::radians(e.Value);
m_Orientation = glm::angleAxis<float>(-val, glm::vec3(0, 1, 0)) * m_Orientation;
}
return false;
}
private:
protected:
const unsigned int m_PlayerID;
glm::quat m_Orientation;
bool m_MouseLocked = false;
EventRelay<EventContext, Events::LockMouse> m_ELockMouse;
bool OnLockMouse(const Events::LockMouse& e) { m_MouseLocked = true; return true; }
EventRelay<EventContext, Events::UnlockMouse> m_EUnlockMouse;
bool OnUnlockMouse(const Events::UnlockMouse& e) { m_MouseLocked = false; return true; }
};
#endif
+2 -1
View File
@@ -13,8 +13,9 @@ public:
, m_InputProxy(inputProxy)
{ }
virtual void Update(double dt) { }
virtual bool BindOrigin(std::string origin, std::string command, float value) = 0;
virtual void Update(double dt) { }
virtual float GetCommandValue(std::string command) = 0;
protected:
EventBroker* m_EventBroker;
+6 -2
View File
@@ -20,13 +20,17 @@ public:
void Process();
template <typename T>
void AddHandler();
void Publish(const Events::InputCommand& e);
protected:
EventBroker* m_EventBroker;
std::vector<InputHandler*> m_Handlers;
std::map<std::string, std::set<InputHandler*>> m_CommandHandlers;
// Represents every unique command (has of PlayerID & Command) and all values reported for that command this frame
std::map<std::pair<unsigned int, std::string>, std::vector<float>> m_CommandQueue;
//std::map<std::pair<unsigned int, std::string>, std::vector<float>> m_CommandQueue;
std::map<std::string, float> m_CurrentCommandValues;
std::map<std::string, float> m_LastCommandValues;
EventRelay<InputProxy, Events::BindOrigin> m_EBindOrigin;
bool OnBindOrigin(const Events::BindOrigin& e);
@@ -12,10 +12,12 @@ public:
KeyboardInputHandler(EventBroker* eventBroker, InputProxy* inputProxy);
bool BindOrigin(std::string origin, std::string command, float value) override;
virtual float GetCommandValue(std::string command) override;
private:
std::unordered_map<std::string, int> m_OriginKeyCodes;
std::unordered_map<int, std::tuple<std::string, float>> m_KeyBindings; // GLFW_KEY... -> command string & value
std::unordered_map<std::string, float> m_CommandValues;
EventRelay<InputHandler, Events::KeyDown> m_EKeyDown;
bool OnKeyDown(const Events::KeyDown& e);
+7 -4
View File
@@ -3,10 +3,13 @@ Sensitivity=0.5
InvertPitch=false
[Bindings]
W=Forward
A=Left
S=Back
D=Right
MouseLeft=PrimaryFire
MouseX=Yaw
MouseY=Pitch
W=+Forward
S=-Forward
D=+Right
A=-Right
R=Reload
Space=Jump
LeftControl=Crouch
+30 -19
View File
@@ -22,7 +22,16 @@ void InputProxy::LoadBindings(std::string file)
e.Origin = origin.first;
e.Command = origin.second;
e.Value = 1.f;
OnBindOrigin(e);
if (!e.Command.empty()) {
char prefix = e.Command.at(0);
if (prefix == '+' || prefix == '-') {
e.Command = e.Command.substr(1);
if (prefix == '-') {
e.Value *= -1.f;
}
}
OnBindOrigin(e);
}
}
}
@@ -37,26 +46,26 @@ void InputProxy::Update(double dt)
void InputProxy::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;
for (auto& pair : m_CommandHandlers) {
const std::string& command = pair.first;
auto handlers = pair.second;
m_CurrentCommandValues[command] = 0.f;
for (auto& handler : handlers) {
m_CurrentCommandValues[command] += handler->GetCommandValue(command);
}
//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();
}
void InputProxy::Publish(const Events::InputCommand& e)
{
auto key = std::make_pair(e.PlayerID, e.Command);
m_CommandQueue[key].push_back(e.Value);
auto last = m_LastCommandValues.find(command);
float currentValue = m_CurrentCommandValues[command];
if (last == m_LastCommandValues.end() || last->second != currentValue) {
Events::InputCommand e;
e.PlayerID = -1;
e.Command = command;
e.Value = currentValue;
m_EventBroker->Publish(e);
LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID);
m_LastCommandValues[command] = currentValue;
}
}
}
bool InputProxy::OnBindOrigin(const Events::BindOrigin& e)
@@ -65,6 +74,8 @@ bool InputProxy::OnBindOrigin(const Events::BindOrigin& e)
for (auto& handler : m_Handlers) {
bool result = handler->BindOrigin(e.Origin, e.Command, e.Value);
if (result) {
m_CommandHandlers[e.Command].insert(handler);
m_LastCommandValues[e.Command] = 0.f;
if (originBound) {
LOG_WARNING("Multiple handlers responded to binding input origin \"%s\"!", e.Origin.c_str());
}
+18 -9
View File
@@ -146,10 +146,10 @@ bool KeyboardInputHandler::OnKeyDown(const Events::KeyDown& e)
return false;
}
Events::InputCommand ic;
ic.PlayerID = 0;
std::tie(ic.Command, ic.Value) = it->second;
m_InputProxy->Publish(ic);
std::string command;
float value;
std::tie(command, value) = it->second;
m_CommandValues[command] += value;
return true;
}
@@ -161,12 +161,21 @@ bool KeyboardInputHandler::OnKeyUp(const Events::KeyUp& e)
return false;
}
Events::InputCommand ic;
ic.PlayerID = 0;
std::tie(ic.Command, std::ignore) = it->second;
ic.Value = 0;
m_InputProxy->Publish(ic);
std::string command;
float value;
std::tie(command, value) = it->second;
m_CommandValues[command] -= value;
return true;
}
float KeyboardInputHandler::GetCommandValue(std::string command)
{
auto it = m_CommandValues.find(command);
if (it != m_CommandValues.end()) {
return m_CommandValues[command];
} else {
return 0.f;
}
}