Files
simian/src/InputManager.cpp
T
2026-03-08 12:14:50 +13:00

242 lines
8.1 KiB
C++

#include "InputManager.h"
#include "log/log.h"
#include <fstream>
#include <sstream>
#include <cmath>
InputManager::InputManager() {
}
InputManager::~InputManager() {
}
void InputManager::RegisterAction(const std::string& actionName) {
if (actions.find(actionName) == actions.end()) {
actions[actionName] = std::vector<InputBinding>();
log_debug("Registered input action: %s", actionName.c_str());
}
}
void InputManager::UnregisterAction(const std::string& actionName) {
actions.erase(actionName);
}
bool InputManager::HasAction(const std::string& actionName) const {
return actions.find(actionName) != actions.end();
}
void InputManager::BindKeyboard(const std::string& actionName, int keyCode) {
RegisterAction(actionName);
actions[actionName].push_back(InputBinding(InputType::Keyboard, keyCode));
log_debug("Bound key %d to action: %s", keyCode, actionName.c_str());
}
void InputManager::BindMouseButton(const std::string& actionName, int mouseButton) {
RegisterAction(actionName);
actions[actionName].push_back(InputBinding(InputType::MouseButton, mouseButton));
}
void InputManager::BindGamepadButton(const std::string& actionName, int gamepadId, int button) {
RegisterAction(actionName);
actions[actionName].push_back(InputBinding(InputType::GamepadButton, button, gamepadId));
}
void InputManager::BindGamepadAxis(const std::string& actionName, int gamepadId, int axis, float threshold, bool negative) {
RegisterAction(actionName);
InputBinding binding(InputType::GamepadAxis, axis, gamepadId);
binding.axisThreshold = threshold;
binding.negative = negative;
actions[actionName].push_back(binding);
}
void InputManager::ClearBindings(const std::string& actionName) {
if (HasAction(actionName)) {
actions[actionName].clear();
}
}
bool InputManager::IsActionPressed(const std::string& actionName) const {
auto it = actions.find(actionName);
if (it == actions.end()) return false;
for (const auto& binding : it->second) {
if (IsBindingPressed(binding)) {
return true;
}
}
return false;
}
bool InputManager::IsActionDown(const std::string& actionName) const {
auto it = actions.find(actionName);
if (it == actions.end()) return false;
for (const auto& binding : it->second) {
if (IsBindingDown(binding)) {
return true;
}
}
return false;
}
bool InputManager::IsActionReleased(const std::string& actionName) const {
auto it = actions.find(actionName);
if (it == actions.end()) return false;
for (const auto& binding : it->second) {
if (IsBindingReleased(binding)) {
return true;
}
}
return false;
}
float InputManager::GetActionStrength(const std::string& actionName) const {
auto it = actions.find(actionName);
if (it == actions.end()) return 0.0f;
float maxStrength = 0.0f;
for (const auto& binding : it->second) {
float strength = GetBindingStrength(binding);
if (std::abs(strength) > std::abs(maxStrength)) {
maxStrength = strength;
}
}
return maxStrength;
}
bool InputManager::IsBindingPressed(const InputBinding& binding) const {
switch (binding.type) {
case InputType::Keyboard:
return IsKeyPressed(binding.code);
case InputType::MouseButton:
return IsMouseButtonPressed(binding.code);
case InputType::GamepadButton:
if (IsGamepadAvailable(binding.gamepadId)) {
return IsGamepadButtonPressed(binding.gamepadId, binding.code);
}
return false;
case InputType::GamepadAxis: {
// Axis "pressed" is harder to detect - simplified to just checking threshold
if (IsGamepadAvailable(binding.gamepadId)) {
float value = GetGamepadAxisMovement(binding.gamepadId, binding.code);
return binding.negative ? value < -binding.axisThreshold : value > binding.axisThreshold;
}
return false;
}
}
return false;
}
bool InputManager::IsBindingDown(const InputBinding& binding) const {
switch (binding.type) {
case InputType::Keyboard:
return IsKeyDown(binding.code);
case InputType::MouseButton:
return IsMouseButtonDown(binding.code);
case InputType::GamepadButton:
if (IsGamepadAvailable(binding.gamepadId)) {
return IsGamepadButtonDown(binding.gamepadId, binding.code);
}
return false;
case InputType::GamepadAxis:
if (IsGamepadAvailable(binding.gamepadId)) {
float value = GetGamepadAxisMovement(binding.gamepadId, binding.code);
return binding.negative ? value < -binding.axisThreshold : value > binding.axisThreshold;
}
return false;
}
return false;
}
bool InputManager::IsBindingReleased(const InputBinding& binding) const {
switch (binding.type) {
case InputType::Keyboard:
return IsKeyReleased(binding.code);
case InputType::MouseButton:
return IsMouseButtonReleased(binding.code);
case InputType::GamepadButton:
if (IsGamepadAvailable(binding.gamepadId)) {
return IsGamepadButtonReleased(binding.gamepadId, binding.code);
}
return false;
case InputType::GamepadAxis:
return false; // Axes don't have a clear "released" state
}
return false;
}
float InputManager::GetBindingStrength(const InputBinding& binding) const {
switch (binding.type) {
case InputType::Keyboard:
return IsKeyDown(binding.code) ? 1.0f : 0.0f;
case InputType::MouseButton:
return IsMouseButtonDown(binding.code) ? 1.0f : 0.0f;
case InputType::GamepadButton:
if (IsGamepadAvailable(binding.gamepadId)) {
return IsGamepadButtonDown(binding.gamepadId, binding.code) ? 1.0f : 0.0f;
}
return 0.0f;
case InputType::GamepadAxis:
if (IsGamepadAvailable(binding.gamepadId)) {
float value = GetGamepadAxisMovement(binding.gamepadId, binding.code);
return binding.negative ? -value : value;
}
return 0.0f;
}
return 0.0f;
}
void InputManager::SetupDefaultBindings() {
// Movement
BindKeyboard("move_up", KEY_W);
BindKeyboard("move_up", KEY_UP);
BindKeyboard("move_down", KEY_S);
BindKeyboard("move_down", KEY_DOWN);
BindKeyboard("move_left", KEY_A);
BindKeyboard("move_left", KEY_LEFT);
BindKeyboard("move_right", KEY_D);
BindKeyboard("move_right", KEY_RIGHT);
// Actions
BindKeyboard("jump", KEY_SPACE);
BindKeyboard("interact", KEY_E);
BindKeyboard("attack", KEY_LEFT_CONTROL);
BindMouseButton("attack", MOUSE_BUTTON_LEFT);
// Gamepad (if available)
BindGamepadButton("jump", 0, GAMEPAD_BUTTON_RIGHT_FACE_DOWN);
BindGamepadButton("interact", 0, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT);
BindGamepadAxis("move_left", 0, GAMEPAD_AXIS_LEFT_X, 0.3f, true);
BindGamepadAxis("move_right", 0, GAMEPAD_AXIS_LEFT_X, 0.3f, false);
log_info("Input manager: Default bindings configured");
}
std::vector<std::string> InputManager::GetAllActions() const {
std::vector<std::string> result;
for (const auto& pair : actions) {
result.push_back(pair.first);
}
return result;
}
const std::vector<InputBinding>& InputManager::GetBindings(const std::string& actionName) const {
static std::vector<InputBinding> empty;
auto it = actions.find(actionName);
if (it != actions.end()) {
return it->second;
}
return empty;
}
void InputManager::LoadFromFile(const std::string& filepath) {
// TODO: Implement config file loading (JSON or simple text format)
log_info("Input config loading not yet implemented: %s", filepath.c_str());
}
void InputManager::SaveToFile(const std::string& filepath) const {
// TODO: Implement config file saving
log_info("Input config saving not yet implemented: %s", filepath.c_str());
}