holesome/src/game/input/input_mapper.cpp

165 lines
4.9 KiB
C++
Raw Normal View History

#include "input_mapper.h"
2023-05-17 23:22:45 +02:00
#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>>();
}
2023-05-08 18:20:55 +02:00
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:
2023-05-09 20:50:50 +02:00
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;
2023-05-16 21:56:55 +02:00
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;
2023-05-09 20:50:50 +02:00
}
}
void InputMapper::handleKeyRelease(sf::Event::KeyEvent event)
{
auto button = ButtonConfigFactory::fromKey(event.code);
if (button.deviceGroup != InputDeviceGroup::UNKNOWN)
2023-05-09 20:50:50 +02:00
{
getInputIdentity(button.deviceGroup)->release(button);
return;
}
}
2023-05-16 21:56:55 +02:00
void InputMapper::handleJoystickMovement(sf::Event::JoystickMoveEvent event)
{
2023-05-17 23:22:45 +02:00
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;
}
2023-05-17 14:41:30 +02:00
if (axis == sf::Joystick::Axis::X)
{
gamepadIdentity->direction.setX(value);
2023-05-17 14:41:30 +02:00
} else if (axis == sf::Joystick::Axis::Y)
{
2023-05-17 14:41:30 +02:00
value *= -1; // Is inverted
gamepadIdentity->direction.setY(value);
}
2023-05-16 21:56:55 +02:00
}
std::shared_ptr<InputIdentity> InputMapper::getInputIdentity(InputDeviceGroup deviceGroup, unsigned int gamepadId)
2023-05-16 21:56:55 +02:00
{
if (deviceGroup == InputDeviceGroup::UNKNOWN)
2023-05-16 21:56:55 +02:00
{
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;
}
2023-05-16 21:56:55 +02:00
}
// 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()
{
2023-05-17 14:41:30 +02:00
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();
2023-05-16 21:56:55 +02:00
}