diff --git a/autoloads/options.gd b/autoloads/options.gd index 505f65b..8f86717 100644 --- a/autoloads/options.gd +++ b/autoloads/options.gd @@ -1,30 +1,45 @@ extends Node #Enums -enum ScalingModes {INTEGER,ASPECT,STRETCH} -enum Filters {NONE,CRT,LCD,BILINEAR} +enum ScalingMode {INTEGER,ASPECT,STRETCH} +enum Filter {NONE,CRT,LCD,BILINEAR} enum RumbleMode {NONE,NORMAL,BPM} enum TransSpeed {NONE = 0,SLOW = 1,NORMAL = 2,FAST = 3} var TRANS_SPEEDS = [0.0000001, 0.8, 0.4, 0.2] #Game var rumble = RumbleMode.NONE #Video -var fullscreen = false -var scaling_mode = ScalingModes.INTEGER -var transition_speed = TransSpeed.NORMAL setget , _get_transition_speed +var fullscreen = false setget _set_fullscreen +var scaling_mode = ScalingMode.INTEGER setget _set_scaling_mode +var transition_speed = TransSpeed.NORMAL setget _set_transition_speed +var transition_speed_secs setget , _get_transition_speed_sex #Audio -var master_volume = 100 setget _set_master_volume -var music_volume = 100 setget _set_music_volume -var sound_volume = 100 setget _set_sound_volume - +var master_volume = 1.0 setget _set_master_volume +var music_volume = 1.0 setget _set_music_volume +var sound_volume = 1.0 setget _set_sound_volume +# default values +var defaults = null func _ready(): + # clone self into defaults before loading stored values + if defaults == null: + defaults = duplicate() load_options() func load_options(): var file = ConfigFile.new() file.load("user://options.pr") + # game + rumble = file.get_value("game", "rumble", RumbleMode.NONE) + # video + _set_fullscreen(file.get_value("video", "fullscreen", false)) + _set_scaling_mode(file.get_value("video", "scaling_mode", ScalingMode.INTEGER)) + _set_transition_speed(file.get_value("video", "transition_speed", TransSpeed.NORMAL)) + # audio + _set_master_volume(file.get_value("audio", "master_volume", 1.0)) + _set_music_volume(file.get_value("audio", "music_volume", 1.0)) + _set_sound_volume(file.get_value("audio", "sound_volume", 1.0)) func save_options(): var file = ConfigFile.new() @@ -42,13 +57,21 @@ func save_options(): # Setters +# video setters func _set_fullscreen(value): fullscreen = value OS.set_window_fullscreen(value) -func _get_transition_speed(): +func _set_scaling_mode(value): + scaling_mode = value + +func _set_transition_speed(value): + transition_speed = value + +func _get_transition_speed_sex(): return TRANS_SPEEDS[transition_speed] +# audio setters func _set_master_volume(value): master_volume = value AudioServer.set_bus_volume_db(0, linear2db(value)) diff --git a/objects/hud/options_screen.gd b/objects/hud/options_screen.gd index b985db3..3b2d42d 100644 --- a/objects/hud/options_screen.gd +++ b/objects/hud/options_screen.gd @@ -1,13 +1,63 @@ extends Control +# emmitted when "back" is pressed +signal exit + export (StyleBox) var tab_selected_style onready var tabs = $Tabs +onready var confirm_dialog = $ConfirmDialog + +# option controls # +# game +onready var rumble = $"%Rumble" +# video +onready var fullscreen = $"%Fullscreen" +onready var window_size = $"%WindowSize" +onready var scaling_mode = $"%ScalingMode" +onready var transition_speed = $"%TransitionSpeed" +# audio +onready var master_volume = $"%MasterSlider" +onready var music_volume = $"%MusicSlider" +onready var sound_volume = $"%SoundSlider" + +# flagged when options have been changed +var dirty = false func focus(): + load_options(Options) + dirty = false visible = true + confirm_dialog.visible = false grab_focus() +func load_options(options): + # game + rumble.select(options.rumble) + # video + fullscreen.select(1 if options.fullscreen else 0) # index 1 is the "on" button +# window_size.select(options.window_size) + scaling_mode.select(options.scaling_mode) + transition_speed.select(options.transition_speed) + # audio + master_volume.value = options.master_volume + music_volume.value = options.music_volume + sound_volume.value = options.sound_volume + +func apply_options(): + # game + Options.rumble = rumble.get_selection() + # video + Options.fullscreen = fullscreen.get_selection() == 1 # true if 1, otherwise false +# Options.window_size = window_size.get_selection() + Options.scaling_mode = scaling_mode.get_selection() + Options.transition_speed = transition_speed.get_selection() + # audio + Options.master_volume = master_volume.value + Options.music_volume = music_volume.value + Options.sound_volume = sound_volume.value + print(Options.master_volume) + func _gui_input(event): if event.is_action_pressed("ui_left"): tabs.current_tab = posmod(tabs.current_tab - 1, tabs.get_child_count()) @@ -18,10 +68,35 @@ func _gui_input(event): current_tab.get_node(current_tab.focus_neighbour_bottom).grab_focus() accept_event() +func _physics_process(delta): + if Input.is_action_just_pressed("ui_accept"): + apply_options() + elif Input.is_action_just_pressed("ui_cancel"): + if dirty: + confirm_dialog.visible = true + confirm_dialog.grab_focus() + else: + emit_signal("exit") + elif Input.is_action_just_pressed("ui_reset"): + load_options(Options.defaults) + dirty = true + +# "_unused" is a dirty hack, +# but it means we can connect signals that provide parameters +func _mark_dirty(_unused = null, _unused2 = null): + dirty = true + +func _on_ConfirmDialog_gui_input(event): + if event.is_action_pressed("ui_accept"): + apply_options() + confirm_dialog.visible = false + emit_signal("exit") + elif event.is_action_pressed("ui_cancel"): + confirm_dialog.visible = false + emit_signal("exit") func _on_tabs_focus_entered(): tabs.set("custom_styles/tab_fg", tab_selected_style) - func _on_tabs_focus_exited(): tabs.set("custom_styles/tab_fg", null) diff --git a/objects/hud/options_screen.tscn b/objects/hud/options_screen.tscn index e2f874f..18082f1 100644 --- a/objects/hud/options_screen.tscn +++ b/objects/hud/options_screen.tscn @@ -1,8 +1,7 @@ -[gd_scene load_steps=11 format=2] +[gd_scene load_steps=10 format=2] [ext_resource path="res://objects/hud/options_screen.gd" type="Script" id=1] [ext_resource path="res://ui/theme.tres" type="Theme" id=2] -[ext_resource path="res://ui/border.png" type="Texture" id=3] [ext_resource path="res://objects/hud/selection_group.gd" type="Script" id=4] [sub_resource type="StyleBoxFlat" id=6] @@ -31,24 +30,11 @@ theme = ExtResource( 2 ) script = ExtResource( 1 ) tab_selected_style = SubResource( 6 ) -[node name="Border" type="NinePatchRect" parent="."] -show_behind_parent = true +[node name="Panel" type="Panel" parent="."] margin_left = 8.0 -margin_top = 17.0 +margin_top = 16.0 margin_right = 248.0 -margin_bottom = 175.0 -texture = ExtResource( 3 ) -patch_margin_left = 3 -patch_margin_top = 3 -patch_margin_right = 3 -patch_margin_bottom = 3 - -[node name="ColorRect" type="ColorRect" parent="."] -margin_left = 11.0 -margin_top = 20.0 -margin_right = 245.0 -margin_bottom = 172.0 -color = Color( 0.239216, 0.239216, 0.443137, 1 ) +margin_bottom = 176.0 [node name="OptionsTitle" type="Label" parent="."] margin_left = 16.0 @@ -67,6 +53,7 @@ margin_bottom = 152.0 theme = ExtResource( 2 ) [node name="Game" type="VBoxContainer" parent="Tabs"] +visible = false anchor_right = 1.0 anchor_bottom = 1.0 margin_top = 7.0 @@ -79,6 +66,7 @@ margin_bottom = 8.0 rect_min_size = Vector2( 0, 8 ) [node name="Rumble" type="HBoxContainer" parent="Tabs/Game"] +unique_name_in_owner = true margin_top = 8.0 margin_right = 224.0 margin_bottom = 28.0 @@ -134,7 +122,6 @@ text = "BPM" align = 0 [node name="Video" type="VBoxContainer" parent="Tabs"] -visible = false anchor_right = 1.0 anchor_bottom = 1.0 margin_top = 7.0 @@ -147,6 +134,7 @@ margin_bottom = 8.0 rect_min_size = Vector2( 0, 8 ) [node name="Fullscreen" type="HBoxContainer" parent="Tabs/Video"] +unique_name_in_owner = true margin_top = 8.0 margin_right = 224.0 margin_bottom = 28.0 @@ -172,6 +160,7 @@ focus_neighbour_right = NodePath("../On") size_flags_horizontal = 6 size_flags_vertical = 0 toggle_mode = true +pressed = true action_mode = 0 group = SubResource( 7 ) text = "Off" @@ -185,12 +174,12 @@ focus_neighbour_right = NodePath(".") size_flags_horizontal = 6 size_flags_vertical = 0 toggle_mode = true -pressed = true action_mode = 0 group = SubResource( 7 ) text = "on" [node name="WindowSize" type="HBoxContainer" parent="Tabs/Video"] +unique_name_in_owner = true margin_top = 28.0 margin_right = 224.0 margin_bottom = 48.0 @@ -267,6 +256,7 @@ group = SubResource( 3 ) text = "5x" [node name="ScalingMode" type="HBoxContainer" parent="Tabs/Video"] +unique_name_in_owner = true margin_top = 48.0 margin_right = 224.0 margin_bottom = 68.0 @@ -321,6 +311,7 @@ text = "stretch" align = 0 [node name="TransitionSpeed" type="HBoxContainer" parent="Tabs/Video"] +unique_name_in_owner = true margin_top = 68.0 margin_right = 224.0 margin_bottom = 88.0 @@ -410,6 +401,7 @@ size_flags_vertical = 1 text = "Master vol.:" [node name="MasterSlider" type="HSlider" parent="Tabs/Audio/MasterVolume"] +unique_name_in_owner = true margin_left = 99.0 margin_right = 199.0 margin_bottom = 10.0 @@ -417,7 +409,10 @@ rect_min_size = Vector2( 100, 0 ) focus_neighbour_top = NodePath("../../../..") focus_neighbour_bottom = NodePath("../../MusicVolume/MusicSlider") size_flags_horizontal = 3 -value = 100.0 +max_value = 1.0 +step = 0.05 +value = 1.0 +scrollable = false __meta__ = { "_edit_group_": true } @@ -444,6 +439,7 @@ size_flags_vertical = 1 text = "music vol.:" [node name="MusicSlider" type="HSlider" parent="Tabs/Audio/MusicVolume"] +unique_name_in_owner = true margin_left = 99.0 margin_right = 199.0 margin_bottom = 10.0 @@ -451,7 +447,10 @@ rect_min_size = Vector2( 100, 0 ) focus_neighbour_top = NodePath("../../MasterVolume/MasterSlider") focus_neighbour_bottom = NodePath("../../SoundVolume/SoundSlider") size_flags_horizontal = 3 -value = 100.0 +max_value = 1.0 +step = 0.05 +value = 1.0 +scrollable = false __meta__ = { "_edit_group_": true } @@ -478,13 +477,17 @@ size_flags_vertical = 1 text = "SOund vol.:" [node name="SoundSlider" type="HSlider" parent="Tabs/Audio/SoundVolume"] +unique_name_in_owner = true margin_left = 99.0 margin_right = 199.0 margin_bottom = 10.0 rect_min_size = Vector2( 100, 0 ) focus_neighbour_top = NodePath("../../MusicVolume/MusicSlider") size_flags_horizontal = 3 -value = 100.0 +max_value = 1.0 +step = 0.05 +value = 1.0 +scrollable = false __meta__ = { "_edit_group_": true } @@ -509,6 +512,40 @@ margin_right = 224.0 margin_bottom = 7.0 text = "Z: back, X: apply, C: defaults" +[node name="ConfirmDialog" type="PanelContainer" parent="."] +visible = false +margin_left = 48.0 +margin_top = 40.0 +margin_right = 208.0 +margin_bottom = 88.0 +focus_mode = 2 + +[node name="Label" type="Label" parent="ConfirmDialog"] +margin_left = 3.0 +margin_top = 3.0 +margin_right = 157.0 +margin_bottom = 45.0 +size_flags_vertical = 5 +text = "Apply Changes?" +align = 1 + +[node name="Label2" type="Label" parent="ConfirmDialog"] +margin_left = 3.0 +margin_top = 20.0 +margin_right = 157.0 +margin_bottom = 27.0 +text = "X: apply, Z: discard" +align = 1 + [connection signal="focus_entered" from="." to="." method="_on_tabs_focus_entered"] [connection signal="focus_exited" from="." to="." method="_on_tabs_focus_exited"] [connection signal="gui_input" from="OptionsTitle" to="." method="_on_Tabs_gui_input"] +[connection signal="selection_changed" from="Tabs/Game/Rumble" to="." method="_mark_dirty"] +[connection signal="selection_changed" from="Tabs/Video/Fullscreen" to="." method="_mark_dirty"] +[connection signal="selection_changed" from="Tabs/Video/WindowSize" to="." method="_mark_dirty"] +[connection signal="selection_changed" from="Tabs/Video/ScalingMode" to="." method="_mark_dirty"] +[connection signal="selection_changed" from="Tabs/Video/TransitionSpeed" to="." method="_mark_dirty"] +[connection signal="value_changed" from="Tabs/Audio/MasterVolume/MasterSlider" to="." method="_mark_dirty"] +[connection signal="value_changed" from="Tabs/Audio/MusicVolume/MusicSlider" to="." method="_mark_dirty"] +[connection signal="value_changed" from="Tabs/Audio/SoundVolume/SoundSlider" to="." method="_mark_dirty"] +[connection signal="gui_input" from="ConfirmDialog" to="." method="_on_ConfirmDialog_gui_input"] diff --git a/objects/hud/pause_screen.gd b/objects/hud/pause_screen.gd index f2e6614..79cbc54 100644 --- a/objects/hud/pause_screen.gd +++ b/objects/hud/pause_screen.gd @@ -34,3 +34,8 @@ func _on_ExitLevel_pressed(): get_tree().paused = false Game.change_map(load("res://maps/level_select.tscn")) queue_free() + + +func _on_OptionsScreen_exit(): + options_screen.visible = false + $Body/Settings.grab_focus() diff --git a/objects/hud/pause_screen.tscn b/objects/hud/pause_screen.tscn index 729388a..21da41e 100644 --- a/objects/hud/pause_screen.tscn +++ b/objects/hud/pause_screen.tscn @@ -101,3 +101,4 @@ visible = false [connection signal="pressed" from="Body/Restart" to="." method="_on_Restart_pressed"] [connection signal="pressed" from="Body/Settings" to="." method="_on_Settings_pressed"] [connection signal="pressed" from="Body/ExitLevel" to="." method="_on_ExitLevel_pressed"] +[connection signal="exit" from="OptionsScreen" to="." method="_on_OptionsScreen_exit" flags=3] diff --git a/objects/hud/selection_group.gd b/objects/hud/selection_group.gd index 08cb3c6..4cd4f72 100644 --- a/objects/hud/selection_group.gd +++ b/objects/hud/selection_group.gd @@ -1,15 +1,33 @@ extends HBoxContainer +signal selection_changed(selection) + export (ButtonGroup) var group +var _selection = 0 + func _ready(): focus_mode = FOCUS_ALL + connect("focus_entered", self, "_focused") for child in get_children(): if child is BaseButton: child.focus_neighbour_top = "../%s" % focus_neighbour_top child.focus_neighbour_bottom = "../%s" % focus_neighbour_bottom child.connect("focus_entered", child, "set_pressed", [true]) - connect("focus_entered", self, "_focused") + child.connect("focus_entered", self, "_button_selected", [], CONNECT_DEFERRED) func _focused(): + _selection = get_selection() group.get_pressed_button().grab_focus() + +func _button_selected(): + var new_selection = get_selection() + if _selection != new_selection: + _selection = new_selection + emit_signal("selection_changed", _selection) + +func get_selection(): + return group.get_buttons().find(group.get_pressed_button()) + +func select(selection): + group.get_buttons()[selection].pressed = true diff --git a/project.godot b/project.godot index fd892b6..4b810b6 100644 --- a/project.godot +++ b/project.godot @@ -33,6 +33,7 @@ Audio="*res://autoloads/audio.tscn" LevelData="*res://autoloads/level_data.tscn" Save="*res://autoloads/save.gd" Debug="*res://autoloads/debug.tscn" +Options="*res://autoloads/options.gd" [display] @@ -106,6 +107,19 @@ ui_cancel={ , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":2,"pressure":0.0,"pressed":false,"script":null) ] } +ui_reset={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":67,"unicode":0,"echo":false,"script":null) + ] +} +ui_focus_next={ +"deadzone": 0.5, +"events": [ ] +} +ui_focus_prev={ +"deadzone": 0.5, +"events": [ ] +} ui_up={ "deadzone": 0.5, "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"physical_scancode":0,"unicode":0,"echo":false,"script":null) @@ -121,6 +135,22 @@ ui_down={ , Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":7,"axis_value":1.0,"script":null) ] } +ui_page_up={ +"deadzone": 0.5, +"events": [ ] +} +ui_page_down={ +"deadzone": 0.5, +"events": [ ] +} +ui_home={ +"deadzone": 0.5, +"events": [ ] +} +ui_end={ +"deadzone": 0.5, +"events": [ ] +} jump={ "deadzone": 0.5, "events": [ Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":false,"script":null) diff --git a/ui/panel.png b/ui/panel.png new file mode 100644 index 0000000..af53798 Binary files /dev/null and b/ui/panel.png differ diff --git a/ui/panel.png.import b/ui/panel.png.import new file mode 100644 index 0000000..2818487 --- /dev/null +++ b/ui/panel.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/panel.png-4debde5d1941508c13098c29f52f1bf0.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://ui/panel.png" +dest_files=[ "res://.import/panel.png-4debde5d1941508c13098c29f52f1bf0.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/ui/theme.tres b/ui/theme.tres index 03d019d..cf81e2f 100644 --- a/ui/theme.tres +++ b/ui/theme.tres @@ -1,9 +1,10 @@ -[gd_resource type="Theme" load_steps=13 format=2] +[gd_resource type="Theme" load_steps=15 format=2] [ext_resource path="res://ui/2ndpuberty..fnt" type="BitmapFont" id=1] [ext_resource path="res://graphics/hud/hslider_slider.png" type="Texture" id=2] [ext_resource path="res://graphics/hud/hslider_grabber.png" type="Texture" id=3] [ext_resource path="res://graphics/hud/hslider_grabber_focused.png" type="Texture" id=4] +[ext_resource path="res://ui/panel.png" type="Texture" id=5] [sub_resource type="StyleBoxEmpty" id=3] @@ -24,6 +25,14 @@ expand_margin_bottom = 6.0 texture = ExtResource( 2 ) region_rect = Rect2( 0, 0, 1, 8 ) +[sub_resource type="StyleBoxTexture" id=11] +texture = ExtResource( 5 ) +region_rect = Rect2( 0, 0, 9, 9 ) +margin_left = 3.0 +margin_right = 3.0 +margin_top = 3.0 +margin_bottom = 3.0 + [sub_resource type="StyleBoxEmpty" id=1] [sub_resource type="StyleBoxEmpty" id=2] @@ -43,6 +52,8 @@ HSlider/icons/grabber_highlight = ExtResource( 4 ) HSlider/styles/grabber_area = SubResource( 4 ) HSlider/styles/grabber_area_highlight = SubResource( 10 ) HSlider/styles/slider = SubResource( 6 ) +Panel/styles/panel = SubResource( 11 ) +PanelContainer/styles/panel = SubResource( 11 ) TabContainer/colors/font_color_fg = Color( 1, 1, 1, 1 ) TabContainer/styles/panel = SubResource( 1 ) TabContainer/styles/tab_bg = SubResource( 2 )