Jelajahi Sumber

Merge pull request #1499 from dydzio0614/battle-queue-improvement

Battle queue improvement
Ivan Savenko 2 tahun lalu
induk
melakukan
a5f51b21c4

+ 42 - 1
client/battle/BattleInterfaceClasses.cpp

@@ -784,6 +784,14 @@ StackQueue::StackQueue(bool Embedded, BattleInterface & owner)
 
 void StackQueue::show(SDL_Surface * to)
 {
+	auto unitIdsToHighlight = owner.stacksController->getHoveredStacksUnitIds();
+
+	for(auto & stackBox : stackBoxes)
+	{
+		bool isBoundUnitCurrentlyHovered = vstd::contains(unitIdsToHighlight, stackBox->getBoundUnitID());
+		stackBox->toggleHighlight(isBoundUnitCurrentlyHovered);
+	}
+
 	if (embedded)
 		showAll(to);
 	CIntObject::show(to);
@@ -812,8 +820,21 @@ int32_t StackQueue::getSiegeShooterIconID()
 	return owner.siegeController->getSiegedTown()->town->faction->getIndex();
 }
 
+boost::optional<uint32_t> StackQueue::getHoveredUnitIdIfAny() const
+{
+	for(const auto & stackBox : stackBoxes)
+	{
+		if(stackBox->hovered || stackBox->mouseState(EIntObjMouseBtnType::RIGHT))
+		{
+			return stackBox->getBoundUnitID();
+		}
+	}
+
+	return boost::none;
+}
+
 StackQueue::StackBox::StackBox(StackQueue * owner):
-	owner(owner)
+	CIntObject(RCLICK | HOVER), owner(owner)
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
 	background = std::make_shared<CPicture>(owner->embedded ? "StackQueueSmall" : "StackQueueLarge");
@@ -843,6 +864,7 @@ void StackQueue::StackBox::setUnit(const battle::Unit * unit, size_t turn)
 {
 	if(unit)
 	{
+		boundUnitID = unit->unitId();
 		background->colorize(unit->unitOwner());
 		icon->visible = true;
 
@@ -877,6 +899,7 @@ void StackQueue::StackBox::setUnit(const battle::Unit * unit, size_t turn)
 	}
 	else
 	{
+		boundUnitID = boost::none;
 		background->colorize(PlayerColor::NEUTRAL);
 		icon->visible = false;
 		icon->setFrame(0);
@@ -886,3 +909,21 @@ void StackQueue::StackBox::setUnit(const battle::Unit * unit, size_t turn)
 			stateIcon->visible = false;
 	}
 }
+
+boost::optional<uint32_t> StackQueue::StackBox::getBoundUnitID() const
+{
+	return boundUnitID;
+}
+
+void StackQueue::StackBox::toggleHighlight(bool value)
+{
+	highlighted = value;
+}
+
+void StackQueue::StackBox::show(SDL_Surface *to)
+{
+	if(highlighted)
+		CSDL_Ext::drawBorder(to, background->pos.x, background->pos.y, background->pos.w, background->pos.h,  { 0, 255, 255, 255 }, 2);
+
+	CIntObject::show(to);
+}

+ 9 - 1
client/battle/BattleInterfaceClasses.h

@@ -196,14 +196,21 @@ class StackQueue : public CIntObject
 	class StackBox : public CIntObject
 	{
 		StackQueue * owner;
+		boost::optional<uint32_t> boundUnitID;
+		bool highlighted = false;
+
 	public:
 		std::shared_ptr<CPicture> background;
 		std::shared_ptr<CAnimImage> icon;
 		std::shared_ptr<CLabel> amount;
 		std::shared_ptr<CAnimImage> stateIcon;
 
-		void setUnit(const battle::Unit * unit, size_t turn = 0);
 		StackBox(StackQueue * owner);
+		void setUnit(const battle::Unit * unit, size_t turn = 0);
+		void toggleHighlight(bool value);
+		boost::optional<uint32_t> getBoundUnitID() const;
+
+		void show(SDL_Surface * to) override;
 	};
 
 	static const int QUEUE_SIZE = 10;
@@ -220,6 +227,7 @@ public:
 
 	StackQueue(bool Embedded, BattleInterface & owner);
 	void update();
+	boost::optional<uint32_t> getHoveredUnitIdIfAny() const;
 
 	void show(SDL_Surface * to) override;
 };

+ 17 - 0
client/battle/BattleStacksController.cpp

@@ -896,6 +896,12 @@ std::vector<const CStack *> BattleStacksController::selectHoveredStacks()
 	if(owner.getAnimationCondition(EAnimationEvents::ACTION) == true)
 		return {};
 
+	auto hoveredQueueUnitId = owner.windowObject->getQueueHoveredUnitId();
+	if(hoveredQueueUnitId.is_initialized())
+	{
+		return { owner.curInt->cb->battleGetStackByID(hoveredQueueUnitId.value(), true) };
+	}
+
 	auto hoveredHex = owner.fieldController->getHoveredHex();
 
 	if (!hoveredHex.isValid())
