1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +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.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.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.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.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.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", "vcmi.battleWindow.pressKeyToSkipIntro" : "Press any key to start battle immediately",

View File

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

View File

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

View File

@@ -296,9 +296,20 @@ void BattleHero::heroLeftClicked()
void BattleHero::heroRightClicked() void BattleHero::heroRightClicked()
{ {
if(settings["battle"]["stickyHeroInfoWindows"].Bool())
return;
Point windowPosition; Point windowPosition;
windowPosition.x = (!defender) ? owner.fieldController->pos.left() + 1 : owner.fieldController->pos.right() - 79; if(GH.screenDimensions().x < 1000)
windowPosition.y = owner.fieldController->pos.y + 135; {
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; InfoAboutHero targetHero;
if(owner.makingTurn() || settings["session"]["spectate"].Bool()) if(owner.makingTurn() || settings["session"]["spectate"].Bool())
@@ -364,13 +375,19 @@ BattleHero::BattleHero(const BattleInterface & owner, const CGHeroInstance * her
addUsedEvents(TIME); addUsedEvents(TIME);
} }
HeroInfoWindow::HeroInfoWindow(const InfoAboutHero & hero, Point * position) HeroInfoBasicPanel::HeroInfoBasicPanel(const InfoAboutHero & hero, Point * position, bool initializeBackground)
: CWindowObject(RCLICK_POPUP | SHADOW_DISABLED, "CHRPOP") : CIntObject(0)
{ {
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
if (position != nullptr) if (position != nullptr)
moveTo(*position); 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 attack = hero.details->primskills[0];
auto defense = hero.details->primskills[1]; 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))); 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) BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface & _owner, bool allowReplay)
: owner(_owner) : owner(_owner)
{ {

View File

@@ -127,11 +127,22 @@ public:
BattleHero(const BattleInterface & owner, const CGHeroInstance * hero, bool defender); 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 class HeroInfoWindow : public CWindowObject
{ {
private: private:
std::vector<std::shared_ptr<CLabel>> labels; std::shared_ptr<HeroInfoBasicPanel> content;
std::vector<std::shared_ptr<CAnimImage>> icons;
public: public:
HeroInfoWindow(const InfoAboutHero & hero, Point * position); 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_SELECT_ACTION, std::bind(&BattleWindow::bSwitchActionf, this));
addShortcut(EShortcut::BATTLE_TOGGLE_QUEUE, [this](){ this->toggleQueueVisibility();}); 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::BATTLE_USE_CREATURE_SPELL, [this](){ this->owner.actionsController->enterCreatureCastingMode(); });
addShortcut(EShortcut::GLOBAL_CANCEL, [this](){ this->owner.actionsController->endCastingSpell(); }); addShortcut(EShortcut::GLOBAL_CANCEL, [this](){ this->owner.actionsController->endCastingSpell(); });
@@ -80,6 +81,7 @@ BattleWindow::BattleWindow(BattleInterface & owner):
owner.fieldController->createHeroes(); owner.fieldController->createHeroes();
createQueue(); createQueue();
createStickyHeroInfoWindows();
if ( owner.tacticsMode ) if ( owner.tacticsMode )
tacticPhaseStarted(); tacticPhaseStarted();
@@ -116,6 +118,41 @@ void BattleWindow::createQueue()
queue->disable(); 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() BattleWindow::~BattleWindow()
{ {
CPlayerInterface::battleInt = nullptr; CPlayerInterface::battleInt = nullptr;
@@ -170,6 +207,49 @@ void BattleWindow::showQueue()
GH.windows().totalRedraw(); 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() void BattleWindow::updateQueue()
{ {
queue->update(); queue->update();

View File

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

View File

@@ -133,6 +133,7 @@ enum class EShortcut
BATTLE_TACTICS_NEXT, BATTLE_TACTICS_NEXT,
BATTLE_TACTICS_END, BATTLE_TACTICS_END,
BATTLE_SELECT_ACTION, // Alternative actions toggle BATTLE_SELECT_ACTION, // Alternative actions toggle
BATTLE_TOGGLE_HEROES_STATS,
// Town screen // Town screen
TOWN_OPEN_TAVERN, 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_RETURN, EShortcut::BATTLE_TACTICS_END },
{SDLK_KP_ENTER, EShortcut::BATTLE_TACTICS_END }, {SDLK_KP_ENTER, EShortcut::BATTLE_TACTICS_END },
{SDLK_s, EShortcut::BATTLE_SELECT_ACTION }, {SDLK_s, EShortcut::BATTLE_SELECT_ACTION },
{SDLK_i, EShortcut::BATTLE_TOGGLE_HEROES_STATS},
{SDLK_t, EShortcut::TOWN_OPEN_TAVERN }, {SDLK_t, EShortcut::TOWN_OPEN_TAVERN },
{SDLK_SPACE, EShortcut::TOWN_SWAP_ARMIES }, {SDLK_SPACE, EShortcut::TOWN_SWAP_ARMIES },
{SDLK_END, EShortcut::RECRUITMENT_MAX }, {SDLK_END, EShortcut::RECRUITMENT_MAX },

View File

@@ -60,6 +60,10 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner)
{ {
skipBattleIntroMusicChangedCallback(value); skipBattleIntroMusicChangedCallback(value);
}); });
addCallback("showStickyHeroWindowsChanged", [this, owner](bool value)
{
showStickyHeroWindowsChangedCallback(value, owner);
});
build(config); build(config);
std::shared_ptr<CToggleGroup> animationSpeedToggle = widget<CToggleGroup>("animationSpeedPicker"); std::shared_ptr<CToggleGroup> animationSpeedToggle = widget<CToggleGroup>("animationSpeedPicker");
@@ -80,6 +84,9 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner)
std::shared_ptr<CToggleButton> rangeLimitHighlightOnHoverCheckbox = widget<CToggleButton>("rangeLimitHighlightOnHoverCheckbox"); std::shared_ptr<CToggleButton> rangeLimitHighlightOnHoverCheckbox = widget<CToggleButton>("rangeLimitHighlightOnHoverCheckbox");
rangeLimitHighlightOnHoverCheckbox->setSelected(settings["battle"]["rangeLimitHighlightOnHover"].Bool()); 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"); std::shared_ptr<CToggleButton> mouseShadowCheckbox = widget<CToggleButton>("mouseShadowCheckbox");
mouseShadowCheckbox->setSelected(settings["battle"]["mouseShadow"].Bool()); 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) void BattleOptionsTab::queueSizeChangedCallback(int value, BattleInterface * parentBattleInterface)
{ {
if (value == -1) if (value == -1)

View File

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

View File

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

View File

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