Browse Source

refactoring

SoundSSGood 2 years ago
parent
commit
f47def3588

+ 2 - 0
client/CMakeLists.txt

@@ -94,6 +94,7 @@ set(client_SRCS
 	widgets/Buttons.cpp
 	widgets/CArtifactHolder.cpp
 	widgets/CComponent.cpp
+	widgets/CExchangeController.cpp
 	widgets/CGarrisonInt.cpp
 	widgets/CreatureCostBox.cpp
 	widgets/ComboBox.cpp
@@ -255,6 +256,7 @@ set(client_HEADERS
 	widgets/Buttons.h
 	widgets/CArtifactHolder.h
 	widgets/CComponent.h
+	widgets/CExchangeController.h
 	widgets/CGarrisonInt.h
 	widgets/CreatureCostBox.h
 	widgets/ComboBox.h

+ 2 - 2
client/widgets/CArtifactHolder.cpp

@@ -186,8 +186,8 @@ void CHeroArtPlace::clickPressed(const Point & cursorPosition)
 
 void CHeroArtPlace::showPopupWindow(const Point & cursorPosition)
 {
-	if(rightClickCallback)
-		rightClickCallback(*this);
+	if(showPopupCallback)
+		showPopupCallback(*this);
 }
 
 void CHeroArtPlace::showAll(Canvas & to)

+ 3 - 3
client/widgets/CArtifactHolder.h

@@ -65,11 +65,11 @@ public:
 class CHeroArtPlace: public CArtPlace
 {
 public:
-	using ClickHandler = std::function<void(CHeroArtPlace&)>;
+	using ClickFunctor = std::function<void(CHeroArtPlace&)>;
 
 	ArtifactPosition slot;
-	ClickHandler leftClickCallback;
-	ClickHandler rightClickCallback;
+	ClickFunctor leftClickCallback;
+	ClickFunctor showPopupCallback;
 
 	CHeroArtPlace(Point position, const CArtifactInstance * Art = nullptr);
 	void lockSlot(bool on);

+ 1 - 1
client/widgets/CArtifactsOfHeroBackpack.cpp

@@ -42,7 +42,7 @@ CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(const Point & position)
 		artPlace = std::make_shared<CHeroArtPlace>(pos);
 		artPlace->setArtifact(nullptr);
 		artPlace->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1);
-		artPlace->rightClickCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
+		artPlace->showPopupCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
 		artPlaceIdx++;
 	}
 

+ 9 - 9
client/widgets/CArtifactsOfHeroBase.cpp

@@ -55,10 +55,10 @@ void CArtifactsOfHeroBase::setPutBackPickedArtifactCallback(PutBackPickedArtCall
 }
 
 void CArtifactsOfHeroBase::init(
-	CHeroArtPlace::ClickHandler lClickCallback,
-	CHeroArtPlace::ClickHandler rClickCallback,
+	CHeroArtPlace::ClickFunctor lClickCallback,
+	CHeroArtPlace::ClickFunctor showPopupCallback,
 	const Point & position,
-	BpackScrollHandler scrollHandler)
+	BpackScrollFunctor scrollCallback)
 {
 	// CArtifactsOfHeroBase::init may be transform to CArtifactsOfHeroBase::CArtifactsOfHeroBase if OBJECT_CONSTRUCTION_CAPTURING is removed
 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
@@ -78,16 +78,16 @@ void CArtifactsOfHeroBase::init(
 		artPlace.second->slot = artPlace.first;
 		artPlace.second->setArtifact(nullptr);
 		artPlace.second->leftClickCallback = lClickCallback;
-		artPlace.second->rightClickCallback = rClickCallback;
+		artPlace.second->showPopupCallback = showPopupCallback;
 	}
 	for(auto artPlace : backpack)
 	{
 		artPlace->setArtifact(nullptr);
 		artPlace->leftClickCallback = lClickCallback;
-		artPlace->rightClickCallback = rClickCallback;
+		artPlace->showPopupCallback = showPopupCallback;
 	}
-	leftBackpackRoll = std::make_shared<CButton>(Point(379, 364), AnimationPath::builtin("hsbtns3.def"), CButton::tooltip(), [scrollHandler]() { scrollHandler(-1); }, EShortcut::MOVE_LEFT);
-	rightBackpackRoll = std::make_shared<CButton>(Point(632, 364), AnimationPath::builtin("hsbtns5.def"), CButton::tooltip(), [scrollHandler]() { scrollHandler(+1); }, EShortcut::MOVE_RIGHT);
+	leftBackpackRoll = std::make_shared<CButton>(Point(379, 364), AnimationPath::builtin("hsbtns3.def"), CButton::tooltip(), [scrollCallback]() {scrollCallback(-1);}, EShortcut::MOVE_LEFT);
+	rightBackpackRoll = std::make_shared<CButton>(Point(632, 364), AnimationPath::builtin("hsbtns5.def"), CButton::tooltip(), [scrollCallback]() {scrollCallback(+1);}, EShortcut::MOVE_RIGHT);
 	leftBackpackRoll->block(true);
 	rightBackpackRoll->block(true);
 
@@ -102,8 +102,8 @@ void CArtifactsOfHeroBase::leftClickArtPlace(CHeroArtPlace & artPlace)
 
 void CArtifactsOfHeroBase::rightClickArtPlace(CHeroArtPlace & artPlace)
 {
-	if(rightClickCallback)
-		rightClickCallback(*this, artPlace);
+	if(showPopupCallback)
+		showPopupCallback(*this, artPlace);
 }
 
 void CArtifactsOfHeroBase::setHero(const CGHeroInstance * hero)

+ 6 - 6
client/widgets/CArtifactsOfHeroBase.h

@@ -15,15 +15,15 @@ class CArtifactsOfHeroBase : public CIntObject
 {
 protected:
 	using ArtPlacePtr = std::shared_ptr<CHeroArtPlace>;
-	using BpackScrollHandler = std::function<void(int)>;
+	using BpackScrollFunctor = std::function<void(int)>;
 
 public:
 	using ArtPlaceMap = std::map<ArtifactPosition, ArtPlacePtr>;
-	using ClickHandler = std::function<void(CArtifactsOfHeroBase&, CHeroArtPlace&)>;
+	using ClickFunctor = std::function<void(CArtifactsOfHeroBase&, CHeroArtPlace&)>;
 	using PutBackPickedArtCallback = std::function<void()>;
 
-	ClickHandler leftClickCallback;
-	ClickHandler rightClickCallback;
+	ClickFunctor leftClickCallback;
+	ClickFunctor showPopupCallback;
 	
 	CArtifactsOfHeroBase();
 	virtual void putBackPickedArtifact();
@@ -61,8 +61,8 @@ protected:
 		Point(381,296) //18
 	};
 
-	virtual void init(CHeroArtPlace::ClickHandler lClickCallback, CHeroArtPlace::ClickHandler rClickCallback,
-		const Point & position, BpackScrollHandler scrollHandler);
+	virtual void init(CHeroArtPlace::ClickFunctor lClickCallback, CHeroArtPlace::ClickFunctor showPopupCallback,
+		const Point & position, BpackScrollFunctor scrollCallback);
 	// Assigns an artifacts to an artifact place depending on it's new slot ID
 	virtual void setSlotData(ArtPlacePtr artPlace, const ArtifactPosition & slot, const CArtifactSet & artSet);
 	virtual void scrollBackpackForArtSet(int offset, const CArtifactSet & artSet);

+ 2 - 2
client/widgets/CArtifactsOfHeroKingdom.cpp

@@ -29,13 +29,13 @@ CArtifactsOfHeroKingdom::CArtifactsOfHeroKingdom(ArtPlaceMap ArtWorn, std::vecto
 		artPlace.second->slot = artPlace.first;
 		artPlace.second->setArtifact(nullptr);
 		artPlace.second->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1);
-		artPlace.second->rightClickCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
+		artPlace.second->showPopupCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
 	}
 	for(auto artPlace : backpack)
 	{
 		artPlace->setArtifact(nullptr);
 		artPlace->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1);
