generated from krampus/template-godot4
Volume mixer settings with persistence to disk
This commit is contained in:
parent
f75af2196d
commit
12fbbb82bc
|
@ -1,6 +1,7 @@
|
|||
[gd_resource type="AudioBusLayout" format=3 uid="uid://cwxndi28bii8d"]
|
||||
|
||||
[resource]
|
||||
bus/0/volume_db = 0.0
|
||||
bus/1/name = &"SFX"
|
||||
bus/1/solo = false
|
||||
bus/1/mute = false
|
||||
|
|
|
@ -61,6 +61,7 @@ config/controls/camera/y_axis_acceleration=30.0
|
|||
config/controls/camera/invert_pitch=false
|
||||
config/accessibility/enable_screen_shake=true
|
||||
config/accessibility/enable_hit_lag=true
|
||||
audio/buses/override_bus_layout="user://audio_bus_layout.tres"
|
||||
|
||||
[global_group]
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ class_name GameSettingsType extends Node
|
|||
## Container for project settings, for quick runtime access.
|
||||
|
||||
var settings_file: String
|
||||
var audio_bus_file: String
|
||||
|
||||
var free_camera_speed: float
|
||||
var x_sensitivity: float
|
||||
|
@ -15,10 +16,13 @@ var enable_hit_lag: bool
|
|||
|
||||
func _init() -> void:
|
||||
ProjectSettings.settings_changed.connect(_read_settings)
|
||||
_read_settings()
|
||||
_load_audio_bus_override()
|
||||
|
||||
|
||||
func _read_settings() -> void:
|
||||
settings_file = ProjectSettings.get_setting("application/config/project_settings_override")
|
||||
audio_bus_file = ProjectSettings.get_setting("game/audio/buses/override_bus_layout")
|
||||
|
||||
free_camera_speed = ProjectSettings.get_setting("game/config/controls/camera/free_camera_speed")
|
||||
x_sensitivity = ProjectSettings.get_setting("game/config/controls/camera/x_axis_sensitivity")
|
||||
|
@ -31,3 +35,18 @@ func _read_settings() -> void:
|
|||
"game/config/accessibility/enable_screen_shake"
|
||||
)
|
||||
enable_hit_lag = ProjectSettings.get_setting("game/config/accessibility/enable_hit_lag")
|
||||
|
||||
|
||||
func _load_audio_bus_override() -> void:
|
||||
# Load override audio bus file
|
||||
if FileAccess.file_exists(audio_bus_file):
|
||||
print_debug("Loading audio bus override from ", audio_bus_file)
|
||||
var bus_layout: AudioBusLayout = load(audio_bus_file)
|
||||
AudioServer.set_bus_layout(bus_layout)
|
||||
|
||||
|
||||
func write() -> void:
|
||||
print_debug("Writing settings to ", settings_file)
|
||||
ProjectSettings.save_custom(settings_file)
|
||||
print_debug("Writing audio bus levels to ", audio_bus_file)
|
||||
ResourceSaver.save(AudioServer.generate_bus_layout(), audio_bus_file)
|
||||
|
|
|
@ -56,6 +56,12 @@ CancelButton/colors/font_outline_color = Color(0, 0, 0, 1)
|
|||
CancelButton/constants/outline_size = 6
|
||||
CancelButton/font_sizes/font_size = 24
|
||||
CancelButton/fonts/font = ExtResource("2_5ty6u")
|
||||
ChannelMixerIcon/base_type = &"Label"
|
||||
ChannelMixerIcon/colors/font_color = Color(1, 1, 0.870588, 1)
|
||||
ChannelMixerIcon/colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
ChannelMixerIcon/constants/outline_size = 5
|
||||
ChannelMixerIcon/font_sizes/font_size = 24
|
||||
ChannelMixerIcon/fonts/font = ExtResource("2_8kux8")
|
||||
CheckerContainerEven/base_type = &"PanelContainer"
|
||||
CheckerContainerEven/styles/panel = SubResource("StyleBoxFlat_rq1no")
|
||||
CheckerContainerOdd/base_type = &"PanelContainer"
|
||||
|
@ -75,10 +81,13 @@ ClubSelectLabelDisabled/colors/font_outline_color = Color(0.2, 0.2, 0.2, 1)
|
|||
ClubSelectLabelDisabled/colors/font_shadow_color = Color(0.2, 0.2, 0.2, 1)
|
||||
ClubSelectLabelDisabled/font_sizes/font_size = 84
|
||||
ClubSelectLabelDisabled/fonts/font = ExtResource("1_3rv2b")
|
||||
HeaderLarge/constants/outline_size = 8
|
||||
HeaderLarge/font_sizes/font_size = 28
|
||||
HeaderMedium/constants/outline_size = 6
|
||||
HeaderMedium/font_sizes/font_size = 24
|
||||
HeaderSmall/font_sizes/font_size = 20
|
||||
HeaderXLarge/base_type = &"Label"
|
||||
HeaderXLarge/constants/outline_size = 10
|
||||
HeaderXLarge/font_sizes/font_size = 36
|
||||
InputBindButton/base_type = &"UIButton"
|
||||
InputBindButton/colors/font_color = Color(1, 1, 0.870588, 1)
|
||||
|
|
|
@ -2,11 +2,14 @@ extends MarginContainer
|
|||
## Menu allowing the user to adjust game configuration.
|
||||
|
||||
const SETTINGS_GROUP := "Settings"
|
||||
const VOLUME_GROUP := "VolumeSliders"
|
||||
|
||||
@onready var bus_mixer_list: HBoxContainer = %BusMixerList
|
||||
@onready var control_binding_list: VBoxContainer = %ControlBindingList
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
populate_volume_mixers()
|
||||
populate_control_bindings()
|
||||
|
||||
|
||||
|
@ -16,12 +19,23 @@ func _get_settings_elements() -> Array[Setting]:
|
|||
return elements
|
||||
|
||||
|
||||
func _get_volume_sliders() -> Array[VolumeSlider]:
|
||||
var elements: Array[VolumeSlider] = []
|
||||
elements.assign(get_tree().get_nodes_in_group(VOLUME_GROUP))
|
||||
return elements
|
||||
|
||||
|
||||
func populate_control_bindings() -> void:
|
||||
for action: StringName in InputMap.get_actions():
|
||||
if not action.begins_with("ui_"):
|
||||
control_binding_list.add_child(ControlBinding.create(action))
|
||||
|
||||
|
||||
func populate_volume_mixers() -> void:
|
||||
for idx: int in range(AudioServer.bus_count):
|
||||
bus_mixer_list.add_child(VolumeSlider.create(idx))
|
||||
|
||||
|
||||
## Close menu without applying settings.
|
||||
func cancel() -> void:
|
||||
queue_free()
|
||||
|
@ -31,12 +45,13 @@ func cancel() -> void:
|
|||
func apply() -> void:
|
||||
for setting: Setting in _get_settings_elements():
|
||||
setting.apply()
|
||||
for mixer: VolumeSlider in _get_volume_sliders():
|
||||
mixer.apply()
|
||||
|
||||
|
||||
## Write all applied settings to disk.
|
||||
func save_settings() -> void:
|
||||
print_debug("Writing settings to ", Game.settings.settings_file)
|
||||
ProjectSettings.save_custom(Game.settings.settings_file)
|
||||
Game.settings.write()
|
||||
BindingLoader.write()
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ script = ExtResource("1_lbcn7")
|
|||
|
||||
[node name="TabContainer" type="TabContainer" parent="."]
|
||||
layout_mode = 2
|
||||
current_tab = 3
|
||||
current_tab = 2
|
||||
|
||||
[node name="Game" type="MarginContainer" parent="TabContainer"]
|
||||
visible = false
|
||||
|
@ -196,7 +196,6 @@ theme_type_variation = &"SettingsListMargin"
|
|||
layout_mode = 2
|
||||
|
||||
[node name="Audio" type="MarginContainer" parent="TabContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"SettingsPageContainer"
|
||||
metadata/_tab_index = 2
|
||||
|
@ -229,10 +228,13 @@ size_flags_horizontal = 3
|
|||
size_flags_vertical = 3
|
||||
theme_type_variation = &"SettingsListMargin"
|
||||
|
||||
[node name="SettingsList" type="VBoxContainer" parent="TabContainer/Audio/VBoxContainer/ScrollContainer/MarginContainer"]
|
||||
[node name="BusMixerList" type="HBoxContainer" parent="TabContainer/Audio/VBoxContainer/ScrollContainer/MarginContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 16
|
||||
|
||||
[node name="Controls" type="MarginContainer" parent="TabContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"SettingsPageContainer"
|
||||
metadata/_tab_index = 3
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
class_name VolumeSlider extends VBoxContainer
|
||||
## Input element for adjusting the volume of a single bus.
|
||||
|
||||
const SCENE := preload("res://src/ui/menus/settings_menu/volume_slider/volume_slider.tscn")
|
||||
const VOLUME_FACTOR := 50.0
|
||||
|
||||
@export var bus_idx: int
|
||||
|
||||
var value: float:
|
||||
get:
|
||||
return slider.value
|
||||
set(v):
|
||||
slider.set_value_no_signal(v)
|
||||
spin_box.set_value_no_signal(v)
|
||||
_set_bus_volume(v)
|
||||
|
||||
var _applied_value: float
|
||||
|
||||
@onready var bus_name: Label = %BusName
|
||||
@onready var slider: VSlider = %Slider
|
||||
@onready var spin_box: SpinBox = %SpinBox
|
||||
@onready var audio_demo: AudioStreamPlayer = %AudioDemo
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
bus_name.text = AudioServer.get_bus_name(bus_idx)
|
||||
audio_demo.bus = bus_name.text
|
||||
_applied_value = _db_to_volume(AudioServer.get_bus_volume_db(bus_idx))
|
||||
value = _applied_value
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
# Revert volume to the value from the last time `apply` was called
|
||||
_set_bus_volume(_applied_value)
|
||||
|
||||
|
||||
func _db_to_volume(db: float) -> float:
|
||||
return db_to_linear(db) * VOLUME_FACTOR
|
||||
|
||||
|
||||
func _volume_to_db(volume: float) -> float:
|
||||
return linear_to_db(volume / VOLUME_FACTOR)
|
||||
|
||||
|
||||
func _on_component_value_changed(new_value: float) -> void:
|
||||
value = new_value
|
||||
|
||||
|
||||
func _set_bus_volume(new_value: float) -> void:
|
||||
AudioServer.set_bus_volume_db(bus_idx, _volume_to_db(new_value))
|
||||
|
||||
|
||||
func apply() -> void:
|
||||
# Prevent value from being reverted during destructor.
|
||||
_applied_value = value
|
||||
|
||||
|
||||
func _on_slider_drag_ended(value_changed: bool) -> void:
|
||||
if value_changed:
|
||||
audio_demo.play()
|
||||
|
||||
|
||||
func _on_spin_box_value_changed(_new_value: float) -> void:
|
||||
audio_demo.play()
|
||||
|
||||
|
||||
static func create(_bus_idx: int) -> VolumeSlider:
|
||||
var instance: VolumeSlider = SCENE.instantiate()
|
||||
instance.bus_idx = _bus_idx
|
||||
return instance
|
|
@ -0,0 +1,51 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://d2ya6ly01724l"]
|
||||
|
||||
[ext_resource type="Script" path="res://src/ui/menus/settings_menu/volume_slider/volume_slider.gd" id="1_rfe0k"]
|
||||
[ext_resource type="AudioStream" uid="uid://cllhgumv1fkju" path="res://assets/sound/sfx/player/drive1.wav" id="2_822gu"]
|
||||
|
||||
[node name="VolumeSlider" type="VBoxContainer" groups=["VolumeSliders"]]
|
||||
custom_minimum_size = Vector2(300, 0)
|
||||
script = ExtResource("1_rfe0k")
|
||||
|
||||
[node name="NameContainer" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="Icon" type="Label" parent="NameContainer"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"ChannelMixerIcon"
|
||||
text = "🎧"
|
||||
|
||||
[node name="BusName" type="Label" parent="NameContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 8
|
||||
theme_type_variation = &"HeaderMedium"
|
||||
text = "Channel"
|
||||
|
||||
[node name="Slider" type="VSlider" parent="."]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 3
|
||||
step = 0.1
|
||||
|
||||
[node name="DigitalDisplay" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
|
||||
[node name="SpinBox" type="SpinBox" parent="DigitalDisplay"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
step = 0.1
|
||||
alignment = 2
|
||||
suffix = "%"
|
||||
|
||||
[node name="AudioDemo" type="AudioStreamPlayer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
stream = ExtResource("2_822gu")
|
||||
|
||||
[connection signal="drag_ended" from="Slider" to="." method="_on_slider_drag_ended"]
|
||||
[connection signal="value_changed" from="Slider" to="." method="_on_component_value_changed"]
|
||||
[connection signal="value_changed" from="DigitalDisplay/SpinBox" to="." method="_on_component_value_changed"]
|
||||
[connection signal="value_changed" from="DigitalDisplay/SpinBox" to="." method="_on_spin_box_value_changed"]
|
Loading…
Reference in New Issue