1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Implemented user-selectable UI scaling mode

This commit is contained in:
Ivan Savenko 2023-05-04 23:50:33 +03:00
parent fd3933e589
commit a0f1bf3928
8 changed files with 133 additions and 19 deletions

View File

@ -49,10 +49,13 @@
"vcmi.systemOptions.fullscreenButton.hover" : "Fullscreen", "vcmi.systemOptions.fullscreenButton.hover" : "Fullscreen",
"vcmi.systemOptions.fullscreenButton.help" : "{Fullscreen}\n\nIf selected, VCMI will run in fullscreen mode, otherwise it will run in windowed mode", "vcmi.systemOptions.fullscreenButton.help" : "{Fullscreen}\n\nIf selected, VCMI will run in fullscreen mode, otherwise it will run in windowed mode",
"vcmi.systemOptions.resolutionButton.hover" : "Resolution: %wx%h", "vcmi.systemOptions.resolutionButton.hover" : "Resolution: %wx%h",
"vcmi.systemOptions.resolutionButton.help" : "{Select Resolution}\n\nChange in-game screen resolution. A game restart is required to apply the new resolution.", "vcmi.systemOptions.resolutionButton.help" : "{Select Resolution}\n\nChange in-game screen resolution.",
"vcmi.systemOptions.resolutionMenu.hover" : "Select Resolution", "vcmi.systemOptions.resolutionMenu.hover" : "Select Resolution",
"vcmi.systemOptions.resolutionMenu.help" : "Change in-game screen resolution.", "vcmi.systemOptions.resolutionMenu.help" : "Change in-game screen resolution.",
"vcmi.systemOptions.fullscreenFailed" : "{Fullscreen}\n\nFailed to switch to fullscreen mode! The current resolution is not supported by the display!", "vcmi.systemOptions.scalingButton.hover" : "Interface Scaling: %p%",
"vcmi.systemOptions.scalingButton.help" : "{Interface Scaling}\n\nChanges scaling of in-game interface",
"vcmi.systemOptions.scalingMenu.hover" : "Select Interface Scaling",
"vcmi.systemOptions.scalingMenu.help" : "Change in-game interface scaling.",
"vcmi.systemOptions.framerateButton.hover" : "Show FPS", "vcmi.systemOptions.framerateButton.hover" : "Show FPS",
"vcmi.systemOptions.framerateButton.help" : "{Show FPS}\n\nToggle the visibility of the Frames Per Second counter in the corner of the game window", "vcmi.systemOptions.framerateButton.help" : "{Show FPS}\n\nToggle the visibility of the Frames Per Second counter in the corner of the game window",

View File

@ -811,6 +811,7 @@ void CAdventureMapInterface::onScreenResize()
widget = std::make_shared<CAdventureMapWidget>(shortcuts); widget = std::make_shared<CAdventureMapWidget>(shortcuts);
widget->setState(EGameState::MAKING_TURN); widget->setState(EGameState::MAKING_TURN);
widget->getMapView()->onViewMapActivated(); widget->getMapView()->onViewMapActivated();
widget->setPlayer(currentPlayerID);
if (isActive()) if (isActive())
widget->activate(); widget->activate();

View File

@ -30,4 +30,7 @@ public:
/// Returns list of resolutions supported by current screen /// Returns list of resolutions supported by current screen
virtual std::vector<Point> getSupportedResolutions() const = 0; virtual std::vector<Point> getSupportedResolutions() const = 0;
/// Returns <min, max> range of possible values for screen scaling
virtual std::tuple<double, double> getSupportedScalingRange() const = 0;
}; };

View File

@ -33,7 +33,7 @@ SDL_Surface * screenBuf = screen; //points to screen (if only advmapint is prese
static const std::string NAME_AFFIX = "client"; static const std::string NAME_AFFIX = "client";
static const std::string NAME = GameConstants::VCMI_VERSION + std::string(" (") + NAME_AFFIX + ')'; //application name static const std::string NAME = GameConstants::VCMI_VERSION + std::string(" (") + NAME_AFFIX + ')'; //application name
Point WindowHandler::getPreferredLogicalResolution() const std::tuple<double, double> WindowHandler::getSupportedScalingRange() const
{ {
// H3 resolution, any resolution smaller than that is not correctly supported // H3 resolution, any resolution smaller than that is not correctly supported
static const Point minResolution = {800, 600}; static const Point minResolution = {800, 600};
@ -41,11 +41,19 @@ Point WindowHandler::getPreferredLogicalResolution() const
static const double minimalScaling = 50; static const double minimalScaling = 50;
Point renderResolution = getPreferredRenderingResolution(); Point renderResolution = getPreferredRenderingResolution();
double userScaling = settings["video"]["resolution"]["scaling"].Float();
double maximalScalingWidth = 100.0 * renderResolution.x / minResolution.x; double maximalScalingWidth = 100.0 * renderResolution.x / minResolution.x;
double maximalScalingHeight = 100.0 * renderResolution.y / minResolution.y; double maximalScalingHeight = 100.0 * renderResolution.y / minResolution.y;
double maximalScaling = std::min(maximalScalingWidth, maximalScalingHeight); double maximalScaling = std::min(maximalScalingWidth, maximalScalingHeight);
return { minimalScaling, maximalScaling };
}
Point WindowHandler::getPreferredLogicalResolution() const
{
Point renderResolution = getPreferredRenderingResolution();
auto [minimalScaling, maximalScaling] = getSupportedScalingRange();
double userScaling = settings["video"]["resolution"]["scaling"].Float();
double scaling = std::clamp(userScaling, minimalScaling, maximalScaling); double scaling = std::clamp(userScaling, minimalScaling, maximalScaling);
Point logicalResolution = renderResolution * 100.0 / scaling; Point logicalResolution = renderResolution * 100.0 / scaling;
@ -182,7 +190,7 @@ void WindowHandler::updateFullscreenState()
} }
case EWindowMode::WINDOWED: case EWindowMode::WINDOWED:
{ {
Point resolution = getPreferredLogicalResolution(); Point resolution = getPreferredRenderingResolution();
SDL_SetWindowFullscreen(mainWindow, 0); SDL_SetWindowFullscreen(mainWindow, 0);
SDL_SetWindowSize(mainWindow, resolution.x, resolution.y); SDL_SetWindowSize(mainWindow, resolution.x, resolution.y);
SDL_SetWindowPosition(mainWindow, SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex), SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex)); SDL_SetWindowPosition(mainWindow, SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex), SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex));