@@ -938,3 +944,14 @@ std::vector<const CStack *> BattleStacksController::selectHoveredStacks()
 
 	return {};
 }
+
+const std::vector<uint32_t> BattleStacksController::getHoveredStacksUnitIds() const
+{
+	auto result = std::vector<uint32_t>();
+	for (auto const * stack : mouseHoveredStacks)
+	{
+		result.push_back(stack->unitId());
+	}
+
+	return result;
+}

+ 2 - 1
client/battle/BattleStacksController.h

@@ -70,7 +70,7 @@ class BattleStacksController
 	/// currently active stack; nullptr - no one
 	const CStack *activeStack;
 
-	/// stacks below mouse pointer (multiple stacks possible while spellcasting), used for border animation
+	/// stacks or their battle queue images below mouse pointer (multiple stacks possible while spellcasting), used for border animation
 	std::vector<const CStack *> mouseHoveredStacks;
 
 	///when animation is playing, we should wait till the end to make the next stack active; nullptr of none
@@ -144,6 +144,7 @@ public:
 
 	const CStack* getActiveStack() const;
 	const CStack* getSelectedStack() const;
+	const std::vector<uint32_t> getHoveredStacksUnitIds() const;
 
 	void update();
 

+ 5 - 0
client/battle/BattleWindow.cpp

@@ -553,6 +553,11 @@ void BattleWindow::blockUI(bool on)
 	}
 }
 
+boost::optional<uint32_t> BattleWindow::getQueueHoveredUnitId()
+{
+	return queue->getHoveredUnitIdIfAny();
+}
+
 void BattleWindow::showAll(SDL_Surface *to)
 {
 	CIntObject::showAll(to);

+ 3 - 0
client/battle/BattleWindow.h

@@ -74,6 +74,9 @@ public:
 	/// Refresh queue after turn order changes
 	void updateQueue();
 
+	/// Get mouse-hovered battle queue unit ID if any found
+	boost::optional<uint32_t> getQueueHoveredUnitId();
+
 	void activate() override;
 	void deactivate() override;
 	void keyPressed(const SDL_KeyboardEvent & key) override;

+ 15 - 11
client/renderSDL/SDL_Extensions.cpp

@@ -479,23 +479,27 @@ void CSDL_Ext::drawLine(SDL_Surface * sur, int x1, int y1, int x2, int y2, const
 	}
 }
 
-void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const SDL_Color &color)
+void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const SDL_Color &color, int depth)
 {
-	for(int i = 0; i < w; i++)
+	depth = std::max(1, depth);
+	for(int depthIterator = 0; depthIterator < depth; depthIterator++)
 	{
-		CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur,x+i,y,color.r,color.g,color.b);
-		CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur,x+i,y+h-1,color.r,color.g,color.b);
-	}
-	for(int i = 0; i < h; i++)
-	{
-		CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur,x,y+i,color.r,color.g,color.b);
-		CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur,x+w-1,y+i,color.r,color.g,color.b);
+		for(int i = 0; i < w; i++)
+		{
+			CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur,x+i,y+depthIterator,color.r,color.g,color.b);
+			CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur,x+i,y+h-1-depthIterator,color.r,color.g,color.b);
+		}
+		for(int i = 0; i < h; i++)
+		{
+			CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur,x+depthIterator,y+i,color.r,color.g,color.b);
+			CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur,x+w-1-depthIterator,y+i,color.r,color.g,color.b);
+		}
 	}
 }
 
-void CSDL_Ext::drawBorder( SDL_Surface * sur, const Rect &r, const SDL_Color &color )
+void CSDL_Ext::drawBorder( SDL_Surface * sur, const Rect &r, const SDL_Color &color, int depth)
 {
-	drawBorder(sur, r.x, r.y, r.w, r.h, color);
+	drawBorder(sur, r.x, r.y, r.w, r.h, color, depth);
 }
 
 void CSDL_Ext::drawDashedBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color)

+ 2 - 2
client/renderSDL/SDL_Extensions.h

@@ -152,8 +152,8 @@ typedef void (*TColorPutterAlpha)(uint8_t *&ptr, const uint8_t & R, const uint8_
 
 	void update(SDL_Surface * what = screen); //updates whole surface (default - main screen)
 	void drawLine(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2);
-	void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const SDL_Color &color);
-	void drawBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color);
+	void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const SDL_Color &color, int depth = 1);
+	void drawBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color, int depth = 1);
 	void drawDashedBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color);
 	void setPlayerColor(SDL_Surface * sur, PlayerColor player); //sets correct color of flags; -1 for neutral
 	std::string processStr(std::string str, std::vector<std::string> & tor); //replaces %s in string