extends CanvasLayer @export var config: SceneConfig @export_group("Transition Timings") @export var fade_in_duration: float = 0.5 @export var black_screen_duration: float = 1.0 @export var fade_out_duration: float = 0.5 @export var logo_fade_in_duration: float = 0.3 @export var logo_fade_out_duration: float = 0.3 @export_group("Cozy Animation") @export var sway_speed: float = 2.5 # Velocità dell'oscillazione (più alto = più veloce) @export var max_sway_angle: float = 6.0 # Gradi massimi di inclinazione a destra/sinistra @export var pulse_speed: float = 2.0 # Velocità del "respiro" @export var pulse_amount: float = 0.015 # Quanto si ingrandisce/rimpicciolisce il logo @export_group("Shader Parameters") @export var base_color: Color = Color.BLACK @export var shape_tiling: float = 16.0 @export var shape_rotation: float = 0.0 @export var shape_scroll: Vector2 = Vector2.ZERO @export var shape_feathering: float = 0.05 @export var shape_treshold: float = 1.0 @export var width: float = 0.5 @onready var color_rect = $ColorRect @onready var loading_screen = $LoadingScreen @onready var logo = $LoadingScreen/Logo const SHADER_PATH := "res://core/transition.gdshader" var transaction_material: ShaderMaterial var time_passed: float = 0.0 var initial_scale: Vector2 = Vector2.ONE var scale_captured: bool = false func _ready() -> void: _build_material() _update_resolution() get_viewport().size_changed.connect(_update_resolution) _set_factor(0.0) color_rect.z_index = 0 loading_screen.z_index = 1 color_rect.visible = false loading_screen.visible = false loading_screen.modulate.a = 0.0 func _process(delta: float) -> void: if loading_screen.visible and logo and logo.visible: # Cattura la scala originale (0.22) impostata nell'editor alla prima attivazione if not scale_captured: initial_scale = logo.scale scale_captured = true time_passed += delta # 1. EFFETTO DONDOLIO (Usa il seno per oscillare morbidamente) var target_rotation = sin(time_passed * sway_speed) * deg_to_rad(max_sway_angle) logo.rotation = target_rotation # 2. EFFETTO RESPIRO (Modifica leggermente lo scale partendo da quello base) var pulse = sin(time_passed * pulse_speed) * pulse_amount logo.scale = initial_scale + Vector2(pulse, pulse) else: # Reset del timer quando la schermata si chiude per ripartire da zero la prossima volta time_passed = 0.0 func _build_material() -> void: transaction_material = ShaderMaterial.new() transaction_material.shader = load(SHADER_PATH) 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) grad_tex.fill_to = Vector2(1.0, 0.0) grad_tex.width = 256 grad_tex.height = 256 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) shape_tex.fill_to = Vector2(0.5, 0.0) shape_tex.width = 64 shape_tex.height = 64 transaction_material.set_shader_parameter("base_color", base_color) 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", shape_tiling) transaction_material.set_shader_parameter("shape_rotation", shape_rotation) transaction_material.set_shader_parameter("shape_scroll", shape_scroll) transaction_material.set_shader_parameter("shape_feathering", shape_feathering) transaction_material.set_shader_parameter("shape_treshold", shape_treshold) transaction_material.set_shader_parameter("width", width) 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 _setup_logo_safety() -> void: if logo and logo.texture: logo.visible = true var texture_center = logo.texture.get_size() / 2 if logo.pivot_offset != texture_center: var old_pivot = logo.pivot_offset logo.pivot_offset = texture_center logo.position -= (texture_center - old_pivot) * (Vector2.ONE - logo.scale) func change_scene_with_standard_fade(scene_enum: SceneConfig.SceneName, show_loading_label: bool = true) -> 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 get_tree().change_scene_to_packed(target_scene) await cover(3.0) if show_loading_label: _setup_logo_safety() loading_screen.modulate.a = 0.0 loading_screen.visible = true var tween_in = create_tween() tween_in.tween_property(loading_screen, "modulate:a", 1.0, logo_fade_in_duration) await tween_in.finished if black_screen_duration > 0.0: await get_tree().create_timer(black_screen_duration).timeout if show_loading_label: var tween_out = create_tween() tween_out.tween_property(loading_screen, "modulate:a", 0.0, logo_fade_out_duration) await tween_out.finished loading_screen.visible = false await reveal(fade_out_duration) color_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE func change_scene(scene_enum: SceneConfig.SceneName, show_loading_label: bool = true) -> 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 await cover(fade_in_duration) get_tree().change_scene_to_packed(target_scene) if show_loading_label: _setup_logo_safety() loading_screen.modulate.a = 0.0 loading_screen.visible = true var tween_in = create_tween() tween_in.tween_property(loading_screen, "modulate:a", 1.0, logo_fade_in_duration) await tween_in.finished if black_screen_duration > 0.0: await get_tree().create_timer(black_screen_duration).timeout if show_loading_label: var tween_out = create_tween() tween_out.tween_property(loading_screen, "modulate:a", 0.0, logo_fade_out_duration) await tween_out.finished loading_screen.visible = false await reveal(fade_out_duration) color_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE func quit_game() -> void: get_tree().quit()