feat: trigger tent animations and piedone transition on click selection

This commit is contained in:
enne2
2026-09-10 23:02:00 +02:00
parent 95ccfc4c92
commit 84a15c7d4c
+185 -58
View File
@@ -17,6 +17,28 @@ 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")
const PLAY_BUTTON := preload("res://menus/assets/common/pulsante_gioca.png")
var piedone: Control
var piedone_title: Label
var piedone_desc: Label
var piedone_play: TextureButton
var selected_tent: String = "" # "juggle" o "gym"
var piedone_tween: Tween
var blue_tent_control: Control
var red_tent_control: Control
# Riferimenti alle animazioni e shader per ciascun tendone
var blue_mat: ShaderMaterial
var red_mat: ShaderMaterial
var blue_curtain_dir: Array = [0]
var blue_curtain_timer: Timer
var blue_lights: TextureRect
var red_curtain_dir: Array = [0]
var red_curtain_timer: Timer
var red_lights: TextureRect
const CURTAIN_FRAMES := [
preload("res://menus/assets/p1/curtain_anim/curtain_00.png"),
@@ -48,11 +70,14 @@ func _build() -> void:
MenuUI.add_full_texture(self, CLOUDS, MenuUI.ambient_material(1.0, 0.16))
_add_sign()
# Solo il tendone blu di riferimento attiva lo shader delle lucine in hover.
var blue := _add_tent_button(BLUE_TENT, Vector2(0.29, 0.46), true)
blue.pressed.connect(func(): juggle_requested.emit(blue))
var red := _add_tent_button(RED_TENT, Vector2(0.71, 0.46), false)
red.pressed.connect(func(): gym_requested.emit(red))
# Costruzione dei due tendoni selezionabili al click (entrambi con luci e sipario)
var blue := _add_tent_button(BLUE_TENT, Vector2(0.29, 0.46), "juggle")
blue_tent_control = blue
blue.pressed.connect(func(): _select_tent("juggle"))
var red := _add_tent_button(RED_TENT, Vector2(0.71, 0.46), "gym")
red_tent_control = red
red.pressed.connect(func(): _select_tent("gym"))
_add_bottom_bar()
MenuUI.add_image(self, SETTINGS_BUTTON, Vector2(0.91, 0.13), Vector2(0.09, 0.14))
@@ -61,36 +86,27 @@ func _build() -> void:
exit_button.pressed.connect(func(): exit_requested.emit())
func _add_tent_button(texture: Texture2D, center: Vector2, has_lights := false) -> TextureButton:
func _add_tent_button(texture: Texture2D, center: Vector2, tent_id: String) -> TextureButton:
var button := MenuUI.add_image_button(self, texture, center, Vector2(0.36, 0.59))
var mat := MenuUI.tent_material(0.0) if has_lights else MenuUI.tent_star_material()
var mat := MenuUI.tent_material(0.0)
button.material = mat
button.tooltip_text = "Apri questo percorso"
button.tooltip_text = "Seleziona questo percorso"
# Glow stella su entrambi i tendoni al passaggio del mouse
button.mouse_entered.connect(func():
mat.set_shader_parameter("hover_strength", 1.0)
if has_lights:
mat.set_shader_parameter("garland_strength", 1.0)
)
button.mouse_exited.connect(func():
mat.set_shader_parameter("hover_strength", 0.0)
if has_lights:
mat.set_shader_parameter("garland_strength", 0.0)
)
# Animazione apertura sipario e lucine in hover
if has_lights:
_setup_hover_curtain_and_garland(button, center)
if tent_id == "juggle":
blue_mat = mat
_setup_tent_interactive(button, center, "blue")
elif tent_id == "gym":
red_mat = mat
_setup_tent_interactive(button, center, "red")
return button
func _setup_hover_curtain_and_garland(parent_button: TextureButton, center: Vector2) -> void:
# Sipario: parte chiuso (frame 0). All'hover-in si apre (0 -> 6).
# All'hover-out si richiude al contrario (6 -> 0).
func _setup_tent_interactive(parent_button: TextureButton, center: Vector2, color_id: String) -> void:
# Sipario: parte chiuso (frame 0). Alla selezione si apre (0 -> 6).
# Alla deselezione si richiude al contrario (6 -> 0).
var curtain := TextureRect.new()
curtain.name = "Curtain"
curtain.name = color_id.capitalize() + "Curtain"
curtain.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
curtain.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
curtain.mouse_filter = Control.MOUSE_FILTER_IGNORE
@@ -98,11 +114,12 @@ func _setup_hover_curtain_and_garland(parent_button: TextureButton, center: Vect
add_child(curtain)
MenuUI.set_normalized_rect(curtain, center, Vector2(0.36, 0.59))
var curtain_idx := [0]
var curtain_dir := [0] # 0 = fermo, 1 = apre, -1 = chiude
var curtain_timer := Timer.new()
curtain_timer.name = color_id.capitalize() + "CurtainTimer"
curtain_timer.wait_time = 1.0 / 12.5
curtain_timer.process_mode = Node.PROCESS_MODE_ALWAYS
var curtain_idx := [0]
curtain_timer.timeout.connect(func():
if curtain_dir[0] == 1:
if curtain_idx[0] < CURTAIN_FRAMES.size() - 1:
@@ -110,7 +127,7 @@ func _setup_hover_curtain_and_garland(parent_button: TextureButton, center: Vect
curtain.texture = CURTAIN_FRAMES[curtain_idx[0]]
curtain.visible = true
else:
# Completamente aperto: frame 06 è vuoto/trasparente
# Completamente aperto
curtain.texture = CURTAIN_FRAMES[curtain_idx[0]]
curtain_dir[0] = 0
curtain_timer.stop()
@@ -120,7 +137,7 @@ func _setup_hover_curtain_and_garland(parent_button: TextureButton, center: Vect
curtain.texture = CURTAIN_FRAMES[curtain_idx[0]]
curtain.visible = true
else:
# Completamente chiuso: resta fermo su frame 00
# Completamente chiuso
curtain.texture = CURTAIN_FRAMES[0]
curtain_dir[0] = 0
curtain_timer.stop()
@@ -129,7 +146,7 @@ func _setup_hover_curtain_and_garland(parent_button: TextureButton, center: Vect
# Lucine a inseguimento
var lights := TextureRect.new()
lights.name = "HoverGarland"
lights.name = color_id.capitalize() + "Garland"
lights.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
lights.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
lights.mouse_filter = Control.MOUSE_FILTER_IGNORE
@@ -140,6 +157,7 @@ func _setup_hover_curtain_and_garland(parent_button: TextureButton, center: Vect
var lights_idx := [0]
var lights_timer := Timer.new()
lights_timer.name = color_id.capitalize() + "GarlandTimer"
lights_timer.wait_time = 1.0 / 12.5
lights_timer.process_mode = Node.PROCESS_MODE_ALWAYS
lights_timer.timeout.connect(func():
@@ -150,28 +168,114 @@ func _setup_hover_curtain_and_garland(parent_button: TextureButton, center: Vect
add_child(lights_timer)
lights_timer.start()
parent_button.mouse_entered.connect(func():
# Avvia apertura sipario (hover in)
curtain_dir[0] = 1
curtain_timer.start()
# Avvia lucine
lights_idx[0] = 0
lights.texture = GARLAND_FRAMES[0]
lights.visible = true
)
parent_button.mouse_exited.connect(func():
# Avvia chiusura sipario al contrario (hover out)
curtain_dir[0] = -1
curtain_timer.start()
# Spegne lucine
lights.visible = false
)
if color_id == "blue":
blue_curtain_dir = curtain_dir
blue_curtain_timer = curtain_timer
blue_lights = lights
elif color_id == "red":
red_curtain_dir = curtain_dir
red_curtain_timer = curtain_timer
red_lights = lights
func _select_tent(which: String) -> void:
if selected_tent == which:
return
selected_tent = which
# Aggiorna animazioni sui tendoni
if which == "juggle":
# Attiva tendone blu
if blue_mat:
blue_mat.set_shader_parameter("hover_strength", 1.0)
blue_mat.set_shader_parameter("garland_strength", 1.0)
if blue_curtain_dir and blue_curtain_timer:
blue_curtain_dir[0] = 1
blue_curtain_timer.start()
if blue_lights:
blue_lights.visible = true
# Spegne e richiude tendone rosso
if red_mat:
red_mat.set_shader_parameter("hover_strength", 0.0)
red_mat.set_shader_parameter("garland_strength", 0.0)
if red_curtain_dir and red_curtain_timer:
red_curtain_dir[0] = -1
red_curtain_timer.start()
if red_lights:
red_lights.visible = false
elif which == "gym":
# Attiva tendone rosso
if red_mat:
red_mat.set_shader_parameter("hover_strength", 1.0)
red_mat.set_shader_parameter("garland_strength", 1.0)
if red_curtain_dir and red_curtain_timer:
red_curtain_dir[0] = 1
red_curtain_timer.start()
if red_lights:
red_lights.visible = true
# Spegne e richiude tendone blu
if blue_mat:
blue_mat.set_shader_parameter("hover_strength", 0.0)
blue_mat.set_shader_parameter("garland_strength", 0.0)
if blue_curtain_dir and blue_curtain_timer:
blue_curtain_dir[0] = -1
blue_curtain_timer.start()
if blue_lights:
blue_lights.visible = false
# Transizione del piedone: scende e risale con le nuove info
_transition_bottom_bar(which)
func _transition_bottom_bar(which: String) -> void:
if not is_instance_valid(piedone):
return
var v_height := get_viewport_rect().size.y
var hidden_y := v_height * 0.29
var target_y := 0.0
if is_instance_valid(piedone_tween) and piedone_tween.is_running():
piedone_tween.kill()
piedone_tween = create_tween()
piedone_tween.set_pause_mode(Tween.TWEEN_PAUSE_PROCESS)
# Se è già visibile/alzato, scende prima di risalire
if piedone.position.y < hidden_y * 0.5:
piedone_tween.tween_property(piedone, "position:y", hidden_y, 0.25).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN)
piedone_tween.tween_callback(func(): _update_piedone_content(which))
piedone_tween.tween_property(piedone, "position:y", v_height * 0.025, 0.45).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
piedone_tween.tween_property(piedone, "position:y", target_y, 0.25).set_trans(Tween.TRANS_BOUNCE).set_ease(Tween.EASE_OUT)
else:
# Parte da nascosto: aggiorna subito e sale
_update_piedone_content(which)
piedone_tween.tween_property(piedone, "position:y", v_height * 0.025, 0.60).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
piedone_tween.tween_property(piedone, "position:y", target_y, 0.35).set_trans(Tween.TRANS_BOUNCE).set_ease(Tween.EASE_OUT)
func _update_piedone_content(which: String) -> void:
if which == "juggle":
piedone_title.text = "JUGGLEBOARD"
piedone_desc.text = "Allena ritmo e coordinazione con le biglie e i lanci a bersaglio."
elif which == "gym":
piedone_title.text = "PALESTRA DI GIOCOLERIA"
piedone_desc.text = "Scopri gli attrezzi del circo: clave, palline, piatti e rola bola."
func _on_play_pressed() -> void:
if selected_tent == "juggle":
juggle_requested.emit(blue_tent_control)
elif selected_tent == "gym":
gym_requested.emit(red_tent_control)
func _add_bottom_bar() -> void:
# Il piedone entra dal basso come un unico blocco; la scritta resta
# invisibile fino a quando il rimbalzo della barra non è terminato.
var piedone := Control.new()
# Il piedone parte abbassato/nascosto all'avvio.
piedone = Control.new()
piedone.name = "Piedone"
piedone.mouse_filter = Control.MOUSE_FILTER_IGNORE
piedone.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
@@ -190,17 +294,40 @@ func _add_bottom_bar() -> void:
piedone.add_child(rule)
MenuUI.set_normalized_rect(rule, Vector2(0.50, item[0]), Vector2(1.0, item[1] / 720.0))
var label := MenuUI.add_label(piedone, "Tocca un tendone e scopri il gioco!", Vector2(0.38, 0.89), Vector2(0.66, 0.10), 24)
label.modulate.a = 0.0
# Titolo del gioco selezionato
piedone_title = MenuUI.add_label(piedone, "", Vector2(0.28, 0.84), Vector2(0.46, 0.07), 24)
piedone_title.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
# Descrizione del gioco
piedone_desc = Label.new()
piedone_desc.text = ""
piedone_desc.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
piedone_desc.vertical_alignment = VERTICAL_ALIGNMENT_TOP
piedone_desc.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
piedone_desc.add_theme_font_override("font", MenuUI.DISPLAY_FONT)
piedone_desc.add_theme_font_size_override("font_size", 16)
piedone_desc.add_theme_color_override("font_color", Color("#423832"))
piedone_desc.mouse_filter = Control.MOUSE_FILTER_IGNORE
piedone.add_child(piedone_desc)
MenuUI.set_normalized_rect(piedone_desc, Vector2(0.28, 0.92), Vector2(0.46, 0.08))
# Pulsante GIOCA sul lato destro del piedone
piedone_play = TextureButton.new()
piedone_play.ignore_texture_size = true
piedone_play.stretch_mode = TextureButton.STRETCH_KEEP_ASPECT_CENTERED
piedone_play.texture_normal = PLAY_BUTTON
piedone_play.texture_hover = PLAY_BUTTON
piedone_play.texture_pressed = PLAY_BUTTON
piedone_play.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
piedone_play.mouse_entered.connect(func(): piedone_play.modulate = Color(1.08, 1.08, 1.08, 1.0))
piedone_play.mouse_exited.connect(func(): piedone_play.modulate = Color.WHITE)
piedone_play.pressed.connect(_on_play_pressed)
piedone.add_child(piedone_play)
MenuUI.set_normalized_rect(piedone_play, Vector2(0.79, 0.88), Vector2(0.24, 0.13))
# Parte nascosto sotto lo schermo
var viewport_height := get_viewport_rect().size.y
piedone.position.y = viewport_height * 0.29
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)
tween.tween_property(piedone, "position:y", viewport_height * 0.025, 0.85).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
tween.tween_property(piedone, "position:y", 0.0, 0.42).set_trans(Tween.TRANS_BOUNCE).set_ease(Tween.EASE_OUT)
tween.tween_property(label, "modulate:a", 1.0, 0.32).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
func _add_sign() -> void: