diff --git a/assets/audio/silly-test.ogg b/assets/audio/silly-test.ogg new file mode 100644 index 0000000..a6b11d8 Binary files /dev/null and b/assets/audio/silly-test.ogg differ diff --git a/assets/audio/silly-test.ogg.import b/assets/audio/silly-test.ogg.import new file mode 100644 index 0000000..3a487af --- /dev/null +++ b/assets/audio/silly-test.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://bftct74auklgw" +path="res://.godot/imported/silly-test.ogg-4a08df8a26b9ee1e5d13235e013c7cfc.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/silly-test.ogg" +dest_files=["res://.godot/imported/silly-test.ogg-4a08df8a26b9ee1e5d13235e013c7cfc.oggvorbisstr"] + +[params] + +loop=true +loop_offset=0.0 +bpm=130.0 +beat_count=0 +bar_beats=4 diff --git a/project.godot b/project.godot index 039fd59..3e531ef 100644 --- a/project.godot +++ b/project.godot @@ -15,6 +15,10 @@ run/main_scene="uid://b4k81taauef4q" config/features=PackedStringArray("4.5", "Forward Plus") config/icon="res://icon.svg" +[autoload] + +MenuMusic="*res://scenes/UI/menu_music.tscn" + [dotnet] project/assembly_name="Promiscuity" diff --git a/scenes/UI/Settings.gd b/scenes/UI/Settings.gd index dcb6380..3a2c0d7 100644 --- a/scenes/UI/Settings.gd +++ b/scenes/UI/Settings.gd @@ -1,5 +1,63 @@ -extends Node +extends Node2D + +@onready var _tab_bar: TabBar = $MarginContainer/VBoxContainer/TabBar +@onready var _tab_container: TabContainer = $MarginContainer/VBoxContainer/TabContainer +@onready var _music_volume_slider: HSlider = $MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/MusicVolumeGroup/MusicVolumeSlider +@onready var _music_volume_value: Label = $MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/MusicVolumeGroup/MusicVolumeValue +@onready var _music_mute_checkbox: CheckBox = $MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/MusicVolumeGroup/MusicMuteCheckBox +@onready var _menu_music: AudioStreamPlayer = get_tree().get_root().get_node_or_null("MenuMusic") + +func _ready() -> void: + _tab_bar.tab_changed.connect(_on_tab_bar_tab_changed) + _tab_container.tab_changed.connect(_on_tab_container_tab_changed) + _tab_container.current_tab = _tab_bar.current_tab + _music_volume_slider.value_changed.connect(_on_music_volume_changed) + _music_mute_checkbox.toggled.connect(_on_music_mute_toggled) + _sync_audio_controls() func _input(event): - if event.is_action_pressed("ui_cancel"): # 'ui_cancel' is a built-in action defined in Project > Project Settings > Input Map + if event.is_action_pressed("ui_cancel"): get_tree().change_scene_to_file("uid://b4k81taauef4q") + +func _on_tab_bar_tab_changed(tab_index: int) -> void: + if _tab_container.current_tab != tab_index: + _tab_container.current_tab = tab_index + +func _on_tab_container_tab_changed(tab_index: int) -> void: + if _tab_bar.current_tab != tab_index: + _tab_bar.current_tab = tab_index + +func _sync_audio_controls() -> void: + var value: float = 0.7 + var muted: bool = false + if _menu_music: + if _menu_music.has_method("get_user_volume"): + value = _menu_music.get_user_volume() + if _menu_music.has_method("is_user_muted"): + muted = _menu_music.is_user_muted() + _music_volume_slider.set_block_signals(true) + _music_volume_slider.value = value + _music_volume_slider.set_block_signals(false) + _music_volume_slider.editable = not muted + _music_mute_checkbox.set_block_signals(true) + _music_mute_checkbox.button_pressed = muted + _music_mute_checkbox.set_block_signals(false) + _update_music_volume_label(value, muted) + +func _on_music_volume_changed(value: float) -> void: + if _menu_music and _menu_music.has_method("set_user_volume"): + _menu_music.set_user_volume(value) + _update_music_volume_label(value, _music_mute_checkbox.button_pressed) + +func _on_music_mute_toggled(pressed: bool) -> void: + if _menu_music and _menu_music.has_method("set_user_muted"): + _menu_music.set_user_muted(pressed) + _music_volume_slider.editable = not pressed + _update_music_volume_label(_music_volume_slider.value, pressed) + +func _update_music_volume_label(value: float, muted: bool) -> void: + if muted: + _music_volume_value.text = "Muted" + else: + var percent: int = int(round(value * 100.0)) + _music_volume_value.text = str(percent) + "%" diff --git a/scenes/UI/Settings.tscn b/scenes/UI/Settings.tscn index 71eabce..836a799 100644 --- a/scenes/UI/Settings.tscn +++ b/scenes/UI/Settings.tscn @@ -43,3 +43,82 @@ tab_3/title = "Dev" [node name="TabContainer" type="TabContainer" parent="MarginContainer/VBoxContainer"] layout_mode = 2 +tabs_visible = false + +[node name="Gameplay" type="Control" parent="MarginContainer/VBoxContainer/TabContainer"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Video" type="Control" parent="MarginContainer/VBoxContainer/TabContainer"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Audio" type="Control" parent="MarginContainer/VBoxContainer/TabContainer"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="AudioVBox" type="VBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Audio"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/separation = 10 +offset_left = 120.0 +offset_top = 120.0 +offset_right = -120.0 +offset_bottom = -120.0 + +[node name="MusicVolumeLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox"] +layout_mode = 2 +text = "Music Volume" +horizontal_alignment = 1 +size_flags_horizontal = 4 + +[node name="MusicVolumeGroup" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox"] +layout_mode = 2 +size_flags_horizontal = 4 +theme_override_constants/separation = 12 +alignment = 1 +custom_minimum_size = Vector2(0, 40) + +[node name="MusicVolumeSlider" type="HSlider" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/MusicVolumeGroup"] +layout_mode = 2 +min_value = 0.0 +max_value = 1.0 +step = 0.01 +size_flags_horizontal = 3 +custom_minimum_size = Vector2(320, 0) + +[node name="MusicVolumeValue" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/MusicVolumeGroup"] +layout_mode = 2 +text = "70%" +size_flags_horizontal = 1 +horizontal_alignment = 1 +custom_minimum_size = Vector2(60, 0) + +[node name="MusicMuteCheckBox" type="CheckBox" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/MusicVolumeGroup"] +layout_mode = 2 +text = "Mute" +size_flags_horizontal = 1 + +[node name="Dev" type="Control" parent="MarginContainer/VBoxContainer/TabContainer"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/scenes/UI/menu_music.gd b/scenes/UI/menu_music.gd new file mode 100644 index 0000000..098b414 --- /dev/null +++ b/scenes/UI/menu_music.gd @@ -0,0 +1,100 @@ +extends AudioStreamPlayer + +const MENU_SCENES: Dictionary = { + "res://scenes/UI/start_screen.tscn": true, + "res://scenes/UI/Settings.tscn": true, +} + +const CONFIG_PATH := "user://settings.cfg" +const CONFIG_SECTION := "audio" +const CONFIG_KEY_MUSIC_VOLUME := "menu_music_volume" +const CONFIG_KEY_MUSIC_MUTED := "menu_music_muted" +const DEFAULT_VOLUME := 0.7 + +var _last_scene: Node = null +var _user_volume_linear: float = DEFAULT_VOLUME +var _is_muted: bool = false + +func _ready() -> void: + set_process(true) + _load_settings() + _apply_volume() + _update_playback(get_tree().current_scene) + +func _process(_delta: float) -> void: + var current := get_tree().current_scene + if current != _last_scene: + _update_playback(current) + +func _update_playback(scene: Node) -> void: + if scene == null: + _last_scene = null + return + + _last_scene = scene + var should_play := false + var scene_path := scene.get_scene_file_path() + should_play = MENU_SCENES.has(scene_path) + if should_play: + if not playing: + play() + elif playing: + stop() + +func set_user_volume(value: float) -> void: + var clamped_value: float = clamp(value, 0.0, 1.0) + if is_equal_approx(_user_volume_linear, clamped_value): + return + _user_volume_linear = clamped_value + _apply_volume() + _save_settings() + +func get_user_volume() -> float: + return _user_volume_linear + +func set_user_muted(muted: bool) -> void: + var new_muted: bool = muted + if _is_muted == new_muted: + return + _is_muted = new_muted + _apply_volume() + _save_settings() + +func is_user_muted() -> bool: + return _is_muted + +func _apply_volume() -> void: + if _is_muted or _user_volume_linear <= 0.0: + volume_db = -80.0 + else: + volume_db = linear_to_db(_user_volume_linear) + +func _load_settings() -> void: + var config: ConfigFile = ConfigFile.new() + var err: int = config.load(CONFIG_PATH) + if err == OK: + var stored_volume: float = float(config.get_value(CONFIG_SECTION, CONFIG_KEY_MUSIC_VOLUME, DEFAULT_VOLUME)) + _user_volume_linear = clamp(stored_volume, 0.0, 1.0) + var stored_muted: bool = bool(config.get_value(CONFIG_SECTION, CONFIG_KEY_MUSIC_MUTED, false)) + _is_muted = stored_muted + elif err == ERR_DOES_NOT_EXIST: + _user_volume_linear = DEFAULT_VOLUME + _is_muted = false + else: + push_warning("Failed to load settings.cfg: %s" % err) + _user_volume_linear = DEFAULT_VOLUME + _is_muted = false + +func _save_settings() -> void: + var config: ConfigFile = ConfigFile.new() + var err: int = config.load(CONFIG_PATH) + if err != OK and err != ERR_DOES_NOT_EXIST: + push_warning("Failed to load settings.cfg before saving: %s" % err) + config = ConfigFile.new() + elif err != OK: + config = ConfigFile.new() + config.set_value(CONFIG_SECTION, CONFIG_KEY_MUSIC_VOLUME, _user_volume_linear) + config.set_value(CONFIG_SECTION, CONFIG_KEY_MUSIC_MUTED, _is_muted) + var save_err: int = config.save(CONFIG_PATH) + if save_err != OK: + push_warning("Failed to save settings.cfg: %s" % save_err) diff --git a/scenes/UI/menu_music.gd.uid b/scenes/UI/menu_music.gd.uid new file mode 100644 index 0000000..579cdad --- /dev/null +++ b/scenes/UI/menu_music.gd.uid @@ -0,0 +1 @@ +uid://l0cqi7dvoou3 diff --git a/scenes/UI/menu_music.tscn b/scenes/UI/menu_music.tscn new file mode 100644 index 0000000..1b4ed67 --- /dev/null +++ b/scenes/UI/menu_music.tscn @@ -0,0 +1,11 @@ +[gd_scene load_steps=3 format=3 uid="uid://dfmq1n507y7d3"] + +[ext_resource type="AudioStream" uid="uid://bftct74auklgw" path="res://assets/audio/silly-test.ogg" id="1_ek0t3"] + +[ext_resource type="Script" path="res://scenes/UI/menu_music.gd" id="2_21d4q"] + +[node name="MenuMusic" type="AudioStreamPlayer"] +stream = ExtResource("1_ek0t3") +autoplay = true +volume_db = -3.0 +script = ExtResource("2_21d4q") diff --git a/scenes/UI/start_screen.tscn b/scenes/UI/start_screen.tscn index fac67b3..943271b 100644 --- a/scenes/UI/start_screen.tscn +++ b/scenes/UI/start_screen.tscn @@ -4,7 +4,6 @@ [ext_resource type="Theme" uid="uid://wpxmub0n2dr3" path="res://themes/button_theme.tres" id="1_tx5wa"] [ext_resource type="Texture2D" uid="uid://dhuosr0p605gj" path="res://assets/images/pp_start_bg.png" id="2_r2jwc"] [ext_resource type="Theme" uid="uid://tn8qndst18d6" path="res://themes/title_font_theme.tres" id="4_hm208"] - [node name="StartScreen" type="Control"] layout_mode = 3 anchors_preset = 15