1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

subclasses for market composition

This commit is contained in:
SoundSSGood 2023-12-04 19:16:26 +02:00
parent 50a5c72d1b
commit d0ca63d2c9
6 changed files with 158 additions and 120 deletions

View File

@ -11,7 +11,6 @@
#include "StdInc.h"
#include "CAltar.h"
#include "../widgets/CAltar.h"
#include "../gui/CGuiHandler.h"
#include "../gui/CursorHandler.h"
#include "../widgets/Buttons.h"
@ -28,32 +27,8 @@
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/CGMarket.h"
CAltar::CAltar(const IMarket * market, const CGHeroInstance * hero)
: CTradeBase(market, hero)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
// Experience needed to reach next level
texts.emplace_back(std::make_shared<CTextBox>(CGI->generaltexth->allTexts[475], Rect(15, 415, 125, 50), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW));
// Total experience on the Altar
texts.emplace_back(std::make_shared<CTextBox>(CGI->generaltexth->allTexts[476], Rect(15, 495, 125, 40), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW));
deal = std::make_shared<CButton>(Point(269, 520), AnimationPath::builtin("ALTSACR.DEF"), CGI->generaltexth->zelp[585], std::bind(&CAltar::makeDeal, this));
expToLevel = std::make_shared<CLabel>(75, 477, FONT_SMALL, ETextAlignment::CENTER);
expForHero = std::make_shared<CLabel>(75, 545, FONT_SMALL, ETextAlignment::CENTER);
}
void CAltar::deselect()
{
if(hLeft)
hLeft->selection->selectSlot(false);
if(hRight)
hRight->selection->selectSlot(false);
hLeft = hRight = nullptr;
deal->block(true);
}
CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero)
: CAltar(market, hero)
: CTradeBase(market, hero)
{
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
@ -63,7 +38,7 @@ CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance *
selectedArt = std::make_shared<CArtPlace>(Point(280, 442));
sacrificeAllButton = std::make_shared<CButton>(Point(393, 520), AnimationPath::builtin("ALTFILL.DEF"),
CGI->generaltexth->zelp[571], std::bind(&CAltar::sacrificeAll, this));
CGI->generaltexth->zelp[571], std::bind(&CExpAltar::sacrificeAll, this));
sacrificeAllButton->block(hero->artifactsInBackpack.empty() && hero->artifactsWorn.empty());
sacrificeBackpackButton = std::make_shared<CButton>(Point(147, 520), AnimationPath::builtin("ALTEMBK.DEF"),
@ -235,7 +210,7 @@ void CAltarArtifacts::onSlotClickPressed(std::shared_ptr<CTradeableItem> altarSl
}
CAltarCreatures::CAltarCreatures(const IMarket * market, const CGHeroInstance * hero)
: CAltar(market, hero)
: CTradeBase(market, hero)
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
@ -246,46 +221,27 @@ CAltarCreatures::CAltarCreatures(const IMarket * market, const CGHeroInstance *
lSubtitle = std::make_shared<CLabel>(180, 503, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
rSubtitle = std::make_shared<CLabel>(426, 503, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
unitsSlider = std::make_shared<CSlider>(Point(231, 481), 137, std::bind(&CAltarCreatures::onUnitsSliderMoved, this, _1), 0, 0, 0, Orientation::HORIZONTAL);
maxUnits = std::make_shared<CButton>(Point(147, 520), AnimationPath::builtin("IRCBTNS.DEF"), CGI->generaltexth->zelp[578], std::bind(&CSlider::scrollToMax, unitsSlider));
offerSlider = std::make_shared<CSlider>(Point(231, 481), 137, std::bind(&CAltarCreatures::onOfferSliderMoved, this, _1), 0, 0, 0, Orientation::HORIZONTAL);
maxUnits = std::make_shared<CButton>(Point(147, 520), AnimationPath::builtin("IRCBTNS.DEF"), CGI->generaltexth->zelp[578], std::bind(&CSlider::scrollToMax, offerSlider));
unitsOnAltar.resize(GameConstants::ARMY_SIZE, 0);
expPerUnit.resize(GameConstants::ARMY_SIZE, 0);
sacrificeAllButton = std::make_shared<CButton>(
Point(393, 520), AnimationPath::builtin("ALTARMY.DEF"), CGI->generaltexth->zelp[579], std::bind(&CAltar::sacrificeAll, this));
Point(393, 520), AnimationPath::builtin("ALTARMY.DEF"), CGI->generaltexth->zelp[579], std::bind(&CExpAltar::sacrificeAll, this));
// Creating slots for hero creatures
SCreaturesPanel::slotsData slots;
for(auto slotId = SlotID(0); slotId.num < GameConstants::ARMY_SIZE; slotId++)
{
if(const auto & creature = hero->getCreature(slotId))
slots.emplace_back(std::make_tuple(creature->getId(), slotId, hero->getStackCount(slotId)));
}
leftTradePanel = std::make_shared<SCreaturesPanel>([this](std::shared_ptr<CTradeableItem> altarSlot) -> void
{
onSlotClickPressed(altarSlot, rightTradePanel, hLeft, hRight);
}, slots);
// Hero creatures panel
assert(leftTradePanel);
leftTradePanel->moveBy(Point(45, 110));
leftTradePanel->updateSlotsCallback = [this]() -> void
{
for(auto & heroSlot : leftTradePanel->slots)
heroSlot->subtitle = std::to_string(this->hero->getStackCount(SlotID(heroSlot->serial)));
};
leftTradePanel->updateSlotsCallback = std::bind(&CCreaturesSelling::updateSubtitle, this);
// Creating slots for creatures on altar
for(auto & slot : slots)
std::get<2>(slot) = 0;
// Altar creatures panel
rightTradePanel = std::make_shared<SCreaturesPanel>([this](std::shared_ptr<CTradeableItem> altarSlot) -> void
{
onSlotClickPressed(altarSlot, leftTradePanel, hRight, hLeft);
}, slots);
onSlotClickPressed(altarSlot, hRight);
}, leftTradePanel->slots);
rightTradePanel->moveBy(Point(334, 110));
leftTradePanel->deleteSlotsCheck = rightTradePanel->deleteSlotsCheck = [this](std::shared_ptr<CTradeableItem> & slot) -> bool
{
return this->hero->getStackCount(SlotID(slot->serial)) == 0 ? true : false;
};
leftTradePanel->deleteSlotsCheck = rightTradePanel->deleteSlotsCheck = std::bind(&CCreaturesSelling::slotDeletingCheck, this, _1);
readExpValues();
calcExpAltarForHero();
deselect();
@ -326,17 +282,17 @@ void CAltarCreatures::updateControls()
if(lastSlot.has_value() && lastSlot.value() == SlotID(hLeft->serial))
sliderAmount--;
}
unitsSlider->setAmount(sliderAmount);
unitsSlider->block(!unitsSlider->getAmount());
offerSlider->setAmount(sliderAmount);
offerSlider->block(!offerSlider->getAmount());
if(hLeft)
unitsSlider->scrollTo(unitsOnAltar[hLeft->serial]);
maxUnits->block(unitsSlider->getAmount() == 0);
offerSlider->scrollTo(unitsOnAltar[hLeft->serial]);
maxUnits->block(offerSlider->getAmount() == 0);
}
void CAltarCreatures::updateSubtitlesForSelected()
{
if(hLeft)
lSubtitle->setText(std::to_string(unitsSlider->getValue()));
lSubtitle->setText(std::to_string(offerSlider->getValue()));
else
lSubtitle->setText("");
if(hRight)
@ -356,8 +312,8 @@ void CAltarCreatures::updateSlots()
void CAltarCreatures::deselect()
{
CAltar::deselect();
unitsSlider->block(true);
CTradeBase::deselect();
offerSlider->block(true);
maxUnits->block(true);
updateSubtitlesForSelected();
}
@ -376,7 +332,7 @@ TExpType CAltarCreatures::calcExpAltarForHero()
void CAltarCreatures::makeDeal()
{
deselect();
unitsSlider->scrollTo(0);
offerSlider->scrollTo(0);
expForHero->setText(std::to_string(0));
std::vector<TradeItemSell> ids;
@ -420,7 +376,7 @@ void CAltarCreatures::sacrificeAll()
unitsOnAltar[lastSlot.value().num]--;
if(hRight)
unitsSlider->scrollTo(unitsOnAltar[hRight->serial]);
offerSlider->scrollTo(unitsOnAltar[hRight->serial]);
for(auto altarSlot : rightTradePanel->slots)
updateAltarSlot(altarSlot);
updateSubtitlesForSelected();
@ -436,7 +392,7 @@ void CAltarCreatures::updateAltarSlot(std::shared_ptr<CTradeableItem> slot)
boost::str(boost::format(CGI->generaltexth->allTexts[122]) % std::to_string(hero->calculateXp(units * expPerUnit[slot->serial]))) : "";
}
void CAltarCreatures::onUnitsSliderMoved(int newVal)
void CAltarCreatures::onOfferSliderMoved(int newVal)
{
if(hLeft)
unitsOnAltar[hLeft->serial] = newVal;
@ -447,30 +403,29 @@ void CAltarCreatures::onUnitsSliderMoved(int newVal)
updateSubtitlesForSelected();
}
void CAltarCreatures::onSlotClickPressed(std::shared_ptr<CTradeableItem> altarSlot, std::shared_ptr<STradePanel> & oppositePanel,
std::shared_ptr<CTradeableItem> & hCurSide, std::shared_ptr<CTradeableItem> & hOppSide)
void CAltarCreatures::onSlotClickPressed(std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSide)
{
std::shared_ptr<CTradeableItem> oppositeSlot;
if(hCurSide == newSlot)
return;
auto * oppositeSlot = &hLeft;
auto oppositePanel = leftTradePanel;
CTradeBase::onSlotClickPressed(newSlot, hCurSide);
if(hCurSide == hLeft)
{
oppositeSlot = &hRight;
oppositePanel = rightTradePanel;
}
std::shared_ptr<CTradeableItem> oppositeNewSlot;
for(const auto & slot : oppositePanel->slots)
if(slot->serial == altarSlot->serial)
if(slot->serial == newSlot->serial)
{
oppositeSlot = slot;
oppositeNewSlot = slot;
break;
}
if(hCurSide)
hCurSide->selection->selectSlot(false);
if(hOppSide)
hOppSide->selection->selectSlot(false);
if(hCurSide != altarSlot && oppositeSlot)
{
hCurSide = altarSlot;
hOppSide = oppositeSlot;
updateControls();
updateSubtitlesForSelected();
redraw();
}
hCurSide->selection->selectSlot(true);
hOppSide->selection->selectSlot(true);
assert(oppositeNewSlot);
CTradeBase::onSlotClickPressed(oppositeNewSlot, *oppositeSlot);
updateControls();
updateSubtitlesForSelected();
redraw();
}

View File

@ -12,23 +12,7 @@
#include "../widgets/CArtifactsOfHeroAltar.h"
#include "../widgets/CTradeBase.h"
class CSlider;
class CAltar : public CTradeBase, public CIntObject
{
public:
std::shared_ptr<CLabel> expToLevel;
std::shared_ptr<CLabel> expForHero;
std::shared_ptr<CButton> sacrificeAllButton;
CAltar(const IMarket * market, const CGHeroInstance * hero);
virtual ~CAltar() = default;
virtual void sacrificeAll() = 0;
virtual void deselect();
virtual TExpType calcExpAltarForHero() = 0;
};
class CAltarArtifacts : public CAltar
class CAltarArtifacts : public CExpAltar
{
public:
CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero);
@ -62,7 +46,7 @@ private:
void onSlotClickPressed(std::shared_ptr<CTradeableItem> altarSlot);
};
class CAltarCreatures : public CAltar
class CAltarCreatures : public CExpAltar, public CCreaturesSelling
{
public:
CAltarCreatures(const IMarket * market, const CGHeroInstance * hero);
@ -75,7 +59,6 @@ public:
private:
std::shared_ptr<CButton> maxUnits;
std::shared_ptr<CSlider> unitsSlider;
std::vector<int> unitsOnAltar;
std::vector<int> expPerUnit;
std::shared_ptr<CLabel> lSubtitle, rSubtitle;
@ -83,7 +66,6 @@ private:
void readExpValues();
void updateControls();
void updateSubtitlesForSelected();
void onUnitsSliderMoved(int newVal);
void onSlotClickPressed(std::shared_ptr<CTradeableItem> altarSlot, std::shared_ptr<STradePanel> & oppositePanel,
std::shared_ptr<CTradeableItem> & hCurSide, std::shared_ptr<CTradeableItem> & hOppSide);
void onOfferSliderMoved(int newVal);
void onSlotClickPressed(std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSide) override;
};

View File

@ -13,6 +13,7 @@
#include "../gui/CGuiHandler.h"
#include "../render/Canvas.h"
#include "../widgets/Buttons.h"
#include "../widgets/TextControls.h"
#include "../windows/InfoWindows.h"
@ -367,8 +368,25 @@ SCreaturesPanel::SCreaturesPanel(CTradeableItem::ClickPressedFunctor clickPresse
slot->clickPressedCallback = clickPressedCallback;
if(creaturesNum != 0)
slot->subtitle = std::to_string(std::get<2>(slotData));
slot->pos.w = 58; slots.back()->pos.h = 64;
slot->selection = std::make_unique<SelectableSlot>(Rect(slotsPos[slotId.num], slots.back()->pos.dimensions()), Point(1, 1), selectionWidth);
slot->pos.w = 58; slot->pos.h = 64;
slot->selection = std::make_unique<SelectableSlot>(Rect(slotsPos[slotId.num], slot->pos.dimensions()), Point(1, 1), selectionWidth);
}
}
SCreaturesPanel::SCreaturesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback,
std::vector<std::shared_ptr<CTradeableItem>> & stsSlots, bool emptySlots)
{
assert(slots.size() <= GameConstants::ARMY_SIZE);
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
for(const auto & srcSlot : stsSlots)
{
auto slot = slots.emplace_back(std::make_shared<CTradeableItem>(slotsPos[srcSlot->serial],
emptySlots ? EType::CREATURE_PLACEHOLDER : EType::CREATURE, srcSlot->id, true, srcSlot->serial));
slot->clickPressedCallback = clickPressedCallback;
slot->subtitle = emptySlots ? "" : srcSlot->subtitle;
slot->pos.w = srcSlot->pos.w; slot->pos.h = srcSlot->pos.h;
slot->selection = std::make_unique<SelectableSlot>(Rect(slotsPos[slot->serial], slot->pos.dimensions()), Point(1, 1), selectionWidth);
}
}
@ -376,6 +394,8 @@ CTradeBase::CTradeBase(const IMarket * market, const CGHeroInstance * hero)
: market(market)
, hero(hero)
{
deal = std::make_shared<CButton>(Point(), AnimationPath::builtin("ALTSACR.DEF"),
CGI->generaltexth->zelp[585], std::bind(&CTradeBase::makeDeal, this));
}
void CTradeBase::removeItems(const std::set<std::shared_ptr<CTradeableItem>> & toRemove)
@ -398,3 +418,63 @@ void CTradeBase::getEmptySlots(std::set<std::shared_ptr<CTradeableItem>> & toRem
if(!hero->getStackCount(SlotID(item->serial)))
toRemove.insert(item);
}
void CTradeBase::deselect()
{
if(hLeft)
hLeft->selection->selectSlot(false);
if(hRight)
hRight->selection->selectSlot(false);
hLeft = hRight = nullptr;
deal->block(true);
}
void CTradeBase::onSlotClickPressed(std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSlot)
{
if(newSlot == hCurSlot)
return;
if(hCurSlot)
hCurSlot->selection->selectSlot(false);
hCurSlot = newSlot;
newSlot->selection->selectSlot(true);
}
CExpAltar::CExpAltar()
{
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
// Experience needed to reach next level
texts.emplace_back(std::make_shared<CTextBox>(CGI->generaltexth->allTexts[475], Rect(15, 415, 125, 50), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW));
// Total experience on the Altar
texts.emplace_back(std::make_shared<CTextBox>(CGI->generaltexth->allTexts[476], Rect(15, 495, 125, 40), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW));
deal->moveBy(dealButtonPos);
expToLevel = std::make_shared<CLabel>(75, 477, FONT_SMALL, ETextAlignment::CENTER);
expForHero = std::make_shared<CLabel>(75, 545, FONT_SMALL, ETextAlignment::CENTER);
}
CCreaturesSelling::CCreaturesSelling()
{
assert(hero);
SCreaturesPanel::slotsData slots;
for(auto slotId = SlotID(0); slotId.num < GameConstants::ARMY_SIZE; slotId++)
{
if(const auto & creature = hero->getCreature(slotId))
slots.emplace_back(std::make_tuple(creature->getId(), slotId, hero->getStackCount(slotId)));
}
leftTradePanel = std::make_shared<SCreaturesPanel>([this](std::shared_ptr<CTradeableItem> altarSlot) -> void
{
onSlotClickPressed(altarSlot, hLeft);
}, slots);
}
bool CCreaturesSelling::slotDeletingCheck(std::shared_ptr<CTradeableItem> & slot)
{
return hero->getStackCount(SlotID(slot->serial)) == 0 ? true : false;
}
void CCreaturesSelling::updateSubtitle()
{
for(auto & heroSlot : leftTradePanel->slots)
heroSlot->subtitle = std::to_string(this->hero->getStackCount(SlotID(heroSlot->serial)));
}

