164 lines
4.9 KiB
C++
164 lines
4.9 KiB
C++
#include "input_mapper.h"
|
|
#include "input_device_group.h"
|
|
#include "button_config_factory.hpp"
|
|
|
|
|
|
InputMapper::InputMapper()
|
|
{
|
|
inputIdentities = std::set<std::shared_ptr<InputIdentity>>();
|
|
newInputIdentities = std::set<std::shared_ptr<InputIdentity>>();
|
|
deprecatedInputIdentities = std::set<std::shared_ptr<InputIdentity>>();
|
|
}
|
|
|
|
|
|
void InputMapper::processEvents()
|
|
{
|
|
sf::Event event{};
|
|
while (Game::getInstance()->window->pollEvent(event))
|
|
{
|
|
switch (event.type)
|
|
{
|
|
case sf::Event::KeyPressed:
|
|
handleKeyPress(event.key);
|
|
break;
|
|
case sf::Event::KeyReleased:
|
|
handleKeyRelease(event.key);
|
|
break;
|
|
case sf::Event::Closed:
|
|
Game::getInstance()->exit();
|
|
break;
|
|
case sf::Event::JoystickButtonPressed:
|
|
getInputIdentity(InputDeviceGroup::GAMEPAD, event.joystickButton.joystickId)->press(
|
|
ButtonConfigFactory::fromGamepadButton(event.joystickButton.button));
|
|
break;
|
|
case sf::Event::JoystickButtonReleased:
|
|
getInputIdentity(InputDeviceGroup::GAMEPAD, event.joystickButton.joystickId)->release(
|
|
ButtonConfigFactory::fromGamepadButton(event.joystickButton.button));
|
|
break;
|
|
case sf::Event::JoystickMoved:
|
|
handleJoystickMovement(event.joystickMove);
|
|
break;
|
|
case sf::Event::JoystickConnected:
|
|
getInputIdentity(InputDeviceGroup::GAMEPAD, event.joystickConnect.joystickId);
|
|
break;
|
|
case sf::Event::JoystickDisconnected:
|
|
deactivateIdentity(getInputIdentity(InputDeviceGroup::GAMEPAD, event.joystickConnect.joystickId));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void InputMapper::handleKeyPress(sf::Event::KeyEvent event)
|
|
{
|
|
// Close game on Escape or Q in DEV Mode
|
|
if (DEVELOPER_MODE && event.code == sf::Keyboard::Escape)
|
|
{
|
|
Game::getInstance()->exit();
|
|
return;
|
|
}
|
|
|
|
// Handle directionVector
|
|
auto button = ButtonConfigFactory::fromKey(event.code);
|
|
if (button.deviceGroup != InputDeviceGroup::UNKNOWN)
|
|
{
|
|
getInputIdentity(button.deviceGroup)->press(button);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void InputMapper::handleKeyRelease(sf::Event::KeyEvent event)
|
|
{
|
|
auto button = ButtonConfigFactory::fromKey(event.code);
|
|
if (button.deviceGroup != InputDeviceGroup::UNKNOWN)
|
|
{
|
|
getInputIdentity(button.deviceGroup)->release(button);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void InputMapper::handleJoystickMovement(sf::Event::JoystickMoveEvent event)
|
|
{
|
|
auto gamepadIdentity = getInputIdentity(InputDeviceGroup::GAMEPAD, event.joystickId);
|
|
|
|
auto value = event.position / 100.f; // Normalize to -1 to 1
|
|
auto axis = event.axis;
|
|
|
|
// Handle deadzone and joystick drift
|
|
if (value > -JOYSTICK_DEADZONE && value < JOYSTICK_DEADZONE)
|
|
{
|
|
value = 0.f;
|
|
}
|
|
|
|
if (axis == sf::Joystick::Axis::X)
|
|
{
|
|
gamepadIdentity->direction.setX(value);
|
|
} else if (axis == sf::Joystick::Axis::Y)
|
|
{
|
|
value *= -1; // Is inverted
|
|
gamepadIdentity->direction.setY(value);
|
|
}
|
|
}
|
|
|
|
std::shared_ptr<InputIdentity> InputMapper::getInputIdentity(InputDeviceGroup deviceGroup, unsigned int gamepadId)
|
|
{
|
|
if (deviceGroup == InputDeviceGroup::UNKNOWN)
|
|
{
|
|
throw std::invalid_argument("InputDeviceGroup cannot be UNKNOWN");
|
|
}
|
|
|
|
for (auto &identity: inputIdentities)
|
|
{
|
|
// Device group must be matched, and gamepad id if it is a gamepad
|
|
if (identity->deviceGroup == deviceGroup &&
|
|
(deviceGroup != InputDeviceGroup::GAMEPAD ||
|
|
identity->gamepadId == gamepadId))
|
|
{
|
|
return identity;
|
|
}
|
|
}
|
|
|
|
// No identity found, create new
|
|
auto newIdentity = std::make_shared<InputIdentity>(deviceGroup, gamepadId);
|
|
inputIdentities.insert(newIdentity);
|
|
newInputIdentities.insert(newIdentity);
|
|
return newIdentity;
|
|
}
|
|
|
|
void InputMapper::deactivateIdentity(const std::shared_ptr<InputIdentity> &identity)
|
|
{
|
|
LOG(INFO) << "Destroyed input identity [" << magic_enum::enum_name(identity->deviceGroup) << ", gamepad "
|
|
<< identity->gamepadId
|
|
<< "]";
|
|
|
|
identity->isActive = false;
|
|
deprecatedInputIdentities.insert(identity);
|
|
inputIdentities.erase(identity);
|
|
}
|
|
|
|
std::shared_ptr<InputMapper> InputMapper::getInstance()
|
|
{
|
|
if (singletonInstance == nullptr)
|
|
{
|
|
singletonInstance = std::make_shared<InputMapper>();
|
|
}
|
|
|
|
return singletonInstance;
|
|
}
|
|
|
|
std::set<std::shared_ptr<InputIdentity>> InputMapper::getInputIdentities()
|
|
{
|
|
return inputIdentities;
|
|
}
|
|
|
|
void InputMapper::updateIdentities()
|
|
{
|
|
for (auto &identity: inputIdentities)
|
|
{
|
|
identity->update();
|
|
}
|
|
|
|
newInputIdentities.clear();
|
|
deprecatedInputIdentities.clear();
|
|
}
|