menu
This commit is contained in:
@@ -12,6 +12,7 @@ GAME_ENTITY(Player)
|
||||
void setGroundTexture(std::shared_ptr<Game::Renderer::Texture> tex);
|
||||
void respawnRandomSea(float landBoundaryX);
|
||||
bool isShipMode() const { return mIsShipMode; }
|
||||
void setShipMode(bool isShip) { mIsShipMode = isShip; } // Set form state for replay
|
||||
void onCollisionEnter(Object::Entity* other) override;
|
||||
private:
|
||||
Object::Sound mSound;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
#include <object/ui/uitextbox.hpp>
|
||||
|
||||
namespace Game::AGame {
|
||||
class SampleTextBox : public Object::UITextBox {
|
||||
using Object::UITextBox::UITextBox; // Inherit constructors
|
||||
|
||||
public:
|
||||
~SampleTextBox() override = default;
|
||||
|
||||
void start() override {
|
||||
// Call the base class start to initialize the text box
|
||||
mZIndex = 1000; // Ensure it renders on top of most other entities
|
||||
Object::UITextBox::start();
|
||||
setText("Hello, World!");
|
||||
|
||||
mIsActive = false;
|
||||
mIsVisible = false;
|
||||
}
|
||||
void update(float deltaTime) override {
|
||||
// Call the base class update to handle input and text refreshing
|
||||
Object::UITextBox::update(deltaTime);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -19,7 +19,8 @@ namespace Game {
|
||||
enum class GameStateEnum {
|
||||
RUNNING,
|
||||
PAUSED,
|
||||
STOPPED
|
||||
STOPPED,
|
||||
REPLAY
|
||||
};
|
||||
|
||||
enum class SharedDataType {
|
||||
@@ -59,7 +60,14 @@ namespace Game {
|
||||
static void processPendingEntityRemovals();
|
||||
|
||||
static void pushPlayerPosition(Object::Transform transform) { mPlayerTransformHistory.push_back(transform); }
|
||||
static void pushPlayerFormState(bool isShipMode) { mPlayerFormHistory.push_back(isShipMode); }
|
||||
static void getPlayerPositionHistory(std::vector<Object::Transform>& outHistory) { outHistory = mPlayerTransformHistory; }
|
||||
static void getPlayerFormHistory(std::vector<bool>& outHistory) { outHistory = mPlayerFormHistory; }
|
||||
|
||||
// Replay mode API
|
||||
static bool initReplayMode();
|
||||
static bool playReplayFrame();
|
||||
static void stopReplayMode();
|
||||
|
||||
private:
|
||||
int mTargetUpdatesPerSecond = TARGET_UPDATE_RATE;
|
||||
@@ -69,8 +77,17 @@ namespace Game {
|
||||
static std::unordered_map<std::string, float> mSharedFloats;
|
||||
static std::unordered_map<std::string, bool> mSharedBools;
|
||||
static std::vector<Object::Transform> mPlayerTransformHistory;
|
||||
static std::vector<bool> mPlayerFormHistory;
|
||||
static GameStateEnum mCurrentGameState;
|
||||
float mLastDelta = 0.f;
|
||||
|
||||
// Replay data
|
||||
struct ReplayFrame {
|
||||
float x, y, rotation, scaleX, scaleY;
|
||||
bool isShipMode;
|
||||
};
|
||||
static std::vector<ReplayFrame> mReplayFrames;
|
||||
static size_t mCurrentReplayFrame;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
namespace Game {
|
||||
class Input {
|
||||
@@ -16,13 +20,23 @@ namespace Game {
|
||||
static bool isMouseButtonJustReleased(Uint8 button);
|
||||
static float getMouseX();
|
||||
static float getMouseY();
|
||||
|
||||
// Text input from SDL text-input events (pushed by window thread, consumed by game thread)
|
||||
static void pushText(const std::string& utf8);
|
||||
static void consumeText(std::vector<std::string>& out);
|
||||
|
||||
private:
|
||||
static const bool* mCurrentKeyStates;
|
||||
static const bool* mPreviousKeyStates;
|
||||
static std::vector<Uint8> mPreviousKeyStates;
|
||||
static int mNumKeys;
|
||||
static int mPrevNumKeys;
|
||||
static SDL_MouseButtonFlags mCurrentMouseButtonStates;
|
||||
static SDL_MouseButtonFlags mPreviousMouseButtonStates;
|
||||
static float mMouseX;
|
||||
static float mMouseY;
|
||||
|
||||
// Text input queue and mutex (window thread writes via pushText, game thread reads via consumeText)
|
||||
static std::mutex mTextMutex;
|
||||
static std::vector<std::string> mPendingText;
|
||||
};
|
||||
}
|
||||
@@ -25,5 +25,6 @@ namespace Game::Object {
|
||||
void* mClickFunction = nullptr;
|
||||
float mX, mY;
|
||||
std::string mText;
|
||||
bool mIsHovered = false;
|
||||
};
|
||||
}
|
||||
@@ -4,62 +4,54 @@
|
||||
#include <renderer/font.hpp>
|
||||
#include <renderer/texture.hpp>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <game/input.hpp>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <mutex>
|
||||
|
||||
namespace Game::Object {
|
||||
|
||||
struct UITextboxConfig {
|
||||
SDL_Color bgColor = {20, 20, 20, 210};
|
||||
SDL_Color borderColor = {110, 110, 110, 255};
|
||||
SDL_Color focusedBorderColor = {200, 175, 70, 255};
|
||||
SDL_Color textColor = {255, 255, 255, 255};
|
||||
SDL_Color focusedTextColor = {255, 240, 180, 255};
|
||||
SDL_Color placeholderColor = {120, 120, 120, 200};
|
||||
float borderThickness = 2.f;
|
||||
float paddingX = 8.f;
|
||||
float paddingY = 4.f;
|
||||
float minWidth = 160.f;
|
||||
float minHeight = 32.f;
|
||||
int maxLength = 0; // 0 = unlimited
|
||||
std::string placeholder = "";
|
||||
float cursorBlinkRate = 0.53f; // seconds per blink phase
|
||||
};
|
||||
|
||||
class UITextBox : public Entity {
|
||||
public:
|
||||
UITextBox(const std::string& name, std::shared_ptr<Renderer::Font> font,
|
||||
const Transform& transform,
|
||||
float x = 0.f, float y = 0.f,
|
||||
UITextboxConfig config = {});
|
||||
UITextBox(const std::string& name, std::shared_ptr<Renderer::Texture> background, std::shared_ptr<Renderer::Font> font, const Transform& transform, float x = 0.f, float y = 0.f);
|
||||
~UITextBox() override = default;
|
||||
|
||||
void start() override;
|
||||
void start() override;
|
||||
void update(float deltaTime) override;
|
||||
|
||||
// Custom render to show both background and text
|
||||
void render(Game::Renderer::Renderer* renderer, Game::Renderer::RendererConfig config) override;
|
||||
|
||||
void setText(const std::string& text);
|
||||
std::string getText() const;
|
||||
std::string getValue() const;
|
||||
bool isFocused() const;
|
||||
void setText(const std::string& text);
|
||||
std::string getText() const;
|
||||
void setPlaceholder(const std::string& placeholder) { mPlaceholder = placeholder; mLastRenderedText.clear(); }
|
||||
|
||||
// Insert UTF-8 text at the current cursor position (delivered from Input queue)
|
||||
void insertText(const std::string& utf8);
|
||||
|
||||
void setMaxLength(size_t maxLen) { mMaxLength = maxLen; }
|
||||
void setPasswordMode(bool enable) { mPasswordMode = enable; }
|
||||
void setOnFocus(void* fn) { mOnFocus = fn; }
|
||||
|
||||
void setPosition(float x, float y) { mX = x; mY = y; }
|
||||
std::pair<float, float> getPosition() const { return {mX, mY}; }
|
||||
|
||||
bool isFocused() const { return mIsFocused; }
|
||||
|
||||
private:
|
||||
bool isMouseInsideBox() const;
|
||||
void refreshVisualText();
|
||||
std::shared_ptr<Renderer::Texture> mBackground; // Background texture for the textbox
|
||||
std::shared_ptr<Renderer::Font> mFont; // Font used to render text
|
||||
|
||||
float mX, mY;
|
||||
std::string mText;
|
||||
size_t mCursorIndex = 0;
|
||||
float mCursorBlinkTimer = 0.f;
|
||||
bool mShowCursor = true;
|
||||
size_t mMaxLength = 1024;
|
||||
bool mPasswordMode = false;
|
||||
bool mIsFocused = false;
|
||||
float mBoxWidth = 0.f;
|
||||
float mBoxHeight = 0.f;
|
||||
bool mNeedsTextRefresh = true;
|
||||
UITextboxConfig mConfig;
|
||||
|
||||
float mCursorTimer = 0.f;
|
||||
bool mCursorVisible = true;
|
||||
void* mOnFocus = nullptr; // optional function pointer
|
||||
std::string mLastRenderedText; // to avoid rebuilding font unnecessarily
|
||||
std::string mPlaceholder = "";
|
||||
float mReservedPlaceholderWidth = 0.f; // Reserved pixel width for placeholder to avoid layout shifts
|
||||
std::mutex mRenderMutex; // Protects mLastRenderedText and mReservedPlaceholderWidth from main-thread updates
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace Game::Renderer {
|
||||
|
||||
// Build the texture for the font; Call getSDLTexture() afterwards
|
||||
void build(SDL_Color color, std::string text);
|
||||
// Rebuild GPU-backed texture after a renderer/device reset
|
||||
bool reload(SDL_Renderer* renderer);
|
||||
// Rebuild GPU-backed texture after a renderer/device reset
|
||||
bool reload(SDL_Renderer* renderer);
|
||||
|
||||
SDL_Texture* getSDLTexture();
|
||||
std::string getId();
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Game::Renderer {
|
||||
float getHeight();
|
||||
bool isTiled() { return mIsTiled; }
|
||||
void setTiled(bool tiled) { mIsTiled = tiled; }
|
||||
void setSDLTexture(SDL_Texture* tex) { mTex = tex; }
|
||||
// Reload GPU-backed texture using a new renderer after device reset
|
||||
virtual bool reload(SDL_Renderer* renderer);
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ namespace Game::Window {
|
||||
|
||||
static SDL_Window* getSDLWindowBackend() { std::scoped_lock lock(sMutex); return sWindowBackend; }
|
||||
Renderer::Renderer* getRenderer() { std::scoped_lock lock(mMutex); return &mRenderer; }
|
||||
// Post a task to be executed on the window/event thread.
|
||||
static void postToMainThread(std::function<void()> fn);
|
||||
|
||||
private:
|
||||
mutable std::mutex mMutex;
|
||||
|
||||
Reference in New Issue
Block a user