1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Add option for persistent hero info window as in HD mod

This commit is contained in:
Dydzio 2023-07-17 23:25:16 +02:00
parent f23de91fad
commit 48a72f90f7
13 changed files with 188 additions and 8 deletions

View File

@ -113,6 +113,8 @@
"vcmi.battleOptions.movementHighlightOnHover.help": "{Movement Highlight on Hover}\n\nHighlight unit's movement range when you hover over it.",
"vcmi.battleOptions.rangeLimitHighlightOnHover.hover": "Show range limits for shooters",
"vcmi.battleOptions.rangeLimitHighlightOnHover.help": "{Show range limits for shooters on Hover}\n\nShow shooter's range limits when you hover over it.",
"vcmi.battleOptions.showStickyHeroInfoWindows.hover": "Permanently show heroes statistics windows",
"vcmi.battleOptions.showStickyHeroInfoWindows.help": "{Permanently show heroes statistics windows}\n\nPermanently toggle on heroes statistics windows that show primary stats and spell points.",
"vcmi.battleOptions.skipBattleIntroMusic.hover": "Skip Intro Music",
"vcmi.battleOptions.skipBattleIntroMusic.help": "{Skip Intro Music}\n\nAllow actions during the intro music that plays at the beginning of each battle",
"vcmi.battleWindow.pressKeyToSkipIntro" : "Press any key to start battle immediately",

View File

@ -810,3 +810,10 @@ void BattleInterface::setBattleQueueVisibility(bool visible)
if(visible)
windowObject->showQueue();
}
void BattleInterface::setStickyHeroWindowsVisibility(bool visible)
{
windowObject->hideStickyHeroWindows();
if(visible)
windowObject->showStickyHeroWindows();
}

View File

@ -178,6 +178,7 @@ public:
void tacticPhaseEnd();
void setBattleQueueVisibility(bool visible);
void setStickyHeroWindowsVisibility(bool visible);
void executeStagedAnimations();
void executeAnimationStage( EAnimationEvents event);

View File

@ -296,9 +296,20 @@ void BattleHero::heroLeftClicked()
void BattleHero::heroRightClicked()
{
if(settings["battle"]["stickyHeroInfoWindows"].Bool())
return;
Point windowPosition;
windowPosition.x = (!defender) ? owner.fieldController->pos.left() + 1 : owner.fieldController->pos.right() - 79;
windowPosition.y = owner.fieldController->pos.y + 135;
if(GH.screenDimensions().x < 1000)
{
windowPosition.x = (!defender) ? owner.fieldController->pos.left() + 1 : owner.fieldController->pos.right() - 79;
windowPosition.y = owner.fieldController->pos.y + 135;
}
else
{
windowPosition.x = (!defender) ? owner.fieldController->pos.left() - 93 : owner.fieldController->pos.right() + 15;
windowPosition.y = owner.fieldController->pos.y;
}
InfoAboutHero targetHero;
if(owner.makingTurn() || settings["session"]["spectate"].Bool())
@ -364,13 +375,19 @@ BattleHero::BattleHero(const BattleInterface & owner, const CGHeroInstance * her
addUsedEvents(TIME);
}
HeroInfoWindow::HeroInfoWindow(const InfoAboutHero & hero, Point * position)
: CWindowObject(RCLICK_POPUP | SHADOW_DISABLED, "CHRPOP")
HeroInfoBasicPanel::HeroInfoBasicPanel(const InfoAboutHero & hero, Point * position, bool initializeBackground)
: CIntObject(0)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
if (position != nullptr)
moveTo(*position);
background->colorize(hero.owner); //maybe add this functionality to base class?
if(initializeBackground)
{
background = std::make_shared<CPicture>("CHRPOP");
background->getSurface()->setBlitMode(EImageBlitMode::OPAQUE);
background->colorize(hero.owner);
}
auto attack = hero.details->primskills[0];
auto defense = hero.details->primskills[1];
@ -406,6 +423,24 @@ HeroInfoWindow::HeroInfoWindow(const InfoAboutHero & hero, Point * position)
labels.push_back(std::make_shared<CLabel>(39, 186, EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, std::to_string(currentSpellPoints) + "/" + std::to_string(maxSpellPoints)));
}
void HeroInfoBasicPanel::show(Canvas & to)
{
showAll(to);
CIntObject::show(to);
}
HeroInfoWindow::HeroInfoWindow(const InfoAboutHero & hero, Point * position)
: CWindowObject(RCLICK_POPUP | SHADOW_DISABLED, "CHRPOP")
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
if (position != nullptr)
moveTo(*position);
background->colorize(hero.owner); //maybe add this functionality to base class?
content = std::make_shared<HeroInfoBasicPanel>(hero, nullptr, false);
}
BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface & _owner, bool allowReplay)
: owner(_owner)
{

View File

@ -127,11 +127,22 @@ public:
BattleHero(const BattleInterface & owner, const CGHeroInstance * hero, bool defender);
};
class HeroInfoBasicPanel : public CIntObject //extracted from InfoWindow to fit better as non-popup embed element
{
private:
std::shared_ptr<CPicture> background;
std::vector<std::shared_ptr<CLabel>> labels;
std::vector<std::shared_ptr<CAnimImage>> icons;
public:
HeroInfoBasicPanel(const InfoAboutHero & hero, Point * position, bool initializeBackground = true);
void show(Canvas & to) override;
};
class HeroInfoWindow : public CWindowObject
{
private:
std::vector<std::shared_ptr<CLabel>> labels;
std::vector<std::shared_ptr<CAnimImage>> icons;
std::shared_ptr<HeroInfoBasicPanel> content;
public:
HeroInfoWindow(const InfoAboutHero & hero, Point * position);
};

