浏览代码

Merge pull request #6158 from Laserlicht/gen_res_assets

generate market windows for 8/9 resources
Ivan Savenko 1 周之前
父节点
当前提交
e81d5bc973

+ 75 - 0
client/render/AssetGenerator.cpp

@@ -57,6 +57,22 @@ void AssetGenerator::initialize()
 		imageFiles[ImagePath::builtin(name)] = [this, color](){ return createResBarElement(std::max(PlayerColor(0), color));};
 	}
 
+	for (PlayerColor color(-1); color < PlayerColor::PLAYER_LIMIT; ++color)
+	{
+		for(int amount : { 8, 9 })
+		{
+			auto addResWindow = [this, amount, color](std::string baseName, CreateResourceWindowType type){
+				std::string name = baseName + "-R" + std::to_string(amount) + (color == -1 ? "" : "-" + color.toString());
+				imageFiles[ImagePath::builtin(name)] = [this, color, amount, type](){ return createResourceWindow(type, amount, std::max(PlayerColor(0), color)); };
+			};
+			addResWindow("TPMRKABS", CreateResourceWindowType::ARTIFACTS_BUYING);
+			addResWindow("TPMRKASS", CreateResourceWindowType::ARTIFACTS_SELLING);
+			addResWindow("TPMRKRES", CreateResourceWindowType::MARKET_RESOURCES);
+			addResWindow("TPMRKCRS", CreateResourceWindowType::FREELANCERS_GUILD);
+			addResWindow("TPMRKPTS", CreateResourceWindowType::TRANSFER_RESOURCES);
+		}
+	}
+
 	imageFiles[ImagePath::builtin("stackWindow/info-panel-0.png")] = [this](){ return createCreatureInfoPanel(2);};
 	imageFiles[ImagePath::builtin("stackWindow/info-panel-1.png")] = [this](){ return createCreatureInfoPanel(3);};
 	imageFiles[ImagePath::builtin("stackWindow/info-panel-2.png")] = [this](){ return createCreatureInfoPanel(4);};
@@ -669,6 +685,65 @@ AssetGenerator::CanvasPtr AssetGenerator::createCreatureInfoPanel(int boxesAmoun
 	return image;
 }
 
