Adding GUI to the black borders of a window

Godot Version

v4.3.stable.official [77dcf97d8]

Question

I’m trying to add GUI to the black borders that appear when resizing the window in window stretch mode.

I’ve decided to use SubViewports, this is what I’ve got so far:

AspectRatioContainer (set `ratio` to `1.3333`)
└── SubViewportContainer (set `stretch` to `true`)
    └── SubViewport
        └── Sprite

It works for the most part, except for one issue: the CanvasItems inside the SubViewport do not scale properly. For I example, when I shrink the window, the canvas items should also shrink, but they do not.

image

image

How can I ensure that the sprite scales with the window size?

Can you use a TextureRect instead of the Sprite perhaps? It has a built in functionality for resizing and rescaling.

I’m trying to implement this into an already existing project and having to update all the UI to scale like that would be a massive pain. Sorry for the late reply! I forgot I made this post.

You can change the Stretch Mode in the Project Settings to e.g. canvas_items to achieve your effect.


This is the effect:


This is the scene structure I used for this demo:

That isn’t quite what I’m going for since the black borders are still there and I’m trying to replace them with my own UI.

I did manage to get the effect I wanted but the method I used was super messy. Here’s the scene structure:

AspectRatioContainer (set `ratio` to `1.3333`)
└── SubViewportContainer (set `stretch` to `true`)
    └── SubViewport
        └── CanvasLayer (set `follow_viewport_enabled` to `true`)
            └── SubViewportContainer (set `stretch` to `true`)
                └── SubViewport
                    └── Sprite2D

then you need to attach this script to the parent of AspectRatioContainer:

extends Control


@onready var subviewport: SubViewport = $AspectRatioContainer/SubViewportContainer/SubViewport
@onready var canvas_layer: CanvasLayer = $AspectRatioContainer/SubViewportContainer/SubViewport/CanvasLayer
@onready var subsubviewportcontainer: SubViewportContainer = $AspectRatioContainer/SubViewportContainer/SubViewport/CanvasLayer/SubViewportContainer


func _process(_delta: float) -> void:
	# Get the project window size
	var width: int = ProjectSettings.get_setting(&"display/window/size/viewport_width")
	var height: int = ProjectSettings.get_setting(&"display/window/size/viewport_height")
	var window_size: = Vector2(width, height)
	
	# Scale the canvas layer
	canvas_layer.scale = Vector2(subviewport.size) / window_size
	# Not sure what this does exactly but it fixes a weird window clipping bug.
	subsubviewportcontainer.size = window_size*2.0

or you can just use this example project

I’d appreciate if anyone could find a cleaner way to do this!

1 Like