diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index c8746356d47c..47d9e2625498 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -1085,6 +1085,10 @@ ProjectSettings::ProjectSettings() {
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_width", PropertyInfo(Variant::INT, "display/window/size/test_width", PROPERTY_HINT_RANGE, "0,7680,1,or_greater")); // 8K resolution
GLOBAL_DEF("display/window/size/test_height", 0);
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_height", PropertyInfo(Variant::INT, "display/window/size/test_height", PROPERTY_HINT_RANGE, "0,4320,1,or_greater")); // 8K resolution
+ GLOBAL_DEF("display/window/size/max_render_width", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/max_render_width", PropertyInfo(Variant::INT, "display/window/size/max_render_width", PROPERTY_HINT_RANGE, "0,7680,1,or_greater")); // 8K resolution
+ GLOBAL_DEF("display/window/size/max_render_height", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/max_render_height", PropertyInfo(Variant::INT, "display/window/size/max_render_height", PROPERTY_HINT_RANGE, "0,4320,1,or_greater")); // 8K resolution
GLOBAL_DEF("audio/default_bus_layout", "res://default_bus_layout.tres");
custom_prop_info["audio/default_bus_layout"] = PropertyInfo(Variant::STRING, "audio/default_bus_layout", PROPERTY_HINT_FILE, "*.tres");
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index fe7572139c8d..b9cbe70d4b7e 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -525,6 +525,12 @@
Sets the game's main viewport height. On desktop platforms, this is the default window size. Stretch mode settings also use this as a reference when enabled.
+
+ Sets the maximum height of the game's main viewport, when the stretch mode is "2D". If set to 0, the maximum height is the screen height.
+
+
+ Sets the maximum width of the game's main viewport, when the stretch mode is "2D". If set to 0, the maximum width is the screen width.
+
Allows the window to be resizable by default.
[b]Note:[/b] This setting is ignored on iOS.
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index 8b4e8becb34b..555e2ac0bb95 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -212,6 +212,13 @@
Marks the most recent [InputEvent] as handled.
+
+
+
+
+ Sets the maximum size of the game's main viewport, when the stretch mode is [constant STRETCH_MODE_2D]. If set to (0, 0), the render size is the screen size.
+
+
diff --git a/main/main.cpp b/main/main.cpp
index b94affd45447..55e11c908171 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -2042,6 +2042,7 @@ bool Main::start() {
String stretch_mode = GLOBAL_DEF("display/window/stretch/mode", "disabled");
String stretch_aspect = GLOBAL_DEF("display/window/stretch/aspect", "ignore");
Size2i stretch_size = Size2(GLOBAL_DEF("display/window/size/width", 0), GLOBAL_DEF("display/window/size/height", 0));
+ Size2i max_render_size = Size2(GLOBAL_DEF("display/window/size/max_render_width", 0), GLOBAL_DEF("display/window/size/max_render_height", 0));
// out of compatibility reasons stretch_scale is called shrink when exposed to the user.
real_t stretch_scale = GLOBAL_DEF("display/window/stretch/shrink", 1.0);
@@ -2064,6 +2065,7 @@ bool Main::start() {
}
sml->set_screen_stretch(sml_sm, sml_aspect, stretch_size, stretch_scale);
+ sml->set_max_render_size(max_render_size);
sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true));
sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true));
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index ca098afd2d53..891a0d4a666c 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -1409,8 +1409,12 @@ void SceneTree::_update_root_rect() {
// Already handled above
} break;
case STRETCH_MODE_2D: {
- _update_font_oversampling((screen_size.x / viewport_size.x) * stretch_scale); //screen / viewport ratio drives oversampling
- root->set_size(screen_size.floor());
+ Size2 render_size = screen_size;
+ if (max_render_size.x > 0 && max_render_size.y > 0 && (screen_size.x > max_render_size.x || screen_size.y > max_render_size.y)) {
+ render_size = max_render_size;
+ }
+ _update_font_oversampling((render_size.x / viewport_size.x) * stretch_scale); //screen / viewport ratio drives oversampling
+ root->set_size(render_size);
root->set_attach_to_screen_rect(Rect2(margin, screen_size));
root->set_size_override_stretch(true);
root->set_size_override(true, (viewport_size / stretch_scale).floor());
@@ -1437,6 +1441,15 @@ void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, c
_update_root_rect();
}
+void SceneTree::set_max_render_size(const Size2 &p_max_render_size) {
+ max_render_size = p_max_render_size;
+ _update_root_rect();
+}
+
+Size2 SceneTree::get_max_render_size() {
+ return max_render_size;
+}
+
void SceneTree::set_edited_scene_root(Node *p_node) {
#ifdef TOOLS_ENABLED
edited_scene_root = p_node;
@@ -2064,6 +2077,7 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame);
ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("set_max_render_size", "max_render_size"), &SceneTree::set_max_render_size);
ClassDB::bind_method(D_METHOD("set_screen_stretch", "mode", "aspect", "minsize", "scale"), &SceneTree::set_screen_stretch, DEFVAL(1));
ClassDB::bind_method(D_METHOD("set_physics_interpolation_enabled", "enabled"), &SceneTree::set_physics_interpolation_enabled);
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index ef8e6ccad401..90fb6b199380 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -160,6 +160,7 @@ class SceneTree : public MainLoop {
StretchAspect stretch_aspect;
Size2i stretch_min;
real_t stretch_scale;
+ Size2 max_render_size;
void _update_font_oversampling(float p_ratio);
void _update_root_rect();
@@ -386,6 +387,9 @@ class SceneTree : public MainLoop {
void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 &p_minsize, real_t p_scale = 1.0);
+ void set_max_render_size(const Size2 &p_max_render_size);
+ Size2 get_max_render_size();
+
void set_use_font_oversampling(bool p_oversampling);
bool is_using_font_oversampling() const;