This repository has been archived on 2024-04-19. You can view files and clone it, but cannot push or open issues or pull requests.
Jessist/addons/scene_transition/scene_transition_manager.gd

134 lines
3.6 KiB
GDScript3
Raw Permalink Normal View History

2022-06-18 13:05:48 +02:00
extends Node
var loading_scene:CanvasItem
var current_scene:Node
var time_to_load_scene:int
var local_thread:Thread
var loading_scene_path
var semaphore:Semaphore
var semaphore_anim_fade:Semaphore
var mutex:Mutex
var play_start_anim:bool
var waiting_for_remove = false
var resource_loader = preload("res://addons/scene_transition/resource_loader.gd").new()
var node_wrapper = Node.new()
var exit_thread = false
func _enter_tree():
#print("init>"+str(get_tree().get_root()));
time_to_load_scene = OS.get_system_time_msecs()
current_scene = detect_current_scene();
if current_scene == null:
print("no current scene detected!")
return
current_scene.connect("ready", self, "_listener_scene_complete_loaded")
func detect_current_scene():
var rt = get_tree().get_root()
for ch in rt.get_children():
if ch.name != self.name:
print("Startup scene:" + ch.name)
return ch
return null
func _init():
local_thread = Thread.new()
semaphore = Semaphore.new()
semaphore_anim_fade = Semaphore.new()
mutex = Mutex.new()
resource_loader.start()
local_thread.start(self, "thread_func", 0)
loading_scene = load("res://addons/scene_transition/loading_scene.tscn").instance()
loading_scene.connect("animation_finished", self, "_listener_animation_is_finished")
func _ready():
node_wrapper.name = "Wrapper"
get_tree().get_root().call_deferred("add_child", node_wrapper)
get_tree().get_root().call_deferred("add_child", loading_scene)
# loading_scene.fade_in()
call_deferred("change_scene_to", current_scene.filename, false)
func _exit_tree():
mutex.lock()
exit_thread = true
semaphore.post()
resource_loader.stop()
mutex.unlock()
local_thread.wait_to_finish()
func change_scene_to(var scene, play_start_anim:bool = true)-> void:
mutex.lock()
self.play_start_anim = play_start_anim
if loading_scene_path == null:
loading_scene_path = scene
semaphore.post()
mutex.unlock()
func load_scene_bg():
# this semaphore will release when change_scene_to is called
semaphore.wait()
# change_scene_to will set this var
if loading_scene_path == null:
return
# just debug purpouse
time_to_load_scene = OS.get_system_time_msecs()
# set loading_scene visible (and, of_course, block any touch in screen)
# lock instance vars
mutex.lock()
if play_start_anim:
loading_scene.visible = true
loading_scene.set_process(true)
loading_scene.fade_out()
# wait to fade_out finishes,
#before start loading new scene
semaphore_anim_fade.wait()
mutex.unlock()
resource_loader.start_loading(loading_scene_path)
current_scene = resource_loader\
.get_resource()\
.instance()
if not current_scene:
print ("Error loading scene: "+loading_scene_path)
return
mutex.lock()
loading_scene_path = null
mutex.unlock()
current_scene.connect("ready", self, "_listener_scene_complete_loaded")
node_wrapper.add_child(current_scene)
func thread_func(ignore):
while(true):
load_scene_bg()
mutex.lock()
if exit_thread:
break
mutex.unlock()
func _listener_scene_complete_loaded():
# Called when scene is full loaded
loading_scene.fade_in()
var ms = OS.get_system_time_msecs() - time_to_load_scene
print("Loaded new scene with: "+str(ms))
func _listener_animation_is_finished(var anim_name):
if anim_name == "fade_in":
loading_scene.visible = false
loading_scene.set_process(false)
if anim_name == "fade_out":
# Only remove currente scene
# when fade_out is finished
current_scene.queue_free()
# release background thread,
# it is waiting fade out finishes
semaphore_anim_fade.post()
func get_progress():
if loading_scene_path:
return resource_loader.get_progress()