Add settings menu

This commit is contained in:
TheThomaas 2026-10-13 10:12:12 +02:00
parent d230674e02
commit 1eabe951fa
17 changed files with 244 additions and 2 deletions

View file

@ -7,3 +7,9 @@ bus/1/mute = false
bus/1/bypass_fx = false bus/1/bypass_fx = false
bus/1/volume_db = 0.0 bus/1/volume_db = 0.0
bus/1/send = &"Master" bus/1/send = &"Master"
bus/2/name = &"Music"
bus/2/solo = false
bus/2/mute = false
bus/2/bypass_fx = false
bus/2/volume_db = 0.0
bus/2/send = &"Master"

55
game/core/settings.gd Normal file
View file

@ -0,0 +1,55 @@
extends Node
signal changed(key: StringName)
const SAVE_PATH := "user://settings.cfg"
const SECTION := "settings"
const DEFAULTS := {
&"master_volume": 1.0,
&"music_volume": 1.0,
&"sfx_volume": 1.0,
&"fullscreen": false,
}
# clé de réglage -> bus audio
const VOLUME_BUSES := {
&"master_volume": &"Master",
&"music_volume": &"Music",
&"sfx_volume": &"SFX",
}
var _values : Dictionary = DEFAULTS.duplicate()
func _ready() -> void:
load_settings()
for key in _values: _apply(key)
func get_value(key : StringName) -> Variant:
return _values[key]
func set_value(key : StringName, value : Variant) -> void:
if _values[key] == value: return
_values[key] = value
_apply(key)
changed.emit(key)
func load_settings() -> void:
var cfg := ConfigFile.new()
cfg.load(SAVE_PATH) # si le fichier n'existe pas, get_value renvoie la valeur par défaut
for key in DEFAULTS:
_values[key] = cfg.get_value(SECTION, key, DEFAULTS[key])
func save() -> void:
var cfg := ConfigFile.new()
for key in _values: cfg.set_value(SECTION, key, _values[key])
cfg.save(SAVE_PATH)
func _apply(key : StringName) -> void:
var value : Variant = _values[key]
if VOLUME_BUSES.has(key):
var bus := AudioServer.get_bus_index(VOLUME_BUSES[key])
if bus != -1: AudioServer.set_bus_volume_db(bus, linear_to_db(value))
elif key == &"fullscreen":
DisplayServer.window_set_mode(
DisplayServer.WINDOW_MODE_FULLSCREEN if value else DisplayServer.WINDOW_MODE_WINDOWED)

View file

@ -0,0 +1 @@
uid://dyqiytgbiuuk5

View file

@ -6,6 +6,7 @@ extends Node
@onready var music_player: AudioStreamPlayer = %MusicPlayer @onready var music_player: AudioStreamPlayer = %MusicPlayer
@onready var version_label: Label = %VersionLabel @onready var version_label: Label = %VersionLabel
@onready var game_infos: Control = %GameInfos @onready var game_infos: Control = %GameInfos
@onready var options_menu : OptionsMenu = %OptionsMenu
@export var progression_backgrounds: Array[Texture2D] = [] @export var progression_backgrounds: Array[Texture2D] = []
@export var menu_music: AudioStream @export var menu_music: AudioStream
@ -65,3 +66,6 @@ func fade_out_music() -> void:
func _on_quit_pressed() -> void: func _on_quit_pressed() -> void:
get_tree().quit() get_tree().quit()
func _on_options_pressed() -> void:
options_menu.open()

View file

@ -3,6 +3,7 @@
[ext_resource type="Script" uid="uid://cj37ns1ahfvhr" path="res://game/ui/main_menu/main_menu.gd" id="1_ekxnf"] [ext_resource type="Script" uid="uid://cj37ns1ahfvhr" path="res://game/ui/main_menu/main_menu.gd" id="1_ekxnf"]
[ext_resource type="Script" uid="uid://7hglx6nfu063" path="res://addons/controller_icons/objects/ControllerIconTexture.gd" id="2_bqqt6"] [ext_resource type="Script" uid="uid://7hglx6nfu063" path="res://addons/controller_icons/objects/ControllerIconTexture.gd" id="2_bqqt6"]
[ext_resource type="Texture2D" uid="uid://d23fefvrd41re" path="res://assets/textures/background/0.png" id="2_wu84c"] [ext_resource type="Texture2D" uid="uid://d23fefvrd41re" path="res://assets/textures/background/0.png" id="2_wu84c"]
[ext_resource type="PackedScene" uid="uid://bguem4nrp55gu" path="res://game/ui/options_menu/options_menu.tscn" id="4_1x88f"]
[sub_resource type="LabelSettings" id="LabelSettings_3agn1"] [sub_resource type="LabelSettings" id="LabelSettings_3agn1"]
font_size = 64 font_size = 64
@ -16,6 +17,8 @@ script = ExtResource("2_bqqt6")
path = "ui_accept" path = "ui_accept"
metadata/_custom_type_script = "uid://7hglx6nfu063" metadata/_custom_type_script = "uid://7hglx6nfu063"
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_1x88f"]
[node name="MainMenu" type="Control" unique_id=1471802333] [node name="MainMenu" type="Control" unique_id=1471802333]
layout_mode = 3 layout_mode = 3
anchors_preset = 15 anchors_preset = 15
@ -115,6 +118,20 @@ icon = SubResource("Texture2D_mkp5f")
flat = true flat = true
icon_alignment = 2 icon_alignment = 2
[node name="OptionsContainer" type="PanelContainer" parent="GameInfos/Buttons/VBoxContainer" unique_id=710426258]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxEmpty_1x88f")
[node name="HBoxContainer" type="HBoxContainer" parent="GameInfos/Buttons/VBoxContainer/OptionsContainer" unique_id=1625967396]
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
[node name="Options" type="Button" parent="GameInfos/Buttons/VBoxContainer/OptionsContainer/HBoxContainer" unique_id=935792420]
layout_mode = 2
text = "Options"
flat = true
[node name="QuitContainer" type="PanelContainer" parent="GameInfos/Buttons/VBoxContainer" unique_id=24421836] [node name="QuitContainer" type="PanelContainer" parent="GameInfos/Buttons/VBoxContainer" unique_id=24421836]
layout_mode = 2 layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxEmpty_bqqt6") theme_override_styles/panel = SubResource("StyleBoxEmpty_bqqt6")
@ -144,5 +161,11 @@ grow_vertical = 0
[node name="MusicPlayer" type="AudioStreamPlayer" parent="." unique_id=1279071971] [node name="MusicPlayer" type="AudioStreamPlayer" parent="." unique_id=1279071971]
unique_name_in_owner = true unique_name_in_owner = true
[node name="OptionsMenu" parent="." unique_id=2002839596 instance=ExtResource("4_1x88f")]
unique_name_in_owner = true
visible = false
layout_mode = 1
[connection signal="pressed" from="GameInfos/Buttons/VBoxContainer/StartContainer/HBoxContainer/Start" to="." method="_on_start_pressed"] [connection signal="pressed" from="GameInfos/Buttons/VBoxContainer/StartContainer/HBoxContainer/Start" to="." method="_on_start_pressed"]
[connection signal="pressed" from="GameInfos/Buttons/VBoxContainer/OptionsContainer/HBoxContainer/Options" to="." method="_on_options_pressed"]
[connection signal="pressed" from="GameInfos/Buttons/VBoxContainer/QuitContainer/HBoxContainer/Quit" to="." method="_on_quit_pressed"] [connection signal="pressed" from="GameInfos/Buttons/VBoxContainer/QuitContainer/HBoxContainer/Quit" to="." method="_on_quit_pressed"]

View file

@ -0,0 +1,39 @@
class_name OptionsMenu
extends Control
signal closed
# Pour ajouter un réglage : une ligne ici + une entrée dans Settings.DEFAULTS
var ROWS : Array[Dictionary] = [
{"label": "Volume général", "key": &"master_volume", "type": SliderRow},
{"label": "Musique", "key": &"music_volume", "type": SliderRow},
{"label": "Effets sonores", "key": &"sfx_volume", "type": SliderRow},
{"label": "Plein écran", "key": &"fullscreen", "type": ToggleRow},
]
@onready var rows : VBoxContainer = %Rows
@onready var back_button : Button = %Back
var _previous_focus : Control
func _ready() -> void:
hide()
for row in ROWS:
rows.add_child(row.type.new().setup(row.label, row.key))
back_button.pressed.connect(close)
func open() -> void:
_previous_focus = get_viewport().gui_get_focus_owner()
show()
(rows.get_child(0) as SettingRow).control.grab_focus()
func close() -> void:
Settings.save()
hide()
if is_instance_valid(_previous_focus): _previous_focus.grab_focus()
closed.emit()
func _input(event : InputEvent) -> void:
if visible and event.is_action_pressed("ui_cancel"):
close()
get_viewport().set_input_as_handled()

