diff options
author | Spartan322 <Megacake1234@gmail.com> | 2023-02-10 10:18:46 +0100 |
---|---|---|
committer | Spartan322 <Megacake1234@gmail.com> | 2023-02-10 10:31:28 +0100 |
commit | 3798205c740e7e2faf2594866cb497260012508c (patch) | |
tree | 4ca4a0835cb833fbba1983f0e8de5fa66227b86e /game/src/OptionMenu | |
parent | 6525b89a37a31eaf88182b11410bd46b6658e297 (diff) |
Implement a usable settings UI, should fulfill:
SS-58, SS-61, SS-6, SS-9, SS-10, SS-11, SS-13
UI-11, UI-12, UI-19, UI-44, UI-47, UI-22
Diffstat (limited to 'game/src/OptionMenu')
-rw-r--r-- | game/src/OptionMenu/MonitorDisplaySelector.gd | 16 | ||||
-rw-r--r-- | game/src/OptionMenu/OptionsMenu.gd | 72 | ||||
-rw-r--r-- | game/src/OptionMenu/OptionsMenu.tscn | 181 | ||||
-rw-r--r-- | game/src/OptionMenu/ResolutionSelector.gd | 24 | ||||
-rw-r--r-- | game/src/OptionMenu/ScreenModeSelector.gd | 33 | ||||
-rw-r--r-- | game/src/OptionMenu/SettingNodes/SettingHSlider.gd | 20 | ||||
-rw-r--r-- | game/src/OptionMenu/SettingNodes/SettingOptionButton.gd | 22 | ||||
-rw-r--r-- | game/src/OptionMenu/VolumeGrid.gd | 54 | ||||
-rw-r--r-- | game/src/OptionMenu/VolumeGrid.tscn | 8 |
9 files changed, 430 insertions, 0 deletions
diff --git a/game/src/OptionMenu/MonitorDisplaySelector.gd b/game/src/OptionMenu/MonitorDisplaySelector.gd new file mode 100644 index 0000000..600b296 --- /dev/null +++ b/game/src/OptionMenu/MonitorDisplaySelector.gd @@ -0,0 +1,16 @@ +extends SettingOptionButton + + +func _ready(): + clear() + for screen_index in range(DisplayServer.get_screen_count()): + add_item("Monitor %d" % (screen_index + 1)) + +func _on_item_selected(index): + print("Selected index: %d" % index) + var window := get_viewport().get_window() + var mode := window.mode + window.mode = Window.MODE_WINDOWED + get_viewport().get_window().set_current_screen(index) + window.mode = mode + print(get_viewport().get_window().current_screen) diff --git a/game/src/OptionMenu/OptionsMenu.gd b/game/src/OptionMenu/OptionsMenu.gd new file mode 100644 index 0000000..e3c8433 --- /dev/null +++ b/game/src/OptionMenu/OptionsMenu.gd @@ -0,0 +1,72 @@ +extends Control + +@export +var user_settings_file_path : String = "settings.cfg" + +signal back_button_pressed + +signal save_settings(save_file: ConfigFile) +signal load_settings(load_file: ConfigFile) +signal reset_settings() + +@onready +var _settings_file_path := "user://" + user_settings_file_path +var _settings_file := ConfigFile.new() + +func _ready(): + # Prepare options menu before loading user settings + + print("TODO: Load user settings!") + + if FileAccess.file_exists(_settings_file_path): + _settings_file.load(_settings_file_path) + load_settings.emit(_settings_file) + + var tab_bar : TabBar = $Margin/Tab.get_child(0, true) + + # This ends up easier to manage then trying to manually recreate the TabContainer's behavior + # These buttons can be accessed regardless of the tab + var button_list := HBoxContainer.new() + button_list.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + button_list.alignment = BoxContainer.ALIGNMENT_END + tab_bar.add_child(button_list) + + var reset_button := Button.new() + reset_button.text = "R" + reset_button.pressed.connect(func(): reset_settings.emit()) + button_list.add_child(reset_button) + + var back_button := Button.new() + back_button.text = "X" + back_button.pressed.connect(_on_back_button_pressed) + button_list.add_child(back_button) + + get_viewport().get_window().close_requested.connect(_on_window_close_requested) + +func _notification(what): + match what: + NOTIFICATION_CRASH: + _on_window_close_requested() + +# Could pass the LocaleButton between the MainMenu and OptionsMenu +# but that seems a bit excessive +func toggle_locale_button_visibility(locale_visible : bool): + print("Toggling locale button: %s" % locale_visible) + $LocaleVBox/LocaleHBox/LocaleButton.visible = locale_visible + +func _on_ear_exploder_toggled(button_pressed): + print("KABOOM!!!" if button_pressed else "DEFUSED!!!") + + +func _on_back_button_pressed(): + save_settings.emit(_settings_file) + _settings_file.save(_settings_file_path) + back_button_pressed.emit() + + +func _on_spin_box_value_changed(value): + print("Spinbox: %d" % value) + +func _on_window_close_requested() -> void: + if visible: + _on_back_button_pressed() diff --git a/game/src/OptionMenu/OptionsMenu.tscn b/game/src/OptionMenu/OptionsMenu.tscn new file mode 100644 index 0000000..0ed531f --- /dev/null +++ b/game/src/OptionMenu/OptionsMenu.tscn @@ -0,0 +1,181 @@ +[gd_scene load_steps=7 format=3 uid="uid://cnbfxjy1m6wja"] + +[ext_resource type="Script" path="res://src/OptionMenu/OptionsMenu.gd" id="1_tlein"] +[ext_resource type="PackedScene" uid="uid://b7oncobnacxmt" path="res://src/LocaleButton.tscn" id="2_d7wvq"] +[ext_resource type="Script" path="res://src/OptionMenu/ResolutionSelector.gd" id="2_jk1ey"] +[ext_resource type="Script" path="res://src/OptionMenu/ScreenModeSelector.gd" id="3_hsicf"] +[ext_resource type="Script" path="res://src/OptionMenu/MonitorDisplaySelector.gd" id="3_q1cm3"] +[ext_resource type="PackedScene" uid="uid://dy4si8comamnv" path="res://src/OptionMenu/VolumeGrid.tscn" id="4_n4oqr"] + +[node name="OptionsMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_tlein") + +[node name="Margin" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 250 +theme_override_constants/margin_top = 100 +theme_override_constants/margin_right = 250 +theme_override_constants/margin_bottom = 200 + +[node name="Tab" type="TabContainer" parent="Margin"] +layout_mode = 2 +size_flags_vertical = 3 +tab_alignment = 1 +use_hidden_tabs_for_min_size = true + +[node name="Video" type="HBoxContainer" parent="Margin/Tab"] +layout_mode = 2 +tooltip_text = "This is my cool and very nice tooltip" +alignment = 1 + +[node name="VBoxContainer" type="VBoxContainer" parent="Margin/Tab/Video"] +layout_mode = 2 + +[node name="Control" type="Control" parent="Margin/Tab/Video/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +size_flags_stretch_ratio = 0.1 + +[node name="GridContainer" type="GridContainer" parent="Margin/Tab/Video/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +columns = 2 + +[node name="ResolutionLabel" type="Label" parent="Margin/Tab/Video/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Resolution" + +[node name="ResolutionSelector" type="OptionButton" parent="Margin/Tab/Video/VBoxContainer/GridContainer"] +layout_mode = 2 +item_count = 1 +selected = 0 +popup/item_0/text = "MISSING" +popup/item_0/id = 0 +script = ExtResource("2_jk1ey") +section_name = "Video" +setting_name = "Resolution" +default_value = -1 + +[node name="ScreenModeLabel" type="Label" parent="Margin/Tab/Video/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Screen Mode" + +[node name="ScreenModeSelector" type="OptionButton" parent="Margin/Tab/Video/VBoxContainer/GridContainer"] +layout_mode = 2 +item_count = 3 +selected = 0 +popup/item_0/text = "Fullscreen" +popup/item_0/id = 0 +popup/item_1/text = "Borderless" +popup/item_1/id = 1 +popup/item_2/text = "Windowed" +popup/item_2/id = 2 +script = ExtResource("3_hsicf") +section_name = "Video" +setting_name = "Mode Selected" + +[node name="MonitorSelectionLabel" type="Label" parent="Margin/Tab/Video/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Monitor Selection" + +[node name="MonitorDisplaySelector" type="OptionButton" parent="Margin/Tab/Video/VBoxContainer/GridContainer"] +layout_mode = 2 +item_count = 1 +selected = 0 +popup/item_0/text = "MISSING" +popup/item_0/id = 0 +script = ExtResource("3_q1cm3") +section_name = "Video" +setting_name = "Current Screen" + +[node name="Sound" type="HBoxContainer" parent="Margin/Tab"] +visible = false +layout_mode = 2 +alignment = 1 + +[node name="VBoxContainer" type="VBoxContainer" parent="Margin/Tab/Sound"] +layout_mode = 2 + +[node name="Control" type="Control" parent="Margin/Tab/Sound/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +size_flags_stretch_ratio = 0.1 + +[node name="VolumeGrid" parent="Margin/Tab/Sound/VBoxContainer" instance=ExtResource("4_n4oqr")] +layout_mode = 2 + +[node name="ButtonGrid" type="GridContainer" parent="Margin/Tab/Sound/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 2 +columns = 2 + +[node name="Spacer" type="Control" parent="Margin/Tab/Sound/VBoxContainer/ButtonGrid"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="EarExploder" type="CheckButton" parent="Margin/Tab/Sound/VBoxContainer/ButtonGrid"] +layout_mode = 2 +text = "Explode Eardrums on Startup?" + +[node name="Other" type="Control" parent="Margin/Tab"] +visible = false +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="Margin/Tab/Other"] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="Label" type="Label" parent="Margin/Tab/Other/HBoxContainer"] +layout_mode = 2 +text = "Spinbox Example :)" + +[node name="SpinBox" type="SpinBox" parent="Margin/Tab/Other/HBoxContainer"] +layout_mode = 2 + +[node name="LocaleVBox" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +alignment = 2 + +[node name="LocaleHBox" type="HBoxContainer" parent="LocaleVBox"] +layout_mode = 2 +mouse_filter = 2 +alignment = 2 + +[node name="LocaleButton" parent="LocaleVBox/LocaleHBox" instance=ExtResource("2_d7wvq")] +layout_mode = 2 + +[connection signal="load_settings" from="." to="Margin/Tab/Video/VBoxContainer/GridContainer/ResolutionSelector" method="load_setting"] +[connection signal="load_settings" from="." to="Margin/Tab/Video/VBoxContainer/GridContainer/ScreenModeSelector" method="load_setting"] +[connection signal="load_settings" from="." to="Margin/Tab/Video/VBoxContainer/GridContainer/MonitorDisplaySelector" method="load_setting"] +[connection signal="load_settings" from="." to="Margin/Tab/Sound/VBoxContainer/VolumeGrid" method="_on_options_menu_load_settings"] +[connection signal="reset_settings" from="." to="Margin/Tab/Video/VBoxContainer/GridContainer/ResolutionSelector" method="reset_setting"] +[connection signal="reset_settings" from="." to="Margin/Tab/Video/VBoxContainer/GridContainer/ScreenModeSelector" method="reset_setting"] +[connection signal="reset_settings" from="." to="Margin/Tab/Video/VBoxContainer/GridContainer/MonitorDisplaySelector" method="reset_setting"] +[connection signal="reset_settings" from="." to="Margin/Tab/Sound/VBoxContainer/VolumeGrid" method="_on_options_menu_reset_settings"] +[connection signal="save_settings" from="." to="Margin/Tab/Video/VBoxContainer/GridContainer/ResolutionSelector" method="save_setting"] +[connection signal="save_settings" from="." to="Margin/Tab/Video/VBoxContainer/GridContainer/ScreenModeSelector" method="save_setting"] +[connection signal="save_settings" from="." to="Margin/Tab/Video/VBoxContainer/GridContainer/MonitorDisplaySelector" method="save_setting"] +[connection signal="save_settings" from="." to="Margin/Tab/Sound/VBoxContainer/VolumeGrid" method="_on_options_menu_save_settings"] +[connection signal="item_selected" from="Margin/Tab/Video/VBoxContainer/GridContainer/ResolutionSelector" to="Margin/Tab/Video/VBoxContainer/GridContainer/ResolutionSelector" method="_on_item_selected"] +[connection signal="item_selected" from="Margin/Tab/Video/VBoxContainer/GridContainer/ScreenModeSelector" to="Margin/Tab/Video/VBoxContainer/GridContainer/ScreenModeSelector" method="_on_item_selected"] +[connection signal="item_selected" from="Margin/Tab/Video/VBoxContainer/GridContainer/MonitorDisplaySelector" to="Margin/Tab/Video/VBoxContainer/GridContainer/MonitorDisplaySelector" method="_on_item_selected"] +[connection signal="toggled" from="Margin/Tab/Sound/VBoxContainer/ButtonGrid/EarExploder" to="." method="_on_ear_exploder_toggled"] +[connection signal="value_changed" from="Margin/Tab/Other/HBoxContainer/SpinBox" to="." method="_on_spin_box_value_changed"] diff --git a/game/src/OptionMenu/ResolutionSelector.gd b/game/src/OptionMenu/ResolutionSelector.gd new file mode 100644 index 0000000..ef1a0ff --- /dev/null +++ b/game/src/OptionMenu/ResolutionSelector.gd @@ -0,0 +1,24 @@ +extends SettingOptionButton + +func _ready(): + print("Resolution selector ready") + + clear() + var resolution_index := 0 + for resolution in Resolution.get_resolution_name_list(): + add_item(resolution) + + if Vector2(Resolution.get_resolution(resolution)) == Resolution.get_current_resolution(): + if default_value == -1: + default_value = resolution_index + _select_int(resolution_index) + print(resolution) + + resolution_index += 1 + + +func _on_item_selected(index): + print("Selected index: %d" % index) + + var resolution_size : Vector2i = Resolution.get_resolution(get_item_text(index)) + Resolution.set_resolution(resolution_size) diff --git a/game/src/OptionMenu/ScreenModeSelector.gd b/game/src/OptionMenu/ScreenModeSelector.gd new file mode 100644 index 0000000..fae0771 --- /dev/null +++ b/game/src/OptionMenu/ScreenModeSelector.gd @@ -0,0 +1,33 @@ +extends SettingOptionButton + +enum ScreenMode { Unknown = -1, Fullscreen, Borderless, Windowed } + +func get_screen_mode_from_window_mode(window_mode : int) -> ScreenMode: + match window_mode: + Window.MODE_EXCLUSIVE_FULLSCREEN: + return ScreenMode.Fullscreen + Window.MODE_FULLSCREEN: + return ScreenMode.Borderless + Window.MODE_WINDOWED: + return ScreenMode.Windowed + _: + return ScreenMode.Unknown + +func get_window_mode_from_screen_mode(screen_mode : int) -> Window.Mode: + match screen_mode: + ScreenMode.Fullscreen: + return Window.MODE_EXCLUSIVE_FULLSCREEN + ScreenMode.Borderless: + return Window.MODE_FULLSCREEN + ScreenMode.Windowed: + return Window.MODE_WINDOWED + _: + return Window.MODE_EXCLUSIVE_FULLSCREEN + +func _on_item_selected(index : int): + print("Selected index: %d" % index) + + var window := get_viewport().get_window() + var current_resolution := Resolution.get_current_resolution() + window.mode = get_window_mode_from_screen_mode(index) + Resolution.set_resolution(current_resolution) diff --git a/game/src/OptionMenu/SettingNodes/SettingHSlider.gd b/game/src/OptionMenu/SettingNodes/SettingHSlider.gd new file mode 100644 index 0000000..da9348f --- /dev/null +++ b/game/src/OptionMenu/SettingNodes/SettingHSlider.gd @@ -0,0 +1,20 @@ +extends HSlider +class_name SettingHSlider + +@export +var section_name : String = "Setting" + +@export +var setting_name : String = "SettingHSlider" + +@export +var default_value : float = 0 + +func load_setting(file : ConfigFile): + value = file.get_value(section_name, setting_name, default_value) + +func save_setting(file : ConfigFile): + file.set_value(section_name, setting_name, value) + +func reset_setting(): + value = default_value diff --git a/game/src/OptionMenu/SettingNodes/SettingOptionButton.gd b/game/src/OptionMenu/SettingNodes/SettingOptionButton.gd new file mode 100644 index 0000000..46fc825 --- /dev/null +++ b/game/src/OptionMenu/SettingNodes/SettingOptionButton.gd @@ -0,0 +1,22 @@ +extends OptionButton +class_name SettingOptionButton + +@export +var section_name : String = "Setting" + +@export +var setting_name : String = "SettingOptionMenu" + +@export +var default_value : int = 0 + +func load_setting(file : ConfigFile): + selected = file.get_value(section_name, setting_name, default_value) + item_selected.emit(selected) + +func save_setting(file : ConfigFile): + file.set_value(section_name, setting_name, selected) + +func reset_setting(): + selected = default_value + item_selected.emit(selected) diff --git a/game/src/OptionMenu/VolumeGrid.gd b/game/src/OptionMenu/VolumeGrid.gd new file mode 100644 index 0000000..fae5ff6 --- /dev/null +++ b/game/src/OptionMenu/VolumeGrid.gd @@ -0,0 +1,54 @@ +extends GridContainer + +const RATIO_FOR_LINEAR = 100 + +var _slider_dictionary := {} + +func get_db_as_volume_value(db : float) -> float: + # db_to_linear produces a float between 0 and 1 from a db value + return db_to_linear(db) * RATIO_FOR_LINEAR + +func get_volume_value_as_db(value : float) -> float: + # linear_to_db consumes a float between 0 and 1 to produce the db value + return linear_to_db(value / RATIO_FOR_LINEAR) + +func add_volume_column(bus_name : StringName, bus_index : int) -> HSlider: + var volume_label := Label.new() + volume_label.text = bus_name + " Volume" + add_child(volume_label) + + var volume_slider := SettingHSlider.new() + volume_slider.section_name = "Audio" + volume_slider.setting_name = volume_label.text + volume_slider.custom_minimum_size = Vector2(290, 0) + volume_slider.size_flags_vertical = Control.SIZE_FILL + volume_slider.min_value = 0 + volume_slider.default_value = 100 + volume_slider.max_value = 120 # 120 so volume can be boosted somewhat + volume_slider.value_changed.connect(_on_slider_value_changed.bind(bus_index)) + add_child(volume_slider) + + _slider_dictionary[volume_label.text] = volume_slider + return volume_slider + +func _ready(): + for bus_index in AudioServer.bus_count: + add_volume_column(AudioServer.get_bus_name(bus_index), bus_index) + +func _on_slider_value_changed(value : float, bus_index : int) -> void: + AudioServer.set_bus_volume_db(bus_index, get_volume_value_as_db(value)) + + +func _on_options_menu_load_settings(load_file : ConfigFile): + for volume_label_text in _slider_dictionary: + _slider_dictionary[volume_label_text].load_setting(load_file) + + +func _on_options_menu_save_settings(save_file : ConfigFile): + for volume_label_text in _slider_dictionary: + _slider_dictionary[volume_label_text].save_setting(save_file) + + +func _on_options_menu_reset_settings(): + for volume_label_text in _slider_dictionary: + _slider_dictionary[volume_label_text].reset_setting() diff --git a/game/src/OptionMenu/VolumeGrid.tscn b/game/src/OptionMenu/VolumeGrid.tscn new file mode 100644 index 0000000..6d4de3c --- /dev/null +++ b/game/src/OptionMenu/VolumeGrid.tscn @@ -0,0 +1,8 @@ +[gd_scene load_steps=2 format=3 uid="uid://dy4si8comamnv"] + +[ext_resource type="Script" path="res://src/OptionMenu/VolumeGrid.gd" id="1_wb64h"] + +[node name="VolumeGrid" type="GridContainer"] +size_flags_vertical = 0 +columns = 2 +script = ExtResource("1_wb64h") |