Переглянути джерело

Implemented reserved area for iOS notch / cutout

Ivan Savenko 2 роки тому
батько
коміт
0c83e34093

+ 28 - 12
client/renderSDL/ScreenHandler.cpp

@@ -25,7 +25,7 @@
 #include <SDL.h>
 
 // TODO: should be made into a private members of ScreenHandler
-SDL_Window * mainWindow = nullptr;
+static SDL_Window * mainWindow = nullptr;
 SDL_Renderer * mainRenderer = nullptr;
 SDL_Texture * screenTexture = nullptr;
 SDL_Surface * screen = nullptr; //main screen surface
@@ -42,9 +42,12 @@ std::tuple<int, int> ScreenHandler::getSupportedScalingRange() const
 	// 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 maximalScalingWidth = 100.0 * renderResolution.x / minResolution.x;
-	double maximalScalingHeight = 100.0 * renderResolution.y / minResolution.y;
+	Point renderResolution = getActualRenderResolution();
+	double reservedAreaWidth = settings["video"]["reservedWidth"].Float();
+	Point availableResolution = Point(renderResolution.x * (1 - reservedAreaWidth), renderResolution.y);
+
+	double maximalScalingWidth = 100.0 * availableResolution.x / minResolution.x;
+	double maximalScalingHeight = 100.0 * availableResolution.y / minResolution.y;
 	double maximalScaling = std::min(maximalScalingWidth, maximalScalingHeight);
 
 	return { minimalScaling, maximalScaling };
@@ -78,18 +81,31 @@ Rect ScreenHandler::convertLogicalPointsToWindow(const Rect & input) const
 
 Point ScreenHandler::getPreferredLogicalResolution() const
 {
-	Point renderResolution = getPreferredRenderingResolution();
+	Point renderResolution = getActualRenderResolution();
+	double reservedAreaWidth = settings["video"]["reservedWidth"].Float();
+	Point availableResolution = Point(renderResolution.x * (1 - reservedAreaWidth), renderResolution.y);
+
 	auto [minimalScaling, maximalScaling] = getSupportedScalingRange();
 
 	int userScaling = settings["video"]["resolution"]["scaling"].Integer();
 	int scaling = std::clamp(userScaling, minimalScaling, maximalScaling);
 
-	Point logicalResolution = renderResolution * 100.0 / scaling;
+	Point logicalResolution = availableResolution * 100.0 / scaling;
 
 	return logicalResolution;
 }
 
-Point ScreenHandler::getPreferredRenderingResolution() const
+Point ScreenHandler::getActualRenderResolution() const
+{
+	assert(mainRenderer != nullptr);
+
+	Point result;
+	SDL_GetRendererOutputSize(mainRenderer, &result.x, &result.y);
+
+	return result;
+}
+
+Point ScreenHandler::getPreferredWindowResolution() const
 {
 	if (getPreferredWindowMode() == EWindowMode::FULLSCREEN_BORDERLESS_WINDOWED)
 	{
@@ -208,7 +224,7 @@ void ScreenHandler::updateWindowState()
 
 			SDL_DisplayMode mode;
 			SDL_GetDesktopDisplayMode(displayIndex, &mode);
-			Point resolution = getPreferredRenderingResolution();
+			Point resolution = getPreferredWindowResolution();
 
 			mode.w = resolution.x;
 			mode.h = resolution.y;
@@ -226,7 +242,7 @@ void ScreenHandler::updateWindowState()
 		}
 		case EWindowMode::WINDOWED:
 		{
-			Point resolution = getPreferredRenderingResolution();
+			Point resolution = getPreferredWindowResolution();
 			SDL_SetWindowFullscreen(mainWindow, 0);
 			SDL_SetWindowSize(mainWindow, resolution.x, resolution.y);
 			SDL_SetWindowPosition(mainWindow, SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex), SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex));
@@ -316,7 +332,7 @@ SDL_Window * ScreenHandler::createWindowImpl(Point dimensions, int flags, bool c
 SDL_Window * ScreenHandler::createWindow()
 {
 #ifndef VCMI_MOBILE
-	Point dimensions = getPreferredRenderingResolution();
+	Point dimensions = getPreferredWindowResolution();
 
 	switch(getPreferredWindowMode())
 	{
@@ -376,7 +392,7 @@ void ScreenHandler::validateSettings()
 	{
 		//we only check that our desired window size fits on screen
 		int displayIndex = getPreferredDisplayIndex();
-		Point resolution = getPreferredRenderingResolution();
+		Point resolution = getPreferredWindowResolution();
 
 		SDL_DisplayMode mode;
 
@@ -394,7 +410,7 @@ void ScreenHandler::validateSettings()
 	if (getPreferredWindowMode() == EWindowMode::FULLSCREEN_EXCLUSIVE)
 	{
 		auto legalOptions = getSupportedResolutions();
-		Point selectedResolution = getPreferredRenderingResolution();
+		Point selectedResolution = getPreferredWindowResolution();
 
 		if(!vstd::contains(legalOptions, selectedResolution))
 		{

+ 5 - 2
client/renderSDL/ScreenHandler.h

@@ -30,14 +30,17 @@ enum class EWindowMode
 };
 
 /// This class is responsible for management of game window and its main rendering surface
-class ScreenHandler : public IScreenHandler
+class ScreenHandler final : public IScreenHandler
 {
 	/// Dimensions of target surfaces/textures, this value is what game logic views as screen size
 	Point getPreferredLogicalResolution() const;
 
 	/// Dimensions of output window, if different from logicalResolution SDL will perform scaling
 	/// This value is what player views as window size
-	Point getPreferredRenderingResolution() const;
+	Point getPreferredWindowResolution() const;
+
+	/// Dimensions of render output, usually same as window size except for high-DPI screens on macOS / iOS
+	Point getActualRenderResolution() const;
 
 	EWindowMode getPreferredWindowMode() const;
 

+ 13 - 7
config/schemas/settings.json

@@ -109,13 +109,14 @@
 			"additionalProperties" : false,
 			"default" : {},
 			"required" : [ 
-				"resolution", 
-				"fullscreen", 
-				"realFullscreen", 
-				"cursor", 
-				"showIntro", 
-				"spellbookAnimation", 
-				"driver", 
+				"resolution",
+				"reservedWidth",
+				"fullscreen",
+				"realFullscreen",
+				"cursor",
+				"showIntro",
+				"spellbookAnimation",
+				"driver",
 				"displayIndex",
 				"showfps",
 				"targetfps"
@@ -134,6 +135,11 @@
 					"defaultAndroid" : {"width" : 800, "height" : 600, "scaling" : 200 },
 					"default" : {"width" : 800, "height" : 600, "scaling" : 100 }
 				},
+				"reservedWidth" : {
+					"type" : "number",
+					"defaultIOS" : 0.1, // iOS camera cutout / notch is excluded from available area by SDL
+					"default" : 0
+				},
 				"fullscreen" : {
 					"type" : "boolean",
 					"default" : false