簡體   English   中英

SDL 中的文本輸入框

[英]Text input box in SDL

我想知道 SDL 中是否有與 Javascript 的prompt()函數等效的函數。 如果您不知道 Javascript,以下是 Javascript prompt()功能的屏幕截圖:

文本輸入框

所以我想要的是一個 SDL 函數,它打開一個像上面那樣的對話框,並返回一個包含用戶輸入內容的字符串(或者在參數中獲取一個指向字符串的指針並將用戶輸入的內容放入該字符串中)。

我怎樣才能在 SDL 中做到這一點?

也許嘗試像這里提到的 nanogui-sdl 這樣的特定於 SDL 的庫

這是輸入小部件的代碼。

#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>

int windowWidth = 240;
int windowHeight = 320;
SDL_Point mousePos;
SDL_Point realMousePos;
bool keys[SDL_NUM_SCANCODES];
bool buttons[SDL_BUTTON_X2 + 1];
SDL_Renderer* renderer;

int SDL_QueryTextureF(SDL_Texture* texture, Uint32* format, int* access, float* w, float* h)
{
    int wi, hi;
    int result = SDL_QueryTexture(texture, format, access, &wi, &hi);
    if (w) {
        *w = wi;
    }
    if (h) {
        *h = hi;
    }
    return result;
}

SDL_Texture* renderText(SDL_Texture* previousTexture, TTF_Font* font, SDL_Renderer* renderer, const std::string& text, SDL_Color color)
{
    if (previousTexture) {
        SDL_DestroyTexture(previousTexture);
    }
    SDL_Surface* surface;
    if (text.empty()) {
        surface = TTF_RenderUTF8_Blended(font, " ", color);
    }
    else {
        surface = TTF_RenderUTF8_Blended(font, text.c_str(), color);
    }
    if (surface) {
        SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
        SDL_FreeSurface(surface);
        return texture;
    }
    else {
        return 0;
    }
}

struct Text {
    std::string text;
    SDL_Surface* surface = 0;
    SDL_Texture* t = 0;
    SDL_FRect dstR{};
    bool autoAdjustW = false;
    bool autoAdjustH = false;
    float wMultiplier = 1;
    float hMultiplier = 1;

    ~Text()
    {
        if (surface) {
            SDL_FreeSurface(surface);
        }
        if (t) {
            SDL_DestroyTexture(t);
        }
    }

    Text()
    {

    }

    Text(const Text& rightText)
    {
        text = rightText.text;
        if (surface) {
            SDL_FreeSurface(surface);
        }
        if (t) {
            SDL_DestroyTexture(t);
        }
        if (rightText.surface) {
            surface = SDL_ConvertSurface(rightText.surface, rightText.surface->format, SDL_SWSURFACE);
        }
        if (rightText.t) {
            t = SDL_CreateTextureFromSurface(renderer, surface);
        }
        dstR = rightText.dstR;
        autoAdjustW = rightText.autoAdjustW;
        autoAdjustH = rightText.autoAdjustH;
        wMultiplier = rightText.wMultiplier;
        hMultiplier = rightText.hMultiplier;
    }

    Text& operator=(const Text& rightText)
    {
        text = rightText.text;
        if (surface) {
            SDL_FreeSurface(surface);
        }
        if (t) {
            SDL_DestroyTexture(t);
        }
        if (rightText.surface) {
            surface = SDL_ConvertSurface(rightText.surface, rightText.surface->format, SDL_SWSURFACE);
        }
        if (rightText.t) {
            t = SDL_CreateTextureFromSurface(renderer, surface);
        }
        dstR = rightText.dstR;
        autoAdjustW = rightText.autoAdjustW;
        autoAdjustH = rightText.autoAdjustH;
        wMultiplier = rightText.wMultiplier;
        hMultiplier = rightText.hMultiplier;
        return *this;
    }

    void setText(SDL_Renderer* renderer, TTF_Font* font, std::string text, SDL_Color c = { 255,255,255 })
    {
        this->text = text;
#if 1 // NOTE: renderText
        if (surface) {
            SDL_FreeSurface(surface);
        }
        if (t) {
            SDL_DestroyTexture(t);
        }
        if (text.empty()) {
            surface = TTF_RenderUTF8_Blended(font, " ", c);
        }
        else {
            surface = TTF_RenderUTF8_Blended(font, text.c_str(), c);
        }
        if (surface) {
            t = SDL_CreateTextureFromSurface(renderer, surface);
        }
#endif
        if (autoAdjustW) {
            SDL_QueryTextureF(t, 0, 0, &dstR.w, 0);
        }
        if (autoAdjustH) {
            SDL_QueryTextureF(t, 0, 0, 0, &dstR.h);
        }
        dstR.w *= wMultiplier;
        dstR.h *= hMultiplier;
    }

    void setText(SDL_Renderer* renderer, TTF_Font* font, int value, SDL_Color c = { 255,255,255 })
    {
        setText(renderer, font, std::to_string(value), c);
    }

    void draw(SDL_Renderer* renderer)
    {
        if (t) {
            SDL_RenderCopyF(renderer, t, 0, &dstR);
        }
    }
};

std::string ucs4ToUtf8(const std::u32string& in)
{
    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
    return conv.to_bytes(in);
}

std::u32string utf8ToUcs4(const std::string& in)
{
    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
    return conv.from_bytes(in);
}

void utf8Insert(std::string& buffer, int index, std::string text)
{
    std::u32string u32Buffer = utf8ToUcs4(buffer);
    if (index > u32Buffer.size()) {
        index = u32Buffer.size();
    }
    u32Buffer.insert(index, utf8ToUcs4(text));
    buffer = ucs4ToUtf8(u32Buffer);
}

