diff --git a/game/core/default_bus_layout.tres b/game/core/default_bus_layout.tres index 052f901..ae0301b 100644 --- a/game/core/default_bus_layout.tres +++ b/game/core/default_bus_layout.tres @@ -7,3 +7,9 @@ bus/1/mute = false bus/1/bypass_fx = false bus/1/volume_db = 0.0 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" diff --git a/game/core/settings.gd b/game/core/settings.gd new file mode 100644 index 0000000..9c15a41 --- /dev/null +++ b/game/core/settings.gd @@ -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) diff --git a/game/core/settings.gd.uid b/game/core/settings.gd.uid new file mode 100644 index 0000000..9422cd4 --- /dev/null +++ b/game/core/settings.gd.uid @@ -0,0 +1 @@ +uid://dyqiytgbiuuk5 diff --git a/game/ui/main_menu/main_menu.gd b/game/ui/main_menu/main_menu.gd index a715ed3..829c5b7 100644 --- a/game/ui/main_menu/main_menu.gd +++ b/game/ui/main_menu/main_menu.gd @@ -6,6 +6,7 @@ extends Node @onready var music_player: AudioStreamPlayer = %MusicPlayer @onready var version_label: Label = %VersionLabel @onready var game_infos: Control = %GameInfos +@onready var options_menu : OptionsMenu = %OptionsMenu @export var progression_backgrounds: Array[Texture2D] = [] @export var menu_music: AudioStream @@ -65,3 +66,6 @@ func fade_out_music() -> void: func _on_quit_pressed() -> void: get_tree().quit() + +func _on_options_pressed() -> void: + options_menu.open() diff --git a/game/ui/main_menu/main_menu.tscn b/game/ui/main_menu/main_menu.tscn index c65bb9d..ebb3ecd 100644 --- a/game/ui/main_menu/main_menu.tscn +++ b/game/ui/main_menu/main_menu.tscn @@ -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://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="PackedScene" uid="uid://bguem4nrp55gu" path="res://game/ui/options_menu/options_menu.tscn" id="4_1x88f"] [sub_resource type="LabelSettings" id="LabelSettings_3agn1"] font_size = 64 @@ -16,6 +17,8 @@ script = ExtResource("2_bqqt6") path = "ui_accept" metadata/_custom_type_script = "uid://7hglx6nfu063" +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_1x88f"] + [node name="MainMenu" type="Control" unique_id=1471802333] layout_mode = 3 anchors_preset = 15 @@ -115,6 +118,20 @@ icon = SubResource("Texture2D_mkp5f") flat = true 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] layout_mode = 2 theme_override_styles/panel = SubResource("StyleBoxEmpty_bqqt6") @@ -144,5 +161,11 @@ grow_vertical = 0 [node name="MusicPlayer" type="AudioStreamPlayer" parent="." unique_id=1279071971] 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/OptionsContainer/HBoxContainer/Options" to="." method="_on_options_pressed"] [connection signal="pressed" from="GameInfos/Buttons/VBoxContainer/QuitContainer/HBoxContainer/Quit" to="." method="_on_quit_pressed"] diff --git a/game/ui/options_menu/options_menu.gd b/game/ui/options_menu/options_menu.gd new file mode 100644 index 0000000..79fe156 --- /dev/null +++ b/game/ui/options_menu/options_menu.gd @@ -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() diff --git a/game/ui/options_menu/options_menu.gd.uid b/game/ui/options_menu/options_menu.gd.uid new file mode 100644 index 0000000..c004c17 --- /dev/null +++ b/game/ui/options_menu/options_menu.gd.uid @@ -0,0 +1 @@ +uid://mwvp6fitq2do diff --git a/game/ui/options_menu/options_menu.tscn b/game/ui/options_menu/options_menu.tscn new file mode 100644 index 0000000..2f77bbc --- /dev/null +++ b/game/ui/options_menu/options_menu.tscn @@ -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" diff --git a/game/ui/options_menu/setting_row.gd b/game/ui/options_menu/setting_row.gd new file mode 100644 index 0000000..93dbd42 --- /dev/null +++ b/game/ui/options_menu/setting_row.gd @@ -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 diff --git a/game/ui/options_menu/setting_row.gd.uid b/game/ui/options_menu/setting_row.gd.uid new file mode 100644 index 0000000..750e2f1 --- /dev/null +++ b/game/ui/options_menu/setting_row.gd.uid @@ -0,0 +1 @@ +uid://by4oyg1m0ktxb diff --git a/game/ui/options_menu/slider_row.gd b/game/ui/options_menu/slider_row.gd new file mode 100644 index 0000000..c87ae16 --- /dev/null +++ b/game/ui/options_menu/slider_row.gd @@ -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) diff --git a/game/ui/options_menu/slider_row.gd.uid b/game/ui/options_menu/slider_row.gd.uid new file mode 100644 index 0000000..a8a6716 --- /dev/null +++ b/game/ui/options_menu/slider_row.gd.uid @@ -0,0 +1 @@ +uid://dcisa8ai7tb5v diff --git a/game/ui/options_menu/toggle_row.gd b/game/ui/options_menu/toggle_row.gd new file mode 100644 index 0000000..e4e520b --- /dev/null +++ b/game/ui/options_menu/toggle_row.gd @@ -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) diff --git a/game/ui/options_menu/toggle_row.gd.uid b/game/ui/options_menu/toggle_row.gd.uid new file mode 100644 index 0000000..28482da --- /dev/null +++ b/game/ui/options_menu/toggle_row.gd.uid @@ -0,0 +1 @@ +uid://c4h7ympjopgqe diff --git a/game/ui/pause_menu/pause_menu.gd b/game/ui/pause_menu/pause_menu.gd index 4773de5..2862070 100644 --- a/game/ui/pause_menu/pause_menu.gd +++ b/game/ui/pause_menu/pause_menu.gd @@ -11,6 +11,7 @@ extends CanvasLayer @onready var load_button: Button = $PanelContainer/VBoxContainer/Load @onready var menu_panel: PanelContainer = $PanelContainer @onready var animation_player: AnimationPlayer = $AnimationPlayer +@onready var options_menu : OptionsMenu = %OptionsMenu var is_transitioning : bool = false 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: UiAudio.play(click_sound) get_tree().quit() + +func _on_options_pressed() -> void: + options_menu.open() diff --git a/game/ui/pause_menu/pause_menu.tscn b/game/ui/pause_menu/pause_menu.tscn index c40685f..1fc8d98 100644 --- a/game/ui/pause_menu/pause_menu.tscn +++ b/game/ui/pause_menu/pause_menu.tscn @@ -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="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"] shader = ExtResource("1_hdmo1") @@ -189,6 +190,10 @@ focus_neighbor_top = NodePath("../Save") focus_next = NodePath("../Restart") 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] layout_mode = 2 focus_neighbor_top = NodePath("../Load") @@ -203,11 +208,14 @@ text = "Quit" [node name="AnimationPlayer" type="AnimationPlayer" parent="." unique_id=3655790] 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/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/Save" to="." method="_on_save_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/Quit" to="." method="_on_quit_pressed"] diff --git a/project.godot b/project.godot index 041179d..ad73569 100644 --- a/project.godot +++ b/project.godot @@ -19,13 +19,14 @@ config/icon="res://icon.svg" [audio] -buses/default_bus_layout="res://game/core/default_bus_layout.tres" +buses/default_bus_layout="uid://cpmscnqvdpn8f" [autoload] ControllerIcons="*uid://b7ho1rjcpht1d" GameData="*uid://d4beiel88cwc7" UiAudio="*uid://7e7fe2xk3aue" +Settings="*uid://dyqiytgbiuuk5" LoadingScreen="*uid://ckyjxhrfhaqlc" Hints="*uid://bqapxkrub0fcs" Pokedex="*uid://dijnkrewbwgmx"