#include "InputManager.h" #include "log/log.h" #include #include #include InputManager::InputManager() { } InputManager::~InputManager() { } void InputManager::RegisterAction(const std::string& actionName) { if (actions.find(actionName) == actions.end()) { actions[actionName] = std::vector(); 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 InputManager::GetAllActions() const { std::vector result; for (const auto& pair : actions) { result.push_back(pair.first); } return result; } const std::vector& InputManager::GetBindings(const std::string& actionName) const { static std::vector 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()); }