mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Merge pull request #3045 from Laserlicht/interface_improvement
various interface shortcuts
This commit is contained in:
commit
ee997a291c
@ -591,6 +591,9 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, BuildingID build
|
||||
// Perform totalRedraw in order to force redraw of updated town list icon from adventure map
|
||||
GH.windows().totalRedraw();
|
||||
}
|
||||
|
||||
for (auto cgh : GH.windows().findWindows<ITownHolder>())
|
||||
cgh->buildChanged();
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleStartBefore(const BattleID & battleID, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2)
|
||||
|
@ -153,6 +153,12 @@ public:
|
||||
virtual void updateGarrisons() = 0;
|
||||
};
|
||||
|
||||
class ITownHolder
|
||||
{
|
||||
public:
|
||||
virtual void buildChanged() = 0;
|
||||
};
|
||||
|
||||
class IStatusBar
|
||||
{
|
||||
public:
|
||||
|
@ -18,6 +18,9 @@
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../PlayerLocalState.h"
|
||||
#include "../gui/WindowHandler.h"
|
||||
#include "../eventsSDL/InputHandler.h"
|
||||
#include "../windows/CTradeWindow.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../widgets/CGarrisonInt.h"
|
||||
#include "../windows/CCastleInterface.h"
|
||||
@ -175,6 +178,27 @@ LRClickableAreaOpenTown::LRClickableAreaOpenTown(const Rect & Pos, const CGTownI
|
||||
{
|
||||
}
|
||||
|
||||
void LRClickableArea::clickPressed(const Point & cursorPosition)
|
||||
{
|
||||
if(onClick)
|
||||
{
|
||||
onClick();
|
||||
GH.input().hapticFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
void LRClickableArea::showPopupWindow(const Point & cursorPosition)
|
||||
{
|
||||
if(onPopup)
|
||||
onPopup();
|
||||
}
|
||||
|
||||
LRClickableArea::LRClickableArea(const Rect & Pos, std::function<void()> onClick, std::function<void()> onPopup)
|
||||
: CIntObject(LCLICK | SHOW_POPUP), onClick(onClick), onPopup(onPopup)
|
||||
{
|
||||
pos = Pos + pos.topLeft();
|
||||
}
|
||||
|
||||
void CMinorResDataBar::show(Canvas & to)
|
||||
{
|
||||
}
|
||||
@ -401,50 +425,93 @@ CTownTooltip::CTownTooltip(Point pos, const CGTownInstance * town)
|
||||
|
||||
CInteractableTownTooltip::CInteractableTownTooltip(Point pos, const CGTownInstance * town)
|
||||
{
|
||||
init(InfoAboutTown(town, true));
|
||||
init(town);
|
||||
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
garrison = std::make_shared<CGarrisonInt>(pos + Point(0, 73), 4, Point(0, 0), town->getUpperArmy(), nullptr, true, true, CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS);
|
||||
}
|
||||
|
||||
void CInteractableTownTooltip::init(const InfoAboutTown & town)
|
||||
void CInteractableTownTooltip::init(const CGTownInstance * town)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
const InfoAboutTown townInfo = InfoAboutTown(town, true);
|
||||
int townId = town->id;
|
||||
|
||||
//order of icons in def: fort, citadel, castle, no fort
|
||||
size_t fortIndex = town.fortLevel ? town.fortLevel - 1 : 3;
|
||||
size_t fortIndex = townInfo.fortLevel ? townInfo.fortLevel - 1 : 3;
|
||||
|
||||
fort = std::make_shared<CAnimImage>(AnimationPath::builtin("ITMCLS"), fortIndex, 0, 105, 31);
|
||||
fastArmyPurchase = std::make_shared<LRClickableArea>(Rect(105, 31, 34, 34), [townId]()
|
||||
{
|
||||
std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo(true);
|
||||
for(auto & town : towns)
|
||||
{
|
||||
if(town->id == townId)
|
||||
std::make_shared<CCastleBuildings>(town)->enterToTheQuickRecruitmentWindow();
|
||||
}
|
||||
});
|
||||
fastTavern = std::make_shared<LRClickableArea>(Rect(3, 2, 58, 64), [townId]()
|
||||
{
|
||||
std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo(true);
|
||||
for(auto & town : towns)
|
||||
{
|
||||
if(town->id == townId && town->builtBuildings.count(BuildingID::TAVERN))
|
||||
LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
|
||||
}
|
||||
});
|
||||
fastMarket = std::make_shared<LRClickableArea>(Rect(143, 31, 30, 34), []()
|
||||
{
|
||||
std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo(true);
|
||||
for(auto & town : towns)
|
||||
{
|
||||
if(town->builtBuildings.count(BuildingID::MARKETPLACE))
|
||||
{
|
||||
GH.windows().createAndPushWindow<CMarketplaceWindow>(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithMarket"));
|
||||
});
|
||||
|
||||
assert(town.tType);
|
||||
assert(townInfo.tType);
|
||||
|
||||
size_t iconIndex = town.tType->clientInfo.icons[town.fortLevel > 0][town.built >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
||||
size_t iconIndex = townInfo.tType->clientInfo.icons[townInfo.fortLevel > 0][townInfo.built >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
||||
|
||||
build = std::make_shared<CAnimImage>(AnimationPath::builtin("itpt"), iconIndex, 0, 3, 2);
|
||||
title = std::make_shared<CLabel>(66, 2, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, town.name);
|
||||
title = std::make_shared<CLabel>(66, 2, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, townInfo.name);
|
||||
|
||||
if(town.details)
|
||||
if(townInfo.details)
|
||||
{
|
||||
hall = std::make_shared<CAnimImage>(AnimationPath::builtin("ITMTLS"), town.details->hallLevel, 0, 67, 31);
|
||||
hall = std::make_shared<CAnimImage>(AnimationPath::builtin("ITMTLS"), townInfo.details->hallLevel, 0, 67, 31);
|
||||
fastTownHall = std::make_shared<LRClickableArea>(Rect(67, 31, 34, 34), [townId]()
|
||||
{
|
||||
std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo(true);
|
||||
for(auto & town : towns)
|
||||
{
|
||||
if(town->id == townId)
|
||||
std::make_shared<CCastleBuildings>(town)->enterTownHall();
|
||||
}
|
||||
});
|
||||
|
||||
if(town.details->goldIncome)
|
||||
if(townInfo.details->goldIncome)
|
||||
{
|
||||
income = std::make_shared<CLabel>(157, 58, FONT_TINY, ETextAlignment::CENTER, Colors::WHITE,
|
||||
std::to_string(town.details->goldIncome));
|
||||
std::to_string(townInfo.details->goldIncome));
|
||||
}
|
||||
if(town.details->garrisonedHero) //garrisoned hero icon
|
||||
if(townInfo.details->garrisonedHero) //garrisoned hero icon
|
||||
garrisonedHero = std::make_shared<CPicture>(ImagePath::builtin("TOWNQKGH"), 149, 76);
|
||||
|
||||
if(town.details->customRes)//silo is built
|
||||
if(townInfo.details->customRes)//silo is built
|
||||
{
|
||||
if(town.tType->primaryRes == EGameResID::WOOD_AND_ORE )// wood & ore
|
||||
if(townInfo.tType->primaryRes == EGameResID::WOOD_AND_ORE )// wood & ore
|
||||
{
|
||||
res1 = std::make_shared<CAnimImage>(AnimationPath::builtin("SMALRES"), GameResID(EGameResID::WOOD), 0, 7, 75);
|
||||
res2 = std::make_shared<CAnimImage>(AnimationPath::builtin("SMALRES"), GameResID(EGameResID::ORE), 0, 7, 88);
|
||||
}
|
||||
else
|
||||
{
|
||||
res1 = std::make_shared<CAnimImage>(AnimationPath::builtin("SMALRES"), town.tType->primaryRes, 0, 7, 81);
|
||||
res1 = std::make_shared<CAnimImage>(AnimationPath::builtin("SMALRES"), townInfo.tType->primaryRes, 0, 7, 81);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ class CGarrisonInt;
|
||||
class CCreatureAnim;
|
||||
class CComponent;
|
||||
class CAnimImage;
|
||||
class LRClickableArea;
|
||||
|
||||
/// Shows a text by moving the mouse cursor over the object
|
||||
class CHoverableArea: public virtual CIntObject
|
||||
@ -133,8 +134,13 @@ class CInteractableTownTooltip : public CIntObject
|
||||
std::shared_ptr<CAnimImage> res1;
|
||||
std::shared_ptr<CAnimImage> res2;
|
||||
std::shared_ptr<CGarrisonInt> garrison;
|
||||
|
||||
std::shared_ptr<LRClickableArea> fastTavern;
|
||||
std::shared_ptr<LRClickableArea> fastMarket;
|
||||
std::shared_ptr<LRClickableArea> fastTownHall;
|
||||
std::shared_ptr<LRClickableArea> fastArmyPurchase;
|
||||
|
||||
void init(const InfoAboutTown & town);
|
||||
void init(const CGTownInstance * town);
|
||||
public:
|
||||
CInteractableTownTooltip(Point pos, const CGTownInstance * town);
|
||||
};
|
||||
@ -215,6 +221,17 @@ public:
|
||||
LRClickableAreaOpenTown(const Rect & Pos, const CGTownInstance * Town);
|
||||
};
|
||||
|
||||
/// Can do action on click
|
||||
class LRClickableArea: public CIntObject
|
||||
{
|
||||
std::function<void()> onClick;
|
||||
std::function<void()> onPopup;
|
||||
public:
|
||||
void clickPressed(const Point & cursorPosition) override;
|
||||
void showPopupWindow(const Point & cursorPosition) override;
|
||||
LRClickableArea(const Rect & Pos, std::function<void()> onClick = nullptr, std::function<void()> onPopup = nullptr);
|
||||
};
|
||||
|
||||
class MoraleLuckBox : public LRClickableAreaWTextComp
|
||||
{
|
||||
std::shared_ptr<CAnimImage> image;
|
||||
|
@ -1294,6 +1294,21 @@ void CCastleInterface::recreateIcons()
|
||||
fastArmyPurchase->setImageOrder(town->fortLevel() - 1, town->fortLevel() - 1, town->fortLevel() - 1, town->fortLevel() - 1);
|
||||
fastArmyPurchase->setAnimateLonelyFrame(true);
|
||||
|
||||
fastMarket = std::make_shared<LRClickableArea>(Rect(163, 410, 64, 42), [&]()
|
||||
{
|
||||
if(town->builtBuildings.count(BuildingID::MARKETPLACE))
|
||||
{
|
||||
if (town->getOwner() == LOCPLINT->playerID)
|
||||
GH.windows().createAndPushWindow<CMarketplaceWindow>(town, town->visitingHero, nullptr, EMarketMode::RESOURCE_RESOURCE);
|
||||
}
|
||||
});
|
||||
|
||||
fastTavern = std::make_shared<LRClickableArea>(Rect(15, 387, 58, 64), [&]()
|
||||
{
|
||||
if(town->builtBuildings.count(BuildingID::TAVERN))
|
||||
LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
|
||||
});
|
||||
|
||||
creainfo.clear();
|
||||
|
||||
bool compactCreatureInfo = useCompactCreatureBox();
|
||||
|
@ -36,6 +36,7 @@ class CTownList;
|
||||
class CGarrisonInt;
|
||||
class CComponent;
|
||||
class CComponentBox;
|
||||
class LRClickableArea;
|
||||
|
||||
/// Building "button"
|
||||
class CBuildingRect : public CShowableAnim
|
||||
@ -154,7 +155,7 @@ class CCastleBuildings : public CIntObject
|
||||
void enterCastleGate();
|
||||
void enterFountain(const BuildingID & building, BuildingSubID::EBuildingSubID subID, BuildingID upgrades);//Rampart's fountains
|
||||
void enterMagesGuild();
|
||||
|
||||
|
||||
void openMagesGuild();
|
||||
void openTownHall();
|
||||
|
||||
@ -228,6 +229,8 @@ class CCastleInterface : public CStatusbarWindow, public IGarrisonHolder
|
||||
std::shared_ptr<CButton> split;
|
||||
std::shared_ptr<CButton> fastTownHall;
|
||||
std::shared_ptr<CButton> fastArmyPurchase;
|
||||
std::shared_ptr<LRClickableArea> fastMarket;
|
||||
std::shared_ptr<LRClickableArea> fastTavern;
|
||||
|
||||
std::vector<std::shared_ptr<CCreaInfo>> creainfo;//small icons of creatures (bottom-left corner);
|
||||
|
||||
|
@ -19,12 +19,14 @@
|
||||
#include "../adventureMap/CResDataBar.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/Shortcut.h"
|
||||
#include "../gui/WindowHandler.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/CGarrisonInt.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../widgets/ObjectLists.h"
|
||||
#include "../windows/CTradeWindow.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
@ -471,6 +473,8 @@ CKingdomInterface::CKingdomInterface()
|
||||
|
||||
statusbar = CGStatusBar::create(std::make_shared<CPicture>(ImagePath::builtin("KSTATBAR"), 10,pos.h - 45));
|
||||
resdatabar = std::make_shared<CResDataBar>(ImagePath::builtin("KRESBAR"), 7, 111+footerPos, 29, 5, 76, 81);
|
||||
|
||||
activateTab(persistentStorage["gui"]["lastKindomInterface"].Integer());
|
||||
}
|
||||
|
||||
void CKingdomInterface::generateObjectsList(const std::vector<const CGObjectInstance * > &ownedObjects)
|
||||
@ -628,11 +632,19 @@ void CKingdomInterface::generateButtons()
|
||||
|
||||
void CKingdomInterface::activateTab(size_t which)
|
||||
{
|
||||
Settings s = persistentStorage.write["gui"]["lastKindomInterface"];
|
||||
s->Integer() = which;
|
||||
|
||||
btnHeroes->block(which == 0);
|
||||
btnTowns->block(which == 1);
|
||||
tabArea->setActive(which);
|
||||
}
|
||||
|
||||
void CKingdomInterface::buildChanged()
|
||||
{
|
||||
tabArea->reset();
|
||||
}
|
||||
|
||||
void CKingdomInterface::townChanged(const CGTownInstance *town)
|
||||
{
|
||||
if(auto townList = std::dynamic_pointer_cast<CKingdTownList>(tabArea->getItem()))
|
||||
@ -785,6 +797,35 @@ CTownItem::CTownItem(const CGTownInstance * Town)
|
||||
growth.push_back(std::make_shared<CCreaInfo>(Point(401+37*(int)i, 78), town, (int)i, true, true));
|
||||
available.push_back(std::make_shared<CCreaInfo>(Point(48+37*(int)i, 78), town, (int)i, true, false));
|
||||
}
|
||||
|
||||
fastTownHall = std::make_shared<CButton>(Point(69, 31), AnimationPath::builtin("ITMTL.def"), CButton::tooltip(), [&]() { std::make_shared<CCastleBuildings>(town)->enterTownHall(); });
|
||||
fastTownHall->setImageOrder(town->hallLevel() - 1, town->hallLevel() - 1, town->hallLevel() - 1, town->hallLevel() - 1);
|
||||
fastTownHall->setAnimateLonelyFrame(true);
|
||||
fastArmyPurchase = std::make_shared<CButton>(Point(111, 31), AnimationPath::builtin("itmcl.def"), CButton::tooltip(), [&]() { std::make_shared<CCastleBuildings>(town)->enterToTheQuickRecruitmentWindow(); });
|
||||
fastArmyPurchase->setImageOrder(town->fortLevel() - 1, town->fortLevel() - 1, town->fortLevel() - 1, town->fortLevel() - 1);
|
||||
fastArmyPurchase->setAnimateLonelyFrame(true);
|
||||
fastTavern = std::make_shared<LRClickableArea>(Rect(5, 6, 58, 64), [&]()
|
||||
{
|
||||
if(town->builtBuildings.count(BuildingID::TAVERN))
|
||||
LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
|
||||
});
|
||||
fastMarket = std::make_shared<LRClickableArea>(Rect(153, 6, 65, 64), []()
|
||||
{
|
||||
std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo(true);
|
||||
for(auto & town : towns)
|
||||
{
|
||||
if(town->builtBuildings.count(BuildingID::MARKETPLACE))
|
||||
{
|
||||
GH.windows().createAndPushWindow<CMarketplaceWindow>(town, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithMarket"));
|
||||
});
|
||||
fastTown = std::make_shared<LRClickableArea>(Rect(67, 6, 165, 20), [&]()
|
||||
{
|
||||
GH.windows().createAndPushWindow<CCastleInterface>(town);
|
||||
});
|
||||
}
|
||||
|
||||
void CTownItem::updateGarrisons()
|
||||
|
@ -200,7 +200,7 @@ public:
|
||||
};
|
||||
|
||||
/// Class which holds all parts of kingdom overview window
|
||||
class CKingdomInterface : public CWindowObject, public IGarrisonHolder, public CArtifactHolder
|
||||
class CKingdomInterface : public CWindowObject, public IGarrisonHolder, public CArtifactHolder, public ITownHolder
|
||||
{
|
||||
private:
|
||||
struct OwnedObjectInfo
|
||||
@ -257,6 +257,7 @@ public:
|
||||
void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc, bool withRedraw) override;
|
||||
void artifactDisassembled(const ArtifactLocation &artLoc) override;
|
||||
void artifactAssembled(const ArtifactLocation &artLoc) override;
|
||||
void buildChanged() override;
|
||||
};
|
||||
|
||||
/// List item with town
|
||||
@ -277,6 +278,12 @@ class CTownItem : public CIntObject, public IGarrisonHolder
|
||||
|
||||
std::shared_ptr<LRClickableAreaOpenTown> openTown;
|
||||
|
||||
std::shared_ptr<CButton> fastTownHall;
|
||||
std::shared_ptr<CButton> fastArmyPurchase;
|
||||
std::shared_ptr<LRClickableArea> fastMarket;
|
||||
std::shared_ptr<LRClickableArea> fastTavern;
|
||||
std::shared_ptr<LRClickableArea> fastTown;
|
||||
|
||||
public:
|
||||
const CGTownInstance * town;
|
||||
|
||||
|
@ -489,7 +489,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::func
|
||||
recruit->addHoverText(CButton::NORMAL, boost::str(boost::format(CGI->generaltexth->tavernInfo[1]) % LOCPLINT->cb->howManyHeroes(false)));
|
||||
recruit->block(true);
|
||||
}
|
||||
else if(LOCPLINT->castleInt && LOCPLINT->castleInt->town->visitingHero)
|
||||
else if(dynamic_cast<const CGTownInstance *>(TavernObj) && dynamic_cast<const CGTownInstance *>(TavernObj)->visitingHero)
|
||||
{
|
||||
recruit->addHoverText(CButton::NORMAL, CGI->generaltexth->tavernInfo[2]); //Cannot recruit. You already have a Hero in this town.
|
||||
recruit->block(true);
|
||||
@ -501,6 +501,8 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::func
|
||||
}
|
||||
if(LOCPLINT->castleInt)
|
||||
CCS->videoh->open(LOCPLINT->castleInt->town->town->clientInfo.tavernVideo);
|
||||
else if(const auto * townObj = dynamic_cast<const CGTownInstance *>(TavernObj))
|
||||
CCS->videoh->open(townObj->town->clientInfo.tavernVideo);
|
||||
else
|
||||
CCS->videoh->open(VideoPath::builtin("TAVERN.BIK"));
|
||||
}
|
||||
|
@ -41,6 +41,14 @@ Some of H3 mechanics can't be straight considered as bug, but default VCMI behav
|
||||
- [Alt] + [LCtrl] + LClick - move all units of selected stack to the city's garrison or to the met hero
|
||||
- [Alt] + [LShift] + LClick - dismiss selected stack`
|
||||
|
||||
## Interface Shourtcuts
|
||||
|
||||
It's now possible to open Tavern (click on town icon), Townhall, Quick Recruitment and Marketplace (click on gold) from various places:
|
||||
|
||||
- Town screen (left bottom)
|
||||
- Kingdom overview for each town
|
||||
- Infobox (only if info box army management is enabled)
|
||||
|
||||
## Quick Recruitment
|
||||
|
||||
Mouse click on castle icon in the town screen open quick recruitment window, where we can purhase in fast way units.
|
||||
|
Loading…
Reference in New Issue
Block a user