#include "Input/InputManager.h" #include namespace XCEngine { namespace Input { InputManager& InputManager::Get() { static InputManager instance; return instance; } void InputManager::Initialize(void* platformWindowHandle) { if (m_initialized) return; m_platformWindowHandle = platformWindowHandle; m_keyDownThisFrame.resize(256, false); m_keyDownLastFrame.resize(256, false); m_keyDown.resize(256, false); m_mouseButtonDownThisFrame.resize(5, false); m_mouseButtonDownLastFrame.resize(5, false); m_mouseButtonDown.resize(5, false); m_buttonDownThisFrame.resize(32, false); m_buttonDownLastFrame.resize(32, false); RegisterAxis(InputAxis("Horizontal", KeyCode::D, KeyCode::A)); RegisterAxis(InputAxis("Vertical", KeyCode::W, KeyCode::S)); RegisterAxis(InputAxis("Mouse X", KeyCode::None, KeyCode::None)); RegisterAxis(InputAxis("Mouse Y", KeyCode::None, KeyCode::None)); RegisterButton("Jump", KeyCode::Space); RegisterButton("Fire1", KeyCode::LeftCtrl); RegisterButton("Fire2", KeyCode::LeftAlt); RegisterButton("Fire3", KeyCode::LeftShift); m_initialized = true; } void InputManager::Shutdown() { if (!m_initialized) return; m_keyDownThisFrame.clear(); m_keyDownLastFrame.clear(); m_keyDown.clear(); m_mouseButtonDownThisFrame.clear(); m_mouseButtonDownLastFrame.clear(); m_mouseButtonDown.clear(); m_axes.clear(); m_buttons.clear(); m_buttonDownThisFrame.clear(); m_buttonDownLastFrame.clear(); m_platformWindowHandle = nullptr; m_initialized = false; } void InputManager::Update(float deltaTime) { if (!m_initialized) return; m_keyDownLastFrame = m_keyDownThisFrame; m_mouseButtonDownLastFrame = m_mouseButtonDownThisFrame; m_buttonDownLastFrame = m_buttonDownThisFrame; m_mouseDelta = Math::Vector2::Zero(); m_mouseScrollDelta = 0.0f; } size_t InputManager::GetKeyIndex(KeyCode key) const { return static_cast(key); } size_t InputManager::GetMouseButtonIndex(MouseButton button) const { return static_cast(button); } bool InputManager::IsKeyDown(KeyCode key) const { if (!m_initialized) return false; size_t index = GetKeyIndex(key); if (index >= m_keyDown.size()) return false; return m_keyDown[index]; } bool InputManager::IsKeyUp(KeyCode key) const { if (!m_initialized) return true; return !IsKeyDown(key); } bool InputManager::IsKeyPressed(KeyCode key) const { if (!m_initialized) return false; size_t index = GetKeyIndex(key); if (index >= m_keyDownThisFrame.size()) return false; return m_keyDownThisFrame[index] && !m_keyDownLastFrame[index]; } Math::Vector2 InputManager::GetMousePosition() const { return m_mousePosition; } Math::Vector2 InputManager::GetMouseDelta() const { return m_mouseDelta; } float InputManager::GetMouseScrollDelta() const { return m_mouseScrollDelta; } bool InputManager::IsMouseButtonDown(MouseButton button) const { if (!m_initialized) return false; size_t index = GetMouseButtonIndex(button); if (index >= m_mouseButtonDown.size()) return false; return m_mouseButtonDown[index]; } bool InputManager::IsMouseButtonUp(MouseButton button) const { if (!m_initialized) return true; return !IsMouseButtonDown(button); } bool InputManager::IsMouseButtonClicked(MouseButton button) const { if (!m_initialized) return false; size_t index = GetMouseButtonIndex(button); if (index >= m_mouseButtonDownThisFrame.size()) return false; return m_mouseButtonDownThisFrame[index] && !m_mouseButtonDownLastFrame[index]; } int InputManager::GetTouchCount() const { return static_cast(m_touches.size()); } TouchState InputManager::GetTouch(int index) const { if (index >= 0 && index < static_cast(m_touches.size())) { return m_touches[index]; } return TouchState{}; } float InputManager::GetAxis(const Containers::String& axisName) const { auto it = m_axes.find(axisName); if (it == m_axes.end()) return 0.0f; const auto& axis = it->second; float value = 0.0f; if (axis.GetPositiveKey() != KeyCode::None && IsKeyDown(axis.GetPositiveKey())) { value += 1.0f; } if (axis.GetNegativeKey() != KeyCode::None && IsKeyDown(axis.GetNegativeKey())) { value -= 1.0f; } return value; } float InputManager::GetAxisRaw(const Containers::String& axisName) const { auto it = m_axes.find(axisName); if (it == m_axes.end()) return 0.0f; const auto& axis = it->second; float value = 0.0f; if (axis.GetPositiveKey() != KeyCode::None && IsKeyPressed(axis.GetPositiveKey())) { value += 1.0f; } if (axis.GetNegativeKey() != KeyCode::None && IsKeyPressed(axis.GetNegativeKey())) { value -= 1.0f; } return value; } bool InputManager::GetButton(const Containers::String& buttonName) const { auto it = m_buttons.find(buttonName); if (it == m_buttons.end()) return false; return IsKeyDown(it->second); } bool InputManager::GetButtonDown(const Containers::String& buttonName) const { auto it = m_buttons.find(buttonName); if (it == m_buttons.end()) return false; return IsKeyPressed(it->second); } bool InputManager::GetButtonUp(const Containers::String& buttonName) const { auto it = m_buttons.find(buttonName); if (it == m_buttons.end()) return true; return IsKeyUp(it->second); } void InputManager::RegisterAxis(const InputAxis& axis) { m_axes[axis.GetName()] = axis; } void InputManager::RegisterButton(const Containers::String& name, KeyCode key) { m_buttons[name] = key; } void InputManager::ClearAxes() { m_axes.clear(); m_buttons.clear(); } void InputManager::ProcessKeyDown(KeyCode key, bool repeat) { if (!m_initialized) return; size_t index = GetKeyIndex(key); if (index >= m_keyDown.size()) return; m_keyDown[index] = true; m_keyDownThisFrame[index] = true; KeyEvent event; event.keyCode = key; event.type = repeat ? KeyEvent::Repeat : KeyEvent::Down; event.alt = false; event.ctrl = false; event.shift = false; event.meta = false; m_onKeyEvent.Invoke(event); } void InputManager::ProcessKeyUp(KeyCode key) { if (!m_initialized) return; size_t index = GetKeyIndex(key); if (index >= m_keyDown.size()) return; m_keyDown[index] = false; KeyEvent event; event.keyCode = key; event.type = KeyEvent::Up; event.alt = false; event.ctrl = false; event.shift = false; event.meta = false; m_onKeyEvent.Invoke(event); } void InputManager::ProcessMouseMove(int x, int y, int deltaX, int deltaY) { if (!m_initialized) return; m_mousePosition.x = static_cast(x); m_mousePosition.y = static_cast(y); m_mouseDelta.x = static_cast(deltaX); m_mouseDelta.y = static_cast(deltaY); MouseMoveEvent event; event.position = m_mousePosition; event.delta = m_mouseDelta; m_onMouseMove.Invoke(event); } void InputManager::ProcessMouseButton(MouseButton button, bool pressed, int x, int y) { if (!m_initialized) return; size_t index = GetMouseButtonIndex(button); if (index >= m_mouseButtonDown.size()) return; m_mouseButtonDown[index] = pressed; if (pressed) { m_mouseButtonDownThisFrame[index] = true; } MouseButtonEvent event; event.button = button; event.position.x = static_cast(x); event.position.y = static_cast(y); event.type = pressed ? MouseButtonEvent::Pressed : MouseButtonEvent::Released; m_onMouseButton.Invoke(event); } void InputManager::ProcessMouseWheel(float delta, int x, int y) { if (!m_initialized) return; m_mouseScrollDelta = delta; MouseWheelEvent event; event.position.x = static_cast(x); event.position.y = static_cast(y); event.delta = delta; m_onMouseWheel.Invoke(event); } void InputManager::ProcessTextInput(char c) { if (!m_initialized) return; TextInputEvent event; event.character = c; event.text = Containers::String(&c, 1); m_onTextInput.Invoke(event); } } // namespace Input } // namespace XCEngine