View File

@ -67,6 +67,7 @@ BattleWindow::BattleWindow(BattleInterface & owner):
addShortcut(EShortcut::BATTLE_SELECT_ACTION, std::bind(&BattleWindow::bSwitchActionf, this));
addShortcut(EShortcut::BATTLE_TOGGLE_QUEUE, [this](){ this->toggleQueueVisibility();});
addShortcut(EShortcut::BATTLE_TOGGLE_HEROES_STATS, [this](){ this->toggleStickyHeroWindowsVisibility();});
addShortcut(EShortcut::BATTLE_USE_CREATURE_SPELL, [this](){ this->owner.actionsController->enterCreatureCastingMode(); });
addShortcut(EShortcut::GLOBAL_CANCEL, [this](){ this->owner.actionsController->endCastingSpell(); });
@ -80,6 +81,7 @@ BattleWindow::BattleWindow(BattleInterface & owner):
owner.fieldController->createHeroes();
createQueue();
createStickyHeroInfoWindows();
if ( owner.tacticsMode )
tacticPhaseStarted();
@ -116,6 +118,41 @@ void BattleWindow::createQueue()
queue->disable();
}
void BattleWindow::createStickyHeroInfoWindows()
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
if(owner.defendingHeroInstance)
{
InfoAboutHero info;
info.initFromHero(owner.defendingHeroInstance, InfoAboutHero::EInfoLevel::INBATTLE);
Point position = (GH.screenDimensions().x >= 1000)
? Point(pos.x + pos.w + 15, pos.y)
: Point(pos.x + pos.w -79, pos.y + 135);
defenderHeroWindow = std::make_shared<HeroInfoBasicPanel>(info, &position);
}
if(owner.attackingHeroInstance)
{
InfoAboutHero info;
info.initFromHero(owner.attackingHeroInstance, InfoAboutHero::EInfoLevel::INBATTLE);
Point position = (GH.screenDimensions().x >= 1000)
? Point(pos.x - 93, pos.y)
: Point(pos.x + 1, pos.y + 135);
attackerHeroWindow = std::make_shared<HeroInfoBasicPanel>(info, &position);
}
bool showInfoWindows = settings["battle"]["stickyHeroInfoWindows"].Bool();
if(!showInfoWindows)
{
if(attackerHeroWindow)
attackerHeroWindow->disable();
if(defenderHeroWindow)
defenderHeroWindow->disable();
}
}
BattleWindow::~BattleWindow()
{
CPlayerInterface::battleInt = nullptr;
@ -170,6 +207,49 @@ void BattleWindow::showQueue()
GH.windows().totalRedraw();
}
void BattleWindow::toggleStickyHeroWindowsVisibility()
{
if(settings["battle"]["stickyHeroInfoWindows"].Bool())
hideStickyHeroWindows();
else
showStickyHeroWindows();
}
void BattleWindow::hideStickyHeroWindows()
{
if(settings["battle"]["stickyHeroInfoWindows"].Bool() == false)
return;
Settings showStickyHeroInfoWindows = settings.write["battle"]["stickyHeroInfoWindows"];
showStickyHeroInfoWindows->Bool() = false;
if(attackerHeroWindow)
attackerHeroWindow->disable();
if(defenderHeroWindow)
defenderHeroWindow->disable();
GH.windows().totalRedraw();
}
void BattleWindow::showStickyHeroWindows()
{
if(settings["battle"]["stickyHeroInfoWindows"].Bool() == true)
return;
Settings showStickyHeroInfoWIndows = settings.write["battle"]["stickyHeroInfoWindows"];
showStickyHeroInfoWIndows->Bool() = true;
// if(attackerHeroWindow)
// attackerHeroWindow->enable();
//
// if(defenderHeroWindow)
// defenderHeroWindow->enable();
createStickyHeroInfoWindows();
GH.windows().totalRedraw();
}
void BattleWindow::updateQueue()
{
queue->update();

View File

@ -24,6 +24,7 @@ class BattleInterface;
class BattleConsole;
class BattleRenderer;
class StackQueue;
class HeroInfoBasicPanel;
/// GUI object that handles functionality of panel at the bottom of combat screen
class BattleWindow : public InterfaceObjectConfigurable
@ -32,6 +33,8 @@ class BattleWindow : public InterfaceObjectConfigurable
std::shared_ptr<StackQueue> queue;
std::shared_ptr<BattleConsole> console;
std::shared_ptr<HeroInfoBasicPanel> attackerHeroWindow;
std::shared_ptr<HeroInfoBasicPanel> defenderHeroWindow;
/// button press handling functions
void bOptionsf();
@ -60,6 +63,9 @@ class BattleWindow : public InterfaceObjectConfigurable
void toggleQueueVisibility();
void createQueue();
void toggleStickyHeroWindowsVisibility();
void createStickyHeroInfoWindows();
std::shared_ptr<BattleConsole> buildBattleConsole(const JsonNode &) const;
public:
@ -73,6 +79,9 @@ public:
void hideQueue();
void showQueue();
void hideStickyHeroWindows();
void showStickyHeroWindows();
/// block all UI elements when player is not allowed to act, e.g. during enemy turn
void blockUI(bool on);

View File

@ -133,6 +133,7 @@ enum class EShortcut
BATTLE_TACTICS_NEXT,
BATTLE_TACTICS_END,
BATTLE_SELECT_ACTION, // Alternative actions toggle
BATTLE_TOGGLE_HEROES_STATS,
// Town screen
TOWN_OPEN_TAVERN,

View File

@ -134,6 +134,7 @@ std::vector<EShortcut> ShortcutHandler::translateKeycode(SDL_Keycode key) const
{SDLK_RETURN, EShortcut::BATTLE_TACTICS_END },
{SDLK_KP_ENTER, EShortcut::BATTLE_TACTICS_END },
{SDLK_s, EShortcut::BATTLE_SELECT_ACTION },
{SDLK_i, EShortcut::BATTLE_TOGGLE_HEROES_STATS},
{SDLK_t, EShortcut::TOWN_OPEN_TAVERN },
{SDLK_SPACE, EShortcut::TOWN_SWAP_ARMIES },
{SDLK_END, EShortcut::RECRUITMENT_MAX },

View File

@ -60,6 +60,10 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner)
{
skipBattleIntroMusicChangedCallback(value);
});
addCallback("showStickyHeroWindowsChanged", [this, owner](bool value)
{
showStickyHeroWindowsChangedCallback(value, owner);
});
build(config);
std::shared_ptr<CToggleGroup> animationSpeedToggle = widget<CToggleGroup>("animationSpeedPicker");
@ -80,6 +84,9 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner)
std::shared_ptr<CToggleButton> rangeLimitHighlightOnHoverCheckbox = widget<CToggleButton>("rangeLimitHighlightOnHoverCheckbox");
rangeLimitHighlightOnHoverCheckbox->setSelected(settings["battle"]["rangeLimitHighlightOnHover"].Bool());
std::shared_ptr<CToggleButton> showStickyHeroInfoWindowsCheckbox = widget<CToggleButton>("showStickyHeroInfoWindowsCheckbox");
showStickyHeroInfoWindowsCheckbox->setSelected(settings["battle"]["stickyHeroInfoWindows"].Bool());
std::shared_ptr<CToggleButton> mouseShadowCheckbox = widget<CToggleButton>("mouseShadowCheckbox");
mouseShadowCheckbox->setSelected(settings["battle"]["mouseShadow"].Bool());
@ -194,6 +201,19 @@ void BattleOptionsTab::showQueueChangedCallback(bool value, BattleInterface * pa
}
}
void BattleOptionsTab::showStickyHeroWindowsChangedCallback(bool value, BattleInterface * parentBattleInterface)
{
if(!parentBattleInterface)
{
Settings showStickyWindows = settings.write["battle"]["stickyHeroInfoWindows"];
showStickyWindows->Bool() = value;
}
else
{
parentBattleInterface->setStickyHeroWindowsVisibility(value);
}
}
void BattleOptionsTab::queueSizeChangedCallback(int value, BattleInterface * parentBattleInterface)
{
if (value == -1)

View File

@ -31,6 +31,7 @@ private:
void showQueueChangedCallback(bool value, BattleInterface * parentBattleInterface);
void queueSizeChangedCallback(int value, BattleInterface * parentBattleInterface);
void skipBattleIntroMusicChangedCallback(bool value);
void showStickyHeroWindowsChangedCallback(bool value, BattleInterface * parentBattleInterface);
public:
BattleOptionsTab(BattleInterface * owner = nullptr);
};