+AssetGenerator::CanvasPtr AssetGenerator::createResourceWindow(CreateResourceWindowType type, int count, PlayerColor color) const
+{
+	assert(count >= 8 && count <= 9);
+
+	const std::map<CreateResourceWindowType, ImagePath> files = {
+		{ ARTIFACTS_BUYING,   ImagePath::builtin("TPMRKABS") },
+		{ ARTIFACTS_SELLING,  ImagePath::builtin("TPMRKASS") },
+		{ MARKET_RESOURCES,   ImagePath::builtin("TPMRKRES") },
+		{ FREELANCERS_GUILD,  ImagePath::builtin("TPMRKCRS") },
+		{ TRANSFER_RESOURCES, ImagePath::builtin("TPMRKPTS") }
+	};
+
+	auto file = files.at(type);
+	auto locator = ImageLocator(file, EImageBlitMode::COLORKEY);
+	std::shared_ptr<IImage> baseImg = ENGINE->renderHandler().loadImage(locator);
+	baseImg->playerColored(color);
+
+	auto image = ENGINE->renderHandler().createImage(baseImg->dimensions(), CanvasScalingPolicy::IGNORE);
+	Canvas canvas = image->getCanvas();
+	canvas.draw(baseImg, Point(0, 0));
+
+	auto drawBox = [&canvas, &baseImg](bool left, bool one){
+		if(left)
+		{
+			canvas.draw(baseImg, Point(38, 339), Rect(121, 339, 71, 69));
+			if(!one)
+				canvas.draw(baseImg, Point(204, 339), Rect(121, 339, 71, 69));
+		}
+		else
+		{
+			canvas.draw(baseImg, Point(325, 339), Rect(408, 339, 71, 69));
+			if(!one)
+				canvas.draw(baseImg, Point(491, 339), Rect(408, 339, 71, 69));
+		}
+	};
+
+	switch (type)
+	{
+	case ARTIFACTS_BUYING:
+		drawBox(true, count == 8);
+		break;
+	case ARTIFACTS_SELLING:
+		drawBox(false, count == 8);
+		break;
+	case MARKET_RESOURCES:
+		drawBox(true, count == 8);
+		drawBox(false, count == 8);
+		break;
+	case FREELANCERS_GUILD:
+		drawBox(false, count == 8);
+		break;
+	case TRANSFER_RESOURCES:
+		drawBox(true, count == 8);
+		break;
+	}
+
+	return image;
+}
+
 AssetGenerator::CanvasPtr AssetGenerator::createCreatureInfoPanelElement(CreatureInfoPanelElement element) const
 {
 	std::map<CreatureInfoPanelElement, Point> size {

+ 2 - 0
client/render/AssetGenerator.h

@@ -60,6 +60,8 @@ private:
 	CanvasPtr createPaletteShiftedImage(const AnimationPath & source, const std::vector<PaletteAnimation> & animation, int frameIndex, int paletteShiftCounter) const;
 	CanvasPtr createAdventureMapButtonClear(const PlayerColor & player, bool small) const;
 	CanvasPtr createCreatureInfoPanel(int boxesAmount) const;
+	enum CreateResourceWindowType{ ARTIFACTS_BUYING, ARTIFACTS_SELLING, MARKET_RESOURCES, FREELANCERS_GUILD, TRANSFER_RESOURCES };
+	CanvasPtr createResourceWindow(CreateResourceWindowType type, int count, PlayerColor color) const;
 	enum CreatureInfoPanelElement{ BONUS_EFFECTS, SPELL_EFFECTS, BUTTON_PANEL, COMMANDER_BACKGROUND, COMMANDER_ABILITIES };
 	CanvasPtr createCreatureInfoPanelElement(CreatureInfoPanelElement element) const;
 	CanvasPtr createQuestWindow() const;

+ 28 - 13
client/widgets/markets/CMarketBase.cpp

@@ -46,7 +46,8 @@ void CMarketBase::deselect()
 		offerTradePanel->highlightedSlot->selectSlot(false);
 		offerTradePanel->highlightedSlot.reset();
 	}
-	deal->block(true);
+	if(deal)
+		deal->block(true);
 	bidQty = 0;
 	offerQty = 0;
 	updateShowcases();
@@ -54,7 +55,12 @@ void CMarketBase::deselect()
 
 void CMarketBase::onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<TradePanelBase> & curPanel)
 {
-	assert(newSlot);
+	if(!newSlot)
+	{
+		deselect();
+		return;
+	}
+
 	assert(curPanel);
 	if(newSlot == curPanel->highlightedSlot)
 		return;
@@ -81,13 +87,14 @@ void CMarketBase::updateSubtitlesForBid(EMarketMode marketMode, int bidId)
 	}
 	else
 	{
-		for(const auto & slot : offerTradePanel->slots)
-		{
-			int slotBidQty = 0;
-			int slotOfferQty = 0;
-			market->getOffer(bidId, slot->id, slotBidQty, slotOfferQty, marketMode);
-			offerTradePanel->updateOffer(*slot, slotBidQty, slotOfferQty);
-		}
+		if(offerTradePanel)
+			for(const auto & slot : offerTradePanel->slots)
+			{
+				int slotBidQty = 0;
+				int slotOfferQty = 0;
+				market->getOffer(bidId, slot->id, slotBidQty, slotOfferQty, marketMode);
+				offerTradePanel->updateOffer(*slot, slotBidQty, slotOfferQty);
+			}
 	}
 };
 
@@ -120,6 +127,11 @@ void CMarketBase::highlightingChanged()
 	updateShowcases();
 }
 
