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:
@@ -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",
|
||||
|
@@ -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" : "Всегда показывать стоимость перемещения",
|
||||
|
@@ -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())
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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());
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Reference in New Issue
Block a user