- 新增 Platform 模块:PlatformTypes.h, Window.h, WindowsWindow - 新增 Input 模块:InputTypes, InputEvent, InputAxis, InputModule, InputManager - 新增 WindowsInputModule 处理 Win32 消息转换 - 将 RHI 集成测试从 render_model 迁移到 sphere - 更新 CMakeLists.txt 添加 Platform 和 Input 模块
305 lines
8.2 KiB
C++
305 lines
8.2 KiB
C++
#include "Input/InputManager.h"
|
|
#include <algorithm>
|
|
|
|
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<size_t>(key);
|
|
}
|
|
|
|
size_t InputManager::GetMouseButtonIndex(MouseButton button) const {
|
|
return static_cast<size_t>(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<int>(m_touches.size());
|
|
}
|
|
|
|
TouchState InputManager::GetTouch(int index) const {
|
|
if (index >= 0 && index < static_cast<int>(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<float>(x);
|
|
m_mousePosition.y = static_cast<float>(y);
|
|
m_mouseDelta.x = static_cast<float>(deltaX);
|
|
m_mouseDelta.y = static_cast<float>(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<float>(x);
|
|
event.position.y = static_cast<float>(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<float>(x);
|
|
event.position.y = static_cast<float>(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
|