-		artPlace->rightClickCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
+		artPlace->showPopupCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
 	}
 	leftBackpackRoll->addCallback(std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, -1));
 	rightBackpackRoll->addCallback(std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, +1));

+ 119 - 0
client/widgets/CExchangeController.cpp

@@ -0,0 +1,119 @@
+/*
+ * CExchangeController.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#include "CExchangeController.h"
+
+#include "../CPlayerInterface.h"
+
+#include "../widgets/CGarrisonInt.h"
+
+#include "../../CCallback.h"
+
+#include "../lib/mapObjects/CGHeroInstance.h"
+
+CExchangeController::CExchangeController(ObjectInstanceID hero1, ObjectInstanceID hero2)
+	: left(LOCPLINT->cb->getHero(hero1))
+	, right(LOCPLINT->cb->getHero(hero2))
+{
+}
+
+void CExchangeController::swapArmy()
+{
+	auto getStacks = [](const CArmedInstance * source) -> std::vector<std::pair<SlotID, CStackInstance*>>
+	{
+		auto slots = source->Slots();
+		return std::vector<std::pair<SlotID, CStackInstance*>>(slots.begin(), slots.end());
+	};
+
+	auto leftSlots = getStacks(left);
+	auto rightSlots = getStacks(right);
+
+	auto i = leftSlots.begin(), j = rightSlots.begin();
+
+	for(; i != leftSlots.end() && j != rightSlots.end(); i++, j++)
+	{
+		LOCPLINT->cb->swapCreatures(left, right, i->first, j->first);
+	}
+
+	if(i != leftSlots.end())
+	{
+		auto freeSlots = right->getFreeSlots();
+		auto slot = freeSlots.begin();
+
+		for(; i != leftSlots.end() && slot != freeSlots.end(); i++, slot++)
+		{
+			LOCPLINT->cb->swapCreatures(left, right, i->first, *slot);
+		}
+	}
+	else if(j != rightSlots.end())
+	{
+		auto freeSlots = left->getFreeSlots();
+		auto slot = freeSlots.begin();
+
+		for(; j != rightSlots.end() && slot != freeSlots.end(); j++, slot++)
+		{
+			LOCPLINT->cb->swapCreatures(left, right, *slot, j->first);
+		}
+	}
+}
+
+void CExchangeController::moveArmy(bool leftToRight, std::optional<SlotID> heldSlot)
+{
+	const auto source = leftToRight ? left : right;
+	const auto target = leftToRight ? right : left;
+
+	if(!heldSlot.has_value())
+	{
+		auto weakestSlot = vstd::minElementByFun(source->Slots(),
+			[](const std::pair<SlotID, CStackInstance*> & s) -> int
+			{
+				return s.second->getCreatureID().toCreature()->getAIValue();
+			});
+		heldSlot = weakestSlot->first;
+	}
+	LOCPLINT->cb->bulkMoveArmy(source->id, target->id, heldSlot.value());
+}
+
+void CExchangeController::moveStack(bool leftToRight, SlotID sourceSlot)
+{
+	const auto source = leftToRight ? left : right;
+	const auto target = leftToRight ? right : left;
+	auto creature = source->getCreature(sourceSlot);
+
+	if(creature == nullptr)
+		return;
+
+	SlotID targetSlot = target->getSlotFor(creature);
+	if(targetSlot.validSlot())
+	{
+		if(source->stacksCount() == 1 && source->needsLastStack())
+		{
+			LOCPLINT->cb->splitStack(source, target, sourceSlot, targetSlot,
+				target->getStackCount(targetSlot) + source->getStackCount(sourceSlot) - 1);
+		}
+		else
+		{
+			LOCPLINT->cb->mergeOrSwapStacks(source, target, sourceSlot, targetSlot);
+		}
+	}
+}
+
+void CExchangeController::swapArtifacts(bool equipped, bool baclpack)
+{
+	LOCPLINT->cb->bulkMoveArtifacts(left->id, right->id, true, equipped, baclpack);
+}
+
+void CExchangeController::moveArtifacts(bool leftToRight, bool equipped, bool baclpack)
+{
+	const auto source = leftToRight ? left : right;
+	const auto target = leftToRight ? right : left;
+
+	LOCPLINT->cb->bulkMoveArtifacts(source->id, target->id, false, equipped, baclpack);
+}

+ 30 - 0
client/widgets/CExchangeController.h

@@ -0,0 +1,30 @@
+/*
+ * CExchangeController.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+ #pragma once
+ 
+ #include "../windows/CWindowObject.h"
+ #include "CWindowWithArtifacts.h"
+ 
+class CCallback;
+
+class CExchangeController
+{
+public:
+	CExchangeController(ObjectInstanceID hero1, ObjectInstanceID hero2);
+	void swapArmy();
+	void moveArmy(bool leftToRight, std::optional<SlotID> heldSlot);
+	void moveStack(bool leftToRight, SlotID sourceSlot);
+	void swapArtifacts(bool equipped, bool baclpack);
+	void moveArtifacts(bool leftToRight, bool equipped, bool baclpack);
+
+private:
+	const CGHeroInstance * left;
+	const CGHeroInstance * right;
+};

+ 1 - 1
client/widgets/CWindowWithArtifacts.cpp

@@ -38,7 +38,7 @@ void CWindowWithArtifacts::addSet(CArtifactsOfHeroPtr artSet)
 		{
 			auto artSet = artSetWeak.lock();
 			artSet->leftClickCallback = std::bind(&CWindowWithArtifacts::leftClickArtPlaceHero, this, _1, _2);
-			artSet->rightClickCallback = std::bind(&CWindowWithArtifacts::rightClickArtPlaceHero, this, _1, _2);
+			artSet->showPopupCallback = std::bind(&CWindowWithArtifacts::rightClickArtPlaceHero, this, _1, _2);
 			artSet->setPutBackPickedArtifactCallback(artPutBackHandler);
 		}, artSet);
 }

+ 35 - 245
client/windows/GUIClasses.cpp

@@ -19,62 +19,40 @@
 #include "../CMusicHandler.h"
 #include "../CPlayerInterface.h"
 #include "../CVideoHandler.h"
-#include "../CServerHandler.h"
-
-#include "../battle/BattleInterfaceClasses.h"
-#include "../battle/BattleInterface.h"
 
 #include "../gui/CGuiHandler.h"
 #include "../gui/CursorHandler.h"
-#include "../gui/TextAlignment.h"
 #include "../gui/Shortcut.h"
 #include "../gui/WindowHandler.h"
 
 #include "../widgets/CComponent.h"
 #include "../widgets/CGarrisonInt.h"
-#include "../widgets/MiscWidgets.h"
 #include "../widgets/CreatureCostBox.h"
 #include "../widgets/Buttons.h"
 #include "../widgets/Slider.h"
 #include "../widgets/TextControls.h"
 #include "../widgets/ObjectLists.h"
 
-#include "../lobby/CSavingScreen.h"
 #include "../render/Canvas.h"
 #include "../render/CAnimation.h"
 #include "../render/IRenderHandler.h"
-#include "../CMT.h"
 
 #include "../../CCallback.h"
 
-#include "../lib/mapObjectConstructors/AObjectTypeHandler.h"
 #include "../lib/mapObjectConstructors/CObjectClassesHandler.h"
 #include "../lib/mapObjectConstructors/CommonConstructors.h"
 #include "../lib/mapObjects/CGHeroInstance.h"
 #include "../lib/mapObjects/CGMarket.h"
-#include "../lib/ArtifactUtils.h"
 #include "../lib/mapObjects/CGTownInstance.h"
 #include "../lib/mapObjects/ObjectTemplate.h"
 #include "../lib/gameState/CGameState.h"
-#include "../lib/gameState/InfoAboutArmy.h"
 #include "../lib/gameState/SThievesGuildInfo.h"
-#include "../lib/CArtHandler.h"
-#include "../lib/CBuildingHandler.h"
-#include "../lib/CConfigHandler.h"
-#include "../lib/CCreatureHandler.h"
 #include "../lib/CGeneralTextHandler.h"
 #include "../lib/CHeroHandler.h"
 #include "../lib/GameSettings.h"
 #include "../lib/CondSh.h"
 #include "../lib/CSkillHandler.h"
-#include "../lib/spells/CSpellHandler.h"
 #include "../lib/filesystem/Filesystem.h"
-#include "../lib/CStopWatch.h"
-#include "../lib/CTownHandler.h"
-#include "../lib/GameConstants.h"
-#include "../lib/bonuses/Bonus.h"
-#include "../lib/NetPacksBase.h"
-#include "../lib/StartInfo.h"
 #include "../lib/TextOperations.h"
 
 CRecruitmentWindow::CCreatureCard::CCreatureCard(CRecruitmentWindow * window, const CCreature * crea, int totalAmount)
@@ -623,223 +601,9 @@ static bool isQuickExchangeLayoutAvailable()
 	return CResourceHandler::get()->existsResource(ImagePath::builtin("SPRITES/" + QUICK_EXCHANGE_BG));
 }
 
-CExchangeController::CExchangeController(CExchangeWindow * view, ObjectInstanceID hero1, ObjectInstanceID hero2)
-	:left(LOCPLINT->cb->getHero(hero1)), right(LOCPLINT->cb->getHero(hero2)), cb(LOCPLINT->cb), view(view)
-{
-}
-
-std::function<void()> CExchangeController::onMoveArmyToLeft()
-{
-	return [&]() { moveArmy(false); };
-}
-
-std::function<void()> CExchangeController::onMoveArmyToRight()
-{
-	return [&]() { moveArmy(true); };
-}
-
-std::vector<CArtifactInstance *> getBackpackArts(const CGHeroInstance * hero)
-{
-	std::vector<CArtifactInstance *> result;
-
-	for(auto slot : hero->artifactsInBackpack)
-	{
-		result.push_back(slot.artifact);
-	}
-
-	return result;
-}
-
-std::function<void()> CExchangeController::onSwapArtifacts()
-{
-	return [&]()
-	{
-		if(GH.isKeyboardCtrlDown())
-			cb->bulkMoveArtifacts(left->id, right->id, true, true, false);
-		else if(GH.isKeyboardShiftDown())
-			cb->bulkMoveArtifacts(left->id, right->id, true, false, true);
-		else
-			cb->bulkMoveArtifacts(left->id, right->id, true);
-	};
-}
-
-std::function<void()> CExchangeController::onMoveArtifactsToLeft()
-{
-	return [&]() { moveArtifacts(false); };
-}
-
-std::function<void()> CExchangeController::onMoveArtifactsToRight()
-{
-	return [&]() { moveArtifacts(true); };
-}
-
-std::vector<std::pair<SlotID, CStackInstance *>> getStacks(const CArmedInstance * source)
-{
-	auto slots = source->Slots();
-
-	return std::vector<std::pair<SlotID, CStackInstance *>>(slots.begin(), slots.end());
-}
-
-std::function<void()> CExchangeController::onSwapArmy()
-{
-	return [&]()
-	{
-		if(left->tempOwner != cb->getPlayerID()
-		   || right->tempOwner != cb->getPlayerID())
-		{
-			return;
-		}
-
-		auto leftSlots = getStacks(left);
-		auto rightSlots = getStacks(right);
-
-		auto i = leftSlots.begin(), j = rightSlots.begin();
-
-		for(; i != leftSlots.end() && j != rightSlots.end(); i++, j++)
-		{
-			cb->swapCreatures(left, right, i->first, j->first);
-		}
-
-		if(i != leftSlots.end())
-		{
-			auto freeSlots = right->getFreeSlots();
-			auto slot = freeSlots.begin();
-
-			for(; i != leftSlots.end() && slot != freeSlots.end(); i++, slot++)
-			{
-				cb->swapCreatures(left, right, i->first, *slot);
-			}
-		}
-		else if(j != rightSlots.end())
-		{
-			auto freeSlots = left->getFreeSlots();
-			auto slot = freeSlots.begin();
-
-			for(; j != rightSlots.end() && slot != freeSlots.end(); j++, slot++)
-			{
-				cb->swapCreatures(left, right, *slot, j->first);
-			}
-		}
-	};
-}
-
-std::function<void()> CExchangeController::onMoveStackToLeft(SlotID slotID)
-{
-	return [=]()
-	{
-		if(right->tempOwner != cb->getPlayerID())
-		{
-			return;
-		}
-
-		moveStack(right, left, slotID);
-	};
-}
-
-std::function<void()> CExchangeController::onMoveStackToRight(SlotID slotID)
-{
-	return [=]()
-	{
-		if(left->tempOwner != cb->getPlayerID())
-		{
-			return;
-		}
-
-		moveStack(left, right, slotID);
-	};
-}
-
-void CExchangeController::moveStack(
-	const CGHeroInstance * source,
-	const CGHeroInstance * target,
-	SlotID sourceSlot)
-{
-	auto creature = source->getCreature(sourceSlot);
-	if(creature == nullptr)
-		return;
-
-	SlotID targetSlot = target->getSlotFor(creature);
-
-	if(targetSlot.validSlot())
-	{
-		if(source->stacksCount() == 1 && source->needsLastStack())
-		{
-			cb->splitStack(
-				source,
-				target,
-				sourceSlot,
-				targetSlot,
-				target->getStackCount(targetSlot) + source->getStackCount(sourceSlot) - 1);
-		}
-		else
-		{
-			cb->mergeOrSwapStacks(source, target, sourceSlot, targetSlot);
-		}
-	}
-}
-
-void CExchangeController::moveArmy(bool leftToRight)
-{
-	const CGHeroInstance * source = leftToRight ? left : right;
-	const CGHeroInstance * target = leftToRight ? right : left;
-	const CGarrisonSlot * selection =  this->view->getSelectedSlotID();
-	SlotID slot;
-
-	if(source->tempOwner != cb->getPlayerID())
-	{
-		return;
-	}
-
-	if(selection && selection->our() && selection->getObj() == source)
-	{
-		slot = selection->getSlot();
-	}
-	else
-	{
-		auto weakestSlot = vstd::minElementByFun(
-			source->Slots(), 
-			[](const std::pair<SlotID, CStackInstance *> & s) -> int
-			{
-				return s.second->getCreatureID().toCreature()->getAIValue();
-			});
-
-		slot = weakestSlot->first;
-	}
-
-	cb->bulkMoveArmy(source->id, target->id, slot);
-}
-
-void CExchangeController::moveArtifacts(bool leftToRight)
-{
-	const CGHeroInstance * source = leftToRight ? left : right;
-	const CGHeroInstance * target = leftToRight ? right : left;
-
-	if(source->tempOwner != cb->getPlayerID())
-		return;
-
-	if(GH.isKeyboardCtrlDown())
-		cb->bulkMoveArtifacts(source->id, target->id, false, true, false);
-	else if(GH.isKeyboardShiftDown())
-		cb->bulkMoveArtifacts(source->id, target->id, false, false, true);
-	else
-		cb->bulkMoveArtifacts(source->id, target->id, false);
-}
-
-void CExchangeController::moveArtifact(
-	const CGHeroInstance * source,
-	const CGHeroInstance * target,
-	ArtifactPosition srcPosition)
-{
-	auto srcLocation = ArtifactLocation(source, srcPosition);
-	auto dstLocation = ArtifactLocation(target,
-		ArtifactUtils::getArtAnyPosition(target, source->getArt(srcPosition)->getTypeId()));
-
-	cb->swapArtifacts(srcLocation, dstLocation);
-}
-
 CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID queryID)
 	: CStatusbarWindow(PLAYER_COLORED | BORDERED, ImagePath::builtin(isQuickExchangeLayoutAvailable() ? QUICK_EXCHANGE_BG : "TRADE2")),
-	controller(this, hero1, hero2),
+	controller(hero1, hero2),
 	moveStackLeftButtons(),
 	moveStackRightButtons()
 {
@@ -990,12 +754,38 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
 
 	if(qeLayout)
 	{
-		moveAllGarrButtonLeft    = std::make_shared<CButton>(Point(325, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/armRight.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[1]), controller.onMoveArmyToRight());
-		echangeGarrButton        = std::make_shared<CButton>(Point(377, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/swapAll.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[2]), controller.onSwapArmy());
-		moveAllGarrButtonRight   = std::make_shared<CButton>(Point(425, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/armLeft.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[1]), controller.onMoveArmyToLeft());
-		moveArtifactsButtonLeft  = std::make_shared<CButton>(Point(325, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/artRight.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[3]), controller.onMoveArtifactsToRight());
-		echangeArtifactsButton   = std::make_shared<CButton>(Point(377, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/swapAll.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[4]), controller.onSwapArtifacts());
-		moveArtifactsButtonRight = std::make_shared<CButton>(Point(425, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/artLeft.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[3]), controller.onMoveArtifactsToLeft());
+		auto moveArtifacts = [this](std::function<void(bool, bool)> moveRoutine) -> void
+		{
+			bool moveEquipped = true;
+			bool moveBackpack = true;
+
+			if(GH.isKeyboardCtrlDown())
+				moveBackpack = false;
+			else if(GH.isKeyboardShiftDown())
+				moveEquipped = false;
+			moveRoutine(moveEquipped, moveBackpack);
+		};
+
+		auto moveArmy = [this](bool leftToRight) -> void
+		{
+			std::optional<SlotID> slotId = std::nullopt;
+			if(auto slot = getSelectedSlotID())
+				slotId = slot->getSlot();
+			controller.moveArmy(leftToRight, slotId);
+		};
+
+		moveAllGarrButtonLeft    = std::make_shared<CButton>(Point(325, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/armRight.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[1]),
+			std::bind(moveArmy, true));
+		echangeGarrButton        = std::make_shared<CButton>(Point(377, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/swapAll.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[2]),
+			std::bind(&CExchangeController::swapArmy, &controller));
+		moveAllGarrButtonRight   = std::make_shared<CButton>(Point(425, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/armLeft.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[1]),
+			std::bind(moveArmy, false));
+		moveArtifactsButtonLeft  = std::make_shared<CButton>(Point(325, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/artRight.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[3]),
+			std::bind(moveArtifacts, [this](bool equipped, bool baclpack) -> void {controller.moveArtifacts(true, equipped, baclpack);}));
+		echangeArtifactsButton   = std::make_shared<CButton>(Point(377, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/swapAll.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[4]),
+			std::bind(moveArtifacts, [this](bool equipped, bool baclpack) -> void {controller.swapArtifacts(equipped, baclpack);}));
+		moveArtifactsButtonRight = std::make_shared<CButton>(Point(425, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/artLeft.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[3]),
+			std::bind(moveArtifacts, [this](bool equipped, bool baclpack) -> void {controller.moveArtifacts(false, equipped, baclpack);}));
 
 		for(int i = 0; i < GameConstants::ARMY_SIZE; i++)
 		{
@@ -1004,14 +794,14 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
 					Point(484 + 35 * i, 154),
 					AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/unitLeft.DEF"),
 					CButton::tooltip(CGI->generaltexth->qeModCommands[1]),
-					controller.onMoveStackToLeft(SlotID(i))));
+					std::bind(&CExchangeController::moveStack, &controller, false, SlotID(i))));
 
 			moveStackRightButtons.push_back(
 				std::make_shared<CButton>(
 					Point(66 + 35 * i, 154),
 					AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/unitRight.DEF"),
 					CButton::tooltip(CGI->generaltexth->qeModCommands[1]),
-					controller.onMoveStackToRight(SlotID(i))));
+					std::bind(&CExchangeController::moveStack, &controller, true, SlotID(i))));
 		}
 	}
 

+ 1 - 35
client/windows/GUIClasses.h

@@ -9,10 +9,8 @@
  */
 #pragma once
 
