Scaling the viewport manually (2D)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Sammy Gillespie
:warning: Old Version Published before Godot 3 was released.

I have a UI that I want to scale to all resolutions, however I want it to scale in a particular way.

In effect, I want to have a 2D stretch mode with fixed aspect ratio (never stretch my textures weirdly) HOWEVER, instead of black bars, I wish the width to be fully fluid. By this I mean that the entire viewport would scale as vPortHeight/projectHeight but the width would then expand or shrink to match the correct aspect ratio. This would be akin to expanding the FoV when using a higher aspect ratio.

You can see the effect in this video that I threw together from some temp assets for a small projects I’m messing with:

You can see that the scaling only occurs when the height changes, and otherwise the two PCB strips (which are attached to the edges of the viewport) slide in and out.


Now I know of two ways to get this effect, but I can’t work out which is best, or if they are, in fact, identical.

The first is using a camera (note that my project’s size is 1920x1080):

func _on_viewport_resized():
var viewport = get_node("/root")
var height = viewport.get_rect().size.y
var width = viewport.get_rect().size.x

# Set viewpoint to run at 1080px tall, but adjust width to match aspect ratio of screen
viewport.set_size_override(true, Vector2(1080*width/height,1080))

# Adjust the cameras zoom level to match the view with the screen's height
var zoom_ratio = 1080/height
get_node("Camera2D").set_zoom(Vector2(zoom_ratio, zoom_ratio))

This sets the viewport to always be a constant height, but adapts the width to match aspect ratio. I then use a camera to ensure that when the screen is small than 1080px high the viewport is scaled down correctly.

This works well, and I know that it ups the render target resolution to ensure it uses higher quality textures when available.


The second method is to do a very similar thing, but turn on stretching.

func _on_viewport_resized():
var viewport = get_node("/root")
var height = viewport.get_rect().size.y
var width = viewport.get_rect().size.x

# Set viewpoint to run at 1080px tall, but adjust width to match aspect ratio of screen
viewport.set_size_override(true, Vector2(1080*width/height,1080))
viewport.set_size_override_stretch(true)

This is simpler in that it doesn’t even need a camera which I like but I have no idea what set_size_override_stretch(true) actually ends up doing. Does that up the target render resolution? Or does it just turn on viewport scaling and thus I’ll lose out on higher resolution textures on high DPI screens (though I could build the project against a higher resolution).

So I guess the question is… what does set_size_override_stretch(true) actually do? And will either of these methods come back to haunt me (I feel like with the camera I’ll need viewports in viewports if I ever want an actual camera).

Anyone done stuff like this before?


Truthfully, I worked out half of this while writing this question… And I feel like the camera method offers more flexibility if anything comes up later as I have full control. I also know how it works…

:bust_in_silhouette: Reply From: AsP

In Godot 3.2 you would probably just need to adjust in Project SettingsDisplayWindowStretch the values of Mode to 2D and Aspect to keep height.

See: