This commit is contained in:
2026-05-19 22:35:10 +02:00
parent d93e71e716
commit 0b45643ef2
21 changed files with 806 additions and 235 deletions

View File

@@ -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
};
}