From e097fde9fbcb4b86861c0ba2912c5599019457f3 Mon Sep 17 00:00:00 2001 From: Vsevolod Kremianskii Date: Sun, 11 Oct 2020 09:46:34 +0700 Subject: [PATCH] refactor: Extract text input from console to a separate class --- CMakeLists.txt | 2 + src/game/console.cpp | 52 ++++------------ src/game/console.h | 3 +- src/game/gui/chargen/name.cpp | 1 + src/gui/textinput.cpp | 108 ++++++++++++++++++++++++++++++++++ src/gui/textinput.h | 55 +++++++++++++++++ 6 files changed, 179 insertions(+), 42 deletions(-) create mode 100644 src/gui/textinput.cpp create mode 100644 src/gui/textinput.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a7dfc64b..c8ed9918 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,7 @@ set(HEADERS src/gui/control/scrollbar.h src/gui/gui.h src/gui/scenebuilder.h + src/gui/textinput.h src/gui/types.h src/net/client.h src/net/connection.h @@ -252,6 +253,7 @@ set(SOURCES src/gui/control/scrollbar.cpp src/gui/gui.cpp src/gui/scenebuilder.cpp + src/gui/textinput.cpp src/net/client.cpp src/net/connection.cpp src/net/command.cpp diff --git a/src/game/console.cpp b/src/game/console.cpp index c564bec8..53b437f6 100644 --- a/src/game/console.cpp +++ b/src/game/console.cpp @@ -29,6 +29,7 @@ using namespace std; +using namespace reone::gui; using namespace reone::render; namespace reone { @@ -37,7 +38,7 @@ namespace game { static const int kLineCount = 10; -Console::Console(const GraphicsOptions &opts) : _opts(opts) { +Console::Console(const GraphicsOptions &opts) : _opts(opts), _input(kTextInputConsole) { } void Console::load() { @@ -46,9 +47,9 @@ void Console::load() { } bool Console::handle(const SDL_Event &event) { + if (_open && _input.handle(event)) return true; + switch (event.type) { - case SDL_KEYDOWN: - return handleKeyDown(event.key); case SDL_KEYUP: return handleKeyUp(event.key); default: @@ -56,38 +57,6 @@ bool Console::handle(const SDL_Event &event) { } } -bool Console::handleKeyDown(const SDL_KeyboardEvent &event) { - if (!_open) return false; - - bool shift = event.keysym.mod & KMOD_SHIFT; - bool digit = event.keysym.sym >= SDLK_0 && event.keysym.sym <= SDLK_9; - bool letter = event.keysym.sym >= SDLK_a && event.keysym.sym <= SDLK_z; - bool underscore = event.keysym.sym == SDLK_MINUS && shift; - - if (digit || letter || underscore || - event.keysym.sym == SDLK_SPACE || - event.keysym.sym == SDLK_COMMA || - event.keysym.sym == SDLK_PERIOD) { - - if (underscore) { - _inputText += SDLK_UNDERSCORE; - } else if (letter && shift) { - _inputText += toupper(event.keysym.sym); - } else { - _inputText += event.keysym.sym; - } - - return true; - - } else if (event.keysym.sym == SDLK_BACKSPACE) { - if (!_inputText.empty()) { - _inputText.resize(_inputText.size() - 1); - } - } - - return false; -} - bool Console::handleKeyUp(const SDL_KeyboardEvent &event) { if (_open) { switch (event.keysym.sym) { @@ -95,13 +64,14 @@ bool Console::handleKeyUp(const SDL_KeyboardEvent &event) { _open = false; return true; - case SDLK_RETURN: - if (!_inputText.empty()) { + case SDLK_RETURN: { + string text(_input.text()); + if (!text.empty()) { executeInputText(); - _inputText.clear(); + _input.clear(); } return true; - + } default: return false; } @@ -118,7 +88,7 @@ bool Console::handleKeyUp(const SDL_KeyboardEvent &event) { } void Console::executeInputText() { - debug(boost::format("Console: execute \"%s\"") % _inputText); + debug(boost::format("Console: execute \"%s\"") % _input.text()); } void Console::render() const { @@ -136,7 +106,7 @@ void Console::render() const { } DefaultQuad.render(GL_TRIANGLES); - string text("> " + _inputText); + string text("> " + _input.text()); { glm::mat4 transform(1.0f); transform = glm::translate(transform, glm::vec3(3.0f, height - 0.5f * _font->height(), 0.0f)); diff --git a/src/game/console.h b/src/game/console.h index 12dc2e95..023989ce 100644 --- a/src/game/console.h +++ b/src/game/console.h @@ -23,6 +23,7 @@ #include "SDL_events.h" +#include "../gui/textinput.h" #include "../render/font.h" #include "../render/types.h" @@ -44,7 +45,7 @@ private: std::shared_ptr _font; render::GraphicsOptions _opts; bool _open { false }; - std::string _inputText; + gui::TextInput _input; Console(const Console &) = delete; Console &operator=(const Console &) = delete; diff --git a/src/game/gui/chargen/name.cpp b/src/game/gui/chargen/name.cpp index 0598937a..97a5799f 100644 --- a/src/game/gui/chargen/name.cpp +++ b/src/game/gui/chargen/name.cpp @@ -41,6 +41,7 @@ NameGui::NameGui(GameVersion version, const GraphicsOptions &opts) : GUI(version void NameGui::load() { GUI::load(); + setControlText("NAME_BOX_EDIT", ""); disableControl("BTN_RANDOM"); glm::vec3 hilightColor(getHilightColor(_version)); diff --git a/src/gui/textinput.cpp b/src/gui/textinput.cpp new file mode 100644 index 00000000..7a2b8027 --- /dev/null +++ b/src/gui/textinput.cpp @@ -0,0 +1,108 @@ +/* + * Copyright © 2020 Vsevolod Kremianskii + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "textinput.h" + +using namespace std; + +namespace reone { + +namespace gui { + +TextInput::TextInput(int mask) : _mask(mask) { +} + +void TextInput::clear() { + _text.clear(); +} + +bool TextInput::handle(const SDL_Event &event) { + switch (event.type) { + case SDL_KEYDOWN: + return handleKeyDown(event.key); + default: + return false; + } +} + +static inline bool isShiftPressed(const SDL_Keysym &key) { + return key.mod & KMOD_SHIFT; +} + +static inline bool isDigitKey(const SDL_Keysym &key) { + return key.sym >= SDLK_0 && key.sym <= SDLK_9; +} + +static inline bool isLetterKey(const SDL_Keysym &key) { + return key.sym >= SDLK_a && key.sym <= SDLK_z; +} + +bool TextInput::handleKeyDown(const SDL_KeyboardEvent &event) { + if (!isKeyAllowed(event.keysym)) return false; + + bool shift = isShiftPressed(event.keysym); + bool digit = isDigitKey(event.keysym); + bool letter = isLetterKey(event.keysym); + bool underscore = event.keysym.sym == SDLK_MINUS && shift; + + if (digit || letter || underscore || + event.keysym.sym == SDLK_SPACE || + event.keysym.sym == SDLK_COMMA || + event.keysym.sym == SDLK_PERIOD) { + + if (underscore) { + _text += SDLK_UNDERSCORE; + } else if (letter && shift) { + _text += toupper(event.keysym.sym); + } else { + _text += event.keysym.sym; + } + + return true; + + } else if (event.keysym.sym == SDLK_BACKSPACE) { + if (!_text.empty()) { + _text.resize(_text.size() - 1); + } + } + + return false; +} + +bool TextInput::isKeyAllowed(const SDL_Keysym &key) const { + if (isDigitKey(key) && !(_mask & kTextInputDigits)) return false; + if (isLetterKey(key) && !(_mask & kTextInputLetters)) return false; + if (key.sym == SDLK_SPACE && !(_mask & kTextInputWhitespace)) return false; + + bool underscore = key.sym == SDLK_MINUS && isShiftPressed(key); + if (underscore || + key.sym == SDLK_COMMA || + key.sym == SDLK_PERIOD) { + + return (_mask & kTextInputPunctuation) != 0; + } + + return true; +} + +const string &TextInput::text() const { + return _text; +} + +} // namespace gui + +} // namespace reone diff --git a/src/gui/textinput.h b/src/gui/textinput.h new file mode 100644 index 00000000..8279227b --- /dev/null +++ b/src/gui/textinput.h @@ -0,0 +1,55 @@ +/* + * Copyright © 2020 Vsevolod Kremianskii + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#include "SDL_events.h" + +namespace reone { + +namespace gui { + +enum TextInputFlags { + kTextInputDigits = 1, + kTextInputLetters = 2, + kTextInputWhitespace = 4, + kTextInputPunctuation = 8, + kTextInputConsole = kTextInputDigits | kTextInputLetters | kTextInputWhitespace | kTextInputPunctuation +}; + +class TextInput { +public: + TextInput(int mask); + + void clear(); + bool handle(const SDL_Event &event); + + const std::string &text() const; + +private: + int _mask { 0 }; + std::string _text; + + bool handleKeyDown(const SDL_KeyboardEvent &event); + bool isKeyAllowed(const SDL_Keysym &key) const; +}; + +} // namespace gui + +} // namespace reone