extends Node enum ScaleMode { ## Stretches to fit as close as possible while maintaining the game's aspect ratio. ASPECT, ## Stretches to fit as close as possible while maintaining aspect ratio and an integer scale. INTEGER, ## Stretches to cover the whole screen, warping the aspect ratio. STRETCH, } ## Strategy to use for scaling from game-native resolution to the window/screen size. @export var scale_mode: ScaleMode = ScaleMode.ASPECT: set(value): scale_mode = value if is_node_ready(): _update_scale() @export_group("Internal References") @export var _viewport: SubViewport @export var _viewport_container: SubViewportContainer ## The native resolution of the game. var size: Vector2i = Vector2i( ProjectSettings.get_setting("display/window/size/viewport_width"), ProjectSettings.get_setting("display/window/size/viewport_height"), ) func _enter_tree() -> void: get_tree().scene_changed.connect(_on_scene_changed) get_tree().root.size_changed.connect(_update_scale) _update_scale.call_deferred() var current_scene = get_tree().current_scene if current_scene and current_scene != self: current_scene.reparent.call_deferred(_viewport) func _on_scene_changed() -> void: for child in _viewport.get_children(): child.queue_free() get_tree().current_scene.reparent(_viewport) func _update_scale() -> void: var screen_size = Vector2(get_tree().root.size) var size_ratio = screen_size / Vector2(size) DisplayServer.window_set_min_size(size) _viewport.size = size _viewport_container.pivot_offset = Vector2(size) * 0.5 _viewport_container.position = screen_size * 0.5 - Vector2(size) * 0.5 match scale_mode: ScaleMode.ASPECT: # get the minimum ratio and use for both axes var min_scale = minf(size_ratio.x, size_ratio.y) _viewport_container.scale = Vector2(min_scale, min_scale) ScaleMode.INTEGER: # get the minimum ratio and use for both axes after flooring var min_scale = floorf(minf(size_ratio.x, size_ratio.y)) _viewport_container.scale = Vector2(min_scale, min_scale) ScaleMode.STRETCH: # just use the ratio as-is _viewport_container.scale = size_ratio