View File

@ -238,7 +238,7 @@
"type" : "object",
"additionalProperties" : false,
"default" : {},
"required" : [ "speedFactor", "mouseShadow", "cellBorders", "stackRange", "movementHighlightOnHover", "rangeLimitHighlightOnHover", "showQueue", "swipeAttackDistance", "queueSize" ],
"required" : [ "speedFactor", "mouseShadow", "cellBorders", "stackRange", "movementHighlightOnHover", "rangeLimitHighlightOnHover", "showQueue", "swipeAttackDistance", "queueSize", "stickyHeroInfoWindows" ],
"properties" : {
"speedFactor" : {
"type" : "number",
@ -276,6 +276,10 @@
"type" : "string",
"default" : "auto",
"enum" : [ "auto", "small", "big" ]
},
"stickyHeroInfoWindows" : {
"type" : "boolean",
"default" : true
}
}
},

View File

@ -110,6 +110,9 @@
{
"text": "vcmi.battleOptions.rangeLimitHighlightOnHover.hover",
},
{
"text": "vcmi.battleOptions.showStickyHeroInfoWindows.hover",
},
{
"text": "core.genrltxt.406",
},
@ -144,6 +147,11 @@
"help": "vcmi.battleOptions.rangeLimitHighlightOnHover",
"callback": "rangeLimitHighlightOnHoverChanged"
},
{
"name": "showStickyHeroInfoWindowsCheckbox",
"help": "vcmi.battleOptions.showStickyHeroInfoWindows",
"callback": "showStickyHeroWindowsChanged"
},
{
"name": "mouseShadowCheckbox",
"help": "core.help.429",