scene manager :)
This commit is contained in:
parent
088ab0b944
commit
1a971bb379
5 changed files with 176 additions and 2 deletions
88
autoloads/scene_manager.gd
Normal file
88
autoloads/scene_manager.gd
Normal file
|
@ -0,0 +1,88 @@
|
|||
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
|
Loading…
Add table
Add a link
Reference in a new issue