1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

vcmi: actually implement AUTO for CInfoWindow

This is possible to use infobar interactions now.
This commit is contained in:
Konstantin
2023-03-07 03:29:04 +03:00
parent 75358a68a7
commit a0c644a0e5
10 changed files with 138 additions and 21 deletions

View File

@@ -47,6 +47,8 @@
"vcmi.systemOptions.framerateButton.hover" : "Show FPS",
"vcmi.systemOptions.framerateButton.help" : "{Show FPS}\n\n Toggles visibility of Frames Per Second counter in corner of game window.",
"vcmi.adventureOptions.infoBarPick.hover" : "Show Messages in Info Panel",
"vcmi.adventureOptions.infoBarPick.help" : "{Show Messages in Info Panel}\n\nWhenever possible, game messages from visiting map objects will be shown in info bar instead of showing up as popup windows",
"vcmi.adventureOptions.numericQuantities.hover" : "Numeric Creature Quantities",
"vcmi.adventureOptions.numericQuantities.help" : "{Numeric Creature Quantities}\n\n Shows approximate enemy creatures quantities in numeric A-B format.",
"vcmi.adventureOptions.forceMovementInfo.hover" : "Always Show Movement Cost",

View File

@@ -47,6 +47,8 @@
"vcmi.systemOptions.framerateButton.hover" : "Показывать частоту кадров",
"vcmi.systemOptions.framerateButton.help" : "{Показывать частоту кадров}\n\n Включить счетчик частоты кадров в углу игрового клиента",
"vcmi.adventureOptions.infoBarPick.hover" : "Сообщения в информационной панели",
"vcmi.adventureOptions.infoBarPick.help" : "{Сообщения в информационной панели}\n\n Если сообщения помещаются, то показывать их в информационной панели (только на интерфейсе карты).",
"vcmi.adventureOptions.numericQuantities.hover" : "Приблизительное число существ",
"vcmi.adventureOptions.numericQuantities.help" : "{Приблизительное число существ}\n\n Показывать приблизительное число существ в формате A-B вместо словесный обозначений",
"vcmi.adventureOptions.forceMovementInfo.hover" : "Всегда показывать стоимость перемещения",

View File

