mirror of
https://forgejo.xatacraft.ru/Sunshine/mkxp-sunshine.git
synced 2026-08-19 13:29:54 +00:00
Add text input function (broken, read description)
Note: using this function breaks the graphics rendering at the moment, due to code inconsistencies (utilizing SDL renderers when the rest of the program uses GL ones, mainly), working on fixes for it!
This commit is contained in:
parent
3913a3ef74
commit
6b5eff715b
5 changed files with 275 additions and 2 deletions
|
|
@ -10,7 +10,6 @@
|
|||
RB_METHOD(oneshotSetYesNo)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
const char *yes;
|
||||
const char *no;
|
||||
rb_get_args(argc, argv, "zz", &yes, &no RB_ARG_END);
|
||||
|
|
@ -21,7 +20,6 @@ RB_METHOD(oneshotSetYesNo)
|
|||
RB_METHOD(oneshotMsgBox)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
int type;
|
||||
VALUE body;
|
||||
VALUE title = Qnil;
|
||||
|
|
@ -31,6 +29,19 @@ RB_METHOD(oneshotMsgBox)
|
|||
return rb_bool_new(shState->oneshot().msgbox(type, bodyStr.c_str(), titleStr.c_str()));
|
||||
}
|
||||
|
||||
RB_METHOD(oneshotTextInput)
|
||||
{
|
||||
// const char* prompt, int char_limit, const char* font
|
||||
RB_UNUSED_PARAM;
|
||||
VALUE prompt;
|
||||
int char_limit = 100;
|
||||
VALUE font = Qnil;
|
||||
rb_get_args(argc, argv, "S|iS", &prompt, &char_limit, &font RB_ARG_END);
|
||||
std::string promptStr = std::string(RSTRING_PTR(prompt), RSTRING_LEN(prompt));
|
||||
std::string fontStr = (font == Qnil) ? "" : std::string(RSTRING_PTR(font), RSTRING_LEN(font));
|
||||
return rb_str_new2(shState->oneshot().textinput(promptStr.c_str(), char_limit, fontStr.c_str()).c_str());
|
||||
}
|
||||
|
||||
RB_METHOD(oneshotResetObscured)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
|
@ -108,6 +119,7 @@ void oneshotBindingInit()
|
|||
//Functions
|
||||
_rb_define_module_function(module, "set_yes_no", oneshotSetYesNo);
|
||||
_rb_define_module_function(module, "msgbox", oneshotMsgBox);
|
||||
_rb_define_module_function(module, "textinput", oneshotTextInput);
|
||||
_rb_define_module_function(module, "reset_obscured", oneshotResetObscured);
|
||||
_rb_define_module_function(module, "obscured_cleared?", oneshotObscuredCleared);
|
||||
_rb_define_module_function(module, "allow_exit", oneshotAllowExit);
|
||||
|
|
|
|||
|
|
@ -282,6 +282,10 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
|
||||
break;
|
||||
|
||||
case SDL_TEXTINPUT:
|
||||
if (rtData.inputText.length() < rtData.inputTextLimit) rtData.inputText += event.text.text;
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN :
|
||||
if (event.key.keysym.scancode == SDL_SCANCODE_F1)
|
||||
{
|
||||
|
|
@ -339,6 +343,15 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
break;
|
||||
}
|
||||
|
||||
if (rtData.acceptingTextInput) {
|
||||
if (event.key.keysym.sym == SDLK_BACKSPACE && rtData.inputText.length() > 0)
|
||||
rtData.inputText.pop_back();
|
||||
else if (event.key.keysym.sym == SDLK_RETURN)
|
||||
rtData.acceptingTextInput.clear();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
keyStates[event.key.keysym.scancode] = true;
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -238,6 +238,9 @@ struct RGSSThreadData
|
|||
/* Set when attempting to exit and allowExit is false */
|
||||
AtomicFlag triedExit;
|
||||
|
||||
/* True if accepting text input */
|
||||
AtomicFlag acceptingTextInput;
|
||||
|
||||
EventThread *ethread;
|
||||
UnidirMessage<Vec2i> windowSizeMsg;
|
||||
UnidirMessage<BDescVec> bindingUpdateMsg;
|
||||
|
|
@ -255,6 +258,8 @@ struct RGSSThreadData
|
|||
Config config;
|
||||
|
||||
std::string rgssErrorMsg;
|
||||
std::string inputText;
|
||||
int inputTextLimit;
|
||||
|
||||
RGSSThreadData(EventThread *ethread,
|
||||
const char *argv0,
|
||||
|
|
|
|||
192
src/oneshot.cpp
192
src/oneshot.cpp
|
|
@ -8,6 +8,8 @@
|
|||
#include "debugwriter.h"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
//OS-Specific code
|
||||
#if defined _WIN32
|
||||
|
|
@ -210,6 +212,9 @@
|
|||
#error "Operating system not detected."
|
||||
#endif
|
||||
|
||||
#define DEF_SCREEN_W 640
|
||||
#define DEF_SCREEN_H 480
|
||||
|
||||
struct OneshotPrivate
|
||||
{
|
||||
//Main SDL window
|
||||
|
|
@ -359,6 +364,130 @@ static WCHAR *w32_toWide(const char *str)
|
|||
}
|
||||
#endif
|
||||
|
||||
LTexture::LTexture() {
|
||||
//Initialize
|
||||
mTexture = NULL;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
}
|
||||
|
||||
LTexture::~LTexture() {
|
||||
//Deallocate
|
||||
free();
|
||||
}
|
||||
|
||||
bool LTexture::loadFromFile(std::string path, SDL_Renderer *gRenderer) {
|
||||
//Get rid of preexisting texture
|
||||
free();
|
||||
|
||||
//The final texture
|
||||
SDL_Texture *newTexture = NULL;
|
||||
|
||||
//Load image at specified path
|
||||
SDL_Surface *loadedSurface = IMG_Load(path.c_str());
|
||||
if (loadedSurface == NULL) {
|
||||
printf("Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError());
|
||||
} else {
|
||||
//Color key image
|
||||
SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, 0, 0xFF, 0xFF));
|
||||
|
||||
//Create texture from surface pixels
|
||||
newTexture = SDL_CreateTextureFromSurface(gRenderer, loadedSurface);
|
||||
if (newTexture == NULL) {
|
||||
printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
|
||||
} else {
|
||||
//Get image dimensions
|
||||
mWidth = loadedSurface->w;
|
||||
mHeight = loadedSurface->h;
|
||||
}
|
||||
|
||||
//Get rid of old loaded surface
|
||||
SDL_FreeSurface(loadedSurface);
|
||||
}
|
||||
|
||||
//Return success
|
||||
mTexture = newTexture;
|
||||
return mTexture != NULL;
|
||||
}
|
||||
|
||||
#ifdef _SDL_TTF_H
|
||||
bool LTexture::loadFromRenderedText(std::string textureText, SDL_Color textColor, SDL_Renderer *gRenderer, TTF_Font *gFont) {
|
||||
//Get rid of preexisting texture
|
||||
free();
|
||||
|
||||
//Render text surface
|
||||
SDL_Surface *textSurface = TTF_RenderText_Solid(gFont, textureText.c_str(), textColor);
|
||||
if (textSurface != NULL) {
|
||||
//Create texture from surface pixels
|
||||
mTexture = SDL_CreateTextureFromSurface(gRenderer, textSurface);
|
||||
if (mTexture == NULL) {
|
||||
printf("Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError());
|
||||
} else {
|
||||
//Get image dimensions
|
||||
mWidth = textSurface->w;
|
||||
mHeight = textSurface->h;
|
||||
}
|
||||
|
||||
//Get rid of old surface
|
||||
SDL_FreeSurface(textSurface);
|
||||
} else {
|
||||
printf("Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError());
|
||||
}
|
||||
|
||||
|
||||
//Return success
|
||||
return mTexture != NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
void LTexture::free() {
|
||||
//Free texture if it exists
|
||||
if (mTexture != NULL) {
|
||||
SDL_DestroyTexture(mTexture);
|
||||
mTexture = NULL;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LTexture::setColor(Uint8 red, Uint8 green, Uint8 blue) {
|
||||
//Modulate texture rgb
|
||||
SDL_SetTextureColorMod(mTexture, red, green, blue);
|
||||
}
|
||||
|
||||
void LTexture::setBlendMode(SDL_BlendMode blending) {
|
||||
//Set blending function
|
||||
SDL_SetTextureBlendMode(mTexture, blending);
|
||||
}
|
||||
|
||||
void LTexture::setAlpha(Uint8 alpha) {
|
||||
//Modulate texture alpha
|
||||
SDL_SetTextureAlphaMod(mTexture, alpha);
|
||||
}
|
||||
|
||||
void LTexture::render(SDL_Renderer *gRenderer, int x, int y, SDL_Rect *clip, double angle, SDL_Point *center,
|
||||
SDL_RendererFlip flip) {
|
||||
//Set rendering space and render to screen
|
||||
SDL_Rect renderQuad = {x, y, mWidth, mHeight };
|
||||
|
||||
//Set clip rendering dimensions
|
||||
if (clip != NULL) {
|
||||
renderQuad.w = clip->w;
|
||||
renderQuad.h = clip->h;
|
||||
}
|
||||
|
||||
//Render to screen
|
||||
SDL_RenderCopyEx(gRenderer, mTexture, clip, &renderQuad, angle, center, flip);
|
||||
}
|
||||
|
||||
int LTexture::getWidth() {
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
int LTexture::getHeight() {
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
Oneshot::Oneshot(RGSSThreadData &threadData) :
|
||||
threadData(threadData)
|
||||
{
|
||||
|
|
@ -778,6 +907,69 @@ bool Oneshot::msgbox(int type, const char *body, const char *title)
|
|||
#endif
|
||||
}
|
||||
|
||||
std::string Oneshot::textinput(const char* prompt, int char_limit, const char* font) {
|
||||
SDL_Color textColor = {0xFF, 0xFF, 0xFF, 0xFF}; //Set text color as black
|
||||
SDL_Renderer *gRenderer = SDL_CreateRenderer(threadData.window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
// SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
LTexture gPromptTextTexture;
|
||||
LTexture gInputTextTexture;
|
||||
|
||||
//Open the font
|
||||
TTF_Font *gFont = TTF_OpenFont("VL-Gothic-Regular.ttf", 18); // XXX Implement font changing
|
||||
if (gFont == NULL) {
|
||||
printf("Failed to load lazy font! SDL_ttf Error: %s\n", TTF_GetError());
|
||||
// success = false;
|
||||
} else {
|
||||
//Render the prompt
|
||||
if (!gPromptTextTexture.loadFromRenderedText(prompt, textColor, gRenderer, gFont)) {
|
||||
printf("Failed to render prompt text!\n");
|
||||
// success = false;
|
||||
}
|
||||
}
|
||||
|
||||
gInputTextTexture.loadFromRenderedText(threadData.inputText.c_str(), textColor, gRenderer, gFont);
|
||||
SDL_StartTextInput();
|
||||
threadData.acceptingTextInput.set();
|
||||
threadData.inputTextLimit = char_limit;
|
||||
threadData.inputText.clear();
|
||||
|
||||
//Main loop
|
||||
while (threadData.acceptingTextInput) {
|
||||
if (threadData.inputText.length() > 0) gInputTextTexture.loadFromRenderedText(threadData.inputText.c_str(), textColor, gRenderer, gFont);
|
||||
else gInputTextTexture.loadFromRenderedText(" ", textColor, gRenderer, gFont);
|
||||
|
||||
//Clear screen
|
||||
// SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
SDL_RenderClear(gRenderer);
|
||||
|
||||
//Render text textures
|
||||
gPromptTextTexture.render(gRenderer, (DEF_SCREEN_W - gPromptTextTexture.getWidth()) / 2,
|
||||
(DEF_SCREEN_H / 2) - gPromptTextTexture.getHeight());
|
||||
gInputTextTexture.render(gRenderer, (DEF_SCREEN_W - gInputTextTexture.getWidth()) / 2,
|
||||
(DEF_SCREEN_H / 2));
|
||||
|
||||
//Update screen
|
||||
SDL_RenderPresent(gRenderer);
|
||||
}
|
||||
|
||||
//Disable text input
|
||||
SDL_StopTextInput();
|
||||
|
||||
//Free loaded images
|
||||
gPromptTextTexture.free();
|
||||
gInputTextTexture.free();
|
||||
|
||||
//Free global font
|
||||
TTF_CloseFont(gFont);
|
||||
gFont = NULL;
|
||||
|
||||
//Destroy renderer
|
||||
SDL_DestroyRenderer(gRenderer);
|
||||
gRenderer = NULL;
|
||||
|
||||
return threadData.inputText;
|
||||
}
|
||||
|
||||
void Oneshot::setWindowPos(int x, int y)
|
||||
{
|
||||
SDL_LockMutex(p->winMutex);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,62 @@
|
|||
#ifndef ONESHOT_H
|
||||
#define ONESHOT_H
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include "etc-internal.h"
|
||||
#include <string>
|
||||
|
||||
struct OneshotPrivate;
|
||||
struct RGSSThreadData;
|
||||
|
||||
//Texture wrapper class
|
||||
class LTexture {
|
||||
public:
|
||||
//Initializes variables
|
||||
LTexture();
|
||||
|
||||
//Deallocates memory
|
||||
~LTexture();
|
||||
|
||||
//Loads image at specified path
|
||||
bool loadFromFile(std::string path, SDL_Renderer *gRenderer);
|
||||
|
||||
#ifdef _SDL_TTF_H
|
||||
//Creates image from font string
|
||||
bool loadFromRenderedText(std::string textureText, SDL_Color textColor, SDL_Renderer *gRenderer, TTF_Font *gFont);
|
||||
#endif
|
||||
|
||||
//Deallocates texture
|
||||
void free();
|
||||
|
||||
//Set color modulation
|
||||
void setColor(Uint8 red, Uint8 green, Uint8 blue);
|
||||
|
||||
//Set blending
|
||||
void setBlendMode(SDL_BlendMode blending);
|
||||
|
||||
//Set alpha modulation
|
||||
void setAlpha(Uint8 alpha);
|
||||
|
||||
//Renders texture at given point
|
||||
void render(SDL_Renderer *gRenderer, int x, int y, SDL_Rect *clip = NULL, double angle = 0.0, SDL_Point *center = NULL,
|
||||
SDL_RendererFlip flip = SDL_FLIP_NONE);
|
||||
|
||||
//Gets image dimensions
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
|
||||
private:
|
||||
//The actual hardware texture
|
||||
SDL_Texture *mTexture;
|
||||
|
||||
//Image dimensions
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
};
|
||||
|
||||
class Oneshot
|
||||
{
|
||||
public:
|
||||
|
|
@ -63,6 +113,7 @@ public:
|
|||
|
||||
//Functions
|
||||
bool msgbox(int type, const char *body, const char *title);
|
||||
std::string textinput(const char* prompt, int char_limit, const char* font);
|
||||
|
||||
//Dirty flag for obscured texture
|
||||
bool obscuredDirty;
|
||||
|
|
|
|||
Loading…
Reference in a new issue