2
0
Эх сурвалжийг харах

Converted timer event into tick event that is called every frame

Ivan Savenko 2 жил өмнө
parent
commit
a8fe8c0f3b

+ 1 - 1
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);

+ 53 - 39
client/adventureMap/CInGameConsole.cpp

@@ -24,71 +24,85 @@
 #include "../../lib/TextOperations.h"
 #include "../../lib/mapObjects/CArmedInstance.h"
 
-#include <SDL_timer.h>
-
 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<std::list< std::pair< std::string, uint32_t > >::iterator> toDel;
-
 	boost::unique_lock<boost::mutex> 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);
-		}
+		number++;
 	}
+}
 
-	for(auto & elem : toDel)
+void CInGameConsole::tick(uint32_t msPassed)
+{
+	size_t sizeBefore = texts.size();
 	{
-		texts.erase(elem);
+		boost::unique_lock<boost::mutex> lock(texts_mx);
+
+		for(auto & text : texts)
+			text.timeOnScreen += msPassed;
+
+		vstd::erase_if(
+			texts,
+			[&](const auto & value)
+			{
+				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)
+void CInGameConsole::print(const std::string & txt)
 {
-	boost::unique_lock<boost::mutex> lock(texts_mx);
-	int lineLen = conf.go()->ac.outputLineLength;
-
-	if(txt.size() < lineLen)
+	// boost::unique_lock scope
 	{
-		texts.push_back(std::make_pair(txt, SDL_GetTicks()));
-		if(texts.size() > maxDisplayedTexts)
+		boost::unique_lock<boost::mutex> lock(texts_mx);
+		int lineLen = conf.go()->ac.outputLineLength;
+
+		if(txt.size() < lineLen)
 		{
-			texts.pop_front();
+			texts.push_back({txt, 0});
 		}
-	}
-	else
-	{
-		assert(lineLen);
-		for(int g=0; g<txt.size() / lineLen + 1; ++g)
+		else
 		{
-			std::string part = txt.substr(g * lineLen, lineLen);
-			if(part.size() == 0)
-				break;
-
-			texts.push_back(std::make_pair(part, SDL_GetTicks()));
-			if(texts.size() > maxDisplayedTexts)
+			assert(lineLen);
+			for(int g = 0; g < txt.size() / lineLen + 1; ++g)
 			{
-				texts.pop_front();
+				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);
 

+ 26 - 7
client/adventureMap/CInGameConsole.h

@@ -14,20 +14,39 @@
 class CInGameConsole : public CIntObject
 {
 private:
-	std::list< std::pair< std::string, uint32_t > > texts; //list<text to show, time of add>
-	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<TextState> texts;
+
+	/// protects texts
+	boost::mutex texts_mx;
+
+	/// previously entered texts, for up/down arrows to work
+	std::vector<std::string> 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<IStatusBar> 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;

+ 23 - 5
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<Component> & components, std::string message, int timer)
 {
 	auto actualPush = [&](const std::vector<Component> & components, std::string message, int timer, size_t max){

+ 3 - 1
client/adventureMap/CInfoBar.h

@@ -138,6 +138,7 @@ private:
 
 	std::shared_ptr<CVisibleInfo> visibleInfo;
 	EState state;
+	uint32_t timerCounter;
 	bool shouldPopAll = false;
 
 	std::queue<std::pair<VisibleComponentInfo::Cache, int>> 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);

+ 1 - 1
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);
 	}
 }
 

+ 0 - 19
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)

+ 1 - 8
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<MouseButton, bool> 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){}