View File

@ -24,6 +24,7 @@ VCMI_LIB_NAMESPACE_END
class CButton;
class CTextBox;
class CSlider;
enum EType
{
@ -137,6 +138,8 @@ struct SCreaturesPanel : public STradePanel
Point(83, 196)
};
SCreaturesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, slotsData & initialSlots);
SCreaturesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback,
std::vector<std::shared_ptr<CTradeableItem>> & stsSlots, bool emptySlots = true);
};
class CTradeBase
@ -153,15 +156,40 @@ public:
std::shared_ptr<CTradeableItem> hLeft;
std::shared_ptr<CTradeableItem> hRight;
std::shared_ptr<CButton> deal;
std::shared_ptr<CSlider> offerSlider;
CTradeBase(const IMarket * market, const CGHeroInstance * hero);
void removeItems(const std::set<std::shared_ptr<CTradeableItem>> & toRemove);
void removeItem(std::shared_ptr<CTradeableItem> item);
void getEmptySlots(std::set<std::shared_ptr<CTradeableItem>> & toRemove);
virtual void makeDeal() = 0;
virtual void deselect();
virtual void onSlotClickPressed(std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSlot);
protected:
std::vector<std::shared_ptr<CLabel>> labels;
std::vector<std::shared_ptr<CButton>> buttons;
std::vector<std::shared_ptr<CTextBox>> texts;
};
// Market subclasses
class CExpAltar : virtual public CTradeBase, virtual public CIntObject
{
public:
std::shared_ptr<CLabel> expToLevel;
std::shared_ptr<CLabel> expForHero;
std::shared_ptr<CButton> sacrificeAllButton;
const Point dealButtonPos = Point(269, 520);
CExpAltar();
virtual void sacrificeAll() = 0;
virtual TExpType calcExpAltarForHero() = 0;
};
class CCreaturesSelling : virtual public CTradeBase, virtual public CIntObject
{
public:
CCreaturesSelling();
bool slotDeletingCheck(std::shared_ptr<CTradeableItem> & slot);
void updateSubtitle();
};

View File

@ -28,7 +28,7 @@ public:
private:
const CGHeroInstance * hero;
std::shared_ptr<CAltar> altar;
std::shared_ptr<CExpAltar> altar;
std::shared_ptr<CButton> changeModeButton;
std::shared_ptr<CButton> quitButton;
std::function<void()> windowClosedCallback;

View File

@ -100,14 +100,7 @@ void CTradeWindow::initItems(bool Left)
auto clickPressedTradePanel = [this](std::shared_ptr<CTradeableItem> newSlot, bool left)
{
auto * selectedSlot = &hRight;
if(left)
selectedSlot = &hLeft;
if(*selectedSlot)
(*selectedSlot)->selection->selectSlot(false);
*selectedSlot = newSlot;
newSlot->selection->selectSlot(true);
CTradeBase::onSlotClickPressed(newSlot, left ? hLeft : hRight);
selectionChanged(left);
};