std::string utf8Substr(const std::string& str, unsigned int start, unsigned int leng)
{
    std::u32string s = utf8ToUcs4(str);
    return ucs4ToUtf8(s.substr(start, leng));
}

std::size_t utf8GetSize(std::string buffer)
{
    std::u32string str = utf8ToUcs4(buffer);
    return str.size();
}

void utf8Erase(std::string& buffer, int index)
{
    buffer = utf8Substr(buffer, 0, index) + utf8Substr(buffer, index + 1, std::string::npos);
}

struct Input {
    SDL_Rect r{};
    Text text;
    SDL_Rect cursorR{};
    int currentLetter = 0;
    std::u32string left;
    std::u32string right;
    bool isPassword = false;
    bool isSelected = false;

    void handleEvent(SDL_Event event, TTF_Font* font)
    {
        if (event.type == SDL_KEYDOWN) {
            if (event.key.keysym.scancode == SDL_SCANCODE_BACKSPACE) {
                if (currentLetter) {
                    utf8Erase(text.text, currentLetter - 1);
                    if (!right.empty()) {
                        std::u32string s = utf8ToUcs4(text.text);
                        s.push_back(right.front());
                        right.erase(0, 1);
                        text.text = ucs4ToUtf8(s);
                    }
                    else if (!left.empty()) {
                        std::u32string s = utf8ToUcs4(text.text);
                        s.insert(0, 1, left.back());
                        left.pop_back();
                        text.text = ucs4ToUtf8(s);
                    }
                    else {
                        --currentLetter;
                    }
                    text.setText(renderer, font, text.text, {});
                }
            }
            else if (event.key.keysym.scancode == SDL_SCANCODE_LEFT) {
                if (currentLetter) {
                    --currentLetter;
                }
                else {
                    if (!left.empty()) {
                        std::u32string s = utf8ToUcs4(text.text);
                        s.insert(s.begin(), left.back());
                        left.pop_back();
                        right.insert(right.begin(), s.back());
                        s.pop_back();
                        text.setText(renderer, font, ucs4ToUtf8(s), {});
                    }
                }
            }
            else if (event.key.keysym.scancode == SDL_SCANCODE_RIGHT) {
                if (currentLetter != utf8ToUcs4(text.text).size()) {
                    ++currentLetter;
                }
                else {
                    if (!right.empty()) {
                        std::u32string s = utf8ToUcs4(text.text);
                        s.push_back(right.front());
                        right.erase(0, 1);
                        left.push_back(s.front());
                        s.erase(0, 1);
                        text.setText(renderer, font, ucs4ToUtf8(s), {});
                    }
                }
            }
        }
        else if (event.type == SDL_TEXTINPUT) {
            utf8Insert(text.text, currentLetter, event.text.text);
            text.setText(renderer, font, text.text, {});
            ++currentLetter;
            while (text.dstR.x + text.dstR.w > r.x + r.w) {
                --currentLetter;
                left.push_back(utf8ToUcs4(text.text)[0]);
                utf8Erase(text.text, 0);
                text.setText(renderer, font, text.text, {});
            }
        }
    }

    void draw(SDL_Renderer* renderer, TTF_Font* font)
    {
        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 0);
        SDL_RenderFillRect(renderer, &r);
        if (isPassword) {
            std::string currPassword = text.text;
            text.setText(renderer, font, std::string(utf8GetSize(currPassword), '*'), {});
            text.draw(renderer);
            text.setText(renderer, font, currPassword, {});
        }
        else {
            text.draw(renderer);
        }
        SDL_SetRenderDrawColor(renderer, 0, 255, 0, 0);
        Text t = text;
        t.text = utf8Substr(t.text, 0, currentLetter);
        t.setText(renderer, font, t.text, {});
        if (currentLetter) {
            cursorR.x = t.dstR.x + t.dstR.w;
        }
        else {
            cursorR.x = t.dstR.x;
        }
        if (isSelected) {
            SDL_RenderFillRect(renderer, &cursorR);
        }
    }
};

int main(int argc, char* argv[])
{
    SDL_Init(SDL_INIT_EVERYTHING);
    TTF_Init();
    SDL_Window* window = SDL_CreateWindow("TextEditInput", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowWidth, windowHeight, SDL_WINDOW_RESIZABLE);
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    TTF_Font* robotoF = TTF_OpenFont("res/roboto.ttf", 72);
    int w, h;
    SDL_GetWindowSize(window, &w, &h);
    SDL_RenderSetScale(renderer, w / (float)windowWidth, h / (float)windowHeight);
    bool running = true;
    Input input;
    input.r.w = 200;
    input.r.h = 30;
    input.r.x = windowWidth / 2 - input.r.w / 2;
    input.r.y = windowHeight / 2.f - input.r.h - 10;
    input.text.dstR.w = input.r.w;
    input.text.dstR.h = input.r.h;
    input.text.dstR.x = input.r.x;
    input.text.dstR.y = input.r.y;
    input.text.autoAdjustW = true;
    input.text.wMultiplier = 0.5;
    input.cursorR.w = 8;
    input.cursorR.h = input.r.h - 2;
    input.cursorR.x = input.r.x;
    input.cursorR.y = input.r.y + input.r.h / 2 - input.cursorR.h / 2;
    input.isSelected = true;
    while (running) {
        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            input.handleEvent(event, robotoF);
            if (event.type == SDL_QUIT || event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) {
                running = false;
            }
        }
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
        SDL_RenderClear(renderer);
        input.draw(renderer, robotoF);
        SDL_RenderPresent(renderer);
    }
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM