瀏覽代碼

vcmi: allows to more than 8 components in infobar

Konstantin 2 年之前
父節點
當前提交
a6cb7fd192
共有 4 個文件被更改,包括 68 次插入26 次删除
  1. 5 6
      client/CPlayerInterface.cpp
  2. 2 0
      client/adventureMap/CAdvMapInt.cpp
  3. 51 18
      client/adventureMap/CInfoBar.cpp
  4. 10 2
      client/adventureMap/CInfoBar.h

+ 5 - 6
client/CPlayerInterface.cpp

@@ -1040,12 +1040,11 @@ void CPlayerInterface::showInfoDialog(EInfoWindowMode type, const std::string &t
 
 	if(autoTryHover || type == EInfoWindowMode::INFO)
 	{
-		if(adventureInt->infoBar->tryShowComponents(components, text, timer))
-		{
-			if (makingTurn && GH.listInt.size() && LOCPLINT == this)
-				CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
-			return;
-		}
+		adventureInt->infoBar->pushComponents(components, text, timer);
+
+		if (makingTurn && GH.listInt.size() && LOCPLINT == this)
+			CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
+		return;
 	}
 
 	if (settings["session"]["autoSkip"].Bool() && !GH.isKeyboardShiftDown())

+ 2 - 0
client/adventureMap/CAdvMapInt.cpp

@@ -869,6 +869,8 @@ boost::optional<Point> CAdvMapInt::keyToMoveDirection(const SDL_Keycode & key)
 void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
 {
 	assert(sel);
+	if(selection != sel)
+		infoBar->popAll();
 	selection = sel;
 	mapAudio->onSelectionChanged(sel);
 	if(centerView)

+ 51 - 18
client/adventureMap/CInfoBar.cpp

@@ -178,7 +178,10 @@ CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const std::vector<Component
 	{
 		auto size = CComponent::large;
 		if(compsToDisplay.size() > 2)
+		{
 			size = CComponent::small;
+			font = FONT_TINY;
+		}
 		if(!message.empty())
 		{
 			textRect = Rect(CInfoBar::offset,
@@ -192,13 +195,11 @@ CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const std::vector<Component
 			if(compsToDisplay.size() > 4)
 				size = CComponent::tiny;
 		}
-		else if(compsToDisplay.size() > 4)
-			size = CComponent::small;
 
 		std::vector<std::shared_ptr<CComponent>> vect;
 
 		for(const auto & c : compsToDisplay)
-			vect.emplace_back(std::make_shared<CComponent>(c, size));
+			vect.emplace_back(std::make_shared<CComponent>(c, size, font));
 
 		comps = std::make_shared<CComponentBox>(vect, imageRect, 4, 4, 1);
 	}
@@ -263,7 +264,7 @@ void CInfoBar::tick()
 {
 	removeUsedEvents(TIME);
 	if(GH.topInt() == adventureInt)
-		showSelection();
+		popComponents();
 }
 
 void CInfoBar::clickLeft(tribool down, bool previousState)
@@ -275,7 +276,7 @@ void CInfoBar::clickLeft(tribool down, bool previousState)
 		else if(state == GAME)
 			showDate();
 		else
-			showSelection();
+			popComponents();
 	}
 }
 
@@ -317,7 +318,24 @@ void CInfoBar::showDate()
 	redraw();
 }
 
-bool CInfoBar::tryShowComponents(const std::vector<Component> & components, std::string message, int timer)
+void CInfoBar::pushComponents(const std::vector<Component> & components, std::string message, int timer)
+{
+	if(components.empty())
+		prepareComponents(components, message, timer);
+	else
+	{
+		std::vector<Component> vect = components; //I do not know currently how to avoid copy here
+		while(!vect.empty())
+		{
+			std::vector<Component> sender =  {vect.begin(), vect.begin() + std::min(vect.size(), 8ul)};
+			prepareComponents(sender, message, timer);
+			vect.erase(vect.begin(), vect.begin() + std::min(vect.size(), 8ul));
+		}
+	}
+	popComponents();
+}
+
+void CInfoBar::prepareComponents(const std::vector<Component> & components, std::string message, int timer)
 {
 	auto imageH = getEstimatedComponentHeight(components.size()) + (components.empty() ? 0 : 2 * CInfoBar::offset);
 	auto textH = CMessage::guessHeight(message,CInfoBar::data_width - 2 * CInfoBar::offset, FONT_SMALL);
@@ -327,27 +345,42 @@ bool CInfoBar::tryShowComponents(const std::vector<Component> & components, std:
 
 	// Order matters - priority form should be chosen first
 	if(imageH + textH < CInfoBar::data_height)
-		showComponents(components, message, textH, false, timer);
+		pushComponents(components, message, textH, false, timer);
 	else if(!imageH && tinyH < CInfoBar::data_height)
-		showComponents(components, message, tinyH, true, timer);
+		pushComponents(components, message, tinyH, true, timer);
 	else if(imageH + headerH < CInfoBar::data_height)
-		showComponents(components, header, headerH, false, timer);
-	else if(imageH < CInfoBar::data_height)
-		showComponents(components, "", 0, false, timer);
+		pushComponents(components, header, headerH, false, timer);
 	else
-		return false; //We cannot fit message to infobar, fallback to window
+		pushComponents(components, "", 0, false, timer);
 
-	return true;
+	return;
 }
 
-void CInfoBar::showComponents(const std::vector<Component> & comps, std::string message, int textH, bool tiny, int timer)
+void CInfoBar::popAll()
+{
+	componentsQueue = {};
+}
+
+void CInfoBar::popComponents()
 {
 	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
-	state = COMPONENT;
-	visibleInfo = std::make_shared<VisibleComponentInfo>(comps, message, textH, tiny);
+	if(!componentsQueue.empty())
+	{
+		state = COMPONENT;
+		const auto & extracted = componentsQueue.front();
+		visibleInfo = extracted.first;
+		setTimer(extracted.second);
+		componentsQueue.pop();
+		redraw();
+		return;
+	}
+	showSelection();
+}
 
-	setTimer(timer);
-	redraw();
+void CInfoBar::pushComponents(const std::vector<Component> & comps, std::string message, int textH, bool tiny, int timer)
+{
+	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
+	componentsQueue.emplace(std::make_shared<VisibleComponentInfo>(comps, message, textH, tiny), timer);
 }
 
 bool CInfoBar::showingComponents()

+ 10 - 2
client/adventureMap/CInfoBar.h

@@ -125,8 +125,13 @@ private:
 	std::shared_ptr<CVisibleInfo> visibleInfo;
 	EState state;
 
+	std::queue<std::pair<std::shared_ptr<VisibleComponentInfo>, int>> componentsQueue;
+
 	//private helper for showing components
-	void showComponents(const std::vector<Component> & comps, std::string message, int textH, bool tiny = false, int timer = 3000);
+	void showComponents(const std::vector<Component> & comps, std::string message, int textH, bool tiny, int timer);
+	void pushComponents(const std::vector<Component> & comps, std::string message, int textH, bool tiny, int timer);
+	void prepareComponents(const std::vector<Component> & comps, std::string message, int timer);
+	void popComponents();
 
 	//removes all information about current state, deactivates timer (if any)
 	void reset();
@@ -146,7 +151,10 @@ public:
 	void showDate();
 
 	/// show components for 3 seconds. Used to display picked up resources. Can display up to 8 components
-	bool tryShowComponents(const std::vector<Component> & comps, std::string message, int timer = 3000);
+	void pushComponents(const std::vector<Component> & comps, std::string message, int timer = 3000);
+
+	/// Remove all queued components
+	void popAll();
 
 	/// print enemy turn progress
 	void startEnemyTurn(PlayerColor color);