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:
parent
fd3933e589
commit
a0f1bf3928
@ -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",
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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));
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
};
|
};
|
||||||
|
@ -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"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user