Improved text input.

This commit is contained in:
Tim Schubert 2016-01-28 03:06:19 +01:00
parent 59f054cefb
commit 921c937439
4 changed files with 116 additions and 41 deletions

View file

@ -1,5 +1,6 @@
#include "Bob.hpp" #include "Bob.hpp"
void Game::handle_event(SDL_Event *event) void Game::handle_event(SDL_Event *event)
{ {
static SDL_Point window_size; static SDL_Point window_size;
@ -16,7 +17,7 @@ void Game::handle_event(SDL_Event *event)
{ {
case SDL_WINDOWEVENT_SIZE_CHANGED: case SDL_WINDOWEVENT_SIZE_CHANGED:
this->grid->update_dimensions({event->window.data1, event->window.data2}); this->grid->update_dimensions({event->window.data1, event->window.data2});
this->text_input_box->update_dimensions({0, event->window.data2 - 12, event->window.data1, this->text_input_box->update_dimensions({0, 0, event->window.data1,
event->window.data2}); event->window.data2});
break; break;
default: default:
@ -71,7 +72,7 @@ void Game::handle_event(SDL_Event *event)
{ {
window_size = this->window->toggle_fullscreen(); window_size = this->window->toggle_fullscreen();
this->grid->update_dimensions(window_size); this->grid->update_dimensions(window_size);
this->text_input_box->update_dimensions({0, window_size.y - window_size.x, 12}); this->text_input_box->update_dimensions({0, window_size.y - 20, 0, 20});
this->next_turn_button->update_position({window_size.x - 100, window_size.y - 100}); this->next_turn_button->update_position({window_size.x - 100, window_size.y - 100});
this->upgrade_box->set_visible(false); this->upgrade_box->set_visible(false);
} }
@ -91,9 +92,9 @@ void Game::handle_event(SDL_Event *event)
break; break;
case SDLK_RETURN: case SDLK_RETURN:
input = this->text_input_box->get_input(); input = this->text_input_box->get_input();
if (input == "/quit") if (this->text_input_box->get_active())
{ {
this->quit = true; this->command(input);
} }
break; break;
default: default:
@ -149,6 +150,47 @@ void Game::handle_event(SDL_Event *event)
} }
} }
void Game::command(std::string input)
{
std::ostringstream prompt;
if (input == "quit")
{
prompt << "Quitting the game";
this->quit = true;
}
else if (input == "test")
{
prompt << "This is a test!";
}
else if (input == "surrender")
{
//Player::current_player->surrender();
}
else if (!this->started)
{
if (input.substr(0, 11) == "add player")
{
Player *added = new Player(input.substr(11, std::string::npos));
/*if (!this->grid->place(added))
{
this->text_input_box->output << "Failed to add player:" << added->get_name();
delete added;
}
else
{
this->players.push_back(added);
}
*/
}
else if (input == "start")
{
//this->start_game();
prompt << "Started the game.";
}
}
this->text_input_box->prompt(prompt.str());
}
int Game::game_loop() int Game::game_loop()
{ {
this->frame_timer->start_timer(); this->frame_timer->start_timer();
@ -233,7 +275,7 @@ int main(int, char **)
SDL_Rect bounds; SDL_Rect bounds;
SDL_GetDisplayBounds(0, &bounds); SDL_GetDisplayBounds(0, &bounds);
SDL_Rect window_dimensions = {SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 600}; SDL_Rect window_dimensions = {SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 600};
Game *game = new Game(&window_dimensions, 20); Game *game = new Game(&window_dimensions, 10);
int exit_status = 1; int exit_status = 1;
exit_status = game->game_loop(); exit_status = game->game_loop();
delete game; delete game;

View file

@ -20,6 +20,7 @@ class Game
public: public:
Game(SDL_Rect *window_dimensions, Sint16 size) Game(SDL_Rect *window_dimensions, Sint16 size)
{ {
this->started = false;
this->layout = new Layout(pointy_orientation, 20, this->layout = new Layout(pointy_orientation, 20,
{window_dimensions->w / 2, window_dimensions->h / 2}, {window_dimensions->w / 2, window_dimensions->h / 2},
{0, 0, window_dimensions->w, window_dimensions->h}); {0, 0, window_dimensions->w, window_dimensions->h});
@ -41,15 +42,14 @@ public:
| SDL_RENDERER_TARGETTEXTURE); | SDL_RENDERER_TARGETTEXTURE);
this->grid = new HexagonGrid(size, this->layout, this->renderer); this->grid = new HexagonGrid(size, this->layout, this->renderer);
FieldMeta *center = this->grid->get_field({0, 0, 0}); FieldMeta *center = this->grid->get_field({0, 0, 0});
this->field_box = new FieldBox(this->renderer, {0, 0, 1, 1}, fg, this->font, center); this->field_box = new FieldBox(this->renderer, {0, 0, 100, 100}, fg, this->font, center);
this->upgrade_box = new UpgradeBox(this->renderer, {0, 0, 1, 1}, fg, this->font, center); this->upgrade_box = new UpgradeBox(this->renderer, {0, 0, 100, 20}, fg, this->font, center);
this->test_box = new TextBox(this->renderer, {0, 0, 1, 1}, fg, this->font); this->test_box = new TextBox(this->renderer, {0, 0, 100, 20}, fg, this->font);
this->test_box->set_visible(true);
this->next_turn_button = new NextTurnButtonBox(this->renderer, this->next_turn_button = new NextTurnButtonBox(this->renderer,
{window_size.x - 100, window_size.y - 100, 1, 1}, fg, {window_size.x - 100, window_size.y - 100, 1, 1}, fg,
this->font, &(this->players)); this->font, &(this->players));
this->text_input_box = new TextInputBox(this->renderer, {0, window_size.y - 12, window_size.x, 12}, fg, int font_height = TTF_FontHeight(this->font);
this->font); this->text_input_box = new TextInputBox(this->renderer, {0, 0, window_size.x, font_height}, fg, this->font);
this->text_input_box->stop(); this->text_input_box->stop();
} }
catch (const SDL_Exception &sdl_except) catch (const SDL_Exception &sdl_except)
@ -79,6 +79,8 @@ public:
delete this->layout; delete this->layout;
} }
void command(std::string command);
void render(); void render();
void handle_event(SDL_Event *event); void handle_event(SDL_Event *event);
@ -86,6 +88,7 @@ public:
int game_loop(); int game_loop();
private: private:
bool started;
TextInputBox *text_input_box; TextInputBox *text_input_box;
std::vector<Player *> players; std::vector<Player *> players;
NextTurnButtonBox *next_turn_button; NextTurnButtonBox *next_turn_button;

View file

@ -23,19 +23,25 @@ bool TextBox::load_text(std::string text)
{ {
this->renderer->set_draw_color({0, 0, 0, 0xff}); this->renderer->set_draw_color({0, 0, 0, 0xff});
const char *displayed_text = text.c_str(); const char *displayed_text = text.c_str();
SDL_Surface *text_surface = TTF_RenderUTF8_Blended_Wrapped(this->font, displayed_text, this->color, 100); SDL_Surface *text_surface = TTF_RenderUTF8_Blended_Wrapped(this->font, displayed_text, this->color,
this->dimensions.w);
if (text_surface == nullptr) if (text_surface == nullptr)
{ {
SDL_FreeSurface(text_surface); SDL_FreeSurface(text_surface);
throw SDL_TTFException(); throw SDL_TTFException();
} }
this->dimensions.w = text_surface->w; //this->dimensions.w = text_surface->w;
this->dimensions.h = text_surface->h; //this->dimensions.h = text_surface->h;
SDL_Surface *surface = SDL_CreateRGBSurface(0, this->dimensions.w, this->dimensions.h, 32, rmask, gmask, bmask, SDL_Surface *surface = SDL_CreateRGBSurface(0, this->dimensions.w, this->dimensions.h, 32, rmask, gmask, bmask,
amask); amask);
if (surface == nullptr if (surface == nullptr || SDL_LockSurface(surface) < 0 ||
|| SDL_FillRect(surface, nullptr, SDL_MapRGB(surface->format, 255, 255, 255)) < 0 SDL_FillRect(surface, nullptr, SDL_MapRGB(surface->format, 255, 255, 255)) < 0)
|| SDL_BlitSurface(text_surface, nullptr, surface, nullptr) < 0) {
throw SDL_Exception("Failed to fill rect behind text!");
}
//SDL_Rect text_rect = {this->dimensions.x, this->dimensions.y, surface->w, surface->h};
SDL_UnlockSurface(surface);
if (SDL_BlitSurface(text_surface, nullptr, surface, nullptr) < 0)
{ {
throw SDL_Exception("Failed to create background text_surface!"); throw SDL_Exception("Failed to create background text_surface!");
} }
@ -328,23 +334,23 @@ void TextInputBox::handle_event(const SDL_Event *event)
{ {
if (event->key.keysym.sym == SDLK_RETURN) if (event->key.keysym.sym == SDLK_RETURN)
{ {
this->input = ""; this->input.str("");
changed = true; changed = true;
} }
else if (event->key.keysym.sym == SDLK_BACKSPACE && this->input.length() > 0) else if (event->key.keysym.sym == SDLK_BACKSPACE)
{ {
input.pop_back(); input << '\b';
input << " ";
changed = true; changed = true;
} }
else if (event->key.keysym.sym == SDLK_c && SDL_GetModState() & KMOD_CTRL) else if (event->key.keysym.sym == SDLK_c && SDL_GetModState() & KMOD_CTRL)
{ {
SDL_SetClipboardText(input.c_str()); SDL_SetClipboardText(input.str().c_str());
changed = true;
} }
else if (event->key.keysym.sym == SDLK_v && SDL_GetModState() & KMOD_CTRL) else if (event->key.keysym.sym == SDLK_v && SDL_GetModState() & KMOD_CTRL)
{ {
input = SDL_GetClipboardText(); input << SDL_GetClipboardText();
changed = true;
} }
} }
else if (event->type == SDL_TEXTINPUT) else if (event->type == SDL_TEXTINPUT)
@ -352,7 +358,7 @@ void TextInputBox::handle_event(const SDL_Event *event)
if (!((event->text.text[0] == 'c' || event->text.text[0] == 'C') if (!((event->text.text[0] == 'c' || event->text.text[0] == 'C')
&& (event->text.text[0] == 'v' || event->text.text[0] == 'V') && SDL_GetModState() & KMOD_CTRL)) && (event->text.text[0] == 'v' || event->text.text[0] == 'V') && SDL_GetModState() & KMOD_CTRL))
{ {
input += event->text.text; input << event->text.text;
changed = true; changed = true;
} }
} }
@ -362,9 +368,26 @@ void TextInputBox::handle_event(const SDL_Event *event)
} }
if (changed) if (changed)
{ {
std::string foo = input; // because SDL_ttf will complain if not std::string text;
foo += " "; text = output.str();
this->load_text(foo); text += input.str();
if (text.empty())
text += " ";
this->load_text(text);
}
}
void TextInputBox::prompt(std::string message)
{
this->output << this->input.str() << "\n" << message << "\n# ";
this->lines += 2;
this->dimensions.h = (this->font_height * lines);
this->load_text(output.str());
if (this->dimensions.h > 500)
{
this->lines = 2;
output.str("");
this->prompt(message);
} }
} }
@ -372,16 +395,15 @@ void TextInputBox::render(Renderer *ext_renderer)
{ {
if (this->texture != nullptr && this->visible) if (this->texture != nullptr && this->visible)
{ {
ext_renderer->set_draw_color({0xff, 0xff, 0xff, 0x00});
SDL_RenderFillRect(ext_renderer->get_renderer(), &(bg_dimensions));
ext_renderer->copy(this->texture, nullptr, &(this->dimensions)); ext_renderer->copy(this->texture, nullptr, &(this->dimensions));
} }
} }
void TextInputBox::update_dimensions(SDL_Rect rect) void TextInputBox::update_dimensions(SDL_Rect rect)
{ {
this->bg_dimensions = rect; this->dimensions.x = rect.x;
this->dimensions = bg_dimensions; this->dimensions.y = rect.y;
this->dimensions.w = rect.w;
} }
bool TextInputBox::get_active() bool TextInputBox::get_active()

