From 921c93743987b462478a356092df3a067be17028 Mon Sep 17 00:00:00 2001 From: Tim Schubert Date: Thu, 28 Jan 2016 03:06:19 +0100 Subject: [PATCH] Improved text input. --- src/Bob.cpp | 52 ++++++++++++++++++++++++++++++++++++++----- src/Bob.hpp | 15 ++++++++----- src/Gui.cpp | 64 +++++++++++++++++++++++++++++++++++------------------ src/Gui.hpp | 26 ++++++++++++++-------- 4 files changed, 116 insertions(+), 41 deletions(-) diff --git a/src/Bob.cpp b/src/Bob.cpp index 8a5744c..0329911 100644 --- a/src/Bob.cpp +++ b/src/Bob.cpp @@ -1,5 +1,6 @@ #include "Bob.hpp" + void Game::handle_event(SDL_Event *event) { static SDL_Point window_size; @@ -16,7 +17,7 @@ void Game::handle_event(SDL_Event *event) { case SDL_WINDOWEVENT_SIZE_CHANGED: 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}); break; default: @@ -71,7 +72,7 @@ void Game::handle_event(SDL_Event *event) { window_size = this->window->toggle_fullscreen(); 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->upgrade_box->set_visible(false); } @@ -91,9 +92,9 @@ void Game::handle_event(SDL_Event *event) break; case SDLK_RETURN: input = this->text_input_box->get_input(); - if (input == "/quit") + if (this->text_input_box->get_active()) { - this->quit = true; + this->command(input); } break; 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() { this->frame_timer->start_timer(); @@ -233,7 +275,7 @@ int main(int, char **) SDL_Rect bounds; SDL_GetDisplayBounds(0, &bounds); 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; exit_status = game->game_loop(); delete game; diff --git a/src/Bob.hpp b/src/Bob.hpp index 6a167e7..e156fde 100644 --- a/src/Bob.hpp +++ b/src/Bob.hpp @@ -20,6 +20,7 @@ class Game public: Game(SDL_Rect *window_dimensions, Sint16 size) { + this->started = false; this->layout = new Layout(pointy_orientation, 20, {window_dimensions->w / 2, window_dimensions->h / 2}, {0, 0, window_dimensions->w, window_dimensions->h}); @@ -41,15 +42,14 @@ public: | SDL_RENDERER_TARGETTEXTURE); this->grid = new HexagonGrid(size, this->layout, this->renderer); 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->upgrade_box = new UpgradeBox(this->renderer, {0, 0, 1, 1}, fg, this->font, center); - this->test_box = new TextBox(this->renderer, {0, 0, 1, 1}, fg, this->font); - this->test_box->set_visible(true); + this->field_box = new FieldBox(this->renderer, {0, 0, 100, 100}, 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, 100, 20}, fg, this->font); this->next_turn_button = new NextTurnButtonBox(this->renderer, {window_size.x - 100, window_size.y - 100, 1, 1}, fg, this->font, &(this->players)); - this->text_input_box = new TextInputBox(this->renderer, {0, window_size.y - 12, window_size.x, 12}, fg, - this->font); + int font_height = TTF_FontHeight(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(); } catch (const SDL_Exception &sdl_except) @@ -79,6 +79,8 @@ public: delete this->layout; } + void command(std::string command); + void render(); void handle_event(SDL_Event *event); @@ -86,6 +88,7 @@ public: int game_loop(); private: + bool started; TextInputBox *text_input_box; std::vector players; NextTurnButtonBox *next_turn_button; diff --git a/src/Gui.cpp b/src/Gui.cpp index 73144f6..b8eb3eb 100644 --- a/src/Gui.cpp +++ b/src/Gui.cpp @@ -23,19 +23,25 @@ bool TextBox::load_text(std::string text) { this->renderer->set_draw_color({0, 0, 0, 0xff}); 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) { SDL_FreeSurface(text_surface); throw SDL_TTFException(); } - this->dimensions.w = text_surface->w; - this->dimensions.h = text_surface->h; + //this->dimensions.w = text_surface->w; + //this->dimensions.h = text_surface->h; SDL_Surface *surface = SDL_CreateRGBSurface(0, this->dimensions.w, this->dimensions.h, 32, rmask, gmask, bmask, amask); - if (surface == nullptr - || SDL_FillRect(surface, nullptr, SDL_MapRGB(surface->format, 255, 255, 255)) < 0 - || SDL_BlitSurface(text_surface, nullptr, surface, nullptr) < 0) + if (surface == nullptr || SDL_LockSurface(surface) < 0 || + SDL_FillRect(surface, nullptr, SDL_MapRGB(surface->format, 255, 255, 255)) < 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!"); } @@ -328,23 +334,23 @@ void TextInputBox::handle_event(const SDL_Event *event) { if (event->key.keysym.sym == SDLK_RETURN) { - this->input = ""; + this->input.str(""); 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; } else if (event->key.keysym.sym == SDLK_c && SDL_GetModState() & KMOD_CTRL) { - SDL_SetClipboardText(input.c_str()); - changed = true; + SDL_SetClipboardText(input.str().c_str()); } 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) @@ -352,7 +358,7 @@ void TextInputBox::handle_event(const SDL_Event *event) 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)) { - input += event->text.text; + input << event->text.text; changed = true; } } @@ -362,9 +368,26 @@ void TextInputBox::handle_event(const SDL_Event *event) } if (changed) { - std::string foo = input; // because SDL_ttf will complain if not - foo += " "; - this->load_text(foo); + std::string text; + text = output.str(); + 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) { - 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)); } } void TextInputBox::update_dimensions(SDL_Rect rect) { - this->bg_dimensions = rect; - this->dimensions = bg_dimensions; + this->dimensions.x = rect.x; + this->dimensions.y = rect.y; + this->dimensions.w = rect.w; } bool TextInputBox::get_active() diff --git a/src/Gui.hpp b/src/Gui.hpp index 1a21426..3d65201 100644 --- a/src/Gui.hpp +++ b/src/Gui.hpp @@ -51,7 +51,10 @@ class TextBox : public Box { public: 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); @@ -59,16 +62,18 @@ public: protected: TTF_Font *font; + int font_height; }; class TextInputBox : TextBox { public: 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->load_text(" "); + this->output << "# "; + this->load_text(output.str()); } void start(); @@ -83,11 +88,14 @@ public: 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: - SDL_Rect bg_dimensions; - std::string input; + Uint16 lines; + std::ostringstream output; // what is loaded to the texture - currnt input + std::stringstream input; // editable command prompt }; class FieldBox : public TextBox @@ -150,7 +158,6 @@ private: std::vector::iterator current_player; }; - class UpgradeBox : public Box { public: @@ -160,13 +167,14 @@ public: int y = dimensions.y; 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)); y += 20; this->marked_upgrade = 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()