class_name P1HomeScreen extends Control ## P1: home con i due tendoni/percorsi. signal juggle_requested(focal: Control) signal gym_requested(focal: Control) signal exit_requested signal sign_drop_started signal sign_landed signal sign_bounced const HOME_BG := preload("res://menus/assets/common/1_sfondo.png") const CLOUDS := preload("res://menus/assets/common/1_nuvole.png") const BLUE_TENT := preload("res://menus/assets/p1/1_tendone_1.png") const RED_TENT := preload("res://menus/assets/p1/1_tendone_2.png") const BACK_BUTTON := preload("res://menus/assets/common/pulsante_indietro.png") const SETTINGS_BUTTON := preload("res://menus/assets/common/pulsante_rotellina.png") const CIRCUS_SIGN_PANEL := preload("res://menus/assets/p1/upendi_circus_sign_panel.png") const CIRCUS_SIGN_ROPES := preload("res://menus/assets/p1/upendi_circus_sign_ropes.png") func _ready() -> void: set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) _build() func _build() -> void: MenuUI.add_full_texture(self, HOME_BG) MenuUI.add_full_texture(self, CLOUDS, MenuUI.ambient_material(1.0, 0.16)) _add_sign() var blue := _add_tent_button(BLUE_TENT, Vector2(0.29, 0.46)) blue.pressed.connect(func(): juggle_requested.emit(blue)) var red := _add_tent_button(RED_TENT, Vector2(0.71, 0.46)) red.pressed.connect(func(): gym_requested.emit(red)) _add_bottom_bar() MenuUI.add_image(self, SETTINGS_BUTTON, Vector2(0.91, 0.13), Vector2(0.09, 0.14)) if not OS.has_feature("web"): var exit_button := MenuUI.add_image_button(self, BACK_BUTTON, Vector2(0.075, 0.13), Vector2(0.09, 0.14)) exit_button.pressed.connect(func(): exit_requested.emit()) func _add_tent_button(texture: Texture2D, center: Vector2) -> TextureButton: var button := MenuUI.add_image_button(self, texture, center, Vector2(0.36, 0.59)) var star_material := MenuUI.tent_star_material() button.material = star_material button.tooltip_text = "Apri questo percorso" # L'hover non altera più geometria e hitbox del tendone: mette in risalto # esclusivamente la stella, tramite il parametro dello shader. button.mouse_entered.connect(func(): star_material.set_shader_parameter("hover_strength", 1.0)) button.mouse_exited.connect(func(): star_material.set_shader_parameter("hover_strength", 0.0)) return button func _add_bottom_bar() -> void: var bar := ColorRect.new() bar.color = Color("#f1dfbd") bar.mouse_filter = Control.MOUSE_FILTER_IGNORE add_child(bar) MenuUI.set_normalized_rect(bar, Vector2(0.50, 0.885), Vector2(1.0, 0.23)) for item in [[0.774, 3.0], [0.787, 2.0]]: var rule := ColorRect.new() rule.color = Color("#28201c") rule.mouse_filter = Control.MOUSE_FILTER_IGNORE add_child(rule) MenuUI.set_normalized_rect(rule, Vector2(0.50, item[0]), Vector2(1.0, item[1] / 720.0)) MenuUI.add_label(self, "Tocca un tendone e scopri il gioco!", Vector2(0.38, 0.89), Vector2(0.66, 0.10), 24) func _add_sign() -> void: # Il pannello si muove, mentre le funi restano ancorate al bordo superiore. # Separare i due livelli conserva la texture disegnata originale senza lasciare # un vuoto quando il pannello supera verso il basso il punto di riposo. var rig := Control.new() rig.mouse_filter = Control.MOUSE_FILTER_IGNORE add_child(rig) MenuUI.set_normalized_rect(rig, Vector2(0.50, 0.17), Vector2(0.43, 0.34)) _add_sign_layer(rig, CIRCUS_SIGN_ROPES) var panel := _add_sign_layer(rig, CIRCUS_SIGN_PANEL) var final_y := panel.position.y panel.position.y = final_y - panel.size.y * 1.15 var tween := create_tween() # Il menu viene messo in pausa dalla shell: l'ingresso deve continuare comunque. tween.set_pause_mode(Tween.TWEEN_PAUSE_PROCESS) # Discesa rapida, atterraggio evidente e rimbalzo elastico. call_deferred("_emit_sign_drop_started") tween.tween_property(panel, "position:y", final_y + panel.size.y * 0.11, 1.10).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN) # L'impatto è sincronizzato con la massima estensione, prima del ritorno elastico. tween.tween_callback(func(): sign_landed.emit()) tween.tween_property(panel, "position:y", final_y, 0.50).set_trans(Tween.TRANS_BOUNCE).set_ease(Tween.EASE_OUT) tween.tween_callback(func(): sign_bounced.emit()) func _add_sign_layer(parent: Control, texture: Texture2D) -> TextureRect: var layer := TextureRect.new() layer.texture = texture layer.expand_mode = TextureRect.EXPAND_IGNORE_SIZE layer.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED layer.mouse_filter = Control.MOUSE_FILTER_IGNORE parent.add_child(layer) layer.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) return layer func _emit_sign_drop_started() -> void: if is_inside_tree(): sign_drop_started.emit()