Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Multiple Resolutions demo for Godot 4.0 #733

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions gui/multiple_resolutions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,25 @@ overscan area to prevent GUI elements from being cut off. This can also improve
the gameplay experience on large monitors by bringing HUD elements closer to the
center of the screen.

A DynamicFont is also used to ensure font rendering remains crisp at high
resolutions, thanks to Godot's built-in support for font oversampling. In other
words, the engine will automatically re-rasterize fonts at different resolutions
than the base window size when the window is resized (or when the window scale
factor is changed).
A DynamicFont with multichannel signed distance field (MSDF) rendering is also used.
This allows for crisp font rendering at any resolution, without having to re-rasterize
the font when the font size changes. This makes changing the various settings in this
demo faster, especially when large font sizes are used as a result of the GUI scale factor
setting being increased.

Note that by default, Godot uses font oversampling for traditional rasterized
DynamicFonts. This means MSDF fonts are *not* required to have crisp fonts at
higher-than-default screen resolutions.

Language: GDScript

Renderer: GLES 2
Renderer: Vulkan Mobile

## Technical notes

The demo works with the following project settings:

- `2d` stretch mode (recommended for most non-pixel art games).
- `canvas_items` stretch mode (formerly `2d`). Recommended for most non-pixel art games.
- `expand` stretch aspect (allows support for multiple aspect ratios without
distortion or black bars).
- Using a base window size with a 1:1 aspect ratio (`648×648` in this demo).
Expand Down
29 changes: 14 additions & 15 deletions gui/multiple_resolutions/icon.png.import
Original file line number Diff line number Diff line change
@@ -1,35 +1,34 @@
[remap]

importer="texture"
type="StreamTexture"
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
type="CompressedTexture2D"
uid="uid://cx2c0cunh0e1i"
path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://icon.png"
dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"]

[params]

compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/hdr_compression=1
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
56 changes: 28 additions & 28 deletions gui/multiple_resolutions/main.gd
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,52 @@ var base_window_size = Vector2(ProjectSettings.get_setting("display/window/size/

# These defaults match this demo's project settings. Adjust as needed if adapting this
# in your own project.
var stretch_mode = SceneTree.STRETCH_MODE_2D
var stretch_aspect = SceneTree.STRETCH_ASPECT_EXPAND
var stretch_mode = Window.CONTENT_SCALE_MODE_CANVAS_ITEMS
var stretch_aspect = Window.CONTENT_SCALE_ASPECT_EXPAND

var scale_factor = 1.0
var gui_aspect_ratio = -1.0
var gui_margin = 0.0

onready var panel = $Panel
onready var arc = $Panel/AspectRatioContainer
@onready var panel = $Panel
@onready var arc = $Panel/AspectRatioContainer


func _ready():
# The `resized` signal will be emitted when the window size changes, as the root Control node
# is resized whenever the window size changes. This is because the root Control node
# uses a Full Rect anchor, so its size will always be equal to the window size.
# warning-ignore:return_value_discarded
connect("resized", self, "_on_resized")
connect("resized", self._on_resized)
update_container()


func update_container():
# The code within this function needs to be run twice to work around an issue with containers
# having a 1-frame delay with updates.
# Otherwise, `panel.rect_size` returns a value of the previous frame, which results in incorrect
# Otherwise, `panel.size` returns a value of the previous frame, which results in incorrect
# sizing of the inner AspectRatioContainer when using the Fit to Window setting.
for _i in 2:
if is_equal_approx(gui_aspect_ratio, -1.0):
# Fit to Window. Tell the AspectRatioContainer to use the same aspect ratio as the window,
# making the AspectRatioContainer not have any visible effect.
arc.ratio = panel.rect_size.aspect()
# Apply GUI margin on the AspectRatioContainer's parent (Panel).
# This also makes the GUI margin apply on controls located outside the AspectRatioContainer
arc.ratio = panel.size.aspect()
# Apply GUI offset on the AspectRatioContainer's parent (Panel).
# This also makes the GUI offset apply on controls located outside the AspectRatioContainer
# (such as the inner side label in this demo).
panel.margin_top = gui_margin
panel.margin_bottom = -gui_margin
panel.offset_top = gui_margin
panel.offset_bottom = -gui_margin
else:
# Constrained aspect ratio.
arc.ratio = min(panel.rect_size.aspect(), gui_aspect_ratio)
# Adjust top and bottom margins relative to the aspect ratio when it's constrained.
# This ensures that GUI margin settings behave exactly as if the window had the
arc.ratio = min(panel.size.aspect(), gui_aspect_ratio)
# Adjust top and bottom offsets relative to the aspect ratio when it's constrained.
# This ensures that GUI offset settings behave exactly as if the window had the
# original aspect ratio size.
panel.margin_top = gui_margin / gui_aspect_ratio
panel.margin_bottom = -gui_margin / gui_aspect_ratio
panel.offset_top = gui_margin / gui_aspect_ratio
panel.offset_bottom = -gui_margin / gui_aspect_ratio

panel.margin_left = gui_margin
panel.margin_right = -gui_margin
panel.offset_left = gui_margin
panel.offset_right = -gui_margin


func _on_gui_aspect_ratio_item_selected(index):
Expand Down Expand Up @@ -81,8 +81,8 @@ func _on_resized():


func _on_gui_margin_drag_ended(_value_changed):
gui_margin = $"Panel/AspectRatioContainer/ColorRect/CenterContainer/Options/GUIMargin/HSlider".value
$"Panel/AspectRatioContainer/ColorRect/CenterContainer/Options/GUIMargin/Value".text = str(gui_margin)
gui_margin = $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/GUIMargin/HSlider".value
$"Panel/AspectRatioContainer/Panel/CenterContainer/Options/GUIMargin/Value".text = str(gui_margin)
update_container()


Expand All @@ -105,25 +105,25 @@ func _on_window_base_size_item_selected(index):
7: # 1680×720 (21:9)
base_window_size = Vector2(1680, 720)

get_tree().set_screen_stretch(stretch_mode, stretch_aspect, base_window_size, scale_factor)
get_viewport().content_scale_size = base_window_size
update_container()


func _on_window_stretch_mode_item_selected(index):
stretch_mode = index
get_tree().set_screen_stretch(stretch_mode, stretch_aspect, base_window_size, scale_factor)
get_viewport().content_scale_mode = stretch_mode

# Disable irrelevant options when the stretch mode is Disabled.
$"Panel/AspectRatioContainer/ColorRect/CenterContainer/Options/WindowBaseSize/OptionButton".disabled = stretch_mode == SceneTree.STRETCH_MODE_DISABLED
$"Panel/AspectRatioContainer/ColorRect/CenterContainer/Options/WindowStretchAspect/OptionButton".disabled = stretch_mode == SceneTree.STRETCH_MODE_DISABLED
$"Panel/AspectRatioContainer/Panel/CenterContainer/Options/WindowBaseSize/OptionButton".disabled = stretch_mode == Window.CONTENT_SCALE_MODE_DISABLED
$"Panel/AspectRatioContainer/Panel/CenterContainer/Options/WindowStretchAspect/OptionButton".disabled = stretch_mode == Window.CONTENT_SCALE_MODE_DISABLED


func _on_window_stretch_aspect_item_selected(index):
stretch_aspect = index
get_tree().set_screen_stretch(stretch_mode, stretch_aspect, base_window_size, scale_factor)
get_viewport().content_scale_aspect = stretch_aspect


func _on_window_scale_factor_drag_ended(_value_changed):
scale_factor = $"Panel/AspectRatioContainer/ColorRect/CenterContainer/Options/WindowScaleFactor/HSlider".value
$"Panel/AspectRatioContainer/ColorRect/CenterContainer/Options/WindowScaleFactor/Value".text = "%d%%" % (scale_factor * 100)
get_tree().set_screen_stretch(stretch_mode, stretch_aspect, base_window_size, scale_factor)
scale_factor = $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/WindowScaleFactor/HSlider".value
$"Panel/AspectRatioContainer/Panel/CenterContainer/Options/WindowScaleFactor/Value".text = "%d%%" % (scale_factor * 100)
get_viewport().content_scale_factor = scale_factor
Loading