mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Refactoring of CGarrisonInt
This commit is contained in:
		| @@ -107,6 +107,7 @@ set(client_SRCS | ||||
| 	widgets/CArtifactsOfHeroMarket.cpp | ||||
| 	widgets/CArtifactsOfHeroBackpack.cpp | ||||
| 	widgets/CWindowWithArtifacts.cpp | ||||
| 	widgets/RadialMenu.cpp | ||||
|  | ||||
| 	windows/CCastleInterface.cpp | ||||
| 	windows/CCreatureWindow.cpp | ||||
| @@ -262,6 +263,7 @@ set(client_HEADERS | ||||
| 	widgets/CArtifactsOfHeroMarket.h | ||||
| 	widgets/CArtifactsOfHeroBackpack.h | ||||
| 	widgets/CWindowWithArtifacts.h | ||||
| 	widgets/RadialMenu.h | ||||
|  | ||||
| 	windows/CCastleInterface.h | ||||
| 	windows/CCreatureWindow.h | ||||
|   | ||||
| @@ -34,6 +34,7 @@ | ||||
| #include "windows/CQuestLog.h" | ||||
| #include "windows/CPuzzleWindow.h" | ||||
| #include "widgets/CComponent.h" | ||||
| #include "widgets/CGarrisonInt.h" | ||||
| #include "widgets/Buttons.h" | ||||
| #include "windows/CTradeWindow.h" | ||||
| #include "windows/CSpellWindow.h" | ||||
| @@ -536,8 +537,8 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town) | ||||
| 	if(castleInt) | ||||
| 	{ | ||||
| 		castleInt->garr->selectSlot(nullptr); | ||||
| 		castleInt->garr->setArmy(town->getUpperArmy(), 0); | ||||
| 		castleInt->garr->setArmy(town->visitingHero, 1); | ||||
| 		castleInt->garr->setArmy(town->getUpperArmy(), EGarrisonType::UPPER); | ||||
| 		castleInt->garr->setArmy(town->visitingHero, EGarrisonType::LOWER); | ||||
| 		castleInt->garr->recreateSlots(); | ||||
| 		castleInt->heroes->update(); | ||||
|  | ||||
| @@ -601,7 +602,7 @@ void CPlayerInterface::garrisonsChanged(std::vector<const CGObjectInstance *> ob | ||||
| 			adventureInt->onTownChanged(town); | ||||
| 	} | ||||
|  | ||||
| 	for (auto cgh : GH.windows().findWindows<CGarrisonHolder>()) | ||||
| 	for (auto cgh : GH.windows().findWindows<IGarrisonHolder>()) | ||||
| 		cgh->updateGarrisons(); | ||||
|  | ||||
| 	for (auto cmw : GH.windows().findWindows<CTradeWindow>()) | ||||
|   | ||||
| @@ -143,6 +143,12 @@ protected: | ||||
| 	void close(); | ||||
| }; | ||||
|  | ||||
| class IGarrisonHolder | ||||
| { | ||||
| public: | ||||
| 	virtual void updateGarrisons() = 0; | ||||
| }; | ||||
|  | ||||
| class IStatusBar | ||||
| { | ||||
| public: | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
|  | ||||
| #include "Buttons.h" | ||||
| #include "TextControls.h" | ||||
| #include "RadialMenu.h" | ||||
|  | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/WindowHandler.h" | ||||
| @@ -30,90 +31,6 @@ | ||||
| #include "../../lib/TextOperations.h" | ||||
| #include "../../lib/gameState/CGameState.h" | ||||
|  | ||||
| RadialMenuItem::RadialMenuItem(std::string imageName, std::function<void()> callback) | ||||
| 	: callback(callback) | ||||
| { | ||||
| 	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; | ||||
|  | ||||
| 	image = IImage::createFromFile("radialMenu/" + imageName); | ||||
| 	picture = std::make_shared<CPicture>(image, Point(0,0)); | ||||
| 	pos = picture->pos; | ||||
| } | ||||
|  | ||||
| bool RadialMenuItem::isInside(const Point & position) | ||||
| { | ||||
| 	Point localPosition = position - pos.topLeft(); | ||||
|  | ||||
| 	return !image->isTransparent(localPosition); | ||||
| } | ||||
|  | ||||
| void RadialMenuItem::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| void RadialMenuItem::gesture(bool on, const Point & initialPosition, const Point & finalPosition) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| RadialMenu::RadialMenu(CGarrisonInt * army, CGarrisonSlot * slot) | ||||
| { | ||||
| 	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; | ||||
|  | ||||
| 	bool isExchange = army->armedObjs[0] && army->armedObjs[1]; // two armies exist | ||||
|  | ||||
| 	addItem(ITEM_NW, "stackMerge", [=](){army->bulkMergeStacks(slot);}); | ||||
| 	addItem(ITEM_NE, "stackInfo", [=](){slot->viewInfo();}); | ||||
|  | ||||
| 	addItem(ITEM_WW, "stackSplitOne", [=](){slot->splitIntoParts(slot->upg, 1); }); | ||||
| 	addItem(ITEM_EE, "stackSplitEqual", [=](){army->bulkSmartSplitStack(slot);}); | ||||
|  | ||||
| 	if (isExchange) | ||||
| 	{ | ||||
| 		addItem(ITEM_SW, "stackMove", [=](){army->moveStackToAnotherArmy(slot);}); | ||||
| 		//FIXME: addItem(ITEM_SE, "stackSplitDialog", [=](){slot->split();}); | ||||
| 	} | ||||
|  | ||||
| 	for(const auto & item : items) | ||||
| 		pos = pos.include(item->pos); | ||||
|  | ||||
| } | ||||
|  | ||||
| void RadialMenu::addItem(const Point & offset, const std::string & path, std::function<void()> callback ) | ||||
| { | ||||
| 	auto item = std::make_shared<RadialMenuItem>(path, callback); | ||||
|  | ||||
| 	item->moveBy(offset); | ||||
|  | ||||
| 	items.push_back(item); | ||||
| } | ||||
|  | ||||
| void RadialMenu::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| void RadialMenu::show(Canvas & to) | ||||
| { | ||||
| 	showAll(to); | ||||
| } | ||||
|  | ||||
| void RadialMenu::gesture(bool on, const Point & initialPosition, const Point & finalPosition) | ||||
| { | ||||
| 	if (!on) | ||||
| 	{ | ||||
| 		for(const auto & item : items) | ||||
| 		{ | ||||
| 			if (item->isInside(finalPosition)) | ||||
| 			{ | ||||
| 				item->callback(); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CGarrisonSlot::setHighlight(bool on) | ||||
| { | ||||
| 	if (on) | ||||
| @@ -157,16 +74,16 @@ void CGarrisonSlot::hover (bool on) | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				const bool isHeroOnMap = owner->armedObjs[0] // Hero is not a visitor and not a garrison defender | ||||
| 					&& owner->armedObjs[0]->ID == Obj::HERO | ||||
| 					&& (!owner->armedObjs[1] || owner->armedObjs[1]->ID == Obj::HERO) // one hero or we are in the Heroes exchange window | ||||
| 					&& !(static_cast<const CGHeroInstance*>(owner->armedObjs[0]))->inTownGarrison; | ||||
| 				const bool isHeroOnMap = owner->upperArmy() // Hero is not a visitor and not a garrison defender | ||||
| 					&& owner->upperArmy()->ID == Obj::HERO | ||||
| 					&& (!owner->lowerArmy() || owner->lowerArmy()->ID == Obj::HERO) // one hero or we are in the Heroes exchange window | ||||
| 					&& !(static_cast<const CGHeroInstance*>(owner->upperArmy()))->inTownGarrison; | ||||
|  | ||||
| 				if(isHeroOnMap) | ||||
| 				{ | ||||
| 					temp = CGI->generaltexth->allTexts[481]; //Select %s | ||||
| 				} | ||||
| 				else if(upg == EGarrisonType::UP) | ||||
| 				else if(upg == EGarrisonType::UPPER) | ||||
| 				{ | ||||
| 					temp = CGI->generaltexth->tcommands[12]; //Select %s (in garrison) | ||||
| 				} | ||||
| @@ -210,16 +127,14 @@ void CGarrisonSlot::hover (bool on) | ||||
|  | ||||
| const CArmedInstance * CGarrisonSlot::getObj() const | ||||
| { | ||||
| 	return 	owner->armedObjs[upg]; | ||||
| 	return owner->army(upg); | ||||
| } | ||||
|  | ||||
| /// @return Whether the unit in the slot belongs to the current player. | ||||
| bool CGarrisonSlot::our() const | ||||
| { | ||||
| 	return owner->owned[upg]; | ||||
| 	return owner->isArmyOwned(upg); | ||||
| } | ||||
|  | ||||
| /// @return Whether the unit in the slot belongs to an ally but not to the current player. | ||||
| bool CGarrisonSlot::ally() const | ||||
| { | ||||
| 	if(!getObj()) | ||||
| @@ -337,19 +252,13 @@ bool CGarrisonSlot::split() | ||||
|  | ||||
| 	auto splitFunctor = [this, selection](int amountLeft, int amountRight) | ||||
| 	{ | ||||
| 		owner->splitStacks(selection, owner->armedObjs[upg], ID, amountRight); | ||||
| 		owner->splitStacks(selection, owner->army(upg), ID, amountRight); | ||||
| 	}; | ||||
|  | ||||
| 	GH.windows().createAndPushWindow<CSplitWindow>(selection->creature,  splitFunctor, minLeft, minRight, countLeft, countRight); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| /// If certain creates cannot be moved, the selection should change | ||||
| /// Force reselection in these cases | ||||
| ///     * When attempting to take creatures from ally | ||||
| ///     * When attempting to swap creatures with an ally | ||||
| ///     * When attempting to take unremovable units | ||||
| /// @return Whether reselection must be done | ||||
| bool CGarrisonSlot::mustForceReselection() const | ||||
| { | ||||
| 	const CGarrisonSlot * selection = owner->getSelection(); | ||||
| @@ -364,10 +273,10 @@ bool CGarrisonSlot::mustForceReselection() const | ||||
| 		return true; | ||||
| 	if (!owner->removableUnits) | ||||
| 	{ | ||||
| 		if (selection->upg == EGarrisonType::UP) | ||||
| 		if (selection->upg == EGarrisonType::UPPER) | ||||
| 			return true; | ||||
| 		else | ||||
| 			return creature || upg == EGarrisonType::UP; | ||||
| 			return creature || upg == EGarrisonType::UPPER; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| @@ -405,7 +314,7 @@ void CGarrisonSlot::clickPressed(const Point & cursorPosition) | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			const CArmedInstance * selectedObj = owner->armedObjs[selection->upg]; | ||||
| 			const CArmedInstance * selectedObj = owner->army(selection->upg); | ||||
| 			bool lastHeroStackSelected = false; | ||||
| 			if(selectedObj->stacksCount() == 1 | ||||
| 				&& owner->getSelection()->upg != upg | ||||
| @@ -420,13 +329,13 @@ void CGarrisonSlot::clickPressed(const Point & cursorPosition) | ||||
| 				refr = split(); | ||||
| 			} | ||||
| 			else if(!creature && lastHeroStackSelected) // split all except last creature | ||||
| 				LOCPLINT->cb->splitStack(selectedObj, owner->armedObjs[upg], selection->ID, ID, selection->myStack->count - 1); | ||||
| 				LOCPLINT->cb->splitStack(selectedObj, owner->army(upg), selection->ID, ID, selection->myStack->count - 1); | ||||
| 			else if(creature != selection->creature) // swap | ||||
| 				LOCPLINT->cb->swapCreatures(owner->armedObjs[upg], selectedObj, ID, selection->ID); | ||||
| 				LOCPLINT->cb->swapCreatures(owner->army(upg), selectedObj, ID, selection->ID); | ||||
| 			else if(lastHeroStackSelected) // merge last stack to other hero stack | ||||
| 				refr = split(); | ||||
| 			else // merge | ||||
| 				LOCPLINT->cb->mergeStacks(selectedObj, owner->armedObjs[upg], selection->ID, ID); | ||||
| 				LOCPLINT->cb->mergeStacks(selectedObj, owner->army(upg), selection->ID, ID); | ||||
| 		} | ||||
| 		if(refr) | ||||
| 		{ | ||||
| @@ -499,7 +408,7 @@ void CGarrisonSlot::update() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, CGarrisonSlot::EGarrisonType Upg, const CStackInstance * creature_) | ||||
| CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, EGarrisonType Upg, const CStackInstance * creature_) | ||||
| 	: ID(IID), | ||||
| 	owner(Owner), | ||||
| 	myStack(creature_), | ||||
| @@ -547,14 +456,14 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, CGa | ||||
| 	update(); | ||||
| } | ||||
|  | ||||
| void CGarrisonSlot::splitIntoParts(CGarrisonSlot::EGarrisonType type, int amount) | ||||
| void CGarrisonSlot::splitIntoParts(EGarrisonType type, int amount) | ||||
| { | ||||
| 	auto empty = owner->getEmptySlot(type); | ||||
|  | ||||
| 	if(empty == SlotID()) | ||||
| 		return; | ||||
|  | ||||
| 	owner->splitStacks(this, owner->armedObjs[type], empty, amount); | ||||
| 	owner->splitStacks(this, owner->army(type), empty, amount); | ||||
| } | ||||
|  | ||||
| bool CGarrisonSlot::handleSplittingShortcuts() | ||||
| @@ -618,21 +527,23 @@ void CGarrisonInt::addSplitBtn(std::shared_ptr<CButton> button) | ||||
| void CGarrisonInt::createSlots() | ||||
| { | ||||
| 	int distance = interx + (smallIcons ? 32 : 58); | ||||
| 	for(int i = 0; i < 2; i++) | ||||
| 	for(auto i : { EGarrisonType::UPPER, EGarrisonType::LOWER }) | ||||
| 	{ | ||||
| 		Point offset = garOffset * static_cast<int>(i); | ||||
|  | ||||
| 		std::vector<std::shared_ptr<CGarrisonSlot>> garrisonSlots; | ||||
| 		garrisonSlots.resize(7); | ||||
| 		if(armedObjs[i]) | ||||
| 		if(army(i)) | ||||
| 		{ | ||||
| 			for(auto & elem : armedObjs[i]->Slots()) | ||||
| 			for(auto & elem : army(i)->Slots()) | ||||
| 			{ | ||||
| 				garrisonSlots[elem.first.getNum()] = std::make_shared<CGarrisonSlot>(this, i*garOffset.x + (elem.first.getNum()*distance), i*garOffset.y, elem.first, static_cast<CGarrisonSlot::EGarrisonType>(i), elem.second); | ||||
| 				garrisonSlots[elem.first.getNum()] = std::make_shared<CGarrisonSlot>(this, offset.x + (elem.first.getNum()*distance), offset.y, elem.first, i, elem.second); | ||||
| 			} | ||||
| 		} | ||||
| 		for(int j = 0; j < 7; j++) | ||||
| 		{ | ||||
| 			if(!garrisonSlots[j]) | ||||
| 				garrisonSlots[j] = std::make_shared<CGarrisonSlot>(this, i*garOffset.x + (j*distance), i*garOffset.y, SlotID(j), static_cast<CGarrisonSlot::EGarrisonType>(i), nullptr); | ||||
| 				garrisonSlots[j] = std::make_shared<CGarrisonSlot>(this, offset.x + (j*distance), offset.x, SlotID(j), i, nullptr); | ||||
|  | ||||
| 			if(layout == ESlotsLayout::TWO_ROWS && j >= 4) | ||||
| 			{ | ||||
| @@ -673,6 +584,7 @@ void CGarrisonInt::splitClick() | ||||
| 	setSplittingMode(!getSplittingMode()); | ||||
| 	redraw(); | ||||
| } | ||||
|  | ||||
| void CGarrisonInt::splitStacks(const CGarrisonSlot * from, const CArmedInstance * armyDest, SlotID slotDest, int amount ) | ||||
| { | ||||
| 	LOCPLINT->cb->splitStack(armedObjs[from->upg], armyDest, from->ID, slotDest, amount); | ||||
| @@ -689,9 +601,9 @@ void CGarrisonInt::moveStackToAnotherArmy(const CGarrisonSlot * selected) | ||||
| 		return; | ||||
|  | ||||
| 	const auto srcArmyType = selected->upg; | ||||
| 	const auto destArmyType = srcArmyType == CGarrisonSlot::UP | ||||
| 		? CGarrisonSlot::DOWN | ||||
| 		: CGarrisonSlot::UP; | ||||
| 	const auto destArmyType = srcArmyType == EGarrisonType::UPPER | ||||
| 		? EGarrisonType::LOWER | ||||
| 		: EGarrisonType::UPPER; | ||||
|  | ||||
| 	auto srcArmy = armedObjs[srcArmyType]; | ||||
| 	auto destArmy = armedObjs[destArmyType]; | ||||
| @@ -733,9 +645,9 @@ void CGarrisonInt::bulkMoveArmy(const CGarrisonSlot * selected) | ||||
| 		return; | ||||
|  | ||||
| 	const auto srcArmyType = selected->upg; | ||||
| 	const auto destArmyType = (srcArmyType == CGarrisonSlot::UP) | ||||
| 		? CGarrisonSlot::DOWN | ||||
| 		: CGarrisonSlot::UP; | ||||
| 	const auto destArmyType = (srcArmyType == EGarrisonType::UPPER) | ||||
| 		? EGarrisonType::LOWER | ||||
| 		: EGarrisonType::UPPER; | ||||
|  | ||||
| 	auto srcArmy = armedObjs[srcArmyType]; | ||||
| 	auto destArmy = armedObjs[destArmyType]; | ||||
| @@ -787,7 +699,7 @@ void CGarrisonInt::bulkSmartSplitStack(const CGarrisonSlot * selected) | ||||
| 	LOCPLINT->cb->bulkSmartSplitStack(armedObjs[type]->id, selected->ID); | ||||
| } | ||||
|  | ||||
| CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point & garsOffset, const CArmedInstance * s1, const CArmedInstance * s2, bool _removableUnits, bool smallImgs, ESlotsLayout _layout) | ||||
| CGarrisonInt::CGarrisonInt(const Point & position, int inx, const Point & garsOffset, const CArmedInstance * s1, const CArmedInstance * s2, bool _removableUnits, bool smallImgs, ESlotsLayout _layout) | ||||
| 	: highlighted(nullptr) | ||||
| 	, inSplittingMode(false) | ||||
| 	, interx(inx) | ||||
| @@ -798,10 +710,9 @@ CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point & garsOffset, cons | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
|  | ||||
| 	setArmy(s1, false); | ||||
| 	setArmy(s2, true); | ||||
| 	pos.x += x; | ||||
| 	pos.y += y; | ||||
| 	setArmy(s1, EGarrisonType::UPPER); | ||||
| 	setArmy(s2, EGarrisonType::LOWER); | ||||
| 	pos += position; | ||||
| 	createSlots(); | ||||
| } | ||||
|  | ||||
| @@ -846,19 +757,51 @@ bool CGarrisonInt::getSplittingMode() | ||||
| 	return inSplittingMode; | ||||
| } | ||||
|  | ||||
| SlotID CGarrisonInt::getEmptySlot(CGarrisonSlot::EGarrisonType type) const | ||||
| SlotID CGarrisonInt::getEmptySlot(EGarrisonType type) const | ||||
| { | ||||
| 	assert(armedObjs[type]); | ||||
| 	return armedObjs[type] ? armedObjs[type]->getFreeSlot() : SlotID(); | ||||
| 	assert(army(type)); | ||||
| 	return army(type) ? army(type)->getFreeSlot() : SlotID(); | ||||
| } | ||||
|  | ||||
| bool CGarrisonInt::hasEmptySlot(CGarrisonSlot::EGarrisonType type) const | ||||
| bool CGarrisonInt::hasEmptySlot(EGarrisonType type) const | ||||
| { | ||||
| 	return getEmptySlot(type) != SlotID(); | ||||
| } | ||||
|  | ||||
| void CGarrisonInt::setArmy(const CArmedInstance * army, bool bottomGarrison) | ||||
| const CArmedInstance * CGarrisonInt::upperArmy() const | ||||
| { | ||||
| 	owned[bottomGarrison] =  army ? (army->tempOwner == LOCPLINT->playerID || army->tempOwner == PlayerColor::UNFLAGGABLE) : false; | ||||
| 	armedObjs[bottomGarrison] = army; | ||||
| 	return army(EGarrisonType::UPPER); | ||||
| } | ||||
|  | ||||
| const CArmedInstance * CGarrisonInt::lowerArmy() const | ||||
| { | ||||
| 	return army(EGarrisonType::LOWER); | ||||
| } | ||||
|  | ||||
| const CArmedInstance * CGarrisonInt::army(EGarrisonType which) const | ||||
| { | ||||
| 	if(armedObjs.count(which)) | ||||
| 		return armedObjs.at(which); | ||||
| 	return nullptr; | ||||
| } | ||||
|  | ||||
| bool CGarrisonInt::isArmyOwned(EGarrisonType which) const | ||||
| { | ||||
| 	const auto * object = army(which); | ||||
|  | ||||
| 	if (!object) | ||||
| 		return false; | ||||
|  | ||||
| 	if (object->tempOwner == LOCPLINT->playerID) | ||||
| 		return true; | ||||
|  | ||||
| 	if (object->tempOwner == PlayerColor::UNFLAGGABLE) | ||||
| 		return true; | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| void CGarrisonInt::setArmy(const CArmedInstance * army, EGarrisonType type) | ||||
| { | ||||
| 	armedObjs[type] = army; | ||||
| } | ||||
|   | ||||
| @@ -9,12 +9,11 @@ | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include "../windows/CWindowObject.h" | ||||
| #include "../gui/CIntObject.h" | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
| class CArmedInstance; | ||||
| class CCreatureSet; | ||||
| class CStackInstance; | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_END | ||||
| @@ -22,60 +21,23 @@ VCMI_LIB_NAMESPACE_END | ||||
| class CGarrisonInt; | ||||
| class CButton; | ||||
| class CAnimImage; | ||||
| class CGarrisonSlot; | ||||
| class CLabel; | ||||
| class IImage; | ||||
| class RadialMenu; | ||||
|  | ||||
| class RadialMenuItem : public CIntObject | ||||
| enum class EGarrisonType | ||||
| { | ||||
| 	std::shared_ptr<IImage> image; | ||||
| 	std::shared_ptr<CPicture> picture; | ||||
| public: | ||||
| 	std::function<void()> callback; | ||||
|  | ||||
| 	RadialMenuItem(std::string imageName, std::function<void()> callback); | ||||
|  | ||||
| 	bool isInside(const Point & position); | ||||
|  | ||||
| 	void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override; | ||||
| 	void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override; | ||||
| }; | ||||
|  | ||||
| class RadialMenu : public CIntObject | ||||
| { | ||||
| 	static constexpr Point ITEM_NW = Point( -35, -85); | ||||
| 	static constexpr Point ITEM_NE = Point( +35, -85); | ||||
| 	static constexpr Point ITEM_WW = Point( -85, 0); | ||||
| 	static constexpr Point ITEM_EE = Point( +85, 0); | ||||
| 	static constexpr Point ITEM_SW = Point( -35, +85); | ||||
| 	static constexpr Point ITEM_SE = Point( +35, +85); | ||||
|  | ||||
| 	std::vector<std::shared_ptr<RadialMenuItem>> items; | ||||
|  | ||||
| 	void addItem(const Point & offset, const std::string & path, std::function<void()> callback ); | ||||
| public: | ||||
| 	RadialMenu(CGarrisonInt * army, CGarrisonSlot * slot); | ||||
|  | ||||
| 	void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override; | ||||
| 	void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override; | ||||
| 	void show(Canvas & to) override; | ||||
| 	UPPER, /// up garrison (Garrisoned) | ||||
| 	LOWER, /// down garrison (Visiting) | ||||
| }; | ||||
|  | ||||
| /// A single garrison slot which holds one creature of a specific amount | ||||
| class CGarrisonSlot : public CIntObject | ||||
| { | ||||
| public: | ||||
| 	SlotID ID; //for identification | ||||
| 	CGarrisonInt *owner; | ||||
| 	const CStackInstance * myStack; //nullptr if slot is empty | ||||
| 	const CCreature * creature; | ||||
|  | ||||
| 	/// Type of Garrison for slot (up or down) | ||||
| 	enum EGarrisonType | ||||
| 	{ | ||||
| 		UP=0,  ///< 0 - up garrison (Garrisoned) | ||||
| 		DOWN,  ///< 1 - down garrison (Visiting) | ||||
| 	} upg; ///< Flag indicating if it is the up or down garrison | ||||
| 	EGarrisonType upg; | ||||
|  | ||||
| 	std::shared_ptr<CAnimImage> creatureImage; | ||||
| 	std::shared_ptr<CAnimImage> selectionImage; // image for selection, not always visible | ||||
| @@ -86,24 +48,33 @@ public: | ||||
| 	bool viewInfo(); | ||||
| 	bool highlightOrDropArtifact(); | ||||
| 	bool split(); | ||||
|  | ||||
| 	/// If certain creates cannot be moved, the selection should change | ||||
| 	/// Force reselection in these cases | ||||
| 	///     * When attempting to take creatures from ally | ||||
| 	///     * When attempting to swap creatures with an ally | ||||
| 	///     * When attempting to take unremovable units | ||||
| 	/// @return Whether reselection must be done | ||||
| 	bool mustForceReselection() const; | ||||
|  | ||||
| 	void setHighlight(bool on); | ||||
| 	std::function<void()> getDismiss() const; | ||||
|  | ||||
| 	virtual void hover (bool on) override; //call-in | ||||
| 	const CArmedInstance * getObj() const; | ||||
| 	bool our() const; | ||||
| 	SlotID getSlot() const { return ID; } | ||||
| 	EGarrisonType getGarrison() const { return upg; } | ||||
| 	bool ally() const; | ||||
|  | ||||
| 	// CIntObject overrides | ||||
| 	void showPopupWindow(const Point & cursorPosition) override; | ||||
| 	void clickPressed(const Point & cursorPosition) override; | ||||
|  | ||||
| 	void hover (bool on) override; //call-in | ||||
| 	void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override; | ||||
| 	void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override; | ||||
|  | ||||
| 	void update(); | ||||
| 	CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, EGarrisonType Upg=EGarrisonType::UP, const CStackInstance * creature_ = nullptr); | ||||
| 	CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, EGarrisonType Upg, const CStackInstance * creature_); | ||||
|  | ||||
| 	void splitIntoParts(EGarrisonType type, int amount); | ||||
| 	bool handleSplittingShortcuts(); /// Returns true when some shortcut is pressed, false otherwise | ||||
| @@ -122,6 +93,8 @@ class CGarrisonInt :public CIntObject | ||||
| 	void createSlots(); | ||||
| 	bool checkSelected(const CGarrisonSlot * selected, TQuantity min = 0) const; | ||||
|  | ||||
| 	std::map<EGarrisonType, const CArmedInstance*> armedObjs; | ||||
|  | ||||
| public: | ||||
| 	enum class ESlotsLayout | ||||
| 	{ | ||||
| @@ -137,7 +110,6 @@ public: | ||||
| 	bool smallIcons;      ///< true - 32x32 imgs, false - 58x64 | ||||
| 	bool removableUnits;  ///< player Can remove units from up | ||||
| 	bool twoRows;         ///< slots Will be placed in 2 rows | ||||
| 	bool owned[2];        ///< player Owns up or down army ([0] upper, [1] lower) | ||||
|  | ||||
| 	ESlotsLayout layout; | ||||
|  | ||||
| @@ -147,16 +119,19 @@ public: | ||||
| 	void setSplittingMode(bool on); | ||||
| 	bool getSplittingMode(); | ||||
|  | ||||
| 	bool hasEmptySlot(CGarrisonSlot::EGarrisonType type) const; | ||||
| 	SlotID getEmptySlot(CGarrisonSlot::EGarrisonType type) const; | ||||
| 	bool hasEmptySlot(EGarrisonType type) const; | ||||
| 	SlotID getEmptySlot(EGarrisonType type) const; | ||||
|  | ||||
| 	const CArmedInstance * armedObjs[2];  ///< [0] is upper, [1] is down | ||||
|  | ||||
| 	void setArmy(const CArmedInstance * army, bool bottomGarrison); | ||||
| 	void setArmy(const CArmedInstance * army, EGarrisonType type); | ||||
| 	void addSplitBtn(std::shared_ptr<CButton> button); | ||||
|  | ||||
| 	void recreateSlots(); | ||||
|  | ||||
| 	const CArmedInstance* upperArmy() const; | ||||
| 	const CArmedInstance* lowerArmy() const; | ||||
| 	const CArmedInstance* army(EGarrisonType which) const; | ||||
| 	bool isArmyOwned(EGarrisonType which) const; | ||||
|  | ||||
| 	void splitClick();  ///< handles click on split button | ||||
| 	void splitStacks(const CGarrisonSlot * from, const CArmedInstance * armyDest, SlotID slotDest, int amount);  ///< TODO: comment me | ||||
| 	void moveStackToAnotherArmy(const CGarrisonSlot * selected); | ||||
| @@ -166,24 +141,17 @@ public: | ||||
| 	void bulkSmartSplitStack(const CGarrisonSlot * selected); | ||||
|  | ||||
| 	/// Constructor | ||||
| 	/// @param x, y Position | ||||
| 	/// @param inx Distance between slots; | ||||
| 	/// @param garsOffset | ||||
| 	/// @param position Relative position to parent element | ||||
| 	/// @param slotInterval Distance between slots; | ||||
| 	/// @param secondGarrisonOffset | ||||
| 	/// @param s1, s2 Top and bottom armies | ||||
| 	/// @param _removableUnits You can take units from top | ||||
| 	/// @param smallImgs Units images size 64x58 or 32x32 | ||||
| 	/// @param _layout - when TWO_ROWS - Display slots in 2 rows (1st row = 4 slots, 2nd = 3 slots), REVERSED_TWO_ROWS = 3 slots in 1st row | ||||
| 	CGarrisonInt(int x, int y, int inx, | ||||
| 				 const Point & garsOffset, | ||||
| 				 const CArmedInstance * s1, const CArmedInstance * s2 = nullptr, | ||||
| 	CGarrisonInt(const Point & position, int slotInterval, | ||||
| 				 const Point & secondGarrisonOffset, | ||||
| 				 const CArmedInstance * upperArmy, const CArmedInstance * lowerArmy = nullptr, | ||||
| 				 bool _removableUnits = true, | ||||
| 				 bool smallImgs = false, | ||||
| 				 ESlotsLayout _layout = ESlotsLayout::ONE_ROW); | ||||
| }; | ||||
|  | ||||
| class CGarrisonHolder | ||||
| { | ||||
| public: | ||||
| 	virtual void updateGarrisons() = 0; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -304,7 +304,7 @@ CHeroTooltip::CHeroTooltip(Point pos, const CGHeroInstance * hero): | ||||
| } | ||||
|  | ||||
| CInteractableHeroTooltip::CInteractableHeroTooltip(Point pos, const CGHeroInstance * hero): | ||||
| 		CGarrisonInt(pos.x, pos.y+73, 4, Point(0, 0), hero, nullptr, true, true, CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS) | ||||
| 		CGarrisonInt(pos + Point(0, 73), 4, Point(0, 0), hero, nullptr, true, true, CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS) | ||||
| { | ||||
| 	init(InfoAboutHero(hero, InfoAboutHero::EInfoLevel::DETAILED)); | ||||
| } | ||||
| @@ -383,7 +383,7 @@ CTownTooltip::CTownTooltip(Point pos, const CGTownInstance * town) | ||||
| } | ||||
|  | ||||
| CInteractableTownTooltip::CInteractableTownTooltip(Point pos, const CGTownInstance * town) | ||||
| 		: CGarrisonInt(pos.x, pos.y+73, 4, Point(0, 0), town->getUpperArmy(), nullptr, true, true, CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS) | ||||
| 		: CGarrisonInt(pos + Point(0, 73), 4, Point(0, 0), town->getUpperArmy(), nullptr, true, true, CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS) | ||||
| { | ||||
| 	init(InfoAboutTown(town, true)); | ||||
| } | ||||
|   | ||||
							
								
								
									
										101
									
								
								client/widgets/RadialMenu.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								client/widgets/RadialMenu.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| /* | ||||
|  * RadialMenu.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 "StdInc.h" | ||||
| #include "RadialMenu.h" | ||||
|  | ||||
| #include "Images.h" | ||||
|  | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../render/IImage.h" | ||||
| #include "CGarrisonInt.h" | ||||
|  | ||||
| RadialMenuItem::RadialMenuItem(std::string imageName, std::function<void()> callback) | ||||
| 	: callback(callback) | ||||
| { | ||||
| 	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; | ||||
|  | ||||
| 	image = IImage::createFromFile("radialMenu/" + imageName); | ||||
| 	picture = std::make_shared<CPicture>(image, Point(0,0)); | ||||
| 	pos = picture->pos; | ||||
| } | ||||
|  | ||||
| bool RadialMenuItem::isInside(const Point & position) | ||||
| { | ||||
| 	Point localPosition = position - pos.topLeft(); | ||||
|  | ||||
| 	return !image->isTransparent(localPosition); | ||||
| } | ||||
|  | ||||
| void RadialMenuItem::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| void RadialMenuItem::gesture(bool on, const Point & initialPosition, const Point & finalPosition) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| RadialMenu::RadialMenu(CGarrisonInt * army, CGarrisonSlot * slot) | ||||
| { | ||||
| 	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; | ||||
|  | ||||
| 	bool isExchange = army->upperArmy() && army->lowerArmy(); // two armies exist | ||||
|  | ||||
| 	addItem(ITEM_NW, "stackMerge", [=](){army->bulkMergeStacks(slot);}); | ||||
| 	addItem(ITEM_NE, "stackInfo", [=](){slot->viewInfo();}); | ||||
|  | ||||
| 	addItem(ITEM_WW, "stackSplitOne", [=](){slot->splitIntoParts(slot->getGarrison(), 1); }); | ||||
| 	addItem(ITEM_EE, "stackSplitEqual", [=](){army->bulkSmartSplitStack(slot);}); | ||||
|  | ||||
| 	if (isExchange) | ||||
| 	{ | ||||
| 		addItem(ITEM_SW, "stackMove", [=](){army->moveStackToAnotherArmy(slot);}); | ||||
| 		//FIXME: addItem(ITEM_SE, "stackSplitDialog", [=](){slot->split();}); | ||||
| 	} | ||||
|  | ||||
| 	for(const auto & item : items) | ||||
| 		pos = pos.include(item->pos); | ||||
|  | ||||
| } | ||||
|  | ||||
| void RadialMenu::addItem(const Point & offset, const std::string & path, std::function<void()> callback ) | ||||
| { | ||||
| 	auto item = std::make_shared<RadialMenuItem>(path, callback); | ||||
|  | ||||
| 	item->moveBy(offset); | ||||
|  | ||||
| 	items.push_back(item); | ||||
| } | ||||
|  | ||||
| void RadialMenu::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| void RadialMenu::show(Canvas & to) | ||||
| { | ||||
| 	showAll(to); | ||||
| } | ||||
|  | ||||
| void RadialMenu::gesture(bool on, const Point & initialPosition, const Point & finalPosition) | ||||
| { | ||||
| 	if (!on) | ||||
| 	{ | ||||
| 		for(const auto & item : items) | ||||
| 		{ | ||||
| 			if (item->isInside(finalPosition)) | ||||
| 			{ | ||||
| 				item->callback(); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										52
									
								
								client/widgets/RadialMenu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								client/widgets/RadialMenu.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| /* | ||||
|  * RadialMenu.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 "../gui/CIntObject.h" | ||||
|  | ||||
| class IImage; | ||||
|  | ||||
| class CGarrisonInt; | ||||
| class CGarrisonSlot; | ||||
|  | ||||
| class RadialMenuItem : public CIntObject | ||||
| { | ||||
| 	std::shared_ptr<IImage> image; | ||||
| 	std::shared_ptr<CPicture> picture; | ||||
| public: | ||||
| 	std::function<void()> callback; | ||||
|  | ||||
| 	RadialMenuItem(std::string imageName, std::function<void()> callback); | ||||
|  | ||||
| 	bool isInside(const Point & position); | ||||
|  | ||||
| 	void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override; | ||||
| 	void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override; | ||||
| }; | ||||
|  | ||||
| class RadialMenu : public CIntObject | ||||
| { | ||||
| 	static constexpr Point ITEM_NW = Point( -35, -85); | ||||
| 	static constexpr Point ITEM_NE = Point( +35, -85); | ||||
| 	static constexpr Point ITEM_WW = Point( -85, 0); | ||||
| 	static constexpr Point ITEM_EE = Point( +85, 0); | ||||
| 	static constexpr Point ITEM_SW = Point( -35, +85); | ||||
| 	static constexpr Point ITEM_SE = Point( +35, +85); | ||||
|  | ||||
| 	std::vector<std::shared_ptr<RadialMenuItem>> items; | ||||
|  | ||||
| 	void addItem(const Point & offset, const std::string & path, std::function<void()> callback ); | ||||
| public: | ||||
| 	RadialMenu(CGarrisonInt * army, CGarrisonSlot * slot); | ||||
|  | ||||
| 	void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override; | ||||
| 	void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override; | ||||
| 	void show(Canvas & to) override; | ||||
| }; | ||||
| @@ -25,6 +25,7 @@ | ||||
| #include "../gui/WindowHandler.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/CGarrisonInt.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../render/Canvas.h" | ||||
| @@ -1154,7 +1155,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst | ||||
| 	center(); | ||||
| 	updateShadow(); | ||||
|  | ||||
| 	garr = std::make_shared<CGarrisonInt>(305, 387, 4, Point(0,96), town->getUpperArmy(), town->visitingHero); | ||||
| 	garr = std::make_shared<CGarrisonInt>(Point(305, 387), 4, Point(0,96), town->getUpperArmy(), town->visitingHero); | ||||
| 	garr->setRedrawParent(true); | ||||
|  | ||||
| 	heroes = std::make_shared<HeroSlots>(town, Point(241, 387), Point(241, 483), garr, true); | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include "../widgets/CGarrisonInt.h" | ||||
| #include "../windows/CWindowObject.h" | ||||
| #include "../widgets/Images.h" | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
| @@ -212,7 +212,7 @@ public: | ||||
| }; | ||||
|  | ||||
| /// Class which manages the castle window | ||||
| class CCastleInterface : public CStatusbarWindow, public CGarrisonHolder | ||||
| class CCastleInterface : public CStatusbarWindow, public IGarrisonHolder | ||||
| { | ||||
| 	std::shared_ptr<CLabel> title; | ||||
| 	std::shared_ptr<CLabel> income; | ||||
|   | ||||
| @@ -24,6 +24,7 @@ | ||||
| #include "../gui/WindowHandler.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/CGarrisonInt.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../render/CAnimation.h" | ||||
| @@ -200,7 +201,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded) | ||||
| 			std::string helpBox = heroscrn[32]; | ||||
| 			boost::algorithm::replace_first(helpBox, "%s", CGI->generaltexth->allTexts[43]); | ||||
|  | ||||
| 			garr = std::make_shared<CGarrisonInt>(15, 485, 8, Point(), curHero); | ||||
| 			garr = std::make_shared<CGarrisonInt>(Point(15, 485), 8, Point(), curHero); | ||||
| 			auto split = std::make_shared<CButton>(Point(539, 519), "hsbtns9.def", CButton::tooltip(CGI->generaltexth->allTexts[256], helpBox), [&](){ garr->splitClick(); }); | ||||
| 			garr->addSplitBtn(split); | ||||
| 		} | ||||
|   | ||||
| @@ -9,12 +9,12 @@ | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include <vcmi/FactionMember.h> | ||||
|  | ||||
| #include "../../lib/bonuses/Bonus.h" | ||||
| #include "../../lib/bonuses/IBonusBearer.h" | ||||
| #include "../widgets/CWindowWithArtifacts.h" | ||||
| #include "../widgets/CGarrisonInt.h" | ||||
| #include "CWindowObject.h" | ||||
|  | ||||
| #include "../../lib/bonuses/IBonusBearer.h" | ||||
|  | ||||
| #include <vcmi/FactionMember.h> | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
| @@ -33,6 +33,7 @@ class CToggleButton; | ||||
| class CToggleGroup; | ||||
| class CGStatusBar; | ||||
| class CTextBox; | ||||
| class CGarrisonInt; | ||||
|  | ||||
| /// Button which switches hero selection | ||||
| class CHeroSwitcher : public CIntObject | ||||
| @@ -46,7 +47,7 @@ public: | ||||
| 	CHeroSwitcher(CHeroWindow * owner_, Point pos_, const CGHeroInstance * hero_); | ||||
| }; | ||||
|  | ||||
| class CHeroWindow : public CStatusbarWindow, public CGarrisonHolder, public CWindowWithArtifacts | ||||
| class CHeroWindow : public CStatusbarWindow, public IGarrisonHolder, public CWindowWithArtifacts | ||||
| { | ||||
| 	std::shared_ptr<CLabel> name; | ||||
| 	std::shared_ptr<CLabel> title; | ||||
|   | ||||
| @@ -20,6 +20,7 @@ | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/CGarrisonInt.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| @@ -646,7 +647,7 @@ void CKingdomInterface::heroRemoved() | ||||
|  | ||||
| void CKingdomInterface::updateGarrisons() | ||||
| { | ||||
| 	if(auto garrison = std::dynamic_pointer_cast<CGarrisonHolder>(tabArea->getItem())) | ||||
| 	if(auto garrison = std::dynamic_pointer_cast<IGarrisonHolder>(tabArea->getItem())) | ||||
| 		garrison->updateGarrisons(); | ||||
| } | ||||
|  | ||||
| @@ -692,7 +693,7 @@ void CKingdHeroList::updateGarrisons() | ||||
| { | ||||
| 	for(std::shared_ptr<CIntObject> object : heroes->getItems()) | ||||
| 	{ | ||||
| 		if(CGarrisonHolder * garrison = dynamic_cast<CGarrisonHolder*>(object.get())) | ||||
| 		if(IGarrisonHolder * garrison = dynamic_cast<IGarrisonHolder*>(object.get())) | ||||
| 			garrison->updateGarrisons(); | ||||
| 	} | ||||
| } | ||||
| @@ -744,7 +745,7 @@ void CKingdTownList::updateGarrisons() | ||||
| { | ||||
| 	for(std::shared_ptr<CIntObject> object : towns->getItems()) | ||||
| 	{ | ||||
| 		if(CGarrisonHolder * garrison = dynamic_cast<CGarrisonHolder*>(object.get())) | ||||
| 		if(IGarrisonHolder * garrison = dynamic_cast<IGarrisonHolder*>(object.get())) | ||||
| 			garrison->updateGarrisons(); | ||||
| 	} | ||||
| } | ||||
| @@ -772,7 +773,7 @@ CTownItem::CTownItem(const CGTownInstance * Town) | ||||
| 	hall = std::make_shared<CTownInfo>( 69, 31, town, true); | ||||
| 	fort = std::make_shared<CTownInfo>(111, 31, town, false); | ||||
|  | ||||
| 	garr = std::make_shared<CGarrisonInt>(313, 3, 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, CGarrisonInt::ESlotsLayout::TWO_ROWS); | ||||
| 	garr = std::make_shared<CGarrisonInt>(Point(313, 3), 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, CGarrisonInt::ESlotsLayout::TWO_ROWS); | ||||
| 	heroes = std::make_shared<HeroSlots>(town, Point(244,6), Point(475,6), garr, false); | ||||
|  | ||||
| 	size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)]; | ||||
| @@ -790,8 +791,8 @@ CTownItem::CTownItem(const CGTownInstance * Town) | ||||
| void CTownItem::updateGarrisons() | ||||
| { | ||||
| 	garr->selectSlot(nullptr); | ||||
| 	garr->setArmy(town->getUpperArmy(), 0); | ||||
| 	garr->setArmy(town->visitingHero, 1); | ||||
| 	garr->setArmy(town->getUpperArmy(), EGarrisonType::UPPER); | ||||
| 	garr->setArmy(town->visitingHero, EGarrisonType::LOWER); | ||||
| 	garr->recreateSlots(); | ||||
| } | ||||
|  | ||||
| @@ -913,7 +914,7 @@ CHeroItem::CHeroItem(const CGHeroInstance * Hero) | ||||
| 	artButtons->addCallback(std::bind(&CHeroItem::onArtChange, this, _1)); | ||||
| 	artButtons->setSelected(0); | ||||
|  | ||||
| 	garr = std::make_shared<CGarrisonInt>(6, 78, 4, Point(), hero, nullptr, true, true); | ||||
| 	garr = std::make_shared<CGarrisonInt>(Point(6, 78), 4, Point(), hero, nullptr, true, true); | ||||
|  | ||||
| 	portrait = std::make_shared<CAnimImage>("PortraitsLarge", hero->portrait, 0, 5, 6); | ||||
| 	heroArea = std::make_shared<CHeroArea>(5, 6, hero); | ||||
|   | ||||
| @@ -10,7 +10,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "../widgets/CWindowWithArtifacts.h" | ||||
| #include "../widgets/CGarrisonInt.h" | ||||
| #include "CWindowObject.h" | ||||
|  | ||||
| class CButton; | ||||
| class CAnimImage; | ||||
| @@ -27,6 +27,7 @@ class MoraleLuckBox; | ||||
| class CListBox; | ||||
| class CTabbedInt; | ||||
| class CGStatusBar; | ||||
| class CGarrisonInt; | ||||
|  | ||||
| class CKingdHeroList; | ||||
| class CKingdTownList; | ||||
| @@ -195,7 +196,7 @@ public: | ||||
| }; | ||||
|  | ||||
| /// Class which holds all parts of kingdom overview window | ||||
| class CKingdomInterface : public CWindowObject, public CGarrisonHolder, public CArtifactHolder | ||||
| class CKingdomInterface : public CWindowObject, public IGarrisonHolder, public CArtifactHolder | ||||
| { | ||||
| private: | ||||
| 	struct OwnedObjectInfo | ||||
| @@ -255,7 +256,7 @@ public: | ||||
| }; | ||||
|  | ||||
| /// List item with town | ||||
| class CTownItem : public CIntObject, public CGarrisonHolder | ||||
| class CTownItem : public CIntObject, public IGarrisonHolder | ||||
| { | ||||
| 	std::shared_ptr<CAnimImage> background; | ||||
| 	std::shared_ptr<CAnimImage> picture; | ||||
| @@ -282,7 +283,7 @@ public: | ||||
| }; | ||||
|  | ||||
| /// List item with hero | ||||
| class CHeroItem : public CIntObject, public CGarrisonHolder | ||||
| class CHeroItem : public CIntObject, public IGarrisonHolder | ||||
| { | ||||
| 	const CGHeroInstance * hero; | ||||
|  | ||||
| @@ -315,7 +316,7 @@ public: | ||||
| }; | ||||
|  | ||||
| /// Tab with all hero-specific data | ||||
| class CKingdHeroList : public CIntObject, public CGarrisonHolder, public CWindowWithArtifacts | ||||
| class CKingdHeroList : public CIntObject, public IGarrisonHolder, public CWindowWithArtifacts | ||||
| { | ||||
| private: | ||||
| 	std::shared_ptr<CListBox> heroes; | ||||
| @@ -331,7 +332,7 @@ public: | ||||
| }; | ||||
|  | ||||
| /// Tab with all town-specific data | ||||
| class CKingdTownList : public CIntObject, public CGarrisonHolder | ||||
| class CKingdTownList : public CIntObject, public IGarrisonHolder | ||||
| { | ||||
| private: | ||||
| 	std::shared_ptr<CListBox> towns; | ||||
|   | ||||
| @@ -31,6 +31,7 @@ | ||||
| #include "../gui/WindowHandler.h" | ||||
|  | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/CGarrisonInt.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/CreatureCostBox.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| @@ -968,7 +969,7 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, | ||||
|  | ||||
| 	//garrison interface | ||||
|  | ||||
| 	garr = std::make_shared<CGarrisonInt>(69, qeLayout ? 122 : 131, 4, Point(418,0), heroInst[0], heroInst[1], true, true); | ||||
| 	garr = std::make_shared<CGarrisonInt>(Point(69, qeLayout ? 122 : 131), 4, Point(418,0), heroInst[0], heroInst[1], true, true); | ||||
| 	auto splitButtonCallback = [&](){ garr->splitClick(); }; | ||||
| 	garr->addSplitBtn(std::make_shared<CButton>( Point( 10, qeLayout ? 122 : 132), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), splitButtonCallback)); | ||||
| 	garr->addSplitBtn(std::make_shared<CButton>( Point(744, qeLayout ? 122 : 132), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), splitButtonCallback)); | ||||
| @@ -1351,7 +1352,7 @@ CGarrisonWindow::CGarrisonWindow(const CArmedInstance * up, const CGHeroInstance | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
|  | ||||
| 	garr = std::make_shared<CGarrisonInt>(92, 127, 4, Point(0,96), up, down, removableUnits); | ||||
| 	garr = std::make_shared<CGarrisonInt>(Point(92, 127), 4, Point(0,96), up, down, removableUnits); | ||||
| 	{ | ||||
| 		auto split = std::make_shared<CButton>(Point(88, 314), "IDV6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3], ""), [&](){ garr->splitClick(); } ); | ||||
| 		garr->addSplitBtn(split); | ||||
| @@ -1424,7 +1425,7 @@ CHillFortWindow::CHillFortWindow(const CGHeroInstance * visitor, const CGObjectI | ||||
| 	quit = std::make_shared<CButton>(Point(294, 275), "IOKAY.DEF", CButton::tooltip(), std::bind(&CHillFortWindow::close, this), EShortcut::GLOBAL_ACCEPT); | ||||
| 	statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); | ||||
|  | ||||
| 	garr = std::make_shared<CGarrisonInt>(108, 60, 18, Point(), hero, nullptr); | ||||
| 	garr = std::make_shared<CGarrisonInt>(Point(108, 60), 18, Point(), hero, nullptr); | ||||
| 	updateGarrisons(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -14,7 +14,6 @@ | ||||
| #include "../lib/ResourceSet.h" | ||||
| #include "../lib/int3.h" | ||||
| #include "../widgets/CWindowWithArtifacts.h" | ||||
| #include "../widgets/CGarrisonInt.h" | ||||
| #include "../widgets/Images.h" | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
| @@ -38,6 +37,8 @@ class CToggleButton; | ||||
| class CGStatusBar; | ||||
| class CTextBox; | ||||
| class CResDataBar; | ||||
| class CGarrisonInt; | ||||
| class CGarrisonSlot; | ||||
|  | ||||
| enum class EUserEvent; | ||||
|  | ||||
| @@ -273,7 +274,7 @@ private: | ||||
| 	void moveStack(const CGHeroInstance * source, const CGHeroInstance * target, SlotID sourceSlot); | ||||
| }; | ||||
|  | ||||
| class CExchangeWindow : public CStatusbarWindow, public CGarrisonHolder, public CWindowWithArtifacts | ||||
| class CExchangeWindow : public CStatusbarWindow, public IGarrisonHolder, public CWindowWithArtifacts | ||||
| { | ||||
| 	std::array<std::shared_ptr<CLabel>, 2> titles; | ||||
| 	std::vector<std::shared_ptr<CAnimImage>> primSkillImages;//shared for both heroes | ||||
| @@ -348,7 +349,7 @@ public: | ||||
| }; | ||||
|  | ||||
| /// Creature transformer window | ||||
| class CTransformerWindow : public CStatusbarWindow, public CGarrisonHolder | ||||
| class CTransformerWindow : public CStatusbarWindow, public IGarrisonHolder | ||||
| { | ||||
| 	class CItem : public CIntObject | ||||
| 	{ | ||||
| @@ -449,7 +450,7 @@ public: | ||||
| }; | ||||
|  | ||||
| /// Garrison window where you can take creatures out of the hero to place it on the garrison | ||||
| class CGarrisonWindow : public CWindowObject, public CGarrisonHolder | ||||
| class CGarrisonWindow : public CWindowObject, public IGarrisonHolder | ||||
| { | ||||
| 	std::shared_ptr<CLabel> title; | ||||
| 	std::shared_ptr<CAnimImage> banner; | ||||
| @@ -466,7 +467,7 @@ public: | ||||
| }; | ||||
|  | ||||
| /// Hill fort is the building where you can upgrade units | ||||
| class CHillFortWindow : public CStatusbarWindow, public CGarrisonHolder | ||||
| class CHillFortWindow : public CStatusbarWindow, public IGarrisonHolder | ||||
| { | ||||
| private: | ||||
| 	static const int slotsCount = 7; | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include "../widgets/CGarrisonInt.h" | ||||
| #include "../windows/CWindowObject.h" | ||||
|  | ||||
| class CButton; | ||||
| class CreatureCostBox; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user