Feat/5 adding settings fundamentals and ui improvements #9

Merged
Dotts merged 9 commits from feat/5-adding-settings-fundamentals-and-ui-improvements into main 2026-06-05 23:03:52 -07:00
16 changed files with 187 additions and 5 deletions
Showing only changes of commit d784045214 - Show all commits
+56 -1
View File
@@ -32,6 +32,12 @@ var resolution_index: int = 2 # Default to 1920x1080
var fps_cap: int = 0
var show_fps: bool = false
# Audio Settings
var vol_master: float = 100.0
var vol_sfx: float = 100.0
var vol_music: float = 100.0
var vol_wind: float = 100.0
var resolutions = [
Vector2i(640, 480), # 480p
Vector2i(1280, 720), # 720p
@@ -55,6 +61,31 @@ func _ready() -> void:
# Apply Video Settings
apply_video_settings()
# Setup & Apply Audio Settings
_setup_audio_buses()
apply_audio_settings()
func _setup_audio_buses() -> void:
if AudioServer.bus_count < 4:
# Assuming bus 0 is Master
if AudioServer.get_bus_name(0) != "Master":
AudioServer.set_bus_name(0, "Master")
# SFX
if AudioServer.bus_count <= 1:
AudioServer.add_bus(1)
AudioServer.set_bus_name(1, "SFX")
# Music
if AudioServer.bus_count <= 2:
AudioServer.add_bus(2)
AudioServer.set_bus_name(2, "Music")
# Wind
if AudioServer.bus_count <= 3:
AudioServer.add_bus(3)
AudioServer.set_bus_name(3, "Wind")
func _apply_all_bindings() -> void:
for action in current_bindings:
if not InputMap.has_action(action):
@@ -101,7 +132,11 @@ func _save_settings() -> void:
"display_mode": display_mode,
"resolution_index": resolution_index,
"fps_cap": fps_cap,
"show_fps": show_fps
"show_fps": show_fps,
"vol_master": vol_master,
"vol_sfx": vol_sfx,
"vol_music": vol_music,
"vol_wind": vol_wind
}
var json_string = JSON.stringify(save_data)
var file = FileAccess.open(SAVE_PATH, FileAccess.WRITE)
@@ -134,6 +169,26 @@ func _load_settings() -> void:
if data.has("resolution_index"): resolution_index = data["resolution_index"]
if data.has("fps_cap"): fps_cap = data["fps_cap"]
if data.has("show_fps"): show_fps = data["show_fps"]
if data.has("vol_master"): vol_master = data["vol_master"]
if data.has("vol_sfx"): vol_sfx = data["vol_sfx"]
if data.has("vol_music"): vol_music = data["vol_music"]
if data.has("vol_wind"): vol_wind = data["vol_wind"]
func apply_audio_settings() -> void:
_set_bus_volume("Master", vol_master)
_set_bus_volume("SFX", vol_sfx)
_set_bus_volume("Music", vol_music)
_set_bus_volume("Wind", vol_wind)
func _set_bus_volume(bus_name: String, vol_100: float) -> void:
var bus_idx = AudioServer.get_bus_index(bus_name)
if bus_idx >= 0:
var linear = clampf(vol_100 / 100.0, 0.0001, 1.0)
if vol_100 <= 0.1:
AudioServer.set_bus_mute(bus_idx, true)
else:
AudioServer.set_bus_mute(bus_idx, false)
AudioServer.set_bus_volume_db(bus_idx, linear_to_db(linear))
func apply_video_settings() -> void:
if display_mode == DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
+12
View File
@@ -74,55 +74,67 @@ func _ready() -> void:
func _setup_audio() -> void:
footstep_player = AudioStreamPlayer.new()
footstep_player.bus = "SFX"
footstep_player.stream = load("res://assets/sounds/footstep.wav")
add_child(footstep_player)
jump_player = AudioStreamPlayer.new()
jump_player.bus = "SFX"
jump_player.stream = load("res://assets/sounds/jump.wav")
add_child(jump_player)
double_jump_player = AudioStreamPlayer.new()
double_jump_player.bus = "SFX"
jump_player.bus = "SFX"
double_jump_player.stream = load("res://assets/sounds/double_jump.wav")
add_child(double_jump_player)
dash_player = AudioStreamPlayer.new()
dash_player.bus = "SFX"
dash_player.stream = load("res://assets/sounds/dash.wav")
dash_player.volume_db = -5.0
add_child(dash_player)
hit_player = AudioStreamPlayer.new()
hit_player.bus = "SFX"
hit_player.stream = load("res://assets/sounds/hit_confirm.wav")
hit_player.max_polyphony = 8
add_child(hit_player)
slide_player = AudioStreamPlayer.new()
slide_player.bus = "SFX"
slide_player.stream = load("res://assets/sounds/slide.wav")
slide_player.volume_db = -10.0
add_child(slide_player)
wallrun_player = AudioStreamPlayer.new()
wallrun_player.bus = "SFX"
wallrun_player.stream = load("res://assets/sounds/wallrun.wav")
wallrun_player.volume_db = -10.0
add_child(wallrun_player)
wind_player = AudioStreamPlayer.new()
wind_player.bus = "Wind"
wind_player.stream = load("res://assets/sounds/wind.wav")
wind_player.volume_db = -80.0 # Start silent
add_child(wind_player)
wind_player.play()
grapple_shoot_player = AudioStreamPlayer.new()
grapple_shoot_player.bus = "SFX"
grapple_shoot_player.stream = load("res://assets/sounds/dash.wav")
grapple_shoot_player.volume_db = -5.0
grapple_shoot_player.pitch_scale = 1.5
add_child(grapple_shoot_player)
grapple_latch_player = AudioStreamPlayer.new()
grapple_latch_player.bus = "SFX"
grapple_latch_player.stream = load("res://assets/sounds/hit_confirm.wav")
grapple_latch_player.pitch_scale = 0.8
add_child(grapple_latch_player)
grapple_swing_player = AudioStreamPlayer.new()
grapple_swing_player.bus = "SFX"
grapple_swing_player.stream = load("res://assets/sounds/wind.wav")
grapple_swing_player.pitch_scale = 1.5
grapple_swing_player.volume_db = -80.0
+95 -4
View File
@@ -31,6 +31,14 @@ var _resolution_opt: OptionButton
var _fps_slider: HSlider
var _fps_input: LineEdit
var _show_fps_checkbox: CheckButton
var _vol_master_slider: HSlider
var _vol_master_input: LineEdit
var _vol_sfx_slider: HSlider
var _vol_sfx_input: LineEdit
var _vol_music_slider: HSlider
var _vol_music_input: LineEdit
var _vol_wind_slider: HSlider
var _vol_wind_input: LineEdit
var keybind_vbox: VBoxContainer
var rebind_overlay: ColorRect
var rebind_label: Label
@@ -325,16 +333,51 @@ func _build_ui() -> void:
# Audio Tab
var audio_tab = VBoxContainer.new()
audio_tab.name = "Audio"
audio_tab.add_theme_constant_override("separation", 10)
tab_container.add_child(audio_tab)
var aud_label = Label.new()
aud_label.text = "Settings coming soon..."
audio_tab.add_child(aud_label)
# Master
var master_arr = _build_vol_control(audio_tab, "Master Volume")
_vol_master_slider = master_arr[0]
_vol_master_input = master_arr[1]
_vol_master_slider.value_changed.connect(func(v): _on_vol_changed("vol_master", v, _vol_master_input))
_vol_master_input.text_submitted.connect(func(t): _on_vol_text_changed("vol_master", t, _vol_master_slider, _vol_master_input))
# SFX
var sfx_arr = _build_vol_control(audio_tab, "Sound Effects")
_vol_sfx_slider = sfx_arr[0]
_vol_sfx_input = sfx_arr[1]
_vol_sfx_slider.value_changed.connect(func(v): _on_vol_changed("vol_sfx", v, _vol_sfx_input))
_vol_sfx_input.text_submitted.connect(func(t): _on_vol_text_changed("vol_sfx", t, _vol_sfx_slider, _vol_sfx_input))
# Music
var music_arr = _build_vol_control(audio_tab, "Music")
_vol_music_slider = music_arr[0]
_vol_music_input = music_arr[1]
_vol_music_slider.value_changed.connect(func(v): _on_vol_changed("vol_music", v, _vol_music_input))
_vol_music_input.text_submitted.connect(func(t): _on_vol_text_changed("vol_music", t, _vol_music_slider, _vol_music_input))
# Wind
var wind_arr = _build_vol_control(audio_tab, "Wind")
_vol_wind_slider = wind_arr[0]
_vol_wind_input = wind_arr[1]
_vol_wind_slider.value_changed.connect(func(v): _on_vol_changed("vol_wind", v, _vol_wind_input))
_vol_wind_input.text_submitted.connect(func(t): _on_vol_text_changed("vol_wind", t, _vol_wind_slider, _vol_wind_input))
var spacer_aud = Control.new()
spacer_aud.size_flags_vertical = Control.SIZE_EXPAND_FILL
audio_tab.add_child(spacer_aud)
var reset_aud_btn = Button.new()
reset_aud_btn.text = "Reset to Defaults"
reset_aud_btn.pressed.connect(func(): pass)
reset_aud_btn.pressed.connect(func():
SettingsManager.vol_master = 100.0
SettingsManager.vol_sfx = 100.0
SettingsManager.vol_music = 100.0
SettingsManager.vol_wind = 100.0
SettingsManager._save_settings()
SettingsManager.apply_audio_settings()
_populate_audio_ui()
)
audio_tab.add_child(reset_aud_btn)
# Mouse Tab
@@ -481,6 +524,43 @@ func _build_ui() -> void:
quit_dialog.dialog_text = "Are you sure you want to close the game?"
add_child(quit_dialog)
func _build_vol_control(parent: Node, label_name: String) -> Array:
var hbox = HBoxContainer.new()
parent.add_child(hbox)
var lbl = Label.new()
lbl.text = label_name
lbl.custom_minimum_size = Vector2(150, 0)
hbox.add_child(lbl)
var slider = HSlider.new()
slider.min_value = 0.0
slider.max_value = 100.0
slider.step = 1.0
slider.size_flags_horizontal = Control.SIZE_EXPAND_FILL
slider.custom_minimum_size = Vector2(150, 0)
hbox.add_child(slider)
var input = LineEdit.new()
input.custom_minimum_size = Vector2(60, 0)
hbox.add_child(input)
return [slider, input]
func _on_vol_changed(setting_name: String, value: float, input_node: LineEdit) -> void:
SettingsManager.set(setting_name, value)
input_node.text = str(value)
SettingsManager._save_settings()
SettingsManager.apply_audio_settings()
func _on_vol_text_changed(setting_name: String, text: String, slider_node: HSlider, input_node: LineEdit) -> void:
var val = clampf(text.to_float(), 0.0, 100.0)
SettingsManager.set(setting_name, val)
slider_node.value = val
input_node.text = str(val)
SettingsManager._save_settings()
SettingsManager.apply_audio_settings()
func _create_label(text: String) -> Label:
var l = Label.new()
l.text = text
@@ -525,12 +605,23 @@ func _populate_video_ui() -> void:
_fps_slider.value = float(SettingsManager.fps_cap)
_fps_input.text = str(SettingsManager.fps_cap)
func _populate_audio_ui() -> void:
if _vol_master_slider: _vol_master_slider.value = SettingsManager.vol_master
if _vol_master_input: _vol_master_input.text = str(SettingsManager.vol_master)
if _vol_sfx_slider: _vol_sfx_slider.value = SettingsManager.vol_sfx
if _vol_sfx_input: _vol_sfx_input.text = str(SettingsManager.vol_sfx)
if _vol_music_slider: _vol_music_slider.value = SettingsManager.vol_music
if _vol_music_input: _vol_music_input.text = str(SettingsManager.vol_music)
if _vol_wind_slider: _vol_wind_slider.value = SettingsManager.vol_wind
if _vol_wind_input: _vol_wind_input.text = str(SettingsManager.vol_wind)
func _show_settings() -> void:
main_vbox.visible = false
loadout_editor.visible = false
settings_editor.visible = true
_populate_keybindings()
_populate_video_ui()
_populate_audio_ui()
if _debug_ui_checkbox:
_debug_ui_checkbox.button_pressed = SettingsManager.show_debug_ui
if _show_fps_checkbox:
+2
View File
@@ -70,11 +70,13 @@ func _build_model() -> void:
# Audio
fire_sound = AudioStreamPlayer3D.new()
fire_sound.bus = "SFX"
fire_sound.stream = load("res://assets/sounds/ak47_fire.wav")
fire_sound.position = muzzle_flash.position
fire_sound.volume_db = -5.0
model_root.add_child(fire_sound)
reload_sound = AudioStreamPlayer3D.new()
reload_sound.bus = "SFX"
reload_sound.stream = load("res://assets/sounds/shotgun_reload.wav") # generic reload
model_root.add_child(reload_sound)
+2
View File
@@ -62,11 +62,13 @@ func _build_model() -> void:
# Audio
fire_sound = AudioStreamPlayer3D.new()
fire_sound.bus = "SFX"
fire_sound.stream = load("res://assets/sounds/awp_fire.wav")
fire_sound.volume_db = 0.0
model_root.add_child(fire_sound)
reload_sound = AudioStreamPlayer3D.new()
reload_sound.bus = "SFX"
reload_sound.stream = load("res://assets/sounds/shotgun_reload.wav") # Reusing for now
model_root.add_child(reload_sound)
+2
View File
@@ -73,12 +73,14 @@ func _build_model() -> void:
# Audio
fire_sound = AudioStreamPlayer3D.new()
fire_sound.bus = "SFX"
fire_sound.stream = load("res://assets/sounds/dmr_fire.wav")
fire_sound.position = muzzle_flash.position
fire_sound.volume_db = -3.0
model_root.add_child(fire_sound)
reload_sound = AudioStreamPlayer3D.new()
reload_sound.bus = "SFX"
reload_sound.stream = load("res://assets/sounds/shotgun_reload.wav")
model_root.add_child(reload_sound)
+2
View File
@@ -66,12 +66,14 @@ func _build_model() -> void:
# Audio Players
fire_sound = AudioStreamPlayer3D.new()
fire_sound.bus = "SFX"
fire_sound.stream = load("res://assets/sounds/shotgun_fire.wav")
fire_sound.position = muzzle_flash.position
fire_sound.volume_db = -20.0
add_child(fire_sound)
reload_sound = AudioStreamPlayer3D.new()
reload_sound.bus = "SFX"
reload_sound.stream = load("res://assets/sounds/shotgun_reload.wav")
add_child(reload_sound)
+1
View File
@@ -59,6 +59,7 @@ func destroy() -> void:
func _setup_effects() -> void:
# Audio
flight_sound = AudioStreamPlayer3D.new()
flight_sound.bus = "SFX"
flight_sound.stream = load("res://assets/sounds/rocket_flight.wav")
flight_sound.autoplay = true
if flight_sound.stream is AudioStreamWAV:
+1
View File
@@ -19,6 +19,7 @@ func _start_homing_effects() -> void:
# Audio
flight_sound = AudioStreamPlayer3D.new()
flight_sound.bus = "SFX"
flight_sound.stream = load("res://assets/sounds/swarm_flight.wav")
flight_sound.autoplay = true
if flight_sound.stream is AudioStreamWAV:
+2
View File
@@ -61,11 +61,13 @@ func _build_model() -> void:
# Audio
fire_sound = AudioStreamPlayer3D.new()
fire_sound.bus = "SFX"
fire_sound.stream = load("res://assets/sounds/m4_fire.wav")
fire_sound.position = muzzle_flash.position
fire_sound.volume_db = -8.0
model_root.add_child(fire_sound)
reload_sound = AudioStreamPlayer3D.new()
reload_sound.bus = "SFX"
reload_sound.stream = load("res://assets/sounds/shotgun_reload.wav")
model_root.add_child(reload_sound)
+2
View File
@@ -35,10 +35,12 @@ func _build_model() -> void:
# Audio
fire_sound = AudioStreamPlayer3D.new()
fire_sound.bus = "SFX"
fire_sound.stream = load("res://assets/sounds/mortar_fire.wav")
model_root.add_child(fire_sound)
reload_sound = AudioStreamPlayer3D.new()
reload_sound.bus = "SFX"
reload_sound.stream = load("res://assets/sounds/shotgun_reload.wav") # Reusing
model_root.add_child(reload_sound)
+2
View File
@@ -70,11 +70,13 @@ func _build_model() -> void:
# Audio
fire_sound = AudioStreamPlayer3D.new()
fire_sound.bus = "SFX"
fire_sound.stream = load("res://assets/sounds/mp7_fire.wav")
fire_sound.position = muzzle_flash.position
fire_sound.volume_db = -10.0
model_root.add_child(fire_sound)
reload_sound = AudioStreamPlayer3D.new()
reload_sound.bus = "SFX"
reload_sound.stream = load("res://assets/sounds/shotgun_reload.wav")
model_root.add_child(reload_sound)
+2
View File
@@ -76,12 +76,14 @@ func _build_model() -> void:
# Audio
fire_sound = AudioStreamPlayer3D.new()
fire_sound.bus = "SFX"
fire_sound.stream = load("res://assets/sounds/nailgun_fire.wav")
fire_sound.position = muzzle_flash.position
fire_sound.volume_db = -5.0
model_root.add_child(fire_sound)
reload_sound = AudioStreamPlayer3D.new()
reload_sound.bus = "SFX"
reload_sound.stream = load("res://assets/sounds/shotgun_reload.wav")
model_root.add_child(reload_sound)
+2
View File
@@ -58,12 +58,14 @@ func _build_model() -> void:
# Audio
fire_sound = AudioStreamPlayer3D.new()
fire_sound.bus = "SFX"
fire_sound.stream = load("res://assets/sounds/plasma_fire.wav")
fire_sound.position = muzzle_flash.position
fire_sound.volume_db = -5.0
model_root.add_child(fire_sound)
reload_sound = AudioStreamPlayer3D.new()
reload_sound.bus = "SFX"
reload_sound.stream = load("res://assets/sounds/shotgun_reload.wav")
model_root.add_child(reload_sound)
+2
View File
@@ -55,10 +55,12 @@ func _build_model() -> void:
# Audio
fire_sound = AudioStreamPlayer3D.new()
fire_sound.bus = "SFX"
fire_sound.stream = load("res://assets/sounds/rocket_fire.wav")
model_root.add_child(fire_sound)
reload_sound = AudioStreamPlayer3D.new()
reload_sound.bus = "SFX"
reload_sound.stream = load("res://assets/sounds/shotgun_reload.wav") # Reusing
model_root.add_child(reload_sound)
+2
View File
@@ -52,10 +52,12 @@ func _build_model() -> void:
# Audio
fire_sound = AudioStreamPlayer3D.new()
fire_sound.bus = "SFX"
fire_sound.stream = load("res://assets/sounds/swarm_fire.wav")
model_root.add_child(fire_sound)
reload_sound = AudioStreamPlayer3D.new()
reload_sound.bus = "SFX"
reload_sound.stream = load("res://assets/sounds/shotgun_reload.wav") # Reusing
model_root.add_child(reload_sound)