extends Node ## Methods of scaling the game viewport. enum ScaleMode { ## Maintain aspect ratio and scale by highest whole number that will fit within the screen. INTEGER, ## Maintain aspect ratio and scale to fill at least one axis. ASPECT, ## Stretch to fill screen, ignoring aspect ratio. STRETCH, } ## The [enum ScaleMode] currently in use. @export var scale_mode: ScaleMode = ScaleMode.INTEGER @export_group("Internal References") ## Viewport the game is rendered in. @export var viewport: SubViewport ## Control that holds the viewport. Resized according to [member scale_mode]. @export var viewport_holder: Control ## Design/native resolution of the game. @onready var resolution: Vector2 = Vector2( ProjectSettings.get_setting("display/window/size/viewport_width"), ProjectSettings.get_setting("display/window/size/viewport_height") ) ## The currently active scene. ## ## Setting this will remove and free the previously active scene if it exists. var current_scene: Node: set(new_scene): # do nothing if already current scene if current_scene == new_scene: return # remove current scene if current_scene: viewport.remove_child(current_scene) current_scene.queue_free() # add new scene if new_scene.is_inside_tree(): new_scene.get_parent().remove_child(new_scene) viewport.add_child(new_scene) current_scene = new_scene func _ready() -> void: var tree := get_tree() await tree.process_frame # capture the main scene if tree.current_scene != self: current_scene = tree.current_scene tree.current_scene = self # gather screen_overlay references for child in tree.root.get_children(): if child is Control:#and child.is_in_group(&"screen_overlay") child.get_parent().remove_child(child) viewport_holder.add_child(child) child.set_anchors_preset(Control.PRESET_CENTER, false) child.size = resolution child.pivot_offset = resolution * 0.5 # set up viewport display viewport.size = resolution viewport_holder.size = resolution viewport_holder.pivot_offset = resolution * 0.5 _on_window_size_changed() tree.root.size_changed.connect(_on_window_size_changed) func _on_window_size_changed() -> void: # gather resolution information var screen_size := Vector2(get_tree().root.size) var scale_delta := screen_size / resolution # apply scale mode match scale_mode: ScaleMode.INTEGER: var scale = floorf(minf(scale_delta.x, scale_delta.y)) viewport_holder.scale = Vector2(scale, scale) ScaleMode.ASPECT: var scale = minf(scale_delta.x, scale_delta.y) viewport_holder.scale = Vector2(scale, scale) ScaleMode.STRETCH: viewport_holder.scale = scale_delta