generated from krampus/template-godot4
Ported settings menu from GFOLF
All checks were successful
linting & formatting / build (push) Successful in 12s
itch.io publish action / build (linux64, x86_64) (push) Successful in 2m35s
itch.io publish action / build (osx, app) (push) Successful in 2m37s
itch.io publish action / build (win64, exe) (push) Successful in 2m40s
All checks were successful
linting & formatting / build (push) Successful in 12s
itch.io publish action / build (linux64, x86_64) (push) Successful in 2m35s
itch.io publish action / build (osx, app) (push) Successful in 2m37s
itch.io publish action / build (win64, exe) (push) Successful in 2m40s
This commit is contained in:
parent
cdd89ea30f
commit
e2ca0cb1a2
58
assets/text/text.csv
Normal file
58
assets/text/text.csv
Normal file
@ -0,0 +1,58 @@
|
||||
keys,en
|
||||
UI_UNSET,unset
|
||||
UI_LISTEN,listening...
|
||||
UI_CANCEL,Cancel
|
||||
UI_ACCEPT,Accept
|
||||
UI_START,Start
|
||||
UI_ON,On
|
||||
UI_OFF,Off
|
||||
UI_BACK,"⏎ Back"
|
||||
UI_LOCKED,Locked
|
||||
UI_QUIT,Quit
|
||||
,
|
||||
PAUSE_HEADING,Paused
|
||||
PAUSE_RESUME,Resume
|
||||
PAUSE_SETTINGS,Settings
|
||||
PAUSE_END,"Quit to Title"
|
||||
PAUSE_END_MSG,"End the game and return to the title screen?\nUnsaved progress will be lost."
|
||||
PAUSE_QUIT,"Quit to Desktop"
|
||||
PAUSE_QUIT_MSG,"Quit to desktop?\nUnsaved progress will be lost."
|
||||
,
|
||||
SETTINGS_GAME,Game
|
||||
SETTINGS_GAME_HEADING,"Game Configuration"
|
||||
SETTINGS_GAME_ACCESSIBILITY_HEADING,Accessibility
|
||||
SETTINGS_GAME_CAMERA_HEADING,Camera
|
||||
SETTINGS_SCREEN_SHAKE,"Enable Screen Shake"
|
||||
SETTINGS_HEAD_BOB,"Enable Head Bob"
|
||||
SETTINGS_SENSITIVITY_X,"Sensitivity, Horizontal"
|
||||
SETTINGS_SENSITIVITY_Y,"Sensitivity, Vertical"
|
||||
SETTINGS_MOUSE_ACCELERATION,"Mouse Acceleration"
|
||||
SETTINGS_INVERT_PITCH,"Invert Pitch"
|
||||
SETTINGS_GRAPHICS,Graphics
|
||||
SETTINGS_GRAPHICS_HEADING,"Graphics & Display"
|
||||
SETTINGS_GRAPHICS_DISPLAY_HEADING,Display
|
||||
SETTINGS_GRAPHICS_FULLSCREEN,Fullscreen
|
||||
SETTINGS_GRAPHICS_VSYNC,V-Sync
|
||||
SETTINGS_AUDIO,Audio
|
||||
SETTINGS_AUDIO_HEADING,"Audio Settings"
|
||||
SETTINGS_CONTROLS,Controls
|
||||
SETTINGS_CONTROLS_HEADING,"Control Bindings"
|
||||
,
|
||||
ACTION_move_forward,"Move forward"
|
||||
ACTION_move_left,"Move left"
|
||||
ACTION_move_back,"Move back"
|
||||
ACTION_move_right,"Move right"
|
||||
ACTION_jump,Jump
|
||||
ACTION_sneak,Sneak
|
||||
ACTION_sprint,Sprint
|
||||
ACTION_fire,"Fire equipped tool"
|
||||
ACTION_interact,Interact
|
||||
ACTION_switch_mode,"Tool mode switch"
|
||||
ACTION_select_next_tool,"Select next tool"
|
||||
ACTION_select_prev_tool,"Select previous tool"
|
||||
ACTION_select_point_spray,"Select spot spray"
|
||||
ACTION_select_wide_spray,"Select wide spray"
|
||||
ACTION_select_brush,"Select toothbrush"
|
||||
ACTION_select_mp3_player,"Select MP3 player"
|
||||
ACTION_select_manual,"Select manual"
|
||||
ACTION_pause,Pause
|
|
17
assets/text/text.csv.import
Normal file
17
assets/text/text.csv.import
Normal file
@ -0,0 +1,17 @@
|
||||
[remap]
|
||||
|
||||
importer="csv_translation"
|
||||
type="Translation"
|
||||
uid="uid://o71c6t5pv7hy"
|
||||
|
||||
[deps]
|
||||
|
||||
files=["res://assets/text/text.en.translation"]
|
||||
|
||||
source_file="res://assets/text/text.csv"
|
||||
dest_files=["res://assets/text/text.en.translation"]
|
||||
|
||||
[params]
|
||||
|
||||
compress=true
|
||||
delimiter=0
|
@ -17,12 +17,15 @@ warnings/threads/thread_model=2
|
||||
|
||||
config/name="Grunk"
|
||||
run/main_scene="uid://884jqafhtrv0"
|
||||
config/project_settings_override="user://settings.godot"
|
||||
config/features=PackedStringArray("4.4", "Forward Plus")
|
||||
run/max_fps=60
|
||||
|
||||
[autoload]
|
||||
|
||||
GameRuntime="*res://src/game/game_runtime.gd"
|
||||
ItemCatalog="*res://src/items/item_catalog.tscn"
|
||||
GameSettings="*res://src/game/game_settings.gd"
|
||||
GameManager="*res://src/game/game_manager.tscn"
|
||||
|
||||
[debug]
|
||||
@ -65,6 +68,9 @@ config/input/mouse_sensitivity_x=0.45
|
||||
config/input/mouse_sensitivity_y=0.45
|
||||
config/input/invert_pitch=false
|
||||
config/input/mouse_acceleration=30.0
|
||||
audio/buses/override_bus_layout="user://audio_bus_layout.tres"
|
||||
config/accessibility/enable_screen_shake=true
|
||||
config/accessibility/enable_head_bob=true
|
||||
|
||||
[input]
|
||||
|
||||
@ -118,6 +124,16 @@ switch_mode={
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
select_next_tool={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":4,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
select_prev_tool={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":5,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
select_point_spray={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":49,"key_label":0,"unicode":49,"location":0,"echo":false,"script":null)
|
||||
@ -133,14 +149,14 @@ select_brush={
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":51,"key_label":0,"unicode":51,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
select_next_tool={
|
||||
select_mp3_player={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":4,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":52,"key_label":0,"unicode":52,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
select_prev_tool={
|
||||
select_manual={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":5,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":53,"key_label":0,"unicode":53,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
pause={
|
||||
@ -149,6 +165,10 @@ pause={
|
||||
]
|
||||
}
|
||||
|
||||
[internationalization]
|
||||
|
||||
locale/translations=PackedStringArray("res://assets/text/text.en.translation")
|
||||
|
||||
[layer_names]
|
||||
|
||||
3d_render/layer_1="World"
|
||||
|
@ -5,6 +5,12 @@ class_name Game extends Node
|
||||
static var manager: GameManagerType:
|
||||
get():
|
||||
return GameManager
|
||||
static var settings: GameSettingsType:
|
||||
get():
|
||||
return GameSettings
|
||||
static var runtime: GameRuntimeType:
|
||||
get():
|
||||
return GameRuntime
|
||||
|
||||
## Global static access to Game singleton
|
||||
static var instance: Game
|
||||
|
9
src/game/game_runtime.gd
Normal file
9
src/game/game_runtime.gd
Normal file
@ -0,0 +1,9 @@
|
||||
class_name GameRuntimeType extends Node
|
||||
## Autoloaded runtime manager
|
||||
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_WM_CLOSE_REQUEST:
|
||||
# Handle close request here
|
||||
# TODO: save?
|
||||
get_tree().quit()
|
1
src/game/game_runtime.gd.uid
Normal file
1
src/game/game_runtime.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dcg434tx4r288
|
53
src/game/game_settings.gd
Normal file
53
src/game/game_settings.gd
Normal file
@ -0,0 +1,53 @@
|
||||
class_name GameSettingsType extends Node
|
||||
## Autoloaded container for project settings, for quick runtime access.
|
||||
|
||||
var version: String
|
||||
|
||||
var settings_file: String
|
||||
var audio_bus_file: String
|
||||
|
||||
var mouse_sensitivity_x: float
|
||||
var mouse_sensitivity_y: float
|
||||
var mouse_acceleration: float
|
||||
var invert_pitch: bool
|
||||
|
||||
var enable_screen_shake: bool
|
||||
var enable_head_bob: bool
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
ProjectSettings.settings_changed.connect(_read_settings)
|
||||
_read_settings()
|
||||
_load_audio_bus_override()
|
||||
|
||||
|
||||
func _read_settings() -> void:
|
||||
version = ProjectSettings.get_setting("application/config/version")
|
||||
|
||||
settings_file = ProjectSettings.get_setting("application/config/project_settings_override")
|
||||
audio_bus_file = ProjectSettings.get_setting("game/audio/buses/override_bus_layout")
|
||||
|
||||
mouse_sensitivity_x = ProjectSettings.get_setting("game/config/input/mouse_sensitivity_x")
|
||||
mouse_sensitivity_y = ProjectSettings.get_setting("game/config/input/mouse_sensitivity_y")
|
||||
mouse_acceleration = ProjectSettings.get_setting("game/config/input/mouse_acceleration")
|
||||
invert_pitch = ProjectSettings.get_setting("game/config/input/invert_pitch")
|
||||
|
||||
enable_screen_shake = ProjectSettings.get_setting(
|
||||
"game/config/accessibility/enable_screen_shake"
|
||||
)
|
||||
enable_head_bob = ProjectSettings.get_setting("game/config/accessibility/enable_head_bob")
|
||||
|
||||
|
||||
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)
|
1
src/game/game_settings.gd.uid
Normal file
1
src/game/game_settings.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://bo00uxdf81beu
|
19
src/ui/elements/checker_container.gd
Normal file
19
src/ui/elements/checker_container.gd
Normal file
@ -0,0 +1,19 @@
|
||||
@tool
|
||||
class_name CheckerContainer extends PanelContainer
|
||||
## PanelContainer that sets its theme based on its parent parity
|
||||
|
||||
@export var even_variation := "CheckerContainerEven"
|
||||
@export var odd_variation := "CheckerContainerOdd"
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
get_parent().child_order_changed.connect(_recompute)
|
||||
|
||||
|
||||
func _is_even_child() -> bool:
|
||||
var parent := get_parent()
|
||||
return parent.get_children().find(self) % 2 == 0 if parent else false
|
||||
|
||||
|
||||
func _recompute() -> void:
|
||||
theme_type_variation = even_variation if _is_even_child() else odd_variation
|
1
src/ui/elements/checker_container.gd.uid
Normal file
1
src/ui/elements/checker_container.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://csuuvuagv6lpf
|
63
src/ui/elements/input_prompt/input_prompt.gd
Normal file
63
src/ui/elements/input_prompt/input_prompt.gd
Normal file
@ -0,0 +1,63 @@
|
||||
@tool
|
||||
extends Label
|
||||
## A prompt with the input symbol bound to the given action.
|
||||
|
||||
const PROMPT_FORMAT := "{0} - {1}"
|
||||
const HOLD_FORMAT := "{0} {1}"
|
||||
|
||||
const UNKNOWN_LABEL_SYM := "[unknown]"
|
||||
|
||||
const ACTION_HOLD_KEY := "ACTION_HOLD_MODIFIER"
|
||||
|
||||
@export var action: StringName:
|
||||
set(value):
|
||||
action = value
|
||||
_update()
|
||||
|
||||
@export var hold := false:
|
||||
set(value):
|
||||
hold = value
|
||||
_update()
|
||||
|
||||
@export var show_name := true:
|
||||
set(value):
|
||||
show_name = value
|
||||
_update()
|
||||
|
||||
@export var event_index := 0:
|
||||
set(value):
|
||||
event_index = value
|
||||
_update()
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_update()
|
||||
|
||||
|
||||
func _update() -> void:
|
||||
var input_symbol: String
|
||||
var actions := InputMap.action_get_events(action)
|
||||
if actions and event_index < len(actions):
|
||||
var primary := actions[event_index]
|
||||
input_symbol = PromptMap.from_event(primary)
|
||||
|
||||
var loc_action := tr(ControlBinding.ACTION_KEY_FMT.format([action]))
|
||||
|
||||
if not input_symbol:
|
||||
input_symbol = str(PromptMap.UNKNOWN_INPUT_SYMBOL)
|
||||
|
||||
if hold:
|
||||
input_symbol = HOLD_FORMAT.format([input_symbol, tr(ACTION_HOLD_KEY)])
|
||||
|
||||
if show_name:
|
||||
text = (
|
||||
PROMPT_FORMAT
|
||||
. format(
|
||||
[
|
||||
input_symbol,
|
||||
loc_action if loc_action else str(action),
|
||||
]
|
||||
)
|
||||
)
|
||||
else:
|
||||
text = input_symbol
|
1
src/ui/elements/input_prompt/input_prompt.gd.uid
Normal file
1
src/ui/elements/input_prompt/input_prompt.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dn50ip335p7oh
|
14
src/ui/elements/input_prompt/input_prompt.tscn
Normal file
14
src/ui/elements/input_prompt/input_prompt.tscn
Normal file
@ -0,0 +1,14 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://b47goj32i6sdh"]
|
||||
|
||||
[ext_resource type="Script" path="res://src/ui/elements/input_prompt/input_prompt.gd" id="1_qq6w5"]
|
||||
|
||||
[node name="InputPrompt" type="Label"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_type_variation = &"InputPrompt"
|
||||
text = "❓ - ACTION_"
|
||||
script = ExtResource("1_qq6w5")
|
||||
hold = null
|
97
src/ui/elements/numeric_slider/numeric_slider.gd
Normal file
97
src/ui/elements/numeric_slider/numeric_slider.gd
Normal file
@ -0,0 +1,97 @@
|
||||
@tool
|
||||
class_name NumericSlider extends HBoxContainer
|
||||
## HSlider with an attached SpinBox
|
||||
|
||||
signal value_changed(value: float)
|
||||
|
||||
@export_category("Shared Range Properties")
|
||||
|
||||
@export var min_value := 0.0:
|
||||
set(v):
|
||||
_set_shared("min_value", v)
|
||||
min_value = v
|
||||
|
||||
@export var max_value := 100.0:
|
||||
set(v):
|
||||
_set_shared("max_value", v)
|
||||
max_value = v
|
||||
|
||||
@export var step := 1.0:
|
||||
set(v):
|
||||
_set_shared("step", v)
|
||||
step = v
|
||||
|
||||
@export var page := 0:
|
||||
set(v):
|
||||
_set_shared("page", v)
|
||||
page = v
|
||||
|
||||
@export var value: float:
|
||||
get:
|
||||
return _value
|
||||
set(v):
|
||||
_value = v
|
||||
value_changed.emit(v)
|
||||
|
||||
@export var exp_edit := false:
|
||||
set(v):
|
||||
_set_shared("exp_edit", v)
|
||||
exp_edit = v
|
||||
|
||||
@export var rounded := false:
|
||||
set(v):
|
||||
_set_shared("rounded", v)
|
||||
rounded = v
|
||||
|
||||
@export var allow_greater := false:
|
||||
set(v):
|
||||
_set_shared("allow_greater", v)
|
||||
allow_greater = v
|
||||
|
||||
@export var allow_lesser := false:
|
||||
set(v):
|
||||
_set_shared("allow_lesser", v)
|
||||
allow_lesser = v
|
||||
|
||||
var _value := 0.0:
|
||||
set(v):
|
||||
if slider:
|
||||
slider.set_value_no_signal(v)
|
||||
if spin_box:
|
||||
spin_box.set_value_no_signal(v)
|
||||
_value = v
|
||||
|
||||
@onready var slider: HSlider = $HSlider
|
||||
@onready var spin_box: SpinBox = $SpinBox
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
# Force propagation of properties to shared range elements
|
||||
min_value = min_value
|
||||
max_value = max_value
|
||||
step = step
|
||||
page = page
|
||||
_value = _value
|
||||
exp_edit = exp_edit
|
||||
rounded = rounded
|
||||
allow_greater = allow_greater
|
||||
allow_lesser = allow_lesser
|
||||
|
||||
|
||||
func set_value_no_signal(new_value: float) -> void:
|
||||
_value = new_value
|
||||
|
||||
|
||||
func _set_shared(property: String, new_value: Variant) -> void:
|
||||
if slider:
|
||||
slider.set(property, new_value)
|
||||
if spin_box:
|
||||
spin_box.set(property, new_value)
|
||||
|
||||
|
||||
func _on_spin_box_value_changed(new_value: float) -> void:
|
||||
value = new_value
|
||||
|
||||
|
||||
func _on_slider_value_changed(new_value: float) -> void:
|
||||
value = new_value
|
1
src/ui/elements/numeric_slider/numeric_slider.gd.uid
Normal file
1
src/ui/elements/numeric_slider/numeric_slider.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://ei2iyprpp4rt
|
27
src/ui/elements/numeric_slider/numeric_slider.tscn
Normal file
27
src/ui/elements/numeric_slider/numeric_slider.tscn
Normal file
@ -0,0 +1,27 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://dqqcyi26d3bpg"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ei2iyprpp4rt" path="res://src/ui/elements/numeric_slider/numeric_slider.gd" id="1_kcr4o"]
|
||||
|
||||
[node name="NumericSlider" type="HBoxContainer"]
|
||||
anchors_preset = 14
|
||||
anchor_top = 0.5
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 0.5
|
||||
offset_top = -8.0
|
||||
offset_bottom = 10.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_kcr4o")
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 4
|
||||
|
||||
[node name="SpinBox" type="SpinBox" parent="."]
|
||||
custom_minimum_size = Vector2(120, 0)
|
||||
layout_mode = 2
|
||||
alignment = 2
|
||||
|
||||
[connection signal="value_changed" from="HSlider" to="." method="_on_slider_value_changed"]
|
||||
[connection signal="value_changed" from="SpinBox" to="." method="_on_spin_box_value_changed"]
|
29
src/ui/elements/text_checkbox/text_checkbox.gd
Normal file
29
src/ui/elements/text_checkbox/text_checkbox.gd
Normal file
@ -0,0 +1,29 @@
|
||||
@tool
|
||||
extends CheckBox
|
||||
## Checkbox which updates its label based on check state.
|
||||
|
||||
@export var true_text := "UI_ON":
|
||||
set(value):
|
||||
true_text = value
|
||||
_refresh()
|
||||
|
||||
@export var false_text := "UI_OFF":
|
||||
set(value):
|
||||
false_text = value
|
||||
_refresh()
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_refresh()
|
||||
|
||||
|
||||
func _set_text(value: bool) -> void:
|
||||
text = true_text if value else false_text
|
||||
|
||||
|
||||
func _refresh() -> void:
|
||||
_set_text(button_pressed)
|
||||
|
||||
|
||||
func _on_toggled(toggled_on: bool) -> void:
|
||||
_set_text(toggled_on)
|
1
src/ui/elements/text_checkbox/text_checkbox.gd.uid
Normal file
1
src/ui/elements/text_checkbox/text_checkbox.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://da0um27cm4eiv
|
10
src/ui/elements/text_checkbox/text_checkbox.tscn
Normal file
10
src/ui/elements/text_checkbox/text_checkbox.tscn
Normal file
@ -0,0 +1,10 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://b7ce38k7rx466"]
|
||||
|
||||
[ext_resource type="Script" path="res://src/ui/elements/text_checkbox/text_checkbox.gd" id="1_6mma0"]
|
||||
|
||||
[node name="TextCheckbox" type="CheckBox"]
|
||||
size_flags_horizontal = 0
|
||||
text = "UI_OFF"
|
||||
script = ExtResource("1_6mma0")
|
||||
|
||||
[connection signal="toggled" from="." to="." method="_on_toggled"]
|
Binary file not shown.
@ -5,14 +5,13 @@ extends Control
|
||||
|
||||
var _freeze_input := false
|
||||
|
||||
@onready var menu_list: VBoxContainer = %MenuList
|
||||
@onready var quit_confirm: CenterContainer = %QuitConfirm
|
||||
@onready var end_game_confirm: CenterContainer = %EndGameConfirm
|
||||
@onready var settings_container: MarginContainer = %SettingsContainer
|
||||
@onready var menu_list: Control = %MenuList
|
||||
@onready var quit_confirm: Control = %QuitConfirm
|
||||
@onready var end_game_confirm: Control = %EndGameConfirm
|
||||
@onready var settings_container: Container = %SettingsContainer
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
print_debug("PAUSING")
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
||||
Engine.time_scale = 1.0
|
||||
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
[ext_resource type="Theme" uid="uid://doq7ay6f7dgfo" path="res://src/ui/menus/menu.theme" id="1_b4t8b"]
|
||||
[ext_resource type="Script" uid="uid://cllx5glqld8wn" path="res://src/ui/menus/pause_menu/pause_menu.gd" id="1_rd0j2"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_6sp1a"]
|
||||
metadata/__load_path__ = "res://src/ui/menus/settings_menu/settings_menu.tscn"
|
||||
[ext_resource type="PackedScene" uid="uid://d3eaqw2rdurct" path="res://src/ui/menus/settings_menu/settings_menu.tscn" id="3_dowgp"]
|
||||
|
||||
[node name="PauseMenu" type="Control"]
|
||||
process_mode = 3
|
||||
@ -16,7 +14,7 @@ grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme = ExtResource("1_b4t8b")
|
||||
script = ExtResource("1_rd0j2")
|
||||
settings_scene = SubResource("Resource_6sp1a")
|
||||
settings_scene = ExtResource("3_dowgp")
|
||||
|
||||
[node name="Shade" type="ColorRect" parent="."]
|
||||
layout_mode = 1
|
||||
@ -57,7 +55,7 @@ layout_mode = 2
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/outline_size = 8
|
||||
text = "paused"
|
||||
text = "PAUSE_HEADING"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="MenuList"]
|
||||
@ -71,34 +69,35 @@ alignment = 1
|
||||
|
||||
[node name="ResumeButton" type="Button" parent="MenuList/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Resume"
|
||||
text = "PAUSE_RESUME"
|
||||
|
||||
[node name="SettingsButton" type="Button" parent="MenuList/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Settings"
|
||||
text = "PAUSE_SETTINGS"
|
||||
|
||||
[node name="EndGameButton" type="Button" parent="MenuList/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DangerButton"
|
||||
text = "Quit to Title"
|
||||
text = "PAUSE_END"
|
||||
|
||||
[node name="QuitButton" type="Button" parent="MenuList/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DangerButton"
|
||||
text = "Quit to Desktop"
|
||||
text = "PAUSE_QUIT"
|
||||
|
||||
[node name="SettingsContainer" type="MarginContainer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(1000, 600)
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -640.0
|
||||
offset_top = -360.0
|
||||
offset_right = 640.0
|
||||
offset_bottom = 360.0
|
||||
offset_left = -400.0
|
||||
offset_top = -300.0
|
||||
offset_right = 430.0
|
||||
offset_bottom = 300.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
@ -130,8 +129,7 @@ theme_override_constants/separation = 16
|
||||
[node name="Label" type="Label" parent="QuitConfirm/PanelContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 24
|
||||
text = "End the game and return to the title screen?
|
||||
Unsaved progress will be lost."
|
||||
text = "PAUSE_QUIT_MSG"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="QuitConfirm/PanelContainer/MarginContainer/VBoxContainer"]
|
||||
@ -141,13 +139,13 @@ theme_override_constants/separation = 16
|
||||
[node name="CancelButton" type="Button" parent="QuitConfirm/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Cancel"
|
||||
text = "UI_CANCEL"
|
||||
|
||||
[node name="ConfirmQuitButton" type="Button" parent="QuitConfirm/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_type_variation = &"DangerButton"
|
||||
text = "Quit"
|
||||
text = "UI_QUIT"
|
||||
|
||||
[node name="EndGameConfirm" type="CenterContainer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
@ -176,8 +174,7 @@ theme_override_constants/separation = 16
|
||||
[node name="Label" type="Label" parent="EndGameConfirm/PanelContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 24
|
||||
text = "End the game and return to the desktop?
|
||||
Unsaved progress will be lost."
|
||||
text = "PAUSE_END_MSG"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="EndGameConfirm/PanelContainer/MarginContainer/VBoxContainer"]
|
||||
@ -187,13 +184,13 @@ theme_override_constants/separation = 16
|
||||
[node name="CancelButton" type="Button" parent="EndGameConfirm/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Cancel"
|
||||
text = "UI_CANCEL"
|
||||
|
||||
[node name="ConfirmEndGameButton" type="Button" parent="EndGameConfirm/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_type_variation = &"DangerButton"
|
||||
text = "Quit"
|
||||
text = "UI_QUIT"
|
||||
|
||||
[connection signal="pressed" from="MenuList/VBoxContainer/ResumeButton" to="." method="resume"]
|
||||
[connection signal="pressed" from="MenuList/VBoxContainer/SettingsButton" to="." method="settings"]
|
||||
|
108
src/ui/menus/settings_menu/control_binding/control_binding.gd
Normal file
108
src/ui/menus/settings_menu/control_binding/control_binding.gd
Normal file
@ -0,0 +1,108 @@
|
||||
class_name ControlBinding extends CheckerContainer
|
||||
## Input for rebinding an action.
|
||||
|
||||
const ACTION_KEY_FMT := "ACTION_{0}"
|
||||
const LISTENING_TEXT := "UI_LISTEN"
|
||||
|
||||
const MOTION_THRESHOLD := 0.5
|
||||
|
||||
@export var key: StringName
|
||||
|
||||
var listening: bool = false:
|
||||
set(value):
|
||||
if button:
|
||||
button.disabled = value
|
||||
listening = value
|
||||
|
||||
@onready var action: Label = %Action
|
||||
@onready var button: Button = %Button
|
||||
|
||||
|
||||
func _get_settings_key() -> String:
|
||||
return "input/%s" % key
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
# gdlint:ignore = private-method-call
|
||||
super._ready()
|
||||
|
||||
# Set action label text
|
||||
var loc_action := tr(ACTION_KEY_FMT.format([key]))
|
||||
# Fall back to just the key if no localization exists
|
||||
@warning_ignore("incompatible_ternary")
|
||||
action.text = loc_action if loc_action else key
|
||||
|
||||
# Set the binding label
|
||||
_set_label_from_binding()
|
||||
|
||||
|
||||
func _set_label_from_binding() -> void:
|
||||
var actions := InputMap.action_get_events(key)
|
||||
if actions:
|
||||
var primary := actions[0]
|
||||
button.text = PromptMap.from_event(primary)
|
||||
if button.text == PromptMap.UNKNOWN_INPUT_SYMBOL:
|
||||
print_debug("No mapping for input event: ", primary)
|
||||
# Special case: Can't rebind things bound to ESC
|
||||
if primary is InputEventKey and (primary as InputEventKey).physical_keycode == KEY_ESCAPE:
|
||||
button.disabled = true
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if not listening:
|
||||
return
|
||||
|
||||
if event is InputEventKey:
|
||||
var key_event: InputEventKey = event
|
||||
if (
|
||||
key_event.physical_keycode in [KEY_CTRL, KEY_ALT, KEY_SHIFT, KEY_META]
|
||||
and key_event.pressed
|
||||
):
|
||||
# Ignore modifier key until release
|
||||
return
|
||||
if key_event.physical_keycode == KEY_ESCAPE:
|
||||
get_viewport().set_input_as_handled()
|
||||
cancel_rebinding()
|
||||
return
|
||||
|
||||
if event is InputEventJoypadMotion:
|
||||
var motion_event: InputEventJoypadMotion = event
|
||||
if abs(motion_event.axis_value) < MOTION_THRESHOLD:
|
||||
# Ignore axis motion unless it's over our threshold
|
||||
return
|
||||
|
||||
if (
|
||||
event is InputEventKey
|
||||
or event is InputEventMouseButton
|
||||
or event is InputEventJoypadButton
|
||||
or event is InputEventJoypadMotion
|
||||
):
|
||||
get_viewport().set_input_as_handled()
|
||||
rebind(event)
|
||||
|
||||
|
||||
func start_listening() -> void:
|
||||
button.text = LISTENING_TEXT
|
||||
listening = true
|
||||
|
||||
|
||||
func cancel_rebinding() -> void:
|
||||
_set_label_from_binding()
|
||||
listening = false
|
||||
|
||||
|
||||
func rebind(event: InputEvent) -> void:
|
||||
# Clear previous binding
|
||||
InputMap.action_erase_events(key)
|
||||
# Add new binding
|
||||
InputMap.action_add_event(key, event)
|
||||
# Update label
|
||||
_set_label_from_binding()
|
||||
|
||||
listening = false
|
||||
|
||||
|
||||
func apply() -> void:
|
||||
var setting: Dictionary = ProjectSettings.get_setting(_get_settings_key())
|
||||
setting["events"] = InputMap.action_get_events(key)
|
||||
ProjectSettings.set_setting(_get_settings_key(), setting)
|
@ -0,0 +1 @@
|
||||
uid://y0kwpyt3w5bt
|
@ -0,0 +1,36 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://dwvpddd7id1h"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://y0kwpyt3w5bt" path="res://src/ui/menus/settings_menu/control_binding/control_binding.gd" id="1_7mwhu"]
|
||||
[ext_resource type="Theme" uid="uid://doq7ay6f7dgfo" path="res://src/ui/menus/menu.theme" id="1_82ajm"]
|
||||
|
||||
[node name="ControlBinding" type="PanelContainer" groups=["ControlBindings"]]
|
||||
theme = ExtResource("1_82ajm")
|
||||
theme_type_variation = &"CheckerContainerOdd"
|
||||
script = ExtResource("1_7mwhu")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 8
|
||||
theme_override_constants/margin_top = 8
|
||||
theme_override_constants/margin_right = 8
|
||||
theme_override_constants/margin_bottom = 8
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 48
|
||||
alignment = 2
|
||||
|
||||
[node name="Action" type="Label" parent="MarginContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"SettingsInputLabel"
|
||||
text = "Action"
|
||||
|
||||
[node name="Button" type="Button" parent="MarginContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(300, 42)
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"InputBindButton"
|
||||
text = "UI_UNSET"
|
||||
|
||||
[connection signal="pressed" from="MarginContainer/HBoxContainer/Button" to="." method="start_listening"]
|
@ -0,0 +1,13 @@
|
||||
extends Setting
|
||||
## Setting with checkbox representing a boolean value.
|
||||
|
||||
@onready var checkbox: CheckBox = %TextCheckbox
|
||||
|
||||
|
||||
func initialize_value(value: Variant) -> void:
|
||||
@warning_ignore("unsafe_cast")
|
||||
checkbox.button_pressed = value as bool
|
||||
|
||||
|
||||
func get_value() -> Variant:
|
||||
return checkbox.button_pressed
|
@ -0,0 +1 @@
|
||||
uid://dv8n1d4g4awyc
|
@ -0,0 +1,12 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://bpmpj4n6xp17l"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://dcah6r3ku60g6" path="res://src/ui/menus/settings_menu/settings/setting/setting.tscn" id="1_5t42f"]
|
||||
[ext_resource type="Script" uid="uid://dv8n1d4g4awyc" path="res://src/ui/menus/settings_menu/settings/checkbox_setting/checkbox_setting.gd" id="2_mwq55"]
|
||||
[ext_resource type="PackedScene" uid="uid://b7ce38k7rx466" path="res://src/ui/elements/text_checkbox/text_checkbox.tscn" id="3_fosy2"]
|
||||
|
||||
[node name="CheckboxSetting" instance=ExtResource("1_5t42f")]
|
||||
script = ExtResource("2_mwq55")
|
||||
|
||||
[node name="TextCheckbox" parent="PanelContainer/MarginContainer" index="0" instance=ExtResource("3_fosy2")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
@ -0,0 +1,11 @@
|
||||
extends "res://src/ui/menus/settings_menu/settings/checkbox_setting/checkbox_setting.gd"
|
||||
## Special case setting for fullscreen mode
|
||||
|
||||
|
||||
func initialize_value(value: Variant) -> void:
|
||||
@warning_ignore("unsafe_cast")
|
||||
checkbox.button_pressed = (value as Window.Mode) == Window.MODE_FULLSCREEN
|
||||
|
||||
|
||||
func get_value() -> Variant:
|
||||
return Window.MODE_FULLSCREEN if checkbox.button_pressed else Window.MODE_WINDOWED
|
@ -0,0 +1 @@
|
||||
uid://wlo8hxahp1x7
|
@ -0,0 +1,13 @@
|
||||
extends Setting
|
||||
## Setting with a dropdown menu representing an enum value
|
||||
|
||||
@onready var dropdown: OptionButton = %Dropdown
|
||||
|
||||
|
||||
func initialize_value(value: Variant) -> void:
|
||||
@warning_ignore("unsafe_cast")
|
||||
dropdown.selected = dropdown.get_item_index(value as int)
|
||||
|
||||
|
||||
func get_value() -> Variant:
|
||||
return dropdown.get_item_id(dropdown.selected)
|
@ -0,0 +1 @@
|
||||
uid://cfsf8k44t38g7
|
@ -0,0 +1,13 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://dpry41u0ctikn"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://dcah6r3ku60g6" path="res://src/ui/menus/settings_menu/settings/setting/setting.tscn" id="1_km84n"]
|
||||
[ext_resource type="Script" path="res://src/ui/menus/settings_menu/settings/dropdown_setting/dropdown_setting.gd" id="2_ubo13"]
|
||||
|
||||
[node name="DropdownSetting" instance=ExtResource("1_km84n")]
|
||||
script = ExtResource("2_ubo13")
|
||||
|
||||
[node name="Dropdown" type="OptionButton" parent="PanelContainer/MarginContainer" index="0"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
selected = 0
|
||||
item_count = 1
|
@ -0,0 +1,13 @@
|
||||
extends Setting
|
||||
## Setting with numeric slider representing a floating-point value
|
||||
|
||||
@onready var slider: NumericSlider = %NumericSlider
|
||||
|
||||
|
||||
func initialize_value(value: Variant) -> void:
|
||||
@warning_ignore("unsafe_cast")
|
||||
slider.value = value as float
|
||||
|
||||
|
||||
func get_value() -> Variant:
|
||||
return slider.value
|
@ -0,0 +1 @@
|
||||
uid://dpxpgs6iw7b7x
|
@ -0,0 +1,12 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://dut1lj8ju37sq"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://dcah6r3ku60g6" path="res://src/ui/menus/settings_menu/settings/setting/setting.tscn" id="1_t2sut"]
|
||||
[ext_resource type="Script" uid="uid://dpxpgs6iw7b7x" path="res://src/ui/menus/settings_menu/settings/numeric_setting/numeric_setting.gd" id="2_3nkup"]
|
||||
[ext_resource type="PackedScene" uid="uid://dqqcyi26d3bpg" path="res://src/ui/elements/numeric_slider/numeric_slider.tscn" id="2_piwkl"]
|
||||
|
||||
[node name="NumericSetting" instance=ExtResource("1_t2sut")]
|
||||
script = ExtResource("2_3nkup")
|
||||
|
||||
[node name="NumericSlider" parent="PanelContainer/MarginContainer" index="0" instance=ExtResource("2_piwkl")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
25
src/ui/menus/settings_menu/settings/setting/setting.gd
Normal file
25
src/ui/menus/settings_menu/settings/setting/setting.gd
Normal file
@ -0,0 +1,25 @@
|
||||
class_name Setting extends HBoxContainer
|
||||
## Base class for settings menu inputs
|
||||
|
||||
@export var key: StringName
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if not Engine.is_editor_hint():
|
||||
initialize_value(ProjectSettings.get_setting(key))
|
||||
|
||||
|
||||
## Initialize the value of this setting from project settings.
|
||||
func initialize_value(_value: Variant) -> void:
|
||||
pass # Implemented in derived type
|
||||
|
||||
|
||||
## Apply the set value of this setting to project settings.
|
||||
func apply() -> void:
|
||||
ProjectSettings.set_setting(key, get_value())
|
||||
|
||||
|
||||
## Get the raw value of this setting.
|
||||
func get_value() -> Variant:
|
||||
# Implemented in derived type
|
||||
return null
|
@ -0,0 +1 @@
|
||||
uid://d2ajb1x2wpm05
|
26
src/ui/menus/settings_menu/settings/setting/setting.tscn
Normal file
26
src/ui/menus/settings_menu/settings/setting/setting.tscn
Normal file
@ -0,0 +1,26 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://dcah6r3ku60g6"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://d2ajb1x2wpm05" path="res://src/ui/menus/settings_menu/settings/setting/setting.gd" id="1_rrash"]
|
||||
|
||||
[node name="Setting" type="HBoxContainer"]
|
||||
script = ExtResource("1_rrash")
|
||||
|
||||
[node name="Spacer" type="HSeparator" parent="."]
|
||||
custom_minimum_size = Vector2(32, 0)
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SettingLabel" type="Label" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Label"
|
||||
|
||||
[node name="PanelContainer" type="PanelContainer" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="PanelContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 4
|
||||
theme_override_constants/margin_top = 2
|
||||
theme_override_constants/margin_right = 4
|
||||
theme_override_constants/margin_bottom = 2
|
77
src/ui/menus/settings_menu/settings_menu.gd
Normal file
77
src/ui/menus/settings_menu/settings_menu.gd
Normal file
@ -0,0 +1,77 @@
|
||||
extends MarginContainer
|
||||
## Menu allowing the user to adjust game configuration.
|
||||
|
||||
const SETTINGS_GROUP := "Settings"
|
||||
const VOLUME_GROUP := "VolumeSliders"
|
||||
const BINDINGS_GROUP := "ControlBindings"
|
||||
|
||||
@export var volume_slider_scene: PackedScene
|
||||
@export var control_binding_scene: PackedScene
|
||||
|
||||
@onready var bus_mixer_list: HBoxContainer = %BusMixerList
|
||||
@onready var control_binding_list: VBoxContainer = %ControlBindingList
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
populate_volume_mixers()
|
||||
populate_control_bindings()
|
||||
|
||||
|
||||
func _get_settings_elements() -> Array[Setting]:
|
||||
var elements: Array[Setting] = []
|
||||
elements.assign(get_tree().get_nodes_in_group(SETTINGS_GROUP))
|
||||
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 _get_control_bindings() -> Array[ControlBinding]:
|
||||
var elements: Array[ControlBinding] = []
|
||||
elements.assign(get_tree().get_nodes_in_group(BINDINGS_GROUP))
|
||||
return elements
|
||||
|
||||
|
||||
func populate_control_bindings() -> void:
|
||||
for action: StringName in InputMap.get_actions():
|
||||
if not action.begins_with("ui_"):
|
||||
var binding: ControlBinding = control_binding_scene.instantiate()
|
||||
binding.key = action
|
||||
control_binding_list.add_child(binding)
|
||||
|
||||
|
||||
func populate_volume_mixers() -> void:
|
||||
for idx: int in range(AudioServer.bus_count):
|
||||
var slider: VolumeSlider = volume_slider_scene.instantiate()
|
||||
slider.bus_idx = idx
|
||||
bus_mixer_list.add_child(slider)
|
||||
|
||||
|
||||
## Close menu without applying settings.
|
||||
func cancel() -> void:
|
||||
queue_free()
|
||||
|
||||
|
||||
## Apply all settings.
|
||||
func apply() -> void:
|
||||
for setting: Setting in _get_settings_elements():
|
||||
setting.apply()
|
||||
for mixer: VolumeSlider in _get_volume_sliders():
|
||||
mixer.apply()
|
||||
for binding: ControlBinding in _get_control_bindings():
|
||||
binding.apply()
|
||||
|
||||
|
||||
## Write all applied settings to disk.
|
||||
func save_settings() -> void:
|
||||
Game.settings.write()
|
||||
|
||||
|
||||
## Apply settings and close menu.
|
||||
func accept() -> void:
|
||||
apply()
|
||||
save_settings()
|
||||
queue_free()
|
1
src/ui/menus/settings_menu/settings_menu.gd.uid
Normal file
1
src/ui/menus/settings_menu/settings_menu.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dyb8cwai3cyw2
|
14
src/ui/menus/settings_menu/settings_menu.gd~
Normal file
14
src/ui/menus/settings_menu/settings_menu.gd~
Normal file
@ -0,0 +1,14 @@
|
||||
extends MarginContainer
|
||||
## Menu allowing the user to adjust game configuration.
|
||||
|
||||
|
||||
## Close menu without applying settings.
|
||||
func cancel() -> void:
|
||||
queue_free()
|
||||
|
||||
|
||||
## Close menu and apply settings.
|
||||
func accept() -> void:
|
||||
# TODO apply settings
|
||||
# TODO write to disk
|
||||
queue_free()
|
336
src/ui/menus/settings_menu/settings_menu.tscn
Normal file
336
src/ui/menus/settings_menu/settings_menu.tscn
Normal file
@ -0,0 +1,336 @@
|
||||
[gd_scene load_steps=8 format=3 uid="uid://d3eaqw2rdurct"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dyb8cwai3cyw2" path="res://src/ui/menus/settings_menu/settings_menu.gd" id="1_lbcn7"]
|
||||
[ext_resource type="Theme" uid="uid://doq7ay6f7dgfo" path="res://src/ui/menus/menu.theme" id="1_vuur6"]
|
||||
[ext_resource type="PackedScene" uid="uid://bpmpj4n6xp17l" path="res://src/ui/menus/settings_menu/settings/checkbox_setting/checkbox_setting.tscn" id="2_f274v"]
|
||||
[ext_resource type="PackedScene" uid="uid://dut1lj8ju37sq" path="res://src/ui/menus/settings_menu/settings/numeric_setting/numeric_setting.tscn" id="3_jox8e"]
|
||||
[ext_resource type="PackedScene" uid="uid://d2ya6ly01724l" path="res://src/ui/menus/settings_menu/volume_slider/volume_slider.tscn" id="3_vuur6"]
|
||||
[ext_resource type="PackedScene" uid="uid://dwvpddd7id1h" path="res://src/ui/menus/settings_menu/control_binding/control_binding.tscn" id="4_6bmd3"]
|
||||
[ext_resource type="Script" uid="uid://wlo8hxahp1x7" path="res://src/ui/menus/settings_menu/settings/checkbox_setting/fullscreen_setting.gd" id="4_ug1id"]
|
||||
|
||||
[node name="SettingsMenu" type="MarginContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme = ExtResource("1_vuur6")
|
||||
script = ExtResource("1_lbcn7")
|
||||
volume_slider_scene = ExtResource("3_vuur6")
|
||||
control_binding_scene = ExtResource("4_6bmd3")
|
||||
|
||||
[node name="TabContainer" type="TabContainer" parent="."]
|
||||
layout_mode = 2
|
||||
current_tab = 0
|
||||
|
||||
[node name="SETTINGS_GAME" type="MarginContainer" parent="TabContainer"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"SettingsPageContainer"
|
||||
metadata/_tab_index = 0
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/SETTINGS_GAME"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/SETTINGS_GAME/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Icon" type="Label" parent="TabContainer/SETTINGS_GAME/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"InputPrompt"
|
||||
theme_override_font_sizes/font_size = 48
|
||||
text = "⚙"
|
||||
|
||||
[node name="Label" type="Label" parent="TabContainer/SETTINGS_GAME/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 8
|
||||
theme_type_variation = &"HeaderXLarge"
|
||||
text = "SETTINGS_GAME_HEADING"
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="TabContainer/SETTINGS_GAME/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_type_variation = &"SettingsListMargin"
|
||||
|
||||
[node name="SettingsList" type="VBoxContainer" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="AccessibilityHeading" type="HBoxContainer" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/AccessibilityHeading"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"HeaderMedium"
|
||||
text = "SETTINGS_GAME_ACCESSIBILITY_HEADING"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/AccessibilityHeading"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="ScreenShake" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList" groups=["Settings"] instance=ExtResource("2_f274v")]
|
||||
layout_mode = 2
|
||||
key = &"game/config/accessibility/enable_screen_shake"
|
||||
|
||||
[node name="SettingLabel" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/ScreenShake" index="1"]
|
||||
text = "SETTINGS_SCREEN_SHAKE"
|
||||
|
||||
[node name="TextCheckbox" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/ScreenShake/PanelContainer/MarginContainer" index="0"]
|
||||
physics_interpolation_mode = 0
|
||||
|
||||
[node name="HeadBob" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList" groups=["Settings"] instance=ExtResource("2_f274v")]
|
||||
layout_mode = 2
|
||||
key = &"game/config/accessibility/enable_head_bob"
|
||||
|
||||
[node name="SettingLabel" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/HeadBob" index="1"]
|
||||
text = "SETTINGS_HEAD_BOB"
|
||||
|
||||
[node name="TextCheckbox" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/HeadBob/PanelContainer/MarginContainer" index="0"]
|
||||
physics_interpolation_mode = 0
|
||||
|
||||
[node name="CameraHeading" type="HBoxContainer" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/CameraHeading"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"HeaderMedium"
|
||||
text = "SETTINGS_GAME_CAMERA_HEADING"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/CameraHeading"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="SensitivityX" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList" groups=["Settings"] instance=ExtResource("3_jox8e")]
|
||||
layout_mode = 2
|
||||
key = &"game/config/input/mouse_sensitivity_x"
|
||||
|
||||
[node name="SettingLabel" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/SensitivityX" index="1"]
|
||||
text = "SETTINGS_SENSITIVITY_X"
|
||||
|
||||
[node name="NumericSlider" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/SensitivityX/PanelContainer/MarginContainer" index="0"]
|
||||
physics_interpolation_mode = 0
|
||||
max_value = 1.0
|
||||
step = 0.01
|
||||
|
||||
[node name="SensitivityY" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList" groups=["Settings"] instance=ExtResource("3_jox8e")]
|
||||
layout_mode = 2
|
||||
key = &"game/config/input/mouse_sensitivity_y"
|
||||
|
||||
[node name="SettingLabel" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/SensitivityY" index="1"]
|
||||
text = "SETTINGS_SENSITIVITY_Y"
|
||||
|
||||
[node name="NumericSlider" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/SensitivityY/PanelContainer/MarginContainer" index="0"]
|
||||
physics_interpolation_mode = 0
|
||||
max_value = 1.0
|
||||
step = 0.01
|
||||
|
||||
[node name="MouseAcceleration" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList" groups=["Settings"] instance=ExtResource("3_jox8e")]
|
||||
layout_mode = 2
|
||||
key = &"game/config/input/mouse_acceleration"
|
||||
|
||||
[node name="SettingLabel" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/MouseAcceleration" index="1"]
|
||||
text = "SETTINGS_MOUSE_ACCELERATION"
|
||||
|
||||
[node name="NumericSlider" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/MouseAcceleration/PanelContainer/MarginContainer" index="0"]
|
||||
physics_interpolation_mode = 0
|
||||
|
||||
[node name="InvertPitch" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList" groups=["Settings"] instance=ExtResource("2_f274v")]
|
||||
layout_mode = 2
|
||||
key = &"game/config/input/invert_pitch"
|
||||
|
||||
[node name="SettingLabel" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/InvertPitch" index="1"]
|
||||
text = "SETTINGS_INVERT_PITCH"
|
||||
|
||||
[node name="TextCheckbox" parent="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/InvertPitch/PanelContainer/MarginContainer" index="0"]
|
||||
physics_interpolation_mode = 0
|
||||
|
||||
[node name="SETTINGS_GRAPHICS" type="MarginContainer" parent="TabContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"SettingsPageContainer"
|
||||
metadata/_tab_index = 1
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/SETTINGS_GRAPHICS"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Icon" type="Label" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
theme_type_variation = &"InputPrompt"
|
||||
theme_override_font_sizes/font_size = 48
|
||||
text = "🖵"
|
||||
|
||||
[node name="Label" type="Label" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 0
|
||||
theme_type_variation = &"HeaderXLarge"
|
||||
text = "SETTINGS_GRAPHICS_HEADING"
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_type_variation = &"SettingsListMargin"
|
||||
|
||||
[node name="SettingsList" type="VBoxContainer" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="DisplayHeading" type="HBoxContainer" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer/MarginContainer/SettingsList"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/DisplayHeading"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"HeaderMedium"
|
||||
text = "SETTINGS_GRAPHICS_DISPLAY_HEADING"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/DisplayHeading"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Fullscreen" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer/MarginContainer/SettingsList" groups=["Settings"] instance=ExtResource("2_f274v")]
|
||||
layout_mode = 2
|
||||
script = ExtResource("4_ug1id")
|
||||
key = &"display/window/size/mode"
|
||||
|
||||
[node name="SettingLabel" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/Fullscreen" index="1"]
|
||||
text = "SETTINGS_GRAPHICS_FULLSCREEN"
|
||||
|
||||
[node name="TextCheckbox" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/Fullscreen/PanelContainer/MarginContainer" index="0"]
|
||||
physics_interpolation_mode = 0
|
||||
|
||||
[node name="VSync" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer/MarginContainer/SettingsList" groups=["Settings"] instance=ExtResource("2_f274v")]
|
||||
layout_mode = 2
|
||||
key = &"display/window/vsync/vsync_mode"
|
||||
|
||||
[node name="SettingLabel" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/VSync" index="1"]
|
||||
text = "SETTINGS_GRAPHICS_VSYNC"
|
||||
|
||||
[node name="TextCheckbox" parent="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/VSync/PanelContainer/MarginContainer" index="0"]
|
||||
physics_interpolation_mode = 0
|
||||
|
||||
[node name="SETTINGS_AUDIO" type="MarginContainer" parent="TabContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"SettingsPageContainer"
|
||||
metadata/_tab_index = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/SETTINGS_AUDIO"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/SETTINGS_AUDIO/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Icon" type="Label" parent="TabContainer/SETTINGS_AUDIO/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"InputPrompt"
|
||||
theme_override_font_sizes/font_size = 48
|
||||
text = "🕬"
|
||||
|
||||
[node name="Label" type="Label" parent="TabContainer/SETTINGS_AUDIO/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 8
|
||||
theme_type_variation = &"HeaderXLarge"
|
||||
text = "SETTINGS_AUDIO_HEADING"
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="TabContainer/SETTINGS_AUDIO/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="TabContainer/SETTINGS_AUDIO/VBoxContainer/ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_type_variation = &"SettingsListMargin"
|
||||
|
||||
[node name="BusMixerList" type="HBoxContainer" parent="TabContainer/SETTINGS_AUDIO/VBoxContainer/ScrollContainer/MarginContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 16
|
||||
|
||||
[node name="SETTINGS_CONTROLS" type="MarginContainer" parent="TabContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"SettingsPageContainer"
|
||||
metadata/_tab_index = 3
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/SETTINGS_CONTROLS"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/SETTINGS_CONTROLS/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Icon" type="Label" parent="TabContainer/SETTINGS_CONTROLS/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"InputPrompt"
|
||||
theme_override_font_sizes/font_size = 48
|
||||
text = ""
|
||||
|
||||
[node name="Label" type="Label" parent="TabContainer/SETTINGS_CONTROLS/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 8
|
||||
theme_type_variation = &"HeaderXLarge"
|
||||
text = "SETTINGS_CONTROLS_HEADING"
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="TabContainer/SETTINGS_CONTROLS/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="TabContainer/SETTINGS_CONTROLS/VBoxContainer/ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_type_variation = &"SettingsListMargin"
|
||||
|
||||
[node name="ControlBindingList" type="VBoxContainer" parent="TabContainer/SETTINGS_CONTROLS/VBoxContainer/ScrollContainer/MarginContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SouthEast" type="MarginContainer" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 8
|
||||
size_flags_vertical = 8
|
||||
theme_override_constants/margin_left = 16
|
||||
theme_override_constants/margin_top = 16
|
||||
theme_override_constants/margin_right = 16
|
||||
theme_override_constants/margin_bottom = 16
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="SouthEast"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 16
|
||||
|
||||
[node name="CancelButton" type="Button" parent="SouthEast/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"CancelButton"
|
||||
text = "UI_CANCEL"
|
||||
|
||||
[node name="AcceptButton" type="Button" parent="SouthEast/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"AlertButton"
|
||||
text = "UI_ACCEPT"
|
||||
|
||||
[connection signal="pressed" from="SouthEast/HBoxContainer/CancelButton" to="." method="cancel"]
|
||||
[connection signal="pressed" from="SouthEast/HBoxContainer/AcceptButton" to="." method="accept"]
|
||||
|
||||
[editable path="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/ScreenShake"]
|
||||
[editable path="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/HeadBob"]
|
||||
[editable path="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/SensitivityX"]
|
||||
[editable path="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/SensitivityY"]
|
||||
[editable path="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/MouseAcceleration"]
|
||||
[editable path="TabContainer/SETTINGS_GAME/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/InvertPitch"]
|
||||
[editable path="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/Fullscreen"]
|
||||
[editable path="TabContainer/SETTINGS_GRAPHICS/VBoxContainer/ScrollContainer/MarginContainer/SettingsList/VSync"]
|
63
src/ui/menus/settings_menu/volume_slider/volume_slider.gd
Normal file
63
src/ui/menus/settings_menu/volume_slider/volume_slider.gd
Normal file
@ -0,0 +1,63 @@
|
||||
class_name VolumeSlider extends VBoxContainer
|
||||
## Input element for adjusting the volume of a single bus.
|
||||
|
||||
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()
|
@ -0,0 +1 @@
|
||||
uid://bt3oajqvevj4k
|
53
src/ui/menus/settings_menu/volume_slider/volume_slider.tscn
Normal file
53
src/ui/menus/settings_menu/volume_slider/volume_slider.tscn
Normal file
@ -0,0 +1,53 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://d2ya6ly01724l"]
|
||||
|
||||
[ext_resource type="Theme" uid="uid://doq7ay6f7dgfo" path="res://src/ui/menus/menu.theme" id="1_k7hk0"]
|
||||
[ext_resource type="Script" uid="uid://bt3oajqvevj4k" path="res://src/ui/menus/settings_menu/volume_slider/volume_slider.gd" id="1_rfe0k"]
|
||||
|
||||
[node name="VolumeSlider" type="VBoxContainer" groups=["VolumeSliders"]]
|
||||
custom_minimum_size = Vector2(300, 0)
|
||||
theme = ExtResource("1_k7hk0")
|
||||
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 = &"InputPrompt"
|
||||
theme_override_constants/outline_size = 5
|
||||
theme_override_font_sizes/font_size = 24
|
||||
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
|
||||
|
||||
[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"]
|
1
src/util/prompt_map.gd.uid
Normal file
1
src/util/prompt_map.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://bjcah3n6wug68
|
@ -25,7 +25,7 @@ func pause() -> void:
|
||||
get_tree().paused = true
|
||||
var pause_menu: Control = pause_scene.instantiate()
|
||||
ui_root.add_child(pause_menu)
|
||||
pause_menu.tree_exited.connect(unpause)
|
||||
pause_menu.tree_exiting.connect(unpause)
|
||||
|
||||
|
||||
func unpause() -> void:
|
||||
|
Loading…
x
Reference in New Issue
Block a user