From a8fe8c0f3bf6f5be9e3578767e394aad17b7c172 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Wed, 22 Mar 2023 23:09:43 +0200 Subject: [PATCH] Converted timer event into tick event that is called every frame --- client/ClientCommandManager.h | 2 +- client/adventureMap/CInGameConsole.cpp | 102 ++++++++++++++----------- client/adventureMap/CInGameConsole.h | 33 ++++++-- client/adventureMap/CInfoBar.cpp | 28 +++++-- client/adventureMap/CInfoBar.h | 4 +- client/gui/CGuiHandler.cpp | 2 +- client/gui/CIntObject.cpp | 19 ----- client/gui/CIntObject.h | 9 +-- 8 files changed, 113 insertions(+), 86 deletions(-) diff --git a/client/ClientCommandManager.h b/client/ClientCommandManager.h index 61b2175fb..14ce180af 100644 --- a/client/ClientCommandManager.h +++ b/client/ClientCommandManager.h @@ -17,7 +17,7 @@ class CIntObject; class ClientCommandManager //take mantis #2292 issue about account if thinking about handling cheats from command-line { - bool currentCallFromIngameConsole; + bool currentCallFromIngameConsole = false; void giveTurn(const PlayerColor &color); void printInfoAboutInterfaceObject(const CIntObject *obj, int level); diff --git a/client/adventureMap/CInGameConsole.cpp b/client/adventureMap/CInGameConsole.cpp index e62ec3e39..ed4588ea4 100644 --- a/client/adventureMap/CInGameConsole.cpp +++ b/client/adventureMap/CInGameConsole.cpp @@ -24,71 +24,85 @@ #include "../../lib/TextOperations.h" #include "../../lib/mapObjects/CArmedInstance.h" -#include - CInGameConsole::CInGameConsole() - : CIntObject(KEYBOARD | TEXTINPUT), - prevEntDisp(-1), - defaultTimeout(10000), - maxDisplayedTexts(10) + : CIntObject(KEYBOARD | TIME | TEXTINPUT) + , prevEntDisp(-1) { + type |= REDRAW_PARENT; +} + +void CInGameConsole::showAll(SDL_Surface * to) +{ + show(to); } void CInGameConsole::show(SDL_Surface * to) { int number = 0; - std::vector >::iterator> toDel; - boost::unique_lock lock(texts_mx); - for(auto it = texts.begin(); it != texts.end(); ++it, ++number) + for(auto & text : texts) { Point leftBottomCorner(0, pos.h); + Point textPosition(leftBottomCorner.x + 50, leftBottomCorner.y - texts.size() * 20 - 80 + number * 20); - graphics->fonts[FONT_MEDIUM]->renderTextLeft(to, it->first, Colors::GREEN, - Point(leftBottomCorner.x + 50, leftBottomCorner.y - (int)texts.size() * 20 - 80 + number*20)); + graphics->fonts[FONT_MEDIUM]->renderTextLeft(to, text.text, Colors::GREEN, textPosition ); - if((int)(SDL_GetTicks() - it->second) > defaultTimeout) - { - toDel.push_back(it); - } - } - - for(auto & elem : toDel) - { - texts.erase(elem); + number++; } } -void CInGameConsole::print(const std::string &txt) +void CInGameConsole::tick(uint32_t msPassed) { - boost::unique_lock lock(texts_mx); - int lineLen = conf.go()->ac.outputLineLength; - - if(txt.size() < lineLen) + size_t sizeBefore = texts.size(); { - texts.push_back(std::make_pair(txt, SDL_GetTicks())); - if(texts.size() > maxDisplayedTexts) - { - texts.pop_front(); - } - } - else - { - assert(lineLen); - for(int g=0; g lock(texts_mx); - texts.push_back(std::make_pair(part, SDL_GetTicks())); - if(texts.size() > maxDisplayedTexts) + for(auto & text : texts) + text.timeOnScreen += msPassed; + + vstd::erase_if( + texts, + [&](const auto & value) { - texts.pop_front(); + return value.timeOnScreen > defaultTimeout; + } + ); + } + + if(sizeBefore != texts.size()) + GH.totalRedraw(); // FIXME: ingame console has no parent widget set +} + +void CInGameConsole::print(const std::string & txt) +{ + // boost::unique_lock scope + { + boost::unique_lock lock(texts_mx); + int lineLen = conf.go()->ac.outputLineLength; + + if(txt.size() < lineLen) + { + texts.push_back({txt, 0}); + } + else + { + assert(lineLen); + for(int g = 0; g < txt.size() / lineLen + 1; ++g) + { + std::string part = txt.substr(g * lineLen, lineLen); + if(part.empty()) + break; + + texts.push_back({part, 0}); } } + + while(texts.size() > maxDisplayedTexts) + texts.erase(texts.begin()); } + + GH.totalRedraw(); // FIXME: ingame console has no parent widget set } void CInGameConsole::keyPressed (const SDL_Keycode & key) @@ -136,7 +150,7 @@ void CInGameConsole::keyPressed (const SDL_Keycode & key) } case SDLK_UP: //up arrow { - if(previouslyEntered.size() == 0) + if(previouslyEntered.empty()) break; if(prevEntDisp == -1) @@ -178,7 +192,7 @@ void CInGameConsole::keyPressed (const SDL_Keycode & key) void CInGameConsole::textInputed(const std::string & inputtedText) { - if(!captureAllKeys || enteredText.size() == 0) + if(!captureAllKeys || enteredText.empty()) return; enteredText.resize(enteredText.size()-1); diff --git a/client/adventureMap/CInGameConsole.h b/client/adventureMap/CInGameConsole.h index 93d5a204d..0d5266967 100644 --- a/client/adventureMap/CInGameConsole.h +++ b/client/adventureMap/CInGameConsole.h @@ -14,20 +14,39 @@ class CInGameConsole : public CIntObject { private: - std::list< std::pair< std::string, uint32_t > > texts; //list - boost::mutex texts_mx; // protects texts - std::vector< std::string > previouslyEntered; //previously entered texts, for up/down arrows to work - int prevEntDisp; //displayed entry from previouslyEntered - if none it's -1 - int defaultTimeout; //timeout for new texts (in ms) - int maxDisplayedTexts; //hiw many texts can be displayed simultaneously + struct TextState + { + std::string text; + uint32_t timeOnScreen; + }; + + /// Currently visible texts in the overlay + std::vector texts; + + /// protects texts + boost::mutex texts_mx; + + /// previously entered texts, for up/down arrows to work + std::vector previouslyEntered; + + /// displayed entry from previouslyEntered - if none it's -1 + int prevEntDisp; + + /// timeout for new texts (in ms) + static constexpr int defaultTimeout = 10000; + + /// how many texts can be displayed simultaneously + static constexpr int maxDisplayedTexts = 10; std::weak_ptr currentStatusBar; std::string enteredText; public: - void print(const std::string &txt); + void print(const std::string & txt); + void tick(uint32_t msPassed) override; void show(SDL_Surface * to) override; + void showAll(SDL_Surface * to) override; void keyPressed(const SDL_Keycode & key) override; void textInputed(const std::string & enteredText) override; void textEdited(const std::string & enteredText) override; diff --git a/client/adventureMap/CInfoBar.cpp b/client/adventureMap/CInfoBar.cpp index a3999c5e5..d1c1b1b6e 100644 --- a/client/adventureMap/CInfoBar.cpp +++ b/client/adventureMap/CInfoBar.cpp @@ -254,11 +254,21 @@ void CInfoBar::showSelection() showGameStatus();//FIXME: may be incorrect but shouldn't happen in general } -void CInfoBar::tick() +void CInfoBar::tick(uint32_t msPassed) { - removeUsedEvents(TIME); - if(GH.topInt() == adventureInt) - popComponents(true); + assert(timerCounter > 0); + + if (msPassed >= timerCounter) + { + timerCounter = 0; + removeUsedEvents(TIME); + if(GH.topInt() == adventureInt) + popComponents(true); + } + else + { + timerCounter -= msPassed; + } } void CInfoBar::clickLeft(tribool down, bool previousState) @@ -290,6 +300,7 @@ void CInfoBar::hover(bool on) CInfoBar::CInfoBar(const Rect & position) : CIntObject(LCLICK | RCLICK | HOVER, position.topLeft()), + timerCounter(0), state(EMPTY) { OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); @@ -302,6 +313,14 @@ CInfoBar::CInfoBar(const Point & position): CInfoBar(Rect(position.x, position.y { } + +void CInfoBar::setTimer(uint32_t msToTrigger) +{ + if (!(active & TIME)) + addUsedEvents(TIME); + timerCounter = msToTrigger; +} + void CInfoBar::showDate() { OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); @@ -312,7 +331,6 @@ void CInfoBar::showDate() redraw(); } - void CInfoBar::pushComponents(const std::vector & components, std::string message, int timer) { auto actualPush = [&](const std::vector & components, std::string message, int timer, size_t max){ diff --git a/client/adventureMap/CInfoBar.h b/client/adventureMap/CInfoBar.h index df7d1b2ef..3a507e879 100644 --- a/client/adventureMap/CInfoBar.h +++ b/client/adventureMap/CInfoBar.h @@ -138,6 +138,7 @@ private: std::shared_ptr visibleInfo; EState state; + uint32_t timerCounter; bool shouldPopAll = false; std::queue> componentsQueue; @@ -151,13 +152,14 @@ private: //removes all information about current state, deactivates timer (if any) void reset(); - void tick() override; + void tick(uint32_t msPassed) override; void clickLeft(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override; void hover(bool on) override; void playNewDaySound(); + void setTimer(uint32_t msToTrigger); public: CInfoBar(const Rect & pos); CInfoBar(const Point & pos); diff --git a/client/gui/CGuiHandler.cpp b/client/gui/CGuiHandler.cpp index 1ebc32c11..3135104fe 100644 --- a/client/gui/CGuiHandler.cpp +++ b/client/gui/CGuiHandler.cpp @@ -192,7 +192,7 @@ void CGuiHandler::updateTime() for (auto & elem : hlp) { if(!vstd::contains(timeinterested,elem)) continue; - (elem)->onTimer(ms); + (elem)->tick(ms); } } diff --git a/client/gui/CIntObject.cpp b/client/gui/CIntObject.cpp index 8e5721e44..79ed430cd 100644 --- a/client/gui/CIntObject.cpp +++ b/client/gui/CIntObject.cpp @@ -29,7 +29,6 @@ CIntObject::CIntObject(int used_, Point pos_): active(active_m) { hovered = captureAllKeys = strongInterest = false; - toNextTick = timerDelay = 0; used = used_; recActions = defActions = GH.defActionsDef; @@ -60,24 +59,6 @@ CIntObject::~CIntObject() parent_m->removeChild(this); } -void CIntObject::setTimer(int msToTrigger) -{ - if (!(active & TIME)) - activate(TIME); - toNextTick = timerDelay = msToTrigger; - used |= TIME; -} - -void CIntObject::onTimer(int timePassed) -{ - toNextTick -= timePassed; - if (toNextTick < 0) - { - toNextTick += timerDelay; - tick(); - } -} - void CIntObject::show(SDL_Surface * to) { if(defActions & UPDATE) diff --git a/client/gui/CIntObject.h b/client/gui/CIntObject.h index 80017d32b..ff26c96d4 100644 --- a/client/gui/CIntObject.h +++ b/client/gui/CIntObject.h @@ -65,14 +65,8 @@ class CIntObject : public IShowActivatable //interface object { ui16 used;//change via addUsed() or delUsed - //time handling - int toNextTick; - int timerDelay; - std::map currentMouseState; - void onTimer(int timePassed); - //non-const versions of fields to allow changing them in CIntObject CIntObject *parent_m; //parent object ui16 active_m; @@ -129,8 +123,7 @@ public: virtual void mouseMoved (const Point & cursorPosition){} //time handling - void setTimer(int msToTrigger);//set timer delay and activate timer if needed. - virtual void tick(){} + virtual void tick(uint32_t msPassed){} //mouse wheel virtual void wheelScrolled(bool down, bool in){}