+CMarketBase::MarketShowcasesParams CMarketBase::getShowcasesParams() const
+{
+	return {};
+}
+
 CExperienceAltar::CExperienceAltar()
 {
 	OBJECT_CONSTRUCTION;
@@ -164,8 +176,9 @@ bool CCreaturesSelling::slotDeletingCheck(const std::shared_ptr<CTradeableItem>
 
 void CCreaturesSelling::updateSubtitles() const
 {
-	for(const auto & heroSlot : bidTradePanel->slots)
-		heroSlot->subtitle->setText(std::to_string(this->hero->getStackCount(SlotID(heroSlot->serial))));
+	if(bidTradePanel)
+		for(const auto & heroSlot : bidTradePanel->slots)
+			heroSlot->subtitle->setText(std::to_string(this->hero->getStackCount(SlotID(heroSlot->serial))));
 }
 
 CResourcesBuying::CResourcesBuying(const CTradeableItem::ClickPressedFunctor & clickPressedCallback,
@@ -188,8 +201,9 @@ CResourcesSelling::CResourcesSelling(const CTradeableItem::ClickPressedFunctor &
 
 void CResourcesSelling::updateSubtitles() const
 {
-	for(const auto & slot : bidTradePanel->slots)
-		slot->subtitle->setText(std::to_string(GAME->interface()->cb->getResourceAmount(static_cast<EGameResID>(slot->serial))));
+	if(bidTradePanel)
+		for(const auto & slot : bidTradePanel->slots)
+			slot->subtitle->setText(std::to_string(GAME->interface()->cb->getResourceAmount(static_cast<EGameResID>(slot->serial))));
 }
 
 CMarketSlider::CMarketSlider(const CSlider::SliderMovingFunctor & movingCallback)
@@ -197,6 +211,7 @@ CMarketSlider::CMarketSlider(const CSlider::SliderMovingFunctor & movingCallback
 	OBJECT_CONSTRUCTION;
 
 	offerSlider = std::make_shared<CSlider>(Point(230, 489), 137, movingCallback, 0, 0, 0, Orientation::HORIZONTAL);
+	offerSlider->setScrollBounds(Rect(-215, -50, 575, 120));
 	maxAmount = std::make_shared<CButton>(Point(228, 520), AnimationPath::builtin("IRCBTNS.DEF"), LIBRARY->generaltexth->zelp[596],
 		[this]()
 		{

+ 1 - 1
client/widgets/markets/CMarketBase.h

@@ -58,7 +58,7 @@ protected:
 	virtual void onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<TradePanelBase> & curPanel);
 	virtual void updateSubtitlesForBid(EMarketMode marketMode, int bidId);
 	virtual void updateShowcases();
-	virtual MarketShowcasesParams getShowcasesParams() const = 0;
+	virtual MarketShowcasesParams getShowcasesParams() const;
 	virtual void highlightingChanged();
 };
 

+ 4 - 2
client/widgets/markets/CMarketResources.cpp

@@ -98,8 +98,10 @@ void CMarketResources::highlightingChanged()
 void CMarketResources::updateSubtitles()
 {
 	CMarketBase::updateSubtitlesForBid(EMarketMode::RESOURCE_RESOURCE, bidTradePanel->getHighlightedItemId());
-	if(bidTradePanel->highlightedSlot)
-		offerTradePanel->slots[bidTradePanel->highlightedSlot->serial]->subtitle->setText(LIBRARY->generaltexth->allTexts[164]); // n/a
+	if(bidTradePanel && bidTradePanel->highlightedSlot)
+		for(auto & slot : offerTradePanel->slots)
+			if(slot->id == bidTradePanel->highlightedSlot->id)
+				slot->subtitle->setText(LIBRARY->generaltexth->allTexts[164]); // n/a
 }
 
 std::string CMarketResources::getTraderText()

+ 37 - 6
client/widgets/markets/TradePanels.cpp

@@ -13,6 +13,7 @@
 #include "../../GameEngine.h"
 #include "../../GameInstance.h"
 #include "../../render/Canvas.h"
+#include "../../widgets/Slider.h"
 #include "../../widgets/TextControls.h"
 #include "../../windows/InfoWindows.h"
 
@@ -262,20 +263,50 @@ bool TradePanelBase::isHighlighted() const
 
 ResourcesPanel::ResourcesPanel(const CTradeableItem::ClickPressedFunctor & clickPressedCallback,
 	const UpdateSlotsFunctor & updateSubtitles)
+	: clickPressedCallback(std::move(clickPressedCallback))
 {
-	assert(resourcesForTrade.size() == slotsPos.size());
 	OBJECT_CONSTRUCTION;
 
-	for(const auto & res : resourcesForTrade)
+	resourcesForTrade = LIBRARY->resourceTypeHandler->getAllObjects();
+
+	int lines = vstd::divideAndCeil(resourcesForTrade.size(), 3);
+	if(lines > 3)
 	{
-		auto slot = slots.emplace_back(std::make_shared<CTradeableItem>(Rect(slotsPos[res.num], slotDimension), EType::RESOURCE, res.num, res.num));
-		slot->clickPressedCallback = clickPressedCallback;
-		slot->setSelectionWidth(selectionWidth);
+		slider = std::make_shared<CSlider>(Point(240, 0), 224, [this](int to){ updateSlots(to); setRedrawParent(true); redraw(); }, 3, lines, 0, Orientation::VERTICAL, CSlider::BROWN);
+		slider->setPanningStep(72);
+		slider->setScrollBounds(Rect(-240, 0, 240, 224));
 	}
-	updateSlotsCallback = updateSubtitles;
+
+	updateSlotsCallback = std::move(updateSubtitles);
+
+	updateSlots(0);
 	showcaseSlot = std::make_shared<CTradeableItem>(Rect(selectedPos, slotDimension), EType::RESOURCE, 0, 0);
 }
 
+void ResourcesPanel::updateSlots(int line)
+{
+	OBJECT_CONSTRUCTION;
+
+	clickPressedCallback(nullptr);
+
+	int offset = line * 3;
+	slots.clear();
+	for (int i = 0; i < std::min(static_cast<int>(resourcesForTrade.size() - offset), 9); i++)
+	{
+		const auto& res = resourcesForTrade[i + offset];
+		auto slotPos = slotsPos[i];
+		if(resourcesForTrade.size() == 7 && i == 6) // for 7 ressources place gold in the middle
+			slotPos = slotsPos[i + 1];
+
+		auto slotPtr = std::make_shared<CTradeableItem>(Rect(slotPos, slotDimension), EType::RESOURCE, res.num, res.num);
+		slotPtr->clickPressedCallback = clickPressedCallback;
+		slotPtr->setSelectionWidth(selectionWidth);
+		slots.push_back(slotPtr);
+	}
+
+	updateSlotsCallback();
+}
+
 ArtifactsPanel::ArtifactsPanel(const CTradeableItem::ClickPressedFunctor & clickPressedCallback,
 	const UpdateSlotsFunctor & updateSubtitles, const std::vector<TradeItemBuy> & arts)
 {

+ 11 - 9
client/widgets/markets/TradePanels.h

@@ -14,6 +14,8 @@
 
 #include "../../../lib/networkPacks/TradeItem.h"
 
+class CSlider;
+
 enum class EType
 {
 	RESOURCE, PLAYER, ARTIFACT_TYPE, CREATURE, ARTIFACT
@@ -68,21 +70,21 @@ public:
 
 class ResourcesPanel : public TradePanelBase
 {
-	const std::vector<GameResID> resourcesForTrade =
-	{
-		GameResID::WOOD, GameResID::MERCURY, GameResID::ORE,
-		GameResID::SULFUR, GameResID::CRYSTAL, GameResID::GEMS,
-		GameResID::GOLD
-	};
 	const std::vector<Point> slotsPos =
 	{
-		Point(0, 0), Point(83, 0), Point(166, 0),
-		Point(0, 79), Point(83, 79), Point(166, 79),
-		Point(83, 158)
+		Point(0, 0),   Point(83, 0),   Point(166, 0),
+		Point(0, 79),  Point(83, 79),  Point(166, 79),
+		Point(0, 158), Point(83, 158), Point(166, 158)
 	};
 	const Point slotDimension = Point(69, 66);
 	const Point selectedPos = Point(83, 267);
 
+	CTradeableItem::ClickPressedFunctor clickPressedCallback;
+
+	std::vector<GameResID> resourcesForTrade;
+	std::shared_ptr<CSlider> slider;
+
+	void updateSlots(int line);
 public:
 	ResourcesPanel(const CTradeableItem::ClickPressedFunctor & clickPressedCallback, const UpdateSlotsFunctor & updateSubtitles);
 };

+ 26 - 5
client/windows/CMarketWindow.cpp

@@ -30,6 +30,7 @@
 #include "../../lib/GameLibrary.h"
 #include "../../lib/callback/CCallback.h"
 #include "../../lib/entities/building/CBuilding.h"
+#include "../../lib/entities/ResourceTypeHandler.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/mapObjects/CGMarket.h"
 #include "../../lib/mapObjects/CGTownInstance.h"
@@ -200,11 +201,23 @@ std::string CMarketWindow::getMarketTitle(const ObjectInstanceID marketId, const
 	return GAME->interface()->cb->getObj(marketId)->getObjectName();
 }
 
+ImagePath CMarketWindow::getImagePathBasedOnResources(std::string name)
+{
+	int res = LIBRARY->resourceTypeHandler->getAllObjects().size();
+	if(res == 8)
+		name += "-R8";
+	else if(res > 8)
+		name += "-R9";
+	return ImagePath::builtin(name);
+}
+
 void CMarketWindow::createArtifactsBuying(const IMarket * market, const CGHeroInstance * hero)
 {
 	OBJECT_CONSTRUCTION;
 
-	background = createBg(ImagePath::builtin("TPMRKABS.bmp"), PLAYER_COLORED);
+	auto image = getImagePathBasedOnResources("TPMRKABS");
+
+	background = createBg(image, PLAYER_COLORED);
 	marketWidget = std::make_shared<CArtifactsBuying>(market, hero, getMarketTitle(market->getObjInstanceID(), EMarketMode::RESOURCE_ARTIFACT));
 	initWidgetInternals(EMarketMode::RESOURCE_ARTIFACT, LIBRARY->generaltexth->zelp[600]);
 }
@@ -213,7 +226,9 @@ void CMarketWindow::createArtifactsSelling(const IMarket * market, const CGHeroI
 {
 	OBJECT_CONSTRUCTION;
 
-	background = createBg(ImagePath::builtin("TPMRKASS.bmp"), PLAYER_COLORED);
+	auto image = getImagePathBasedOnResources("TPMRKASS");
+
+	background = createBg(image, PLAYER_COLORED);
 	// Create image that copies part of background containing slot MISC_1 into position of slot MISC_5
 	artSlotBack = std::make_shared<CPicture>(background->getSurface(), Rect(20, 187, 47, 47), 0, 0);
 	artSlotBack->moveTo(pos.topLeft() + Point(18, 339));
@@ -229,7 +244,9 @@ void CMarketWindow::createMarketResources(const IMarket * market, const CGHeroIn
 {
 	OBJECT_CONSTRUCTION;
 
-	background = createBg(ImagePath::builtin("TPMRKRES.bmp"), PLAYER_COLORED);
+	auto image = getImagePathBasedOnResources("TPMRKRES");
+
+	background = createBg(image, PLAYER_COLORED);
 	marketWidget = std::make_shared<CMarketResources>(market, hero);
 	initWidgetInternals(EMarketMode::RESOURCE_RESOURCE, LIBRARY->generaltexth->zelp[600]);
 }
@@ -238,7 +255,9 @@ void CMarketWindow::createFreelancersGuild(const IMarket * market, const CGHeroI
 {
 	OBJECT_CONSTRUCTION;
 
-	background = createBg(ImagePath::builtin("TPMRKCRS.bmp"), PLAYER_COLORED);
+	auto image = getImagePathBasedOnResources("TPMRKCRS");
+
+	background = createBg(image, PLAYER_COLORED);
 	marketWidget = std::make_shared<CFreelancerGuild>(market, hero);
 	initWidgetInternals(EMarketMode::CREATURE_RESOURCE, LIBRARY->generaltexth->zelp[600]);
 }
@@ -247,7 +266,9 @@ void CMarketWindow::createTransferResources(const IMarket * market, const CGHero
 {
 	OBJECT_CONSTRUCTION;
 
-	background = createBg(ImagePath::builtin("TPMRKPTS.bmp"), PLAYER_COLORED);
+	auto image = getImagePathBasedOnResources("TPMRKPTS");
+
+	background = createBg(image, PLAYER_COLORED);
 	marketWidget = std::make_shared<CTransferResources>(market, hero);
 	initWidgetInternals(EMarketMode::RESOURCE_PLAYER, LIBRARY->generaltexth->zelp[600]);
 }

+ 2 - 0
client/windows/CMarketWindow.h

@@ -38,6 +38,8 @@ private:
 	void createAltarArtifacts(const IMarket * market, const CGHeroInstance * hero);
 	void createAltarCreatures(const IMarket * market, const CGHeroInstance * hero);
 
+	ImagePath getImagePathBasedOnResources(std::string name);
+
 	const int buttonHeightWithMargin = 32 + 3;
 	std::vector<std::shared_ptr<CButton>> changeModeButtons;
 	std::shared_ptr<CButton> quitButton;