extends CanvasLayer @export var config: SceneConfig @onready var color_rect = $ColorRect @onready var loading_screen = $LoadingScreen @export var transition_duration: float = 3 const SHADER_PATH := "res://core/transition.gdshader" var transaction_material: ShaderMaterial func _ready() -> void: _build_material() _update_resolution() get_viewport().size_changed.connect(_update_resolution) _set_factor(0.0) color_rect.visible = false func _build_material() -> void: transaction_material = ShaderMaterial.new() transaction_material.shader = load(SHADER_PATH) #directional gradient: bottom-left-> black; top-right -> white var g := Gradient.new() g.set_color(0, Color.BLACK) g.set_color(1, Color.WHITE) var grad_tex := GradientTexture2D.new() grad_tex.gradient = g grad_tex.fill = GradientTexture2D.FILL_LINEAR grad_tex.fill_from = Vector2(0.0, 1.0) # bottom-left grad_tex.fill_to = Vector2(1.0, 0.0) # top-right grad_tex.width = 256 grad_tex.height = 256 #shape: sphere (white at the center, black around) var sg := Gradient.new() sg.set_color(0, Color.WHITE) sg.set_color(1, Color.BLACK) var shape_tex := GradientTexture2D.new() shape_tex.gradient = sg shape_tex.fill = GradientTexture2D.FILL_RADIAL shape_tex.fill_from = Vector2(0.5, 0.5) # center shape_tex.fill_to = Vector2(0.5, 0.0) # ray shape_tex.width = 64 shape_tex.height = 64 transaction_material.set_shader_parameter("base_color", Color.BLACK) transaction_material.set_shader_parameter("gradient_texture", grad_tex) transaction_material.set_shader_parameter("gradient_fixed", false) transaction_material.set_shader_parameter("shape_texture", shape_tex) transaction_material.set_shader_parameter("shape_tiling", 16.0) transaction_material.set_shader_parameter("shape_rotation", 0.0) transaction_material.set_shader_parameter("shape_scroll", Vector2.ZERO) transaction_material.set_shader_parameter("shape_feathering", 0.05) transaction_material.set_shader_parameter("shape_treshold", 1.0) # >=1 -> full at the end of the transation transaction_material.set_shader_parameter("width", 0.5) color_rect.material = transaction_material func _update_resolution() -> void: var s := get_viewport().get_visible_rect().size if color_rect.material: color_rect.material.set_shader_parameter("node_resolution", s) func _set_factor(v: float) -> void: if color_rect.material: color_rect.material.set_shader_parameter("factor", v) func cover(duration := 0.5) -> void: color_rect.visible = true var t := create_tween() t.tween_method(_set_factor, 0.0, 1.0, duration) await t.finished func reveal(duration := 0.5) -> void: var t := create_tween() t.tween_method(_set_factor, 1.0, 0.0, duration) await t.finished color_rect.visible = false func change_scene_with_standard_fade(scene_enum: SceneConfig.SceneName, duration: float = transition_duration, show_loading_label: bool = false) -> void: if not config or not config.scenes.has(scene_enum): return color_rect.material = null color_rect.color = Color(0,0,0) var target_scene: PackedScene = config.scenes[scene_enum] color_rect.mouse_filter = Control.MOUSE_FILTER_STOP if show_loading_label: loading_screen.visible = true await cover(duration) get_tree().change_scene_to_packed(target_scene) await reveal(duration) if show_loading_label: loading_screen.visible = false color_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE func change_scene(scene_enum: SceneConfig.SceneName, duration: float = transition_duration, show_loading_label: bool = false) -> void: if not config or not config.scenes.has(scene_enum): return color_rect.material = transaction_material color_rect.color = Color(0,0,0,0) var target_scene: PackedScene = config.scenes[scene_enum] color_rect.mouse_filter = Control.MOUSE_FILTER_STOP if show_loading_label: loading_screen.visible = true await cover(duration) get_tree().change_scene_to_packed(target_scene) await reveal(duration) if show_loading_label: loading_screen.visible = false color_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE func quit_game() -> void: get_tree().quit()