206 lines
6.1 KiB
GDScript
206 lines
6.1 KiB
GDScript
extends Control
|
|
class_name SettingsElement
|
|
## The base script for settings elements.
|
|
|
|
## Identifier for the element.
|
|
## This value is used as the key in the settings data.
|
|
@export var IDENTIFIER: String = "Element"
|
|
|
|
## Toggle based on whether the element handles a setting that requires an in game node to exist.
|
|
@export var IS_IN_GAME_SETTING: bool
|
|
|
|
## The name of the section the element is under.
|
|
@onready var SECTION: String = ParentRef.IDENTIFIER
|
|
|
|
## Reference to the section the settings element is under.
|
|
var ParentRef: SettingsSection
|
|
|
|
# Multi element flags
|
|
## Flag to turn an element into the main element of a multi element.
|
|
var IS_MULTI_ELEMENT: bool = false
|
|
## Flag to turn an element into a sub element of a multi element.
|
|
var IS_SUB_ELEMENT: bool = false
|
|
|
|
## Current value of the element.
|
|
var currentValue
|
|
|
|
|
|
func _enter_tree() -> void:
|
|
if not IS_MULTI_ELEMENT:
|
|
ParentRef = owner
|
|
|
|
|
|
func _ready() -> void:
|
|
SettingsDataManager.connect("settings_retrieved", load_settings)
|
|
# Check if the element is a sub element
|
|
if not IS_SUB_ELEMENT:
|
|
ParentRef.connect("apply_button_pressed", _apply_settings)
|
|
# Add an entry of the settings element to the section's reference table
|
|
ParentRef.ELEMENT_REFERENCE_TABLE_[IDENTIFIER] = self
|
|
|
|
|
|
## Used to initialize a settings element.
|
|
## This function is overwritten by each [b]type[/b] of element.
|
|
func init_element() -> void:
|
|
return
|
|
|
|
|
|
## Loads the saved or default value of the element.
|
|
func load_settings() -> void:
|
|
# List of valid values for the element
|
|
var VALUES_: Dictionary = get_valid_values()
|
|
VALUES_.make_read_only()
|
|
|
|
# Check if no save file exists
|
|
if SettingsDataManager.noSaveFile:
|
|
# Assign default value as current value
|
|
currentValue = VALUES_["defaultValue"]
|
|
# Add default value of element to the settings data
|
|
SettingsDataManager.settingsData_[SECTION][IDENTIFIER] = currentValue
|
|
else:
|
|
# Verify the existance and validity of the element in the settings data
|
|
if verify_settings_data(VALUES_):
|
|
# Get the current value from the settings data
|
|
currentValue = SettingsDataManager.settingsData_[SECTION][IDENTIFIER]
|
|
else:
|
|
# Assign default value as current value
|
|
currentValue = VALUES_["defaultValue"]
|
|
# Add default value of the element to the settings data
|
|
SettingsDataManager.settingsData_[SECTION][IDENTIFIER] = currentValue
|
|
SettingsDataManager.invalidSaveFile = true
|
|
|
|
init_element()
|
|
|
|
# Check if the current element is in an in game menu or if it is a sub element
|
|
if (
|
|
ParentRef.SettingsMenuRef.IS_IN_GAME_MENU == IS_IN_GAME_SETTING
|
|
or not IS_SUB_ELEMENT
|
|
):
|
|
# Apply the loaded values to the game
|
|
call_deferred("_apply_settings")
|
|
|
|
|
|
## Used to get the valid values an element can have for validating settings data.
|
|
## This function is overwritten by each [b]type[/b] of element.
|
|
func get_valid_values() -> Dictionary:
|
|
return {}
|
|
|
|
|
|
## Checks if the loaded values are valid for the element.
|
|
## If a value is wrong, it will be fixed automatically.
|
|
func verify_settings_data(VALUES_: Dictionary) -> bool:
|
|
# Check if an entry exists for the element
|
|
if not entry_exists():
|
|
return false
|
|
|
|
# Get the value of the element
|
|
var RETRIEVED_VALUE = SettingsDataManager.settingsData_[SECTION][IDENTIFIER]
|
|
|
|
# Check if the retrieved value is the correct type
|
|
if not is_valid_type(VALUES_, RETRIEVED_VALUE):
|
|
return false
|
|
|
|
# Check if the retrieved value has the expected value
|
|
if not is_valid_value(VALUES_, RETRIEVED_VALUE):
|
|
return false
|
|
|
|
return true
|
|
|
|
|
|
## Used by verify_settings_data() to check if the element
|
|
## and the section it is under exists in the settings data.
|
|
func entry_exists() -> bool:
|
|
# Check if the section exists in settings data
|
|
if not SettingsDataManager.settingsData_.has(SECTION):
|
|
push_warning("Settings section missing: ", SECTION)
|
|
return false
|
|
|
|
# Check if the element exists in the settings data
|
|
if not SettingsDataManager.settingsData_[SECTION].has(IDENTIFIER):
|
|
push_warning("Settings element is missing: ", IDENTIFIER)
|
|
return false
|
|
|
|
return true
|
|
|
|
|
|
## Used by verify_settings_data() to check if the retrieved value has the correct type.
|
|
func is_valid_type(VALUES_: Dictionary, RETRIEVED_VALUE) -> bool:
|
|
if typeof(RETRIEVED_VALUE) != typeof(VALUES_["defaultValue"]):
|
|
push_warning(
|
|
"Invalid value type of '"
|
|
+ type_string(typeof(RETRIEVED_VALUE))
|
|
+ "' for element '"
|
|
+ IDENTIFIER
|
|
+ "' expected value type of '"
|
|
+ type_string(typeof(VALUES_["defaultValue"]))
|
|
+ "'"
|
|
)
|
|
return false
|
|
|
|
return true
|
|
|
|
|
|
## Used by verify_settings_data() to check if the retrieved value has a valid value.
|
|
func is_valid_value(VALUES_: Dictionary, RETRIEVED_VALUE) -> bool:
|
|
# Get the type of the valid value
|
|
match typeof(VALUES_["defaultValue"]):
|
|
# If the type is either string or bool
|
|
TYPE_STRING, TYPE_BOOL:
|
|
# Check if the retrieved value is valid
|
|
if not VALUES_["validOptions"].has(RETRIEVED_VALUE):
|
|
push_warning(
|
|
"Invalid value '"
|
|
+ str(RETRIEVED_VALUE)
|
|
+ "' for element '"
|
|
+ IDENTIFIER
|
|
+ "' expected values: "
|
|
+ str(VALUES_["validOptions"])
|
|
)
|
|
return false
|
|
# If the type is either int or float
|
|
TYPE_INT, TYPE_FLOAT:
|
|
# Check if the retrieved value is valid
|
|
if (
|
|
RETRIEVED_VALUE < VALUES_["minValue"]
|
|
or RETRIEVED_VALUE > VALUES_["maxValue"]
|
|
):
|
|
# Special check if max fps is set to 0 (unlimited)
|
|
if IDENTIFIER == "MaxFPS" and RETRIEVED_VALUE == 0:
|
|
return true
|
|
|
|
push_warning(
|
|
"Invalid value "
|
|
+ str(RETRIEVED_VALUE)
|
|
+ " for element '"
|
|
+ IDENTIFIER
|
|
+ "' expected values between "
|
|
+ str(VALUES_["minValue"])
|
|
+ " and "
|
|
+ str(VALUES_["maxValue"])
|
|
)
|
|
return false
|
|
|
|
return true
|
|
|
|
|
|
## Used to apply in game settings that require a node to exist to be applied,
|
|
## i.e., world environment related settings and or most gameplay settings.
|
|
func apply_in_game_setting(value = null) -> bool:
|
|
if ParentRef.SettingsMenuRef.IS_IN_GAME_MENU:
|
|
SettingsDataManager.call_deferred(
|
|
"emit_signal",
|
|
"applied_in_game_setting",
|
|
SECTION,
|
|
IDENTIFIER,
|
|
value
|
|
)
|
|
return true
|
|
|
|
return false
|
|
|
|
|
|
## Called to apply the setting to the game.
|
|
## This function is overwritten by each [b]element[/b].
|
|
func _apply_settings() -> void:
|
|
return
|