generated from krampus/template-godot4
109 lines
2.9 KiB
GDScript
109 lines
2.9 KiB
GDScript
class_name Game extends Node
|
|
## Wrapper for the game application
|
|
|
|
@export var start_scene: String = "res://src/ui/menus/title_screen/title_screen.tscn"
|
|
|
|
var _loading_resources := {}
|
|
|
|
@onready var viewport: GameViewportContainer = %ViewportContainer
|
|
@onready var sfx: GameSFX = %SFX
|
|
|
|
@onready var content: Node = %Content
|
|
@onready var loader_transition: AnimationPlayer = %LoaderTransition
|
|
@onready var loading_screen: Control = %LoadingScreen
|
|
|
|
static var group := "GameGroup" # hey i'm group
|
|
|
|
## Typesafe accessor for GameSettings singleton
|
|
static var settings: GameSettingsType:
|
|
get:
|
|
return GameSettings
|
|
|
|
|
|
class Promise:
|
|
var _callbacks: Array[Callable] = []
|
|
var _end_callbacks: Array[Callable] = []
|
|
|
|
func then(fn: Callable) -> Promise:
|
|
_callbacks.push_back(fn)
|
|
return self
|
|
|
|
func finally(fn: Callable) -> Promise:
|
|
_end_callbacks.push_back(fn)
|
|
return self
|
|
|
|
func resolve(res: Variant) -> void:
|
|
for fn: Callable in _callbacks + _end_callbacks:
|
|
fn.call(res)
|
|
|
|
|
|
class ScenePromise:
|
|
extends Promise
|
|
|
|
func resolve(res: Variant) -> void:
|
|
@warning_ignore("unsafe_cast")
|
|
var instance: Node = (res as PackedScene).instantiate()
|
|
super.resolve(instance)
|
|
|
|
|
|
func _initial_load() -> void:
|
|
queue_scene(start_scene)
|
|
|
|
|
|
func _ready() -> void:
|
|
call_deferred("_initial_load")
|
|
|
|
|
|
## Unload the running scene & queue up a new scene to be loaded in the background.
|
|
##
|
|
## The loading screen will be shown until the scene is loaded.
|
|
func queue_scene(path: String) -> Promise:
|
|
return queue_load(path, ScenePromise.new(), "PackedScene").finally(_finish_scene_load)
|
|
|
|
|
|
## Queue a resource to be loaded in the background.
|
|
##
|
|
## Returns a `Promise` which can be used to attach callbacks
|
|
## which will be called with the resource after it is loaded.
|
|
func queue_load(path: String, promise: Promise = null, type_hint: String = "") -> Promise:
|
|
if not promise:
|
|
promise = Promise.new()
|
|
_loading_resources[path] = promise
|
|
ResourceLoader.load_threaded_request(path, type_hint)
|
|
return promise
|
|
|
|
|
|
func _unload_content() -> void:
|
|
for child: Node in content.get_children():
|
|
child.queue_free()
|
|
|
|
|
|
func _finish_scene_load(instance: Node) -> void:
|
|
content.add_child(instance)
|
|
instance.reparent(content)
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
if _loading_resources and not loading_screen.visible:
|
|
loader_transition.play("fade_in")
|
|
|
|
if loader_transition.is_playing():
|
|
return
|
|
|
|
for key: String in _loading_resources.keys():
|
|
match ResourceLoader.load_threaded_get_status(key):
|
|
ResourceLoader.THREAD_LOAD_LOADED:
|
|
@warning_ignore("unsafe_cast")
|
|
(_loading_resources[key] as Promise).resolve(ResourceLoader.load_threaded_get(key))
|
|
_loading_resources.erase(key)
|
|
ResourceLoader.THREAD_LOAD_FAILED:
|
|
assert(false, "Failed loading resource: " + key)
|
|
ResourceLoader.THREAD_LOAD_INVALID_RESOURCE:
|
|
assert(false, "Can't load invalid resource: " + key)
|
|
_:
|
|
# Continue loading
|
|
pass
|
|
|
|
if not _loading_resources and loading_screen.visible:
|
|
loader_transition.play("fade_out")
|