View file

@ -51,7 +51,10 @@ class TextBox : public Box
{ {
public: public:
TextBox(Renderer *renderer, SDL_Rect dimensions, SDL_Color color, TTF_Font *font_) TextBox(Renderer *renderer, SDL_Rect dimensions, SDL_Color color, TTF_Font *font_)
: Box(renderer, dimensions, color), font(font_) { } : Box(renderer, dimensions, color), font(font_)
{
this->font_height = TTF_FontHeight(font);
}
bool load_text(std::string text); bool load_text(std::string text);
@ -59,16 +62,18 @@ public:
protected: protected:
TTF_Font *font; TTF_Font *font;
int font_height;
}; };
class TextInputBox : TextBox class TextInputBox : TextBox
{ {
public: public:
TextInputBox(Renderer *renderer_, SDL_Rect dimensions_, SDL_Color color_, TTF_Font *font_) TextInputBox(Renderer *renderer_, SDL_Rect dimensions_, SDL_Color color_, TTF_Font *font_)
: TextBox(renderer_, dimensions_, color_, font_), bg_dimensions(dimensions_), input("") : TextBox(renderer_, dimensions_, color_, font_), input(""), lines(1)
{ {
this->visible = false; this->visible = false;
this->load_text(" "); this->output << "# ";
this->load_text(output.str());
} }
void start(); void start();
@ -83,11 +88,14 @@ public:
void update_dimensions(SDL_Rect rect); void update_dimensions(SDL_Rect rect);
std::string get_input() { return this->input; } std::string get_input() { return this->input.str(); }
void prompt(std::string message);
private: private:
SDL_Rect bg_dimensions; Uint16 lines;
std::string input; std::ostringstream output; // what is loaded to the texture - currnt input
std::stringstream input; // editable command prompt
}; };
class FieldBox : public TextBox class FieldBox : public TextBox
@ -150,7 +158,6 @@ private:
std::vector<Player *>::iterator current_player; std::vector<Player *>::iterator current_player;
}; };
class UpgradeBox : public Box class UpgradeBox : public Box
{ {
public: public:
@ -160,13 +167,14 @@ public:
int y = dimensions.y; int y = dimensions.y;
for (Upgrade upgrade : UPGRADES) for (Upgrade upgrade : UPGRADES)
{ {
UpgradeButtonBox *box = new UpgradeButtonBox(renderer, {0, y, 1, 1}, color, font, this, upgrade); UpgradeButtonBox *box = new UpgradeButtonBox(renderer, {0, y, dimensions.w, 20}, color, font, this,
upgrade);
box->load_text(UPGRADE_NAMES.at(upgrade)); box->load_text(UPGRADE_NAMES.at(upgrade));
y += 20; y += 20;
this->marked_upgrade = box; this->marked_upgrade = box;
this->upgrades.push_back(box); this->upgrades.push_back(box);
} }
this->upgrade_info = new TextBox(renderer, {0, 0, 1, 1}, color, font); this->upgrade_info = new TextBox(renderer, {0, 0, dimensions.w, 200}, color, font);
} }
~UpgradeBox() ~UpgradeBox()