gfolf2/src/game/game.gd

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")