Преглед изворни кода

Implemented user-selectable UI scaling mode

Ivan Savenko пре 2 година
родитељ
комит
a0f1bf3928

+ 5 - 2
Mods/vcmi/config/vcmi/english.json

@@ -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",
 

+ 1 - 0
client/adventureMap/CAdventureMapInterface.cpp

@@ -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();

+ 3 - 0
client/render/IWindowHandler.h

@@ -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;
 };

+ 11 - 3
client/renderSDL/WindowHandler.cpp

@@ -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));

+ 1 - 0
client/renderSDL/WindowHandler.h

@@ -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;
 };

+ 75 - 7
client/windows/settings/GeneralOptionsTab.cpp

@@ -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));
 }

+ 4 - 1
client/windows/settings/GeneralOptionsTab.h

@@ -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();
 };

+ 33 - 6
config/widgets/settings/generalOptionsTab.json

@@ -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"
 		},