View File

@ -78,4 +78,5 @@ public:
std::vector<Point> getSupportedResolutions() const final; std::vector<Point> getSupportedResolutions() const final;
std::vector<Point> getSupportedResolutions(int displayIndex) const; std::vector<Point> getSupportedResolutions(int displayIndex) const;
std::tuple<double, double> getSupportedScalingRange() const final;
}; };

View File

@ -37,6 +37,19 @@ static void setBoolSetting(std::string group, std::string field, bool value)
entry->Bool() = value; entry->Bool() = value;
} }
static std::string scalingToEntryString( int scaling)
{
return std::to_string(scaling) + '%';
}
static std::string scalingToLabelString( int scaling)
{
std::string string = CGI->generaltexth->translate("vcmi.systemOptions.scalingButton.hover");
boost::replace_all(string, "%p", std::to_string(scaling));
return string;
}
static std::string resolutionToEntryString( int w, int h) static std::string resolutionToEntryString( int w, int h)
{ {
std::string string = "%wx%h"; std::string string = "%wx%h";
@ -96,6 +109,10 @@ GeneralOptionsTab::GeneralOptionsTab()
{ {
selectGameResolution(); selectGameResolution();
}); });
addCallback("setGameScaling", [this](int dummyValue)
{
selectGameScaling();
});
addCallback("framerateChanged", [](bool value) addCallback("framerateChanged", [](bool value)
{ {
setBoolSetting("video", "showfps", value); setBoolSetting("video", "showfps", value);
@ -114,10 +131,14 @@ GeneralOptionsTab::GeneralOptionsTab()
build(config); build(config);
std::shared_ptr<CLabel> resolutionLabel = widget<CLabel>("resolutionLabel");
const auto & currentResolution = settings["video"]["resolution"]; const auto & currentResolution = settings["video"]["resolution"];
std::shared_ptr<CLabel> resolutionLabel = widget<CLabel>("resolutionLabel");
resolutionLabel->setText(resolutionToLabelString(currentResolution["width"].Integer(), currentResolution["height"].Integer())); resolutionLabel->setText(resolutionToLabelString(currentResolution["width"].Integer(), currentResolution["height"].Integer()));
std::shared_ptr<CLabel> scalingLabel = widget<CLabel>("scalingLabel");
scalingLabel->setText(scalingToLabelString(currentResolution["scaling"].Integer()));
std::shared_ptr<CToggleButton> spellbookAnimationCheckbox = widget<CToggleButton>("spellbookAnimationCheckbox"); std::shared_ptr<CToggleButton> spellbookAnimationCheckbox = widget<CToggleButton>("spellbookAnimationCheckbox");
spellbookAnimationCheckbox->setSelected(settings["video"]["spellbookAnimation"].Bool()); spellbookAnimationCheckbox->setSelected(settings["video"]["spellbookAnimation"].Bool());
@ -152,7 +173,12 @@ GeneralOptionsTab::GeneralOptionsTab()
void GeneralOptionsTab::selectGameResolution() void GeneralOptionsTab::selectGameResolution()
{ {
fillSelectableResolutions(); supportedResolutions = GH.windowHandler().getSupportedResolutions();
boost::range::sort(supportedResolutions, [](const auto & left, const auto & right)
{
return left.x * left.y < right.x * right.y;
});
std::vector<std::string> items; std::vector<std::string> items;
size_t currentResolutionIndex = 0; size_t currentResolutionIndex = 0;
@ -197,12 +223,54 @@ void GeneralOptionsTab::setFullscreenMode(bool on)
setBoolSetting("video", "fullscreen", on); setBoolSetting("video", "fullscreen", on);
} }
void GeneralOptionsTab::fillSelectableResolutions() void GeneralOptionsTab::selectGameScaling()
{ {
supportedResolutions = GH.windowHandler().getSupportedResolutions(); supportedScaling.clear();
boost::range::sort(supportedResolutions, [](const auto & left, const auto & right) auto [minimalScaling, maximalScaling] = GH.windowHandler().getSupportedScalingRange();
for (int i = 0; i <= static_cast<int>(maximalScaling); i += 10)
{ {
return left.x * left.y < right.x * right.y; if (i >= static_cast<int>(minimalScaling))
}); supportedScaling.push_back(i);
}
std::vector<std::string> items;
size_t currentIndex = 0;
size_t i = 0;
for(const auto & it : supportedScaling)
{
auto resolutionStr = scalingToEntryString(it);
if(widget<CLabel>("scalingLabel")->getText() == scalingToLabelString(it))
currentIndex = i;
items.push_back(std::move(resolutionStr));
++i;
}
GH.pushIntT<CObjectListWindow>(
items,
nullptr,
CGI->generaltexth->translate("vcmi.systemOptions.scalingMenu.hover"),
CGI->generaltexth->translate("vcmi.systemOptions.scalingMenu.help"),
[this](int index)
{
setGameScaling(index);
},
currentIndex
);
}
void GeneralOptionsTab::setGameScaling(int index)
{
assert(index >= 0 && index < supportedScaling.size());
if ( index < 0 || index >= supportedScaling.size() )
return;
int scaling = supportedScaling[index];
Settings gameRes = settings.write["video"]["resolution"];
gameRes["scaling"].Float() = scaling;
widget<CLabel>("scalingLabel")->setText(scalingToLabelString(scaling));
} }

View File

@ -19,13 +19,16 @@ private:
SettingsListener onFullscreenChanged; SettingsListener onFullscreenChanged;
std::vector<Point> supportedResolutions; std::vector<Point> supportedResolutions;
std::vector<double> supportedScaling;
void setFullscreenMode( bool on); void setFullscreenMode( bool on);
void fillSelectableResolutions();
void selectGameResolution(); void selectGameResolution();
void setGameResolution(int index); void setGameResolution(int index);
void selectGameScaling();
void setGameScaling(int index);
public: public:
GeneralOptionsTab(); GeneralOptionsTab();
}; };

View File

@ -58,6 +58,33 @@
] ]
}, },
{
"name": "scalingLabel",
"type": "label",
"font": "medium",
"alignment": "left",
"color": "white",
"position": {"x": 45, "y": 115},
"text": "vcmi.systemOptions.scalingButton.hover"
},
{
"name": "resolutionButton",
"type": "button",
"position": {"x": 10, "y": 113},
"image": "settingsWindow/button32",
"help": "vcmi.systemOptions.scalingButton",
"callback": "setGameScaling",
"items":
[
{
"name": "gearIcon",
"type": "picture",
"image": "settingsWindow/gear",
"position": {"x": 0, "y": 0 }
}
]
},
{ {
"name": "topCheckboxesLabels", "name": "topCheckboxesLabels",
"type": "labelGroup", "type": "labelGroup",
@ -67,15 +94,15 @@
"items": "items":
[ [
{ {
"position": {"x": 45, "y": 115}, "position": {"x": 45, "y": 145},
"text": "vcmi.systemOptions.fullscreenButton.hover" "text": "vcmi.systemOptions.fullscreenButton.hover"
}, },
{ {
"position": {"x": 45, "y": 145}, "position": {"x": 45, "y": 175},
"text": "vcmi.systemOptions.framerateButton.hover" "text": "vcmi.systemOptions.framerateButton.hover"
}, },
{ {
"position": {"x": 45, "y": 175}, "position": {"x": 45, "y": 205},
"text": "core.genrltxt.577" "text": "core.genrltxt.577"
}, },
@ -86,7 +113,7 @@
"type": "toggleButton", "type": "toggleButton",
"image": "sysopchk.def", "image": "sysopchk.def",
"help": "vcmi.systemOptions.fullscreenButton", "help": "vcmi.systemOptions.fullscreenButton",
"position": {"x": 10, "y": 113}, "position": {"x": 10, "y": 143},
"callback": "fullscreenChanged" "callback": "fullscreenChanged"
}, },
{ {
@ -94,7 +121,7 @@
"type": "toggleButton", "type": "toggleButton",
"image": "sysopchk.def", "image": "sysopchk.def",
"help": "vcmi.systemOptions.framerateButton", "help": "vcmi.systemOptions.framerateButton",
"position": {"x": 10, "y": 143}, "position": {"x": 10, "y": 173},
"callback": "framerateChanged" "callback": "framerateChanged"
}, },
@ -103,7 +130,7 @@
"type": "toggleButton", "type": "toggleButton",
"image": "sysopchk.def", "image": "sysopchk.def",
"help": "core.help.364", "help": "core.help.364",
"position": {"x": 10, "y": 173}, "position": {"x": 10, "y": 203},
"callback": "spellbookAnimationChanged" "callback": "spellbookAnimationChanged"
}, },