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.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.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.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.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->setState(EGameState::MAKING_TURN);
|
||||
widget->getMapView()->onViewMapActivated();
|
||||
widget->setPlayer(currentPlayerID);
|
||||
|
||||
if (isActive())
|
||||
widget->activate();
|
||||
|
@ -30,4 +30,7 @@ public:
|
||||
|
||||
/// Returns list of resolutions supported by current screen
|
||||
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 = 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
|
||||
static const Point minResolution = {800, 600};
|
||||
@ -41,11 +41,19 @@ Point WindowHandler::getPreferredLogicalResolution() const
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
Point logicalResolution = renderResolution * 100.0 / scaling;
|
||||
@ -182,7 +190,7 @@ void WindowHandler::updateFullscreenState()
|
||||
}
|
||||
case EWindowMode::WINDOWED:
|
||||
{
|
||||
Point resolution = getPreferredLogicalResolution();
|
||||
Point resolution = getPreferredRenderingResolution();
|
||||
SDL_SetWindowFullscreen(mainWindow, 0);
|
||||
SDL_SetWindowSize(mainWindow, resolution.x, resolution.y);
|
||||
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(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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
std::string string = "%wx%h";
|
||||
@ -96,6 +109,10 @@ GeneralOptionsTab::GeneralOptionsTab()
|
||||
{
|
||||
selectGameResolution();
|
||||
});
|
||||
addCallback("setGameScaling", [this](int dummyValue)
|
||||
{
|
||||
selectGameScaling();
|
||||
});
|
||||
addCallback("framerateChanged", [](bool value)
|
||||
{
|
||||
setBoolSetting("video", "showfps", value);
|
||||
@ -114,10 +131,14 @@ GeneralOptionsTab::GeneralOptionsTab()
|
||||
|
||||
build(config);
|
||||
|
||||
std::shared_ptr<CLabel> resolutionLabel = widget<CLabel>("resolutionLabel");
|
||||
const auto & currentResolution = settings["video"]["resolution"];
|
||||
|
||||
std::shared_ptr<CLabel> resolutionLabel = widget<CLabel>("resolutionLabel");
|
||||
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");
|
||||
spellbookAnimationCheckbox->setSelected(settings["video"]["spellbookAnimation"].Bool());
|
||||
|
||||
@ -152,7 +173,12 @@ GeneralOptionsTab::GeneralOptionsTab()
|
||||
|
||||
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;
|
||||
size_t currentResolutionIndex = 0;
|
||||
@ -197,12 +223,54 @@ void GeneralOptionsTab::setFullscreenMode(bool 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;
|
||||
|
||||
std::vector<Point> supportedResolutions;
|
||||
std::vector<double> supportedScaling;
|
||||
|
||||
void setFullscreenMode( bool on);
|
||||
void fillSelectableResolutions();
|
||||
|
||||
void selectGameResolution();
|
||||
void setGameResolution(int index);
|
||||
|
||||
void selectGameScaling();
|
||||
void setGameScaling(int index);
|
||||
|
||||
public:
|
||||
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",
|
||||
"type": "labelGroup",
|
||||
@ -67,15 +94,15 @@
|
||||
"items":
|
||||
[
|
||||
{
|
||||
"position": {"x": 45, "y": 115},
|
||||
"position": {"x": 45, "y": 145},
|
||||
"text": "vcmi.systemOptions.fullscreenButton.hover"
|
||||
},
|
||||
{
|
||||
"position": {"x": 45, "y": 145},
|
||||
"position": {"x": 45, "y": 175},
|
||||
"text": "vcmi.systemOptions.framerateButton.hover"
|
||||
},
|
||||
{
|
||||
"position": {"x": 45, "y": 175},
|
||||
"position": {"x": 45, "y": 205},
|
||||
"text": "core.genrltxt.577"
|
||||
},
|
||||
|
||||
@ -86,7 +113,7 @@
|
||||
"type": "toggleButton",
|
||||
"image": "sysopchk.def",
|
||||
"help": "vcmi.systemOptions.fullscreenButton",
|
||||
"position": {"x": 10, "y": 113},
|
||||
"position": {"x": 10, "y": 143},
|
||||
"callback": "fullscreenChanged"
|
||||
},
|
||||
{
|
||||
@ -94,7 +121,7 @@
|
||||
"type": "toggleButton",
|
||||
"image": "sysopchk.def",
|
||||
"help": "vcmi.systemOptions.framerateButton",
|
||||
"position": {"x": 10, "y": 143},
|
||||
"position": {"x": 10, "y": 173},
|
||||
"callback": "framerateChanged"
|
||||
},
|
||||
|
||||
@ -103,7 +130,7 @@
|
||||
"type": "toggleButton",
|
||||
"image": "sysopchk.def",
|
||||
"help": "core.help.364",
|
||||
"position": {"x": 10, "y": 173},
|
||||
"position": {"x": 10, "y": 203},
|
||||
"callback": "spellbookAnimationChanged"
|
||||
},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user