132 lines
5.2 KiB
C++
132 lines
5.2 KiB
C++
#include <game/input.hpp>
|
|
#include <window/window.hpp>
|
|
#include <object/ui/uitextbox.hpp>
|
|
#include <state/gamestate.hpp>
|
|
|
|
namespace Game {
|
|
const bool* Input::mCurrentKeyStates = nullptr;
|
|
std::vector<Uint8> Input::mPreviousKeyStates = {};
|
|
int Input::mNumKeys = 0;
|
|
int Input::mPrevNumKeys = 0;
|
|
SDL_MouseButtonFlags Input::mCurrentMouseButtonStates = 0;
|
|
SDL_MouseButtonFlags Input::mPreviousMouseButtonStates = 0;
|
|
float Input::mMouseX = 0.0f;
|
|
float Input::mMouseY = 0.0f;
|
|
std::mutex Input::mTextMutex;
|
|
std::vector<std::string> Input::mPendingText;
|
|
|
|
void Input::update() {
|
|
// Copy the previous keyboard state (snapshot) so we can detect just-pressed
|
|
if (mCurrentKeyStates && mNumKeys > 0) {
|
|
mPreviousKeyStates.assign(mCurrentKeyStates, mCurrentKeyStates + mNumKeys);
|
|
mPrevNumKeys = mNumKeys;
|
|
} else {
|
|
// If we don't have a previous snapshot, initialize previous vector to zeros with current size
|
|
if (mNumKeys > 0) mPreviousKeyStates.assign(mNumKeys, 0);
|
|
mPrevNumKeys = mNumKeys;
|
|
}
|
|
|
|
mCurrentKeyStates = SDL_GetKeyboardState(&mNumKeys);
|
|
|
|
mPreviousMouseButtonStates = mCurrentMouseButtonStates;
|
|
float rawMouseX = 0.0f;
|
|
float rawMouseY = 0.0f;
|
|
mCurrentMouseButtonStates = SDL_GetMouseState(&rawMouseX, &rawMouseY);
|
|
|
|
// Convert mouse coordinates from real display/window pixels into
|
|
// centered logical game coordinates (1280x720 world space).
|
|
static constexpr float LOGICAL_WIDTH = 1280.0f;
|
|
static constexpr float LOGICAL_HEIGHT = 720.0f;
|
|
|
|
float displayW = LOGICAL_WIDTH;
|
|
float displayH = LOGICAL_HEIGHT;
|
|
|
|
SDL_Window* sdlWindow = Window::Window::getSDLWindowBackend();
|
|
if (sdlWindow) {
|
|
int windowPixelsW = static_cast<int>(LOGICAL_WIDTH);
|
|
int windowPixelsH = static_cast<int>(LOGICAL_HEIGHT);
|
|
SDL_GetWindowSizeInPixels(sdlWindow, &windowPixelsW, &windowPixelsH);
|
|
|
|
SDL_DisplayID displayId = SDL_GetDisplayForWindow(sdlWindow);
|
|
const SDL_DisplayMode* displayMode = SDL_GetCurrentDisplayMode(displayId);
|
|
if (displayMode && displayMode->w > 0 && displayMode->h > 0) {
|
|
displayW = static_cast<float>(displayMode->w);
|
|
displayH = static_cast<float>(displayMode->h);
|
|
} else if (windowPixelsW > 0 && windowPixelsH > 0) {
|
|
displayW = static_cast<float>(windowPixelsW);
|
|
displayH = static_cast<float>(windowPixelsH);
|
|
}
|
|
}
|
|
|
|
const float invScaleX = LOGICAL_WIDTH / displayW;
|
|
const float invScaleY = LOGICAL_HEIGHT / displayH;
|
|
mMouseX = rawMouseX * invScaleX - (LOGICAL_WIDTH * 0.5f);
|
|
mMouseY = rawMouseY * invScaleY - (LOGICAL_HEIGHT * 0.5f);
|
|
|
|
// Consume and deliver queued text input from window thread to focused textbox
|
|
std::vector<std::string> texts;
|
|
consumeText(texts);
|
|
if (!texts.empty()) {
|
|
auto entities = State::GameState::getInstance().getEntitiesSnapshot();
|
|
for (auto* e : entities) {
|
|
if (!e) continue;
|
|
auto* tb = dynamic_cast<Game::Object::UITextBox*>(e);
|
|
if (tb && tb->isFocused()) {
|
|
for (auto& s : texts) {
|
|
tb->insertText(s);
|
|
}
|
|
break; // Deliver to first focused textbox only
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Input::isKeyPressed(SDL_Scancode key) {
|
|
if (key < 0 || key >= mNumKeys) return false;
|
|
return mCurrentKeyStates && mCurrentKeyStates[key];
|
|
}
|
|
|
|
bool Input::isKeyJustPressed(SDL_Scancode key) {
|
|
if (key < 0 || key >= mNumKeys) return false;
|
|
bool cur = mCurrentKeyStates && mCurrentKeyStates[key];
|
|
bool prev = (key < static_cast<int>(mPreviousKeyStates.size())) ? static_cast<bool>(mPreviousKeyStates[key]) : false;
|
|
return cur && !prev;
|
|
}
|
|
|
|
bool Input::isKeyJustReleased(SDL_Scancode key) {
|
|
if (key < 0 || key >= mNumKeys) return false;
|
|
bool cur = mCurrentKeyStates && mCurrentKeyStates[key];
|
|
bool prev = (key < static_cast<int>(mPreviousKeyStates.size())) ? static_cast<bool>(mPreviousKeyStates[key]) : false;
|
|
return !cur && prev;
|
|
}
|
|
|
|
bool Input::isMouseButtonPressed(Uint8 button) {
|
|
return (mCurrentMouseButtonStates & SDL_BUTTON_MASK(button)) != 0;
|
|
}
|
|
|
|
bool Input::isMouseButtonJustPressed(Uint8 button) {
|
|
return (mCurrentMouseButtonStates & SDL_BUTTON_MASK(button)) != 0 && (mPreviousMouseButtonStates & SDL_BUTTON_MASK(button)) == 0;
|
|
}
|
|
|
|
bool Input::isMouseButtonJustReleased(Uint8 button) {
|
|
return (mCurrentMouseButtonStates & SDL_BUTTON_MASK(button)) == 0 && (mPreviousMouseButtonStates & SDL_BUTTON_MASK(button)) != 0;
|
|
}
|
|
|
|
float Input::getMouseX() {
|
|
return mMouseX;
|
|
}
|
|
|
|
float Input::getMouseY() {
|
|
return mMouseY;
|
|
}
|
|
|
|
void Input::pushText(const std::string& utf8) {
|
|
std::scoped_lock lock(mTextMutex);
|
|
mPendingText.push_back(utf8);
|
|
}
|
|
|
|
void Input::consumeText(std::vector<std::string>& out) {
|
|
std::scoped_lock lock(mTextMutex);
|
|
out.swap(mPendingText);
|
|
}
|
|
} |