From a4b102e46fce6855b4af9e106ccbbb20a00e7065 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 30 Apr 2023 19:20:40 +0300 Subject: [PATCH] Implemented UI scaling (non-selectable option for now) --- client/renderSDL/WindowHandler.cpp | 24 +++++++++++++++---- client/windows/settings/GeneralOptionsTab.cpp | 4 ++-- config/schemas/settings.json | 11 +++++---- launcher/settingsView/csettingsview_moc.cpp | 6 ++--- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/client/renderSDL/WindowHandler.cpp b/client/renderSDL/WindowHandler.cpp index 71fa74b7a..87f8b1501 100644 --- a/client/renderSDL/WindowHandler.cpp +++ b/client/renderSDL/WindowHandler.cpp @@ -35,8 +35,22 @@ static const std::string NAME = GameConstants::VCMI_VERSION + std::string(" (") Point WindowHandler::getPreferredLogicalResolution() const { - // TODO: CONFIGURABLE ADVMAP - IMPLEMENT UI SCALE SETTING - return {1280, 720}; + // H3 resolution, any resolution smaller than that is not correctly supported + static const Point minResolution = {800, 600}; + // arbitrary limit on *downscaling*. Allow some downscaling, if requested by user. Should be generally limited to 100+ for all but few devices + static const double minimalScaling = 50; + + Point renderResolution = getPreferredRenderingResolution(); + double userScaling = settings["video"]["resolution"]["scaling"].Float(); + double maximalScalingWidth = 100.0 * renderResolution.x / minResolution.x; + double maximalScalingHeight = 100.0 * renderResolution.y / minResolution.y; + double maximalScaling = std::min(maximalScalingWidth, maximalScalingHeight); + + double scaling = std::clamp(userScaling, minimalScaling, maximalScaling); + + Point logicalResolution = renderResolution * 100.0 / scaling; + + return logicalResolution; } Point WindowHandler::getPreferredRenderingResolution() const @@ -50,8 +64,8 @@ Point WindowHandler::getPreferredRenderingResolution() const else { const JsonNode & video = settings["video"]; - int width = video["screenRes"]["width"].Integer(); - int height = video["screenRes"]["height"].Integer(); + int width = video["resolution"]["width"].Integer(); + int height = video["resolution"]["height"].Integer(); return Point(width, height); } @@ -328,7 +342,7 @@ void WindowHandler::validateSettings() { if(resolution.x > mode.w || resolution.y > mode.h) { - Settings writer = settings.write["video"]["screenRes"]; + Settings writer = settings.write["video"]["resolution"]; writer["width"].Float() = mode.w; writer["height"].Float() = mode.h; } diff --git a/client/windows/settings/GeneralOptionsTab.cpp b/client/windows/settings/GeneralOptionsTab.cpp index 241978109..b709020e5 100644 --- a/client/windows/settings/GeneralOptionsTab.cpp +++ b/client/windows/settings/GeneralOptionsTab.cpp @@ -115,7 +115,7 @@ GeneralOptionsTab::GeneralOptionsTab() build(config); std::shared_ptr resolutionLabel = widget("resolutionLabel"); - const auto & currentResolution = settings["video"]["screenRes"]; + const auto & currentResolution = settings["video"]["resolution"]; resolutionLabel->setText(resolutionToLabelString(currentResolution["width"].Integer(), currentResolution["height"].Integer())); std::shared_ptr spellbookAnimationCheckbox = widget("spellbookAnimationCheckbox"); @@ -185,7 +185,7 @@ void GeneralOptionsTab::setGameResolution(int index) Point resolution = supportedResolutions[index]; - Settings gameRes = settings.write["video"]["screenRes"]; + Settings gameRes = settings.write["video"]["resolution"]; gameRes["width"].Float() = resolution.x; gameRes["height"].Float() = resolution.y; diff --git a/config/schemas/settings.json b/config/schemas/settings.json index fcf8b6376..51880fdae 100644 --- a/config/schemas/settings.json +++ b/config/schemas/settings.json @@ -111,7 +111,7 @@ "additionalProperties" : false, "default": {}, "required" : [ - "screenRes", + "resolution", "bitsPerPixel", "fullscreen", "realFullscreen", @@ -124,15 +124,16 @@ "targetfps" ], "properties" : { - "screenRes" : { + "resolution" : { "type" : "object", "additionalProperties" : false, - "required" : [ "width", "height" ], + "required" : [ "width", "height", "scaling" ], "properties" : { "width" : { "type" : "number" }, - "height" : { "type" : "number" } + "height" : { "type" : "number" }, + "scaling" : { "type" : "number" } }, - "default": {"width" : 800, "height": 600 } + "default": {"width" : 800, "height": 600, "scaling" : 100 } }, "bitsPerPixel" : { "type" : "number", diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index 20ad8ba44..7010db19a 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -155,8 +155,8 @@ void CSettingsView::fillValidResolutionsForScreen(int screenIndex) ui->comboBoxResolution->addItem(resolutionToString(resolution)); } - int resX = settings["video"]["screenRes"]["width"].Integer(); - int resY = settings["video"]["screenRes"]["height"].Integer(); + int resX = settings["video"]["resolution"]["width"].Integer(); + int resY = settings["video"]["resolution"]["height"].Integer(); int resIndex = ui->comboBoxResolution->findText(resolutionToString({resX, resY})); ui->comboBoxResolution->setCurrentIndex(resIndex); @@ -186,7 +186,7 @@ void CSettingsView::on_comboBoxResolution_currentTextChanged(const QString & arg { QStringList list = arg1.split("x"); - Settings node = settings.write["video"]["screenRes"]; + Settings node = settings.write["video"]["resolution"]; node["width"].Float() = list[0].toInt(); node["height"].Float() = list[1].toInt(); }