scene manager :)

This commit is contained in:
Haze Weathers 2025-03-02 05:34:09 -05:00
parent 088ab0b944
commit 1a971bb379
5 changed files with 176 additions and 2 deletions

View file

@ -0,0 +1,15 @@
shader_type canvas_item;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture;
vec2 warp(vec2 uv) {
return vec2(
uv.x + sin(TIME + uv.y * 50.0) * 0.005,
uv.y
);
}
void fragment() {
vec2 uv = warp(SCREEN_UV);
COLOR = texture(SCREEN_TEXTURE, uv);
}

View 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

View file

@ -0,0 +1,49 @@
[gd_scene load_steps=2 format=3 uid="uid://ckgsfhfpg00ys"]
[ext_resource type="Script" path="res://autoloads/scene_manager.gd" id="1_1hxm1"]
[node name="SceneManager" type="Node" node_paths=PackedStringArray("viewport", "viewport_holder")]
script = ExtResource("1_1hxm1")
viewport = NodePath("ViewportHolder/ViewportContainer/SubViewport")
viewport_holder = NodePath("ViewportHolder")
[node name="ClearColor" type="CanvasLayer" parent="."]
layer = -128
[node name="ColorRect" type="ColorRect" parent="ClearColor"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0, 0, 0, 1)
[node name="ViewportHolder" type="Control" parent="."]
layout_mode = 3
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -144.0
offset_top = -108.0
offset_right = 144.0
offset_bottom = 108.0
grow_horizontal = 2
grow_vertical = 2
pivot_offset = Vector2(144, 108)
[node name="ViewportContainer" type="SubViewportContainer" parent="ViewportHolder"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
pivot_offset = Vector2(144, 108)
[node name="SubViewport" type="SubViewport" parent="ViewportHolder/ViewportContainer"]
handle_input_locally = false
canvas_item_default_texture_filter = 0
size = Vector2i(288, 216)
render_target_update_mode = 4

View file

@ -0,0 +1,14 @@
[gd_scene load_steps=3 format=3 uid="uid://bbrh8j4w6pgj2"]
[ext_resource type="Shader" path="res://assets/shaders/test_filter.gdshader" id="1_un711"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_au4vs"]
shader = ExtResource("1_un711")
[node name="TestFilter" type="ColorRect" groups=["screen_overlay"]]
material = SubResource("ShaderMaterial_au4vs")
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2

View file

@ -15,12 +15,15 @@ run/main_scene="res://maps/level1.tscn"
config/features=PackedStringArray("4.3", "GL Compatibility") config/features=PackedStringArray("4.3", "GL Compatibility")
config/icon="res://icon.svg" config/icon="res://icon.svg"
[autoload]
SceneManager="*res://autoloads/scene_manager.tscn"
TestFilter="*res://autoloads/test_filter.tscn"
[display] [display]
window/size/viewport_width=288 window/size/viewport_width=288
window/size/viewport_height=216 window/size/viewport_height=216
window/stretch/mode="viewport"
window/stretch/scale_mode="integer"
[editor_plugins] [editor_plugins]
@ -31,11 +34,16 @@ enabled=PackedStringArray("res://addons/godot_state_charts/plugin.cfg")
folder_colors={ folder_colors={
"res://addons/": "gray", "res://addons/": "gray",
"res://assets/": "yellow", "res://assets/": "yellow",
"res://autoloads/": "orange",
"res://maps/": "blue", "res://maps/": "blue",
"res://objects/": "red", "res://objects/": "red",
"res://scripts/": "teal" "res://scripts/": "teal"
} }
[global_group]
screen_overlay="Autoload that will be rendered over the game viewport at full resolution."
[layer_names] [layer_names]
2d_physics/layer_1="solid" 2d_physics/layer_1="solid"