@@ -1034,11 +1034,18 @@ void CPlayerInterface::yourTacticPhase(int distance)
void CPlayerInterface::showInfoDialog(EInfoWindowMode type, const std::string &text, const std::vector<Component> & components, int soundID)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
if(type == InfoWindow::INFO) {
adventureInt->infoBar->showComponents(components, text);
if (makingTurn && GH.listInt.size() && LOCPLINT == this)
CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
return;
bool autoTryHover = settings["gameTweaks"]["infoBarPick"].Bool() && type == EInfoWindowMode::AUTO;
auto timer = type == EInfoWindowMode::INFO ? 3000 : 4500; //Implement long info windows like in HD mod
if(autoTryHover || type == EInfoWindowMode::INFO)
{
if(adventureInt->infoBar->tryShowComponents(components, text, timer))
{
if (makingTurn && GH.listInt.size() && LOCPLINT == this)
CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
return;
}
}
if (settings["session"]["autoSkip"].Bool() && !GH.isKeyboardShiftDown())

View File

@@ -15,6 +15,7 @@
#include "../widgets/CComponent.h"
#include "../widgets/Images.h"
#include "../windows/CMessage.h"
#include "../widgets/TextControls.h"
#include "../widgets/MiscWidgets.h"
#include "../windows/InfoWindows.h"
@@ -29,7 +30,7 @@
#include "../../lib/mapObjects/CGTownInstance.h"
CInfoBar::CVisibleInfo::CVisibleInfo()
: CIntObject(0, Point(8, 12))
: CIntObject(0, Point(offset_x, offset_y))
{
}
@@ -163,24 +164,31 @@ CInfoBar::VisibleGameStatusInfo::VisibleGameStatusInfo()
}
}
CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const std::vector<Component> & compsToDisplay, std::string message)
CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const std::vector<Component> & compsToDisplay, std::string message, int textH, bool tiny)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>("ADSTATOT", 1, 0);
auto fullRect = Rect(4, 4, 171, 171);
auto fullRect = Rect(0, 0, data_width, data_height);
auto textRect = fullRect;
auto imageRect = fullRect;
auto font = FONT_SMALL;
if(!compsToDisplay.empty())
{
auto size = CComponent::large;
if(compsToDisplay.size() > 2)
size = CComponent::small;
if(message != "")
if(!message.empty())
{
textRect = Rect(4, 4, 171, 42);
imageRect = Rect(4, 42, 171, 121);
textRect = Rect(CInfoBar::offset,
CInfoBar::offset,
data_width - 2 * CInfoBar::offset,
textH);
imageRect = Rect(CInfoBar::offset,
textH + CInfoBar::offset,
data_width - 2 * CInfoBar::offset,
CInfoBar::data_height - 2* CInfoBar::offset - textH);
if(compsToDisplay.size() > 4)
size = CComponent::tiny;
}
@@ -194,8 +202,24 @@ CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const std::vector<Component
comps = std::make_shared<CComponentBox>(vect, imageRect, 4, 4, 1);
}
else
font = tiny ? FONT_TINY : font;
text = std::make_shared<CTextBox>(message, textRect, 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
if(!message.empty())
text = std::make_shared<CTextBox>(message, textRect, 0, font, ETextAlignment::CENTER, Colors::WHITE);
}
int CInfoBar::getEstimatedComponentHeight(int numComps) const
{
if (numComps > 8) //Bigger than 8 components - return invalid value
return std::numeric_limits<int>::max();
else if (numComps > 4)
return 48 + 20; // 24px * 2 rows + 20 to offset
else if (numComps > 2)
return 32 + 20; // 32px * 1 row + 20 to offset
else if (numComps)
return 128; // 128 px to offset
return 0;
}
void CInfoBar::playNewDaySound()
@@ -293,13 +317,36 @@ void CInfoBar::showDate()
redraw();
}
void CInfoBar::showComponents(const std::vector<Component> & comps, std::string message)
bool CInfoBar::tryShowComponents(const std::vector<Component> & components, std::string message, int timer)
{
auto imageH = getEstimatedComponentHeight(components.size()) + (components.empty() ? 0 : 2 * CInfoBar::offset);
auto textH = CMessage::guessHeight(message,CInfoBar::data_width - 2 * CInfoBar::offset, FONT_SMALL);
auto tinyH = CMessage::guessHeight(message,CInfoBar::data_width - 2 * CInfoBar::offset, FONT_TINY);
auto header = CMessage::guessHeader(message);
auto headerH = CMessage::guessHeight(header, CInfoBar::data_width - 2 * CInfoBar::offset, FONT_SMALL);
// Order matters - priority form should be chosen first
if(imageH + textH < CInfoBar::data_height)
showComponents(components, message, textH, false, timer);
else if(!imageH && tinyH < CInfoBar::data_height)
showComponents(components, message, tinyH, true, timer);
else if(imageH + headerH < CInfoBar::data_height)
showComponents(components, header, headerH, false, timer);
else if(imageH < CInfoBar::data_height)
showComponents(components, "", 0, false, timer);
else
return false; //We cannot fit message to infobar, fallback to window
return true;
}
void CInfoBar::showComponents(const std::vector<Component> & comps, std::string message, int textH, bool tiny, int timer)
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
state = COMPONENT;
visibleInfo = std::make_shared<VisibleComponentInfo>(comps, message);
visibleInfo = std::make_shared<VisibleComponentInfo>(comps, message, textH, tiny);
setTimer(3000);
setTimer(timer);
redraw();
}

View File

@@ -37,12 +37,15 @@ private:
/// Declare before to compute correct size of widgets
static constexpr int width = 192;
static constexpr int height = 192;
static constexpr int component_offset = 8;
static constexpr int offset = 4;
//all visible information located in one object - for ease of replacing
class CVisibleInfo : public CIntObject
{
public:
static constexpr int offset_x = 8;
static constexpr int offset_y = 12;
void show(SDL_Surface * to) override;
protected:
@@ -52,6 +55,9 @@ private:
CVisibleInfo();
};
static constexpr int data_width = width - 2 * CVisibleInfo::offset_x;
static constexpr int data_height = height - 2 * CVisibleInfo::offset_y + 4; //yes, +4 is required
class EmptyVisibleInfo : public CVisibleInfo
{
public:
@@ -108,7 +114,7 @@ private:
std::shared_ptr<CComponentBox> comps;
std::shared_ptr<CTextBox> text;
public:
VisibleComponentInfo(const std::vector<Component> & compsToDisplay, std::string message);
VisibleComponentInfo(const std::vector<Component> & compsToDisplay, std::string message, int textH, bool tiny);
};
enum EState
@@ -119,6 +125,9 @@ private:
std::shared_ptr<CVisibleInfo> visibleInfo;
EState state;
//private helper for showing components
void showComponents(const std::vector<Component> & comps, std::string message, int textH, bool tiny = false, int timer = 3000);
//removes all information about current state, deactivates timer (if any)
void reset();
@@ -137,7 +146,7 @@ public:
void showDate();
/// show components for 3 seconds. Used to display picked up resources. Can display up to 8 components
void showComponents(const std::vector<Component> & comps, std::string message);
bool tryShowComponents(const std::vector<Component> & comps, std::string message, int timer = 3000);
/// print enemy turn progress
void startEnemyTurn(PlayerColor color);
@@ -154,5 +163,8 @@ public:
/// check if infobar is showed something about pickups
bool showingComponents();
/// get estimated component height for InfoBar
int getEstimatedComponentHeight(int numComps) const;
};

View File

@@ -202,6 +202,25 @@ std::vector<std::string> CMessage::breakText( std::string text, size_t maxLineWi
return ret;
}
std::string CMessage::guessHeader(const std::string & msg)
{
size_t begin = 0;
std::string delimeters = "{}";
size_t start = msg.find_first_of(delimeters[0], begin);
size_t end = msg.find_first_of(delimeters[1], start);
if(start > msg.size() || end > msg.size())
return "";
return msg.substr(begin, end);
}
int CMessage::guessHeight(const std::string & txt, int width, EFonts font)
{
const auto f = graphics->fonts[font];
auto lines = CMessage::breakText(txt, width, font);
int lineHeight = static_cast<int>(f->getLineHeight());
return lineHeight * (int)lines.size();
}
void CMessage::drawIWindow(CInfoWindow * ret, std::string text, PlayerColor player)
{
bool blitOr = false;

View File

@@ -32,6 +32,12 @@ public:
/// split text in lines
static std::vector<std::string> breakText(std::string text, size_t maxLineWidth, EFonts font);
/// Try to guess a header of a message
static std::string guessHeader(const std::string & msg);
/// For convenience
static int guessHeight(const std::string & string, int width, EFonts fnt);
/// constructor
static void init();
/// destructor

View File

@@ -105,11 +105,15 @@ AdventureOptionsTab::AdventureOptionsTab()
addCallback("mapSwipeChanged", [](bool value)
{
#if defined(VCMI_MOBILE)
setBoolSetting("general", "swipe", value);
return setBoolSetting("general", "swipe", value);
#else
setBoolSetting("general", "swipeDesktop", value);
return setBoolSetting("general", "swipeDesktop", value);
#endif
});
addCallback("infoBarPickChanged", [](bool value)
{
return setBoolSetting("gameTweaks", "infoBarPick", value);
});
build(config);
std::shared_ptr<CToggleGroup> playerHeroSpeedToggle = widget<CToggleGroup>("heroMovementSpeedPicker");
@@ -142,4 +146,6 @@ AdventureOptionsTab::AdventureOptionsTab()
#else
mapSwipeCheckbox->setSelected(settings["general"]["swipeDesktop"].Bool());
#endif
std::shared_ptr<CToggleButton> infoBarPickCheckbox = widget<CToggleButton>("infoBarPickCheckbox");
infoBarPickCheckbox->setSelected(settings["gameTweaks"]["infoBarPick"].Bool());
}

View File

@@ -503,6 +503,7 @@
"numericCreaturesQuantities",
"availableCreaturesAsDwellingLabel",
"compactTownCreatureInfo",
"infoBarPick",
"skipBattleIntroMusic"
],
"properties": {
@@ -526,6 +527,10 @@
"type" : "boolean",
"default" : false
},
"infoBarPick" : {
"type" : "boolean",
"default" : false
},
"skipBattleIntroMusic" : {
"type" : "boolean",
"default" : false

View File

@@ -364,6 +364,10 @@
{
"position": {"x": 45, "y": 385},
"text": "vcmi.adventureOptions.mapSwipe.hover"
},
{
"position": {"x": 45, "y": 415},
"text": "vcmi.adventureOptions.infoBarPick.hover"
}
]
},
@@ -399,6 +403,13 @@
"position": {"x": 10, "y": 383},
"callback": "mapSwipeChanged"
},
{
"name": "infoBarPickCheckbox",
"type": "toggleButton",
"image": "sysopchk.def",
"help": "vcmi.adventureOptions.infoBarPick",
"position": {"x": 10, "y": 413},
"callback": "infoBarPickChanged"
}
]
}