aboutsummaryrefslogtreecommitdiff
path: root/game/src/OptionMenu
diff options
context:
space:
mode:
Diffstat (limited to 'game/src/OptionMenu')
-rw-r--r--game/src/OptionMenu/ControlsTab.tscn14
-rw-r--r--game/src/OptionMenu/MonitorDisplaySelector.gd6
-rw-r--r--game/src/OptionMenu/OptionsMenu.gd48
-rw-r--r--game/src/OptionMenu/OptionsMenu.tscn130
-rw-r--r--game/src/OptionMenu/OtherTab.tscn18
-rw-r--r--game/src/OptionMenu/ResolutionSelector.gd62
-rw-r--r--game/src/OptionMenu/ScreenModeSelector.gd6
-rw-r--r--game/src/OptionMenu/SettingNodes/SettingHSlider.gd7
-rw-r--r--game/src/OptionMenu/SettingNodes/SettingOptionButton.gd51
-rw-r--r--game/src/OptionMenu/SoundTab.gd4
-rw-r--r--game/src/OptionMenu/SoundTab.tscn34
-rw-r--r--game/src/OptionMenu/VideoTab.tscn73
12 files changed, 273 insertions, 180 deletions
diff --git a/game/src/OptionMenu/ControlsTab.tscn b/game/src/OptionMenu/ControlsTab.tscn
new file mode 100644
index 0000000..b84dc85
--- /dev/null
+++ b/game/src/OptionMenu/ControlsTab.tscn
@@ -0,0 +1,14 @@
+[gd_scene load_steps=2 format=3 uid="uid://cdwymd51i4b2f"]
+
+[ext_resource type="PackedScene" uid="uid://by4gggse2nsdx" path="res://addons/keychain/ShortcutEdit.tscn" id="1_fv8sh"]
+
+[node name="Controls" type="Control"]
+layout_mode = 3
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="ShortcutEdit" parent="." instance=ExtResource("1_fv8sh")]
+layout_mode = 1
diff --git a/game/src/OptionMenu/MonitorDisplaySelector.gd b/game/src/OptionMenu/MonitorDisplaySelector.gd
index 600b296..f2f0dc8 100644
--- a/game/src/OptionMenu/MonitorDisplaySelector.gd
+++ b/game/src/OptionMenu/MonitorDisplaySelector.gd
@@ -1,16 +1,14 @@
extends SettingOptionButton
-
-func _ready():
+func _setup_button():
clear()
for screen_index in range(DisplayServer.get_screen_count()):
add_item("Monitor %d" % (screen_index + 1))
+ default_selected = get_viewport().get_window().current_screen
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
index e3c8433..5aba7f2 100644
--- a/game/src/OptionMenu/OptionsMenu.gd
+++ b/game/src/OptionMenu/OptionsMenu.gd
@@ -1,27 +1,9 @@
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
@@ -33,7 +15,7 @@ func _ready():
var reset_button := Button.new()
reset_button.text = "R"
- reset_button.pressed.connect(func(): reset_settings.emit())
+ reset_button.pressed.connect(Events.Options.try_reset_settings)
button_list.add_child(reset_button)
var back_button := Button.new()
@@ -42,6 +24,8 @@ func _ready():
button_list.add_child(back_button)
get_viewport().get_window().close_requested.connect(_on_window_close_requested)
+ _save_overrides.call_deferred()
+ Events.Options.save_settings.connect(func(_f): self._save_overrides.call_deferred())
func _notification(what):
match what:
@@ -51,22 +35,24 @@ func _notification(what):
# 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)
+ Events.Options.save_settings_from_file()
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()
+ Events.Options.save_settings_from_file()
+
+func _save_overrides() -> void:
+ var override_path := ProjectSettings.get_setting("application/config/project_settings_override") as String
+ if override_path == null or override_path.is_empty():
+ override_path = ProjectSettings.get_setting("openvic2/settings/settings_file_path") as String
+ var file := ConfigFile.new()
+ file.load(override_path)
+ file.set_value("display", "window/size/mode", get_viewport().get_window().mode)
+ var resolution : Vector2i = Resolution.get_current_resolution()
+ file.set_value("display", "window/size/viewport_width", resolution.x)
+ file.set_value("display", "window/size/viewport_height", resolution.y)
+ file.save(override_path)
diff --git a/game/src/OptionMenu/OptionsMenu.tscn b/game/src/OptionMenu/OptionsMenu.tscn
index 0ed531f..eafe37f 100644
--- a/game/src/OptionMenu/OptionsMenu.tscn
+++ b/game/src/OptionMenu/OptionsMenu.tscn
@@ -2,10 +2,10 @@
[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"]
+[ext_resource type="PackedScene" uid="uid://bq3awxxjn1tuw" path="res://src/OptionMenu/VideoTab.tscn" id="2_ji8xr"]
+[ext_resource type="PackedScene" uid="uid://cbtgwpx2wxi33" path="res://src/OptionMenu/SoundTab.tscn" id="3_4w35t"]
+[ext_resource type="PackedScene" uid="uid://bq7ibhm0txl5p" path="res://addons/keychain/ShortcutEdit.tscn" id="4_vdhjp"]
+[ext_resource type="PackedScene" uid="uid://dp2grvybtecqu" path="res://src/OptionMenu/OtherTab.tscn" id="5_ahefp"]
[node name="OptionsMenu" type="Control"]
layout_mode = 3
@@ -34,114 +34,18 @@ size_flags_vertical = 3
tab_alignment = 1
use_hidden_tabs_for_min_size = true
-[node name="Video" type="HBoxContainer" parent="Margin/Tab"]
+[node name="Video" parent="Margin/Tab" instance=ExtResource("2_ji8xr")]
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"]
+[node name="Sound" parent="Margin/Tab" instance=ExtResource("3_4w35t")]
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"]
+[node name="Controls" parent="Margin/Tab" instance=ExtResource("4_vdhjp")]
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"]
+[node name="Other" parent="Margin/Tab" instance=ExtResource("5_ahefp")]
layout_mode = 2
[node name="LocaleVBox" type="VBoxContainer" parent="."]
@@ -161,21 +65,3 @@ 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/OtherTab.tscn b/game/src/OptionMenu/OtherTab.tscn
new file mode 100644
index 0000000..0ffc92d
--- /dev/null
+++ b/game/src/OptionMenu/OtherTab.tscn
@@ -0,0 +1,18 @@
+[gd_scene format=3 uid="uid://dp2grvybtecqu"]
+
+[node name="Other" type="Control"]
+visible = false
+layout_mode = 3
+anchors_preset = 0
+
+[node name="HBoxContainer" type="HBoxContainer" parent="."]
+layout_mode = 0
+offset_right = 40.0
+offset_bottom = 40.0
+
+[node name="Label" type="Label" parent="HBoxContainer"]
+layout_mode = 2
+text = "Spinbox Example :)"
+
+[node name="SpinBox" type="SpinBox" parent="HBoxContainer"]
+layout_mode = 2
diff --git a/game/src/OptionMenu/ResolutionSelector.gd b/game/src/OptionMenu/ResolutionSelector.gd
index ef1a0ff..e602bab 100644
--- a/game/src/OptionMenu/ResolutionSelector.gd
+++ b/game/src/OptionMenu/ResolutionSelector.gd
@@ -1,24 +1,58 @@
extends SettingOptionButton
-func _ready():
- print("Resolution selector ready")
+@export
+var default_value : Vector2i = Vector2i(-1, -1)
+
+func add_resolution(value : Vector2i, selection_name : String = "") -> void:
+ if selection_name.is_empty():
+ selection_name = "%sx%s" % [value.x, value.y]
+ add_item(selection_name)
+ set_item_metadata(item_count - 1, value)
+
+func find_resolution_value(value : Vector2i) -> int:
+ for item_index in range(item_count):
+ if get_item_metadata(item_index) == value:
+ return item_index
+ return -1
+
+func _setup_button():
+ if default_value.x < 0:
+ default_value.x = ProjectSettings.get_setting("display/window/size/viewport_width")
+
+ if default_value.y < 0:
+ default_value.y = ProjectSettings.get_setting("display/window/size/viewport_height")
clear()
- var resolution_index := 0
+ default_selected = -1
+ selected = -1
for resolution in Resolution.get_resolution_name_list():
- add_item(resolution)
+ var resolution_value := Resolution.get_resolution(resolution)
+ add_resolution(resolution_value, 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)
+ if resolution_value == default_value:
+ default_selected = item_count - 1
- resolution_index += 1
+ if resolution_value == Resolution.get_current_resolution():
+ selected = item_count - 1
+ if default_selected == -1:
+ add_resolution(default_value)
+ default_selected = item_count - 1
-func _on_item_selected(index):
- print("Selected index: %d" % index)
+ if selected == -1:
+ selected = default_selected
+
+func _get_value_for_file(select_value : int):
+ return get_item_metadata(select_value)
- var resolution_size : Vector2i = Resolution.get_resolution(get_item_text(index))
- Resolution.set_resolution(resolution_size)
+func _set_value_from_file(load_value):
+ var resolution_value := load_value as Vector2i
+ selected = find_resolution_value(resolution_value)
+ if selected == -1:
+ if add_nonstandard_value:
+ add_resolution(resolution_value)
+ selected = item_count - 1
+ else: push_error("Setting value '%s' invalid for setting [%s] %s" % [load_value, section_name, setting_name])
+
+func _on_item_selected(index):
+ Resolution.set_resolution(get_item_metadata(index))
diff --git a/game/src/OptionMenu/ScreenModeSelector.gd b/game/src/OptionMenu/ScreenModeSelector.gd
index fae0771..92c5d60 100644
--- a/game/src/OptionMenu/ScreenModeSelector.gd
+++ b/game/src/OptionMenu/ScreenModeSelector.gd
@@ -24,9 +24,11 @@ func get_window_mode_from_screen_mode(screen_mode : int) -> Window.Mode:
_:
return Window.MODE_EXCLUSIVE_FULLSCREEN
-func _on_item_selected(index : int):
- print("Selected index: %d" % index)
+func _setup_button():
+ default_selected = get_screen_mode_from_window_mode(get_viewport().get_window().mode)
+ selected = default_selected
+func _on_item_selected(index : int):
var window := get_viewport().get_window()
var current_resolution := Resolution.get_current_resolution()
window.mode = get_window_mode_from_screen_mode(index)
diff --git a/game/src/OptionMenu/SettingNodes/SettingHSlider.gd b/game/src/OptionMenu/SettingNodes/SettingHSlider.gd
index da9348f..cf2adf4 100644
--- a/game/src/OptionMenu/SettingNodes/SettingHSlider.gd
+++ b/game/src/OptionMenu/SettingNodes/SettingHSlider.gd
@@ -10,10 +10,17 @@ var setting_name : String = "SettingHSlider"
@export
var default_value : float = 0
+func _ready():
+ Events.Options.load_settings.connect(load_setting)
+ Events.Options.save_settings.connect(save_setting)
+ Events.Options.reset_settings.connect(reset_setting)
+
func load_setting(file : ConfigFile):
+ if file == null: return
value = file.get_value(section_name, setting_name, default_value)
func save_setting(file : ConfigFile):
+ if file == null: return
file.set_value(section_name, setting_name, value)
func reset_setting():
diff --git a/game/src/OptionMenu/SettingNodes/SettingOptionButton.gd b/game/src/OptionMenu/SettingNodes/SettingOptionButton.gd
index 46fc825..3a5c979 100644
--- a/game/src/OptionMenu/SettingNodes/SettingOptionButton.gd
+++ b/game/src/OptionMenu/SettingNodes/SettingOptionButton.gd
@@ -8,15 +8,52 @@ var section_name : String = "Setting"
var setting_name : String = "SettingOptionMenu"
@export
-var default_value : int = 0
+var default_selected : int = -1:
+ get: return default_selected
+ set(v):
+ if v == -1:
+ default_selected = -1
+ return
+ default_selected = v % item_count
-func load_setting(file : ConfigFile):
- selected = file.get_value(section_name, setting_name, default_value)
+@export
+var add_nonstandard_value := false
+
+func _get_value_for_file(select_value : int):
+ if select_value > -1:
+ return get_item_text(select_value)
+ else:
+ return null
+
+func _set_value_from_file(load_value) -> void:
+ selected = -1
+ for item_index in range(item_count):
+ if load_value == get_item_text(item_index):
+ selected = item_index
+ if selected == -1:
+ if add_nonstandard_value:
+ add_item(load_value)
+ selected = item_count - 1
+ else: push_error("Setting value '%s' invalid for setting [%s] \"%s\"" % [load_value, section_name, setting_name])
+
+func _setup_button() -> void:
+ pass
+
+func _ready():
+ Events.Options.load_settings.connect(load_setting)
+ Events.Options.save_settings.connect(save_setting)
+ Events.Options.reset_settings.connect(reset_setting)
+ _setup_button()
+
+func load_setting(file : ConfigFile) -> void:
+ if file == null: return
+ _set_value_from_file(file.get_value(section_name, setting_name, _get_value_for_file(default_selected)))
item_selected.emit(selected)
-func save_setting(file : ConfigFile):
- file.set_value(section_name, setting_name, selected)
+func save_setting(file : ConfigFile) -> void:
+ if file == null: return
+ file.set_value(section_name, setting_name, _get_value_for_file(selected))
-func reset_setting():
- selected = default_value
+func reset_setting() -> void:
+ selected = default_selected
item_selected.emit(selected)
diff --git a/game/src/OptionMenu/SoundTab.gd b/game/src/OptionMenu/SoundTab.gd
new file mode 100644
index 0000000..c707605
--- /dev/null
+++ b/game/src/OptionMenu/SoundTab.gd
@@ -0,0 +1,4 @@
+extends HBoxContainer
+
+func _on_ear_exploder_toggled(button_pressed):
+ print("KABOOM!!!" if button_pressed else "DEFUSED!!!")
diff --git a/game/src/OptionMenu/SoundTab.tscn b/game/src/OptionMenu/SoundTab.tscn
new file mode 100644
index 0000000..10d7f10
--- /dev/null
+++ b/game/src/OptionMenu/SoundTab.tscn
@@ -0,0 +1,34 @@
+[gd_scene load_steps=3 format=3 uid="uid://cbtgwpx2wxi33"]
+
+[ext_resource type="Script" path="res://src/OptionMenu/SoundTab.gd" id="1_a7k0s"]
+[ext_resource type="PackedScene" uid="uid://dy4si8comamnv" path="res://src/OptionMenu/VolumeGrid.tscn" id="1_okpft"]
+
+[node name="Sound" type="HBoxContainer"]
+alignment = 1
+script = ExtResource("1_a7k0s")
+
+[node name="VBoxContainer" type="VBoxContainer" parent="."]
+layout_mode = 2
+
+[node name="Control" type="Control" parent="VBoxContainer"]
+layout_mode = 2
+size_flags_vertical = 3
+size_flags_stretch_ratio = 0.1
+
+[node name="VolumeGrid" parent="VBoxContainer" instance=ExtResource("1_okpft")]
+layout_mode = 2
+
+[node name="ButtonGrid" type="GridContainer" parent="VBoxContainer"]
+layout_mode = 2
+size_flags_vertical = 2
+columns = 2
+
+[node name="Spacer" type="Control" parent="VBoxContainer/ButtonGrid"]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="EarExploder" type="CheckButton" parent="VBoxContainer/ButtonGrid"]
+layout_mode = 2
+text = "Explode Eardrums on Startup?"
+
+[connection signal="toggled" from="VBoxContainer/ButtonGrid/EarExploder" to="." method="_on_ear_exploder_toggled"]
diff --git a/game/src/OptionMenu/VideoTab.tscn b/game/src/OptionMenu/VideoTab.tscn
new file mode 100644
index 0000000..d46f056
--- /dev/null
+++ b/game/src/OptionMenu/VideoTab.tscn
@@ -0,0 +1,73 @@
+[gd_scene load_steps=4 format=3 uid="uid://bq3awxxjn1tuw"]
+
+[ext_resource type="Script" path="res://src/OptionMenu/ResolutionSelector.gd" id="1_i8nro"]
+[ext_resource type="Script" path="res://src/OptionMenu/ScreenModeSelector.gd" id="2_wa7vw"]
+[ext_resource type="Script" path="res://src/OptionMenu/MonitorDisplaySelector.gd" id="3_y6lyb"]
+
+[node name="Video" type="HBoxContainer"]
+tooltip_text = "This is my cool and very nice tooltip"
+alignment = 1
+
+[node name="VBoxContainer" type="VBoxContainer" parent="."]
+layout_mode = 2
+
+[node name="Control" type="Control" parent="VBoxContainer"]
+layout_mode = 2
+size_flags_vertical = 3
+size_flags_stretch_ratio = 0.1
+
+[node name="GridContainer" type="GridContainer" parent="VBoxContainer"]
+layout_mode = 2
+size_flags_vertical = 3
+columns = 2
+
+[node name="ResolutionLabel" type="Label" parent="VBoxContainer/GridContainer"]
+layout_mode = 2
+text = "Resolution"
+
+[node name="ResolutionSelector" type="OptionButton" parent="VBoxContainer/GridContainer"]
+layout_mode = 2
+item_count = 1
+selected = 0
+popup/item_0/text = "MISSING"
+popup/item_0/id = 0
+script = ExtResource("1_i8nro")
+section_name = "Video"
+setting_name = "Resolution"
+add_nonstandard_value = true
+
+[node name="ScreenModeLabel" type="Label" parent="VBoxContainer/GridContainer"]
+layout_mode = 2
+text = "Screen Mode"
+
+[node name="ScreenModeSelector" type="OptionButton" parent="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("2_wa7vw")
+section_name = "Video"
+setting_name = "Mode Selected"
+
+[node name="MonitorSelectionLabel" type="Label" parent="VBoxContainer/GridContainer"]
+layout_mode = 2
+text = "Monitor Selection"
+
+[node name="MonitorDisplaySelector" type="OptionButton" parent="VBoxContainer/GridContainer"]
+layout_mode = 2
+item_count = 1
+selected = 0
+popup/item_0/text = "MISSING"
+popup/item_0/id = 0
+script = ExtResource("3_y6lyb")
+section_name = "Video"
+setting_name = "Current Screen"
+
+[connection signal="item_selected" from="VBoxContainer/GridContainer/ResolutionSelector" to="VBoxContainer/GridContainer/ResolutionSelector" method="_on_item_selected"]
+[connection signal="item_selected" from="VBoxContainer/GridContainer/ScreenModeSelector" to="VBoxContainer/GridContainer/ScreenModeSelector" method="_on_item_selected"]
+[connection signal="item_selected" from="VBoxContainer/GridContainer/MonitorDisplaySelector" to="VBoxContainer/GridContainer/MonitorDisplaySelector" method="_on_item_selected"]