extends CanvasLayer ## Menù di configurazione in-game: slider/spinbox per calibrare velocità e ## moltiplicatori. "Salva e riavvia" persiste le impostazioni e ricarica la ## scena applicando i nuovi valori. var rows := {} # key -> {slider, spin} var curve_option: OptionButton func _ready() -> void: # Critico: il menù deve ricevere input anche quando il gioco è in pausa, # altrimenti slider/spinbox/pulsanti risultano congelati e inutilizzabili. process_mode = Node.PROCESS_MODE_ALWAYS visible = false _build() func _build() -> void: # sfondo scuro che blocca i click sottostanti var dim := ColorRect.new() dim.color = Color(0, 0, 0, 0.65) dim.set_anchors_preset(Control.PRESET_FULL_RECT) dim.mouse_filter = Control.MOUSE_FILTER_STOP add_child(dim) # pannello centrato var center := CenterContainer.new() center.set_anchors_preset(Control.PRESET_FULL_RECT) add_child(center) var panel := PanelContainer.new() center.add_child(panel) var margin := MarginContainer.new() margin.add_theme_constant_override("margin_left", 24) margin.add_theme_constant_override("margin_right", 24) margin.add_theme_constant_override("margin_top", 16) margin.add_theme_constant_override("margin_bottom", 16) panel.add_child(margin) var vb := VBoxContainer.new() vb.add_theme_constant_override("separation", 8) margin.add_child(vb) var title := Label.new() title.text = "CONFIGURAZIONE" title.add_theme_font_size_override("font_size", 30) title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER vb.add_child(title) var entries := [ ["start_time", "Tempo iniziale (s)", 1.0, 10.0, 0.1], ["min_time", "Tempo minimo (s)", 0.3, 3.0, 0.1], ["time_ramp", "Rampa tempo (s)", 30.0, 600.0, 10.0], ["score_ramp", "Rampa punteggio", 100.0, 10000.0, 100.0], ["points_per_combo", "Punti per combo", 1.0, 50.0, 1.0], ["combo_decay_threshold", "Soglia decay combo", 0.0, 30.0, 1.0], ["combo_decay_rate", "Rate decay combo", 0.0, 0.5, 0.01], ["difficulty_decay_rate", "Rate decay difficoltà", 0.0, 2.0, 0.05], ] for e in entries: rows[e[0]] = _build_row(vb, e[0], e[1], e[2], e[3], e[4]) # selettore curva punteggio var ccurve := HBoxContainer.new() ccurve.add_theme_constant_override("separation", 6) vb.add_child(ccurve) var clbl := Label.new() clbl.text = "Curva punteggio" clbl.custom_minimum_size.x = 230 ccurve.add_child(clbl) curve_option = OptionButton.new() curve_option.custom_minimum_size.x = 360 curve_option.add_item("Quadratica (attuale)") curve_option.add_item("A scaglioni (ogni 5 tap)") curve_option.add_item("Radice quadrata") curve_option.add_item("Additiva (base + combo)") curve_option.select(Settings.score_curve) curve_option.item_selected.connect(func(idx: int): Settings.score_curve = idx) ccurve.add_child(curve_option) # pulsanti var hb := HBoxContainer.new() hb.add_theme_constant_override("separation", 8) vb.add_child(hb) var save := Button.new() save.text = "Salva e riavvia" save.pressed.connect(_on_save) var reset := Button.new() reset.text = "Ripristina default" reset.pressed.connect(_on_reset) var cancel := Button.new() cancel.text = "Annulla" cancel.pressed.connect(_on_cancel) hb.add_child(save) hb.add_child(reset) hb.add_child(cancel) func _build_row(parent: Node, key: String, label_text: String, mn: float, mx: float, step: float) -> Dictionary: var hb := HBoxContainer.new() hb.add_theme_constant_override("separation", 6) parent.add_child(hb) var lbl := Label.new() lbl.text = label_text lbl.custom_minimum_size.x = 230 hb.add_child(lbl) var slider := HSlider.new() slider.min_value = mn slider.max_value = mx slider.step = step slider.custom_minimum_size.x = 260 slider.custom_minimum_size.y = 40 slider.add_theme_constant_override("grabber_radius", 14) # più facile da toccare slider.value = Settings.get(key) hb.add_child(slider) var spin := SpinBox.new() spin.min_value = mn spin.max_value = mx spin.step = step spin.value = Settings.get(key) spin.custom_minimum_size.x = 90 hb.add_child(spin) slider.value_changed.connect(func(v: float): spin.value = v Settings.set(key, v)) spin.value_changed.connect(func(v: float): slider.value = v Settings.set(key, v)) return {"slider": slider, "spin": spin} func show_menu() -> void: # aggiorna i valori correnti ogni volta che si apre for key in rows: var val: float = Settings.get(key) rows[key].slider.value = val rows[key].spin.value = val if curve_option: curve_option.select(Settings.score_curve) visible = true get_tree().paused = true func hide_menu() -> void: visible = false get_tree().paused = false func _on_save() -> void: Settings.save_settings() hide_menu() get_tree().call_deferred("reload_current_scene") func _on_reset() -> void: Settings.reset_defaults() for key in rows: var val: float = Settings.get(key) rows[key].slider.value = val rows[key].spin.value = val if curve_option: curve_option.select(Settings.score_curve) func _on_cancel() -> void: hide_menu()