View file

@ -0,0 +1 @@
uid://mwvp6fitq2do

View file

@ -0,0 +1,51 @@
[gd_scene format=3 uid="uid://bguem4nrp55gu"]
[ext_resource type="Script" uid="uid://mwvp6fitq2do" path="res://game/ui/options_menu/options_menu.gd" id="1_x8bvn"]
[node name="OptionsMenu" type="Control" unique_id=2002839596]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_x8bvn")
[node name="Dim" type="ColorRect" parent="." unique_id=1274443184]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0, 0, 0, 0.6)
[node name="CenterContainer" type="CenterContainer" parent="." unique_id=156922485]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="PanelContainer" type="PanelContainer" parent="CenterContainer" unique_id=284080291]
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="CenterContainer/PanelContainer" unique_id=1759618096]
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer/PanelContainer/MarginContainer" unique_id=669983340]
layout_mode = 2
[node name="Label" type="Label" parent="CenterContainer/PanelContainer/MarginContainer/VBoxContainer" unique_id=1265616038]
layout_mode = 2
text = "Options"
[node name="Rows" type="VBoxContainer" parent="CenterContainer/PanelContainer/MarginContainer/VBoxContainer" unique_id=221748107]
unique_name_in_owner = true
layout_mode = 2
[node name="Back" type="Button" parent="CenterContainer/PanelContainer/MarginContainer/VBoxContainer" unique_id=98602709]
unique_name_in_owner = true
layout_mode = 2
text = "Retour"

View file

@ -0,0 +1,24 @@
class_name SettingRow
extends HBoxContainer
var key : StringName
var control : Control
func setup(label_text : String, setting_key : StringName) -> SettingRow:
key = setting_key
var label := Label.new()
label.text = label_text
label.custom_minimum_size.x = 220
add_child(label)
control = _create_control()
control.size_flags_horizontal = Control.SIZE_EXPAND_FILL
add_child(control)
_display(Settings.get_value(key))
return self
# à surcharger
func _create_control() -> Control: return null
func _display(_value : Variant) -> void: pass

View file

@ -0,0 +1 @@
uid://by4oyg1m0ktxb

View file

@ -0,0 +1,12 @@
class_name SliderRow
extends SettingRow
func _create_control() -> Control:
var slider := HSlider.new()
slider.max_value = 1.0
slider.step = 0.05
slider.value_changed.connect(func(v : float) -> void: Settings.set_value(key, v))
return slider
func _display(value : Variant) -> void:
(control as HSlider).set_value_no_signal(value)

View file

@ -0,0 +1 @@
uid://dcisa8ai7tb5v

View file

@ -0,0 +1,10 @@
class_name ToggleRow
extends SettingRow
func _create_control() -> Control:
var toggle := CheckButton.new()
toggle.toggled.connect(func(on : bool) -> void: Settings.set_value(key, on))
return toggle
func _display(value : Variant) -> void:
(control as CheckButton).set_pressed_no_signal(value)

View file

@ -0,0 +1 @@
uid://c4h7ympjopgqe

View file

@ -11,6 +11,7 @@ extends CanvasLayer
@onready var load_button: Button = $PanelContainer/VBoxContainer/Load @onready var load_button: Button = $PanelContainer/VBoxContainer/Load
@onready var menu_panel: PanelContainer = $PanelContainer @onready var menu_panel: PanelContainer = $PanelContainer
@onready var animation_player: AnimationPlayer = $AnimationPlayer @onready var animation_player: AnimationPlayer = $AnimationPlayer
@onready var options_menu : OptionsMenu = %OptionsMenu
var is_transitioning : bool = false var is_transitioning : bool = false
var sub_screen : Control = null #page ouverte depuis le menu (equipe, PC...) var sub_screen : Control = null #page ouverte depuis le menu (equipe, PC...)
@ -123,3 +124,6 @@ func _on_restart_pressed() -> void:
func _on_quit_pressed() -> void: func _on_quit_pressed() -> void:
UiAudio.play(click_sound) UiAudio.play(click_sound)
get_tree().quit() get_tree().quit()
func _on_options_pressed() -> void:
options_menu.open()

View file

