GameUI refactor (part 2/X): Move Game::guitext to GameUI + enhancements on StaticText
authorLoic Blot <loic.blot@unix-experience.fr>
Wed, 3 Jan 2018 16:28:57 +0000 (17:28 +0100)
committerLoïc Blot <nerzhul@users.noreply.github.com>
Fri, 5 Jan 2018 19:59:30 +0000 (20:59 +0100)
Other enhancements:
* C++ friendlyness for addStaticText() -> move to static StaticText::add()

src/client/gameui.cpp
src/client/gameui.h
src/game.cpp
src/game.h
src/gui/guiEngine.cpp
src/gui/guiFormSpecMenu.cpp
src/irrlicht_changes/static_text.h
src/unittest/test_gameui.cpp

index 7307daf75b9513f3ae2831667af49dc947ddfa89..53d9f4a9cf5f3c15df138e2d7f1a0649c0e26869 100644 (file)
@@ -19,7 +19,55 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "gameui.h"
-#include "settings.h"
+#include <irrlicht_changes/static_text.h>
+#include "gui/mainmenumanager.h"
+#include "client.h"
+#include "fontengine.h"
+#include "clientmap.h"
+#include "version.h"
+#include "renderingengine.h"
+
+void GameUI::init()
+{
+       // First line of debug text
+       m_guitext = gui::StaticText::add(guienv, utf8_to_wide(PROJECT_NAME_C).c_str(),
+               core::rect<s32>(0, 0, 0, 0), false, false, guiroot);
+}
+
+void GameUI::update(const RunStats &stats, Client *client,
+       const MapDrawControl *draw_control)
+{
+       if (m_flags.show_debug) {
+               static float drawtime_avg = 0;
+               drawtime_avg = drawtime_avg * 0.95 + stats.drawtime * 0.05;
+               u16 fps = 1.0 / stats.dtime_jitter.avg;
+
+               std::ostringstream os(std::ios_base::binary);
+               os << std::fixed
+                       << PROJECT_NAME_C " " << g_version_hash
+                       << ", FPS: " << fps
+                       << std::setprecision(0)
+                       << ", drawtime: " << drawtime_avg << "ms"
+                       << std::setprecision(1)
+                       << ", dtime jitter: "
+                       << (stats.dtime_jitter.max_fraction * 100.0) << "%"
+                       << std::setprecision(1)
+                       << ", view range: "
+                       << (draw_control->range_all ? "All" : itos(draw_control->wanted_range))
+                       << std::setprecision(3)
+                       << ", RTT: " << client->getRTT() << "s";
+               setStaticText(m_guitext, utf8_to_wide(os.str()).c_str());
+               m_guitext->setVisible(true);
+       } else {
+               m_guitext->setVisible(false);
+       }
+
+       if (m_guitext->isVisible()) {
+               v2u32 screensize = RenderingEngine::get_instance()->getWindowSize();
+               m_guitext->setRelativePosition(core::rect<s32>(5, 5, screensize.X,
+                       5 + g_fontengine->getTextHeight()));
+       }
+}
 
 void GameUI::initFlags()
 {
@@ -29,7 +77,7 @@ void GameUI::initFlags()
        m_flags.show_debug = g_settings->getBool("show_debug");
 }
 
-void GameUI::showMinimap(const bool show)
+void GameUI::showMinimap(bool show)
 {
        m_flags.show_minimap = show;
 }
index bd9c0f626d64d5f7a9ea123d16cad687820cea2a..593fd4ff3573eb1612d65af233f3c91840cc442f 100644 (file)
@@ -20,9 +20,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #pragma once
 
-#include "IGUIEnvironment.h"
+#include <IGUIEnvironment.h>
+#include "game.h"
 
 using namespace irr;
+class Client;
+struct MapDrawControl;
 
 class GameUI
 {
@@ -30,6 +33,9 @@ class GameUI
        friend class Game;
 
 public:
+       GameUI() = default;
+       ~GameUI() = default;
+
        // Flags that can, or may, change during main game loop
        struct Flags
        {
@@ -42,16 +48,19 @@ public:
                bool disable_camera_update;
        };
 
+       void init();
+       void update(const RunStats &stats, Client *client, const MapDrawControl *draw_control);
+
        void initFlags();
        const Flags &getFlags() const { return m_flags; }
 
-       void showMinimap(const bool show);
+       void showMinimap(bool show);
 
 private:
        Flags m_flags;
 
+       gui::IGUIStaticText *m_guitext;          // First line of debug text
        // @TODO future move
-       //      gui::IGUIStaticText *m_guitext;          // First line of debug text
        //      gui::IGUIStaticText *m_guitext2;         // Second line of debug text
        //      gui::IGUIStaticText *m_guitext_info;     // At the middle of the screen
        //      gui::IGUIStaticText *m_guitext_status;
index f1ee9f8e29efd43f42dcc38788aaba64ed423cbc..d31daf32b88edb303b24a81d44173ab5aa5c8bfd 100644 (file)
@@ -1174,16 +1174,6 @@ struct GameRunData {
        float time_of_day_smooth;
 };
 
-struct Jitter {
-       f32 max, min, avg, counter, max_sample, min_sample, max_fraction;
-};
-
-struct RunStats {
-       u32 drawtime;
-
-       Jitter dtime_jitter, busy_time_jitter;
-};
-
 class Game;
 
 struct ClientEventHandler
@@ -1452,7 +1442,6 @@ private:
 
        /* GUI stuff
         */
-       gui::IGUIStaticText *guitext;          // First line of debug text
        gui::IGUIStaticText *guitext2;         // Second line of debug text
        gui::IGUIStaticText *guitext_info;     // At the middle of the screen
        gui::IGUIStaticText *guitext_status;
@@ -1998,34 +1987,30 @@ bool Game::createClient(const std::string &playername,
 
 bool Game::initGui()
 {
-       // First line of debug text
-       guitext = addStaticText(guienv,
-                       utf8_to_wide(PROJECT_NAME_C).c_str(),
-                       core::rect<s32>(0, 0, 0, 0),
-                       false, false, guiroot);
+       m_game_ui->init();
 
        // Second line of debug text
-       guitext2 = addStaticText(guienv,
+       guitext2 = gui::StaticText::add(guienv,
                        L"",
                        core::rect<s32>(0, 0, 0, 0),
                        false, false, guiroot);
 
        // At the middle of the screen
        // Object infos are shown in this
-       guitext_info = addStaticText(guienv,
+       guitext_info = gui::StaticText::add(guienv,
                        L"",
                        core::rect<s32>(0, 0, 400, g_fontengine->getTextHeight() * 5 + 5) + v2s32(100, 200),
                        false, true, guiroot);
 
        // Status text (displays info when showing and hiding GUI stuff, etc.)
-       guitext_status = addStaticText(guienv,
+       guitext_status = gui::StaticText::add(guienv,
                        L"<Status>",
                        core::rect<s32>(0, 0, 0, 0),
                        false, false, guiroot);
        guitext_status->setVisible(false);
 
        // Chat text
-       guitext_chat = addStaticText(
+       guitext_chat = gui::StaticText::add(
                        guienv,
                        L"",
                        core::rect<s32>(0, 0, 0, 0),
@@ -2048,7 +2033,7 @@ bool Game::initGui()
        }
 
        // Profiler text (size is updated when text is updated)
-       guitext_profiler = addStaticText(guienv,
+       guitext_profiler = gui::StaticText::add(guienv,
                        L"<Profiler>",
                        core::rect<s32>(0, 0, 0, 0),
                        false, false, guiroot);
@@ -4410,38 +4395,7 @@ void Game::updateGui(const RunStats &stats, f32 dtime, const CameraOrientation &
        LocalPlayer *player = client->getEnv().getLocalPlayer();
        v3f player_position = player->getPosition();
 
-       if (m_game_ui->m_flags.show_debug) {
-               static float drawtime_avg = 0;
-               drawtime_avg = drawtime_avg * 0.95 + stats.drawtime * 0.05;
-               u16 fps = 1.0 / stats.dtime_jitter.avg;
-
-               std::ostringstream os(std::ios_base::binary);
-               os << std::fixed
-                       << PROJECT_NAME_C " " << g_version_hash
-                       << ", FPS: " << fps
-                       << std::setprecision(0)
-                       << ", drawtime: " << drawtime_avg << "ms"
-                       << std::setprecision(1)
-                       << ", dtime jitter: "
-                       << (stats.dtime_jitter.max_fraction * 100.0) << "%"
-                       << std::setprecision(1)
-                       << ", view range: "
-                       << (draw_control->range_all ? "All" : itos(draw_control->wanted_range))
-                       << std::setprecision(3)
-                       << ", RTT: " << client->getRTT() << "s";
-               setStaticText(guitext, utf8_to_wide(os.str()).c_str());
-               guitext->setVisible(true);
-       } else {
-               guitext->setVisible(false);
-       }
-
-       if (guitext->isVisible()) {
-               core::rect<s32> rect(
-                               5,              5,
-                               screensize.X,   5 + g_fontengine->getTextHeight()
-               );
-               guitext->setRelativePosition(rect);
-       }
+       m_game_ui->update(stats, client, draw_control);
 
        if (m_game_ui->m_flags.show_debug) {
                std::ostringstream os(std::ios_base::binary);
index 2232780066398c064116639241388253d967e9ab..6101c4f7a1f2df87927efa62db0101d1ecaf5001 100644 (file)
@@ -26,6 +26,16 @@ class InputHandler;
 class ChatBackend;  /* to avoid having to include chat.h */
 struct SubgameSpec;
 
+struct Jitter {
+       f32 max, min, avg, counter, max_sample, min_sample, max_fraction;
+};
+
+struct RunStats {
+       u32 drawtime;
+
+       Jitter dtime_jitter, busy_time_jitter;
+};
+
 void the_game(bool *kill,
                bool random_input,
                InputHandler *input,
index e9b4e54c19c8e1d8a86806f685097de6e7a91de7..3f9bcd888668c6de5abf1f6647ae0dc3eaf13b88 100644 (file)
@@ -149,9 +149,8 @@ GUIEngine::GUIEngine(JoystickController *joystick,
                g_fontengine->getTextHeight());
        rect += v2s32(4, 0);
 
-       m_irr_toplefttext =
-               addStaticText(RenderingEngine::get_gui_env(), m_toplefttext,
-                       rect, false, true, 0, -1);
+       m_irr_toplefttext = gui::StaticText::add(RenderingEngine::get_gui_env(),
+                       m_toplefttext, rect, false, true, 0, -1);
 
        //create formspecsource
        m_formspecgui = new FormspecFormSource("");
@@ -560,9 +559,8 @@ void GUIEngine::updateTopLeftTextSize()
        rect += v2s32(4, 0);
 
        m_irr_toplefttext->remove();
-       m_irr_toplefttext =
-               addStaticText(RenderingEngine::get_gui_env(), m_toplefttext,
-                       rect, false, true, 0, -1);
+       m_irr_toplefttext = gui::StaticText::add(RenderingEngine::get_gui_env(),
+                       m_toplefttext, rect, false, true, 0, -1);
 }
 
 /******************************************************************************/
index c83e6aa4965050f5572333ae56af9c2a9bed38e8..5926cca3a3364eae22fdcff4be2b16cb247af5ae 100644 (file)
@@ -950,12 +950,12 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element
                        Environment->setFocus(e);
                }
 
-               if (label.length() >= 1)
-               {
+               if (label.length() >= 1) {
                        int font_height = g_fontengine->getTextHeight();
                        rect.UpperLeftCorner.Y -= font_height;
                        rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height;
-                       addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, 0);
+                       gui::StaticText::add(Environment, spec.flabel.c_str(), rect, false, true,
+                               this, 0);
                }
 
                e->setPasswordBox(true,L'*');
@@ -1017,7 +1017,8 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,
 
        if (name.empty()) {
                // spec field id to 0, this stops submit searching for a value that isn't there
-               addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, spec.fid);
+               gui::StaticText::add(Environment, spec.flabel.c_str(), rect, false, true, this,
+                       spec.fid);
        } else {
                spec.send = true;
                gui::IGUIElement *e;
@@ -1050,7 +1051,8 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,
                        int font_height = g_fontengine->getTextHeight();
                        rect.UpperLeftCorner.Y -= font_height;
                        rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height;
-                       addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, 0);
+                       gui::StaticText::add(Environment, spec.flabel.c_str(), rect, false, true,
+                               this, 0);
                }
        }
 
@@ -1162,7 +1164,8 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, std::vector<std::string>&
                int font_height = g_fontengine->getTextHeight();
                rect.UpperLeftCorner.Y -= font_height;
                rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height;
-               addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, 0);
+               gui::StaticText::add(Environment, spec.flabel.c_str(), rect, false, true,
+                       this, 0);
        }
 
        if (parts.size() >= 6) {
@@ -1237,11 +1240,9 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element)
                                L"",
                                258+m_fields.size()
                        );
-                       gui::IGUIStaticText *e =
-                               addStaticText(Environment, spec.flabel.c_str(),
-                                       rect, false, false, this, spec.fid);
-                       e->setTextAlignment(gui::EGUIA_UPPERLEFT,
-                                               gui::EGUIA_CENTER);
+                       gui::IGUIStaticText *e = gui::StaticText::add(Environment,
+                               spec.flabel.c_str(), rect, false, false, this, spec.fid);
+                       e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER);
                        m_fields.push_back(spec);
                }
 
@@ -1291,8 +1292,8 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data, const std::string &elemen
                        L"",
                        258+m_fields.size()
                );
-               gui::IGUIStaticText *t =
-                               addStaticText(Environment, spec.flabel.c_str(), rect, false, false, this, spec.fid);
+               gui::IGUIStaticText *t = gui::StaticText::add(Environment, spec.flabel.c_str(),
+                       rect, false, false, this, spec.fid);
                t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
                m_fields.push_back(spec);
                return;
@@ -2024,7 +2025,8 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
        {
                assert(!m_tooltip_element);
                // Note: parent != this so that the tooltip isn't clipped by the menu rectangle
-               m_tooltip_element = addStaticText(Environment, L"",core::rect<s32>(0,0,110,18));
+               m_tooltip_element = gui::StaticText::add(Environment, L"",
+                       core::rect<s32>(0,0,110,18));
                m_tooltip_element->enableOverrideColor(true);
                m_tooltip_element->setBackgroundColor(m_default_tooltip_bgcolor);
                m_tooltip_element->setDrawBackground(true);
@@ -3669,14 +3671,14 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
                        m_invmgr->inventoryAction(a);
                } else if (craft_amount > 0) {
                        assert(s.isValid());
-                       
+
                        // if there are no items selected or the selected item
                        // belongs to craftresult list, proceed with crafting
                        if (m_selected_item == NULL ||
                                        !m_selected_item->isValid() || m_selected_item->listname == "craftresult") {
-                               
+
                                m_selected_content_guess = ItemStack(); // Clear
-                               
+
                                assert(inv_s);
 
                                // Send IACTION_CRAFT
index de7b47e766671532a2cf0a12c12eee725c75b9dd..6bb85bd6b1507e343424e18c04e1c7f14b7014a2 100644 (file)
@@ -42,6 +42,59 @@ namespace gui
                //! destructor
                virtual ~StaticText();
 
+               static irr::gui::IGUIStaticText *add(
+                       irr::gui::IGUIEnvironment *guienv,
+                       const EnrichedString &text,
+                       const core::rect< s32 > &rectangle,
+                       bool border = false,
+                       bool wordWrap = true,
+                       irr::gui::IGUIElement *parent = NULL,
+                       s32 id = -1,
+                       bool fillBackground = false)
+               {
+                       if (parent == NULL) {
+                               // parent is NULL, so we must find one, or we need not to drop
+                               // result, but then there will be a memory leak.
+                               //
+                               // What Irrlicht does is to use guienv as a parent, but the problem
+                               // is that guienv is here only an IGUIEnvironment, while it is a
+                               // CGUIEnvironment in Irrlicht, which inherits from both IGUIElement
+                               // and IGUIEnvironment.
+                               //
+                               // A solution would be to dynamic_cast guienv to a
+                               // IGUIElement*, but Irrlicht is shipped without rtti support
+                               // in some distributions, causing the dymanic_cast to segfault.
+                               //
+                               // Thus, to find the parent, we create a dummy StaticText and ask
+                               // for its parent, and then remove it.
+                               irr::gui::IGUIStaticText *dummy_text =
+                                       guienv->addStaticText(L"", rectangle, border, wordWrap,
+                                               parent, id, fillBackground);
+                               parent = dummy_text->getParent();
+                               dummy_text->remove();
+                       }
+                       irr::gui::IGUIStaticText *result = new irr::gui::StaticText(
+                               text, border, guienv, parent,
+                               id, rectangle, fillBackground);
+
+                       result->setWordWrap(wordWrap);
+                       result->drop();
+                       return result;
+               }
+
+               static irr::gui::IGUIStaticText *add(
+                       irr::gui::IGUIEnvironment *guienv,
+                       const wchar_t *text,
+                       const core::rect< s32 > &rectangle,
+                       bool border = false,
+                       bool wordWrap = true,
+                       irr::gui::IGUIElement *parent = NULL,
+                       s32 id = -1,
+                       bool fillBackground = false)
+               {
+                       return add(guienv, EnrichedString(text), rectangle, border, wordWrap, parent, id, fillBackground);
+               }
+
                //! draws the element and its children
                virtual void draw();
 
@@ -171,46 +224,6 @@ namespace gui
 
 } // end namespace irr
 
-inline irr::gui::IGUIStaticText *addStaticText(
-               irr::gui::IGUIEnvironment *guienv,
-               const EnrichedString &text,
-               const core::rect< s32 > &rectangle,
-               bool border = false,
-               bool wordWrap = true,
-               irr::gui::IGUIElement *parent = NULL,
-               s32 id = -1,
-               bool fillBackground = false)
-{
-       if (parent == NULL) {
-               // parent is NULL, so we must find one, or we need not to drop
-               // result, but then there will be a memory leak.
-               //
-               // What Irrlicht does is to use guienv as a parent, but the problem
-               // is that guienv is here only an IGUIEnvironment, while it is a
-               // CGUIEnvironment in Irrlicht, which inherits from both IGUIElement
-               // and IGUIEnvironment.
-               //
-               // A solution would be to dynamic_cast guienv to a
-               // IGUIElement*, but Irrlicht is shipped without rtti support
-               // in some distributions, causing the dymanic_cast to segfault.
-               //
-               // Thus, to find the parent, we create a dummy StaticText and ask
-               // for its parent, and then remove it.
-               irr::gui::IGUIStaticText *dummy_text =
-                       guienv->addStaticText(L"", rectangle, border, wordWrap,
-                       parent, id, fillBackground);
-               parent = dummy_text->getParent();
-               dummy_text->remove();
-       }
-       irr::gui::IGUIStaticText *result = new irr::gui::StaticText(
-               text, border, guienv, parent,
-               id, rectangle, fillBackground);
-
-       result->setWordWrap(wordWrap);
-       result->drop();
-       return result;
-}
-
 inline void setStaticText(irr::gui::IGUIStaticText *static_text, const EnrichedString &text)
 {
        // dynamic_cast not possible due to some distributions shipped
@@ -245,18 +258,6 @@ inline void setStaticText(irr::gui::IGUIStaticText *static_text, const EnrichedS
 
 #endif
 
-inline irr::gui::IGUIStaticText *addStaticText(
-               irr::gui::IGUIEnvironment *guienv,
-               const wchar_t *text,
-               const core::rect< s32 > &rectangle,
-               bool border = false,
-               bool wordWrap = true,
-               irr::gui::IGUIElement *parent = NULL,
-               s32 id = -1,
-               bool fillBackground = false) {
-       return addStaticText(guienv, EnrichedString(text), rectangle, border, wordWrap, parent, id, fillBackground);
-}
-
 inline void setStaticText(irr::gui::IGUIStaticText *static_text, const wchar_t *text)
 {
        setStaticText(static_text, EnrichedString(text));
index 56f44ed87528d6f727f72df93595f19e0df25175..3c6f2a5a4c357cb05151343d8fe4b8a79c64bd5c 100644 (file)
@@ -47,11 +47,14 @@ void TestGameUI::testInit()
        gui.initFlags();
        UASSERT(gui.getFlags().show_chat)
        UASSERT(gui.getFlags().show_hud)
+
+       // @TODO verify if we can create non UI nulldevice to test this function
+       gui.init();
 }
 
 void TestGameUI::testFlagSetters()
 {
-       GameUI gui;
+       GameUI gui{};
        gui.showMinimap(true);
        UASSERT(gui.getFlags().show_minimap);