-#include "CWindowObject.h"
-#include "../lib/GameConstants.h"
 #include "../lib/ResourceSet.h"
-#include "../lib/int3.h"
+#include "../widgets/CExchangeController.h"
 #include "../widgets/CWindowWithArtifacts.h"
 #include "../widgets/Images.h"
 
@@ -28,16 +26,13 @@ class CreatureCostBox;
 class CCreaturePic;
 class MoraleLuckBox;
 class CHeroArea;
-class CMinorResDataBar;
 class CSlider;
 class CComponentBox;
 class CTextInput;
 class CListBox;
 class CLabelGroup;
-class CToggleButton;
 class CGStatusBar;
 class CTextBox;
-class CResDataBar;
 class CGarrisonInt;
 class CGarrisonSlot;
 
@@ -246,35 +241,6 @@ public:
 	void show(Canvas & to) override;
 };
 
-class CCallback;
-class CExchangeWindow;
-
-class CExchangeController
-{
-private:
-	const CGHeroInstance * left;
-	const CGHeroInstance * right;
-	std::shared_ptr<CCallback> cb;
-	CExchangeWindow * view;
-
-public:
-	CExchangeController(CExchangeWindow * view, ObjectInstanceID hero1, ObjectInstanceID hero2);
-	std::function<void()> onMoveArmyToRight();
-	std::function<void()> onSwapArmy();
-	std::function<void()> onMoveArmyToLeft();
-	std::function<void()> onSwapArtifacts();
-	std::function<void()> onMoveArtifactsToLeft();
-	std::function<void()> onMoveArtifactsToRight();
-	std::function<void()> onMoveStackToLeft(SlotID slotID);
-	std::function<void()> onMoveStackToRight(SlotID slotID);
-
-private:
-	void moveArmy(bool leftToRight);
-	void moveArtifacts(bool leftToRight);
-	void moveArtifact(const CGHeroInstance * source, const CGHeroInstance * target, ArtifactPosition srcPosition);
-	void moveStack(const CGHeroInstance * source, const CGHeroInstance * target, SlotID sourceSlot);
-};
-
 class CExchangeWindow : public CStatusbarWindow, public IGarrisonHolder, public CWindowWithArtifacts
 {
 	std::array<std::shared_ptr<CLabel>, 2> titles;

+ 0 - 1
lib/ArtifactUtils.cpp

@@ -171,7 +171,6 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(CArtifa
 	auto * artInst = new CArtifactInstance(art);
 	if(art->isCombined())
 	{
-		assert(art->isCombined());
 		for(const auto & part : art->getConstituents())
 			artInst->addPart(ArtifactUtils::createNewArtifactInstance(part), ArtifactPosition::PRE_FIRST);
 	}

+ 0 - 6
lib/CArtifactInstance.cpp

@@ -44,12 +44,6 @@ bool CCombinedArtifactInstance::isPart(const CArtifactInstance * supposedPart) c
 	return false;
 }
 
-std::vector<CCombinedArtifactInstance::PartInfo> & CCombinedArtifactInstance::getPartsInfo()
-{
-	// TODO romove this func. encapsulation violation
-	return partsInfo;
-}
-
 const std::vector<CCombinedArtifactInstance::PartInfo> & CCombinedArtifactInstance::getPartsInfo() const
 {
 	return partsInfo;

+ 0 - 1
lib/CArtifactInstance.h

@@ -38,7 +38,6 @@ public:
 	void addPart(CArtifactInstance * art, const ArtifactPosition & slot);
 	// Checks if supposed part inst is part of this combined art inst
 	bool isPart(const CArtifactInstance * supposedPart) const;
-	std::vector<PartInfo> & getPartsInfo();
 	const std::vector<PartInfo> & getPartsInfo() const;
 	void addPlacementMap(CArtifactSet::ArtPlacementMap & placementMap);
 

+ 1 - 1
lib/mapping/CMap.cpp

@@ -492,7 +492,7 @@ void CMap::checkForObjectives()
 	}
 }
 
-void CMap::addNewArtifactInstance(CArtifactInstance * art)
+void CMap::addNewArtifactInstance(ConstTransitivePtr<CArtifactInstance> art)
 {
 	art->setId(static_cast<ArtifactInstanceID>(artInstances.size()));
 	artInstances.emplace_back(art);

+ 1 - 1
lib/mapping/CMap.h

@@ -94,7 +94,7 @@ public:
 	void removeBlockVisTiles(CGObjectInstance * obj, bool total = false);
 	void calculateGuardingGreaturePositions();
 
-	void addNewArtifactInstance(CArtifactInstance * art);
+	void addNewArtifactInstance(ConstTransitivePtr<CArtifactInstance> art);
 	void eraseArtifactInstance(CArtifactInstance * art);
 
 	void addNewQuestInstance(CQuest * quest);