@ -2,6 +2,7 @@
[ext_resource type="Shader" uid="uid://dg3j314tijk1e" path="res://game/ui/pause_menu/pause_menu.gdshader" id="1_hdmo1"] [ext_resource type="Shader" uid="uid://dg3j314tijk1e" path="res://game/ui/pause_menu/pause_menu.gdshader" id="1_hdmo1"]
[ext_resource type="Script" uid="uid://bu3n6rboirk5r" path="res://game/ui/pause_menu/pause_menu.gd" id="1_kukqi"] [ext_resource type="Script" uid="uid://bu3n6rboirk5r" path="res://game/ui/pause_menu/pause_menu.gd" id="1_kukqi"]
[ext_resource type="PackedScene" uid="uid://bguem4nrp55gu" path="res://game/ui/options_menu/options_menu.tscn" id="3_hj2f6"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_3agn1"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_3agn1"]
shader = ExtResource("1_hdmo1") shader = ExtResource("1_hdmo1")
@ -189,6 +190,10 @@ focus_neighbor_top = NodePath("../Save")
focus_next = NodePath("../Restart") focus_next = NodePath("../Restart")
text = "Charger" text = "Charger"
[node name="Options" type="Button" parent="PanelContainer/VBoxContainer" unique_id=89858857]
layout_mode = 2
text = "Options"
[node name="Restart" type="Button" parent="PanelContainer/VBoxContainer" unique_id=389396198] [node name="Restart" type="Button" parent="PanelContainer/VBoxContainer" unique_id=389396198]
layout_mode = 2 layout_mode = 2
focus_neighbor_top = NodePath("../Load") focus_neighbor_top = NodePath("../Load")
@ -203,11 +208,14 @@ text = "Quit"
[node name="AnimationPlayer" type="AnimationPlayer" parent="." unique_id=3655790] [node name="AnimationPlayer" type="AnimationPlayer" parent="." unique_id=3655790]
libraries/ = SubResource("AnimationLibrary_2nc7s") libraries/ = SubResource("AnimationLibrary_2nc7s")
[node name="OptionsMenu" parent="." unique_id=2002839596 instance=ExtResource("3_hj2f6")]
unique_name_in_owner = true
[connection signal="pressed" from="PanelContainer/VBoxContainer/Resume" to="." method="_on_resume_pressed"] [connection signal="pressed" from="PanelContainer/VBoxContainer/Resume" to="." method="_on_resume_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/Team" to="." method="_on_team_pressed"] [connection signal="pressed" from="PanelContainer/VBoxContainer/Team" to="." method="_on_team_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/Team" to="." method="_on_team_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/Storage" to="." method="_on_storage_pressed"] [connection signal="pressed" from="PanelContainer/VBoxContainer/Storage" to="." method="_on_storage_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/Save" to="." method="_on_save_pressed"] [connection signal="pressed" from="PanelContainer/VBoxContainer/Save" to="." method="_on_save_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/Load" to="." method="_on_load_pressed"] [connection signal="pressed" from="PanelContainer/VBoxContainer/Load" to="." method="_on_load_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/Options" to="." method="_on_options_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/Restart" to="." method="_on_restart_pressed"] [connection signal="pressed" from="PanelContainer/VBoxContainer/Restart" to="." method="_on_restart_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/Quit" to="." method="_on_quit_pressed"] [connection signal="pressed" from="PanelContainer/VBoxContainer/Quit" to="." method="_on_quit_pressed"]

View file

@ -19,13 +19,14 @@ config/icon="res://icon.svg"
[audio] [audio]
buses/default_bus_layout="res://game/core/default_bus_layout.tres" buses/default_bus_layout="uid://cpmscnqvdpn8f"
[autoload] [autoload]
ControllerIcons="*uid://b7ho1rjcpht1d" ControllerIcons="*uid://b7ho1rjcpht1d"
GameData="*uid://d4beiel88cwc7" GameData="*uid://d4beiel88cwc7"
UiAudio="*uid://7e7fe2xk3aue" UiAudio="*uid://7e7fe2xk3aue"
Settings="*uid://dyqiytgbiuuk5"
LoadingScreen="*uid://ckyjxhrfhaqlc" LoadingScreen="*uid://ckyjxhrfhaqlc"
Hints="*uid://bqapxkrub0fcs" Hints="*uid://bqapxkrub0fcs"
Pokedex="*uid://dijnkrewbwgmx" Pokedex="*uid://dijnkrewbwgmx"