Added menu settings add-on
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
extends Node
|
||||
## Handles the loading and saving of settings data.
|
||||
|
||||
## Emitted when loading the settings data.
|
||||
signal settings_retrieved
|
||||
## Emitted when applying specific settings to in game objects.
|
||||
signal applied_in_game_setting(section: String, setting: String, value)
|
||||
|
||||
## PATH to the settings save file.
|
||||
var DATA_FOLDER: String = OS.get_user_data_dir()
|
||||
## Name of the file that the settings data is saved in.
|
||||
const FILE_NAME: String = "settings"
|
||||
## Extension for the save file.
|
||||
const FILE_EXTENSION: String = ".cfg"
|
||||
## The PATH to the save file on the computer.
|
||||
var PATH: String = DATA_FOLDER + "/" + FILE_NAME + FILE_EXTENSION
|
||||
|
||||
## Dictionary that stores all settings data.
|
||||
var settingsData_: Dictionary
|
||||
## A reference table of all sections.
|
||||
var SECTION_REFERENCE_TABLE_: Dictionary
|
||||
## A reference table of all element panels.
|
||||
var ELEMENT_PANEL_REFERENCE_TABLE_: Dictionary
|
||||
|
||||
## The number of elements that have been changed since the settings have been saved.
|
||||
var changedElementsCount: int = 0
|
||||
|
||||
## Flag for checking if a save file exists.
|
||||
var noSaveFile: bool
|
||||
## Flag for checking if an invalid value was found in the save file.
|
||||
var invalidSaveFile: bool = false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
# Verify the directory
|
||||
DirAccess.make_dir_absolute(DATA_FOLDER)
|
||||
|
||||
# Check if a save file exists
|
||||
if FileAccess.file_exists(PATH):
|
||||
# Proceed normally by retrieving data from the save file
|
||||
call_deferred("get_data")
|
||||
else:
|
||||
# Enable the no save file flag
|
||||
noSaveFile = true
|
||||
push_warning("No save file found")
|
||||
|
||||
|
||||
## Called to save the settings data to the save file.
|
||||
func save_data() -> void:
|
||||
# Create a new config instance
|
||||
var config := ConfigFile.new()
|
||||
|
||||
# Add the data from the settings data dictionary
|
||||
for section in settingsData_:
|
||||
for element in settingsData_[section]:
|
||||
config.set_value(section, element, settingsData_[section][element])
|
||||
|
||||
# Save the data to the specified directory
|
||||
var err = config.save(PATH)
|
||||
|
||||
# Check for errors
|
||||
if err != OK:
|
||||
push_error("Failed to save data_: ", err)
|
||||
return
|
||||
|
||||
# Disable the no save file flag if it was enabled
|
||||
if noSaveFile:
|
||||
noSaveFile = false
|
||||
|
||||
# Disable the invalid save file flag if it was enabled
|
||||
if invalidSaveFile:
|
||||
invalidSaveFile = false
|
||||
|
||||
|
||||
## Called to retrieve data from the save file.
|
||||
func get_data() -> void:
|
||||
# Create a new config instance
|
||||
var config := ConfigFile.new()
|
||||
# Load the save data
|
||||
var err := config.load(PATH)
|
||||
# Temporary data dictionary
|
||||
var data_: Dictionary = {}
|
||||
|
||||
# Check for errors
|
||||
if err != OK:
|
||||
push_error("Failed to load settings data_: ", err)
|
||||
return
|
||||
|
||||
# Add the retrieved data to the settings data dictionary
|
||||
for section in config.get_sections():
|
||||
data_[section] = {}
|
||||
for key in config.get_section_keys(section):
|
||||
data_[section][key] = config.get_value(section, key)
|
||||
|
||||
# Verify the validity of the loaded data
|
||||
verify_settings_data_(data_)
|
||||
|
||||
# Copy the retrieved data into the settings data dictionary
|
||||
settingsData_ = data_.duplicate(true)
|
||||
|
||||
|
||||
## Checks if the save file has any invalid entries and removes them or adds missing sections.
|
||||
func verify_settings_data_(data_: Dictionary) -> void:
|
||||
# List of valid entries to compare to
|
||||
var validEntries_: Dictionary = SECTION_REFERENCE_TABLE_.duplicate()
|
||||
# Merge the element panel references into the valid entries
|
||||
validEntries_.merge(ELEMENT_PANEL_REFERENCE_TABLE_)
|
||||
# List of invalid entries to be removed
|
||||
var invalidEntries_: Dictionary = {}
|
||||
|
||||
# Itterate through the loaded settings data
|
||||
for section in data_:
|
||||
if is_valid_section(invalidEntries_, section):
|
||||
verify_elements(data_, invalidEntries_, section)
|
||||
|
||||
# Check if there are any sections missing from the retrieved data
|
||||
check_for_missing_sections(data_, validEntries_)
|
||||
|
||||
# Check if there are any invalid entries
|
||||
if invalidEntries_.size() > 0:
|
||||
# Set the invalid save file flag to true
|
||||
invalidSaveFile = true
|
||||
remove_invalid_entries(data_, invalidEntries_, validEntries_)
|
||||
|
||||
|
||||
## Used by the verify_settings_data() function to verify the retrieved sections.
|
||||
func is_valid_section(invalidEntries_: Dictionary, SECTION: String) -> bool:
|
||||
# Check if the section is in either of the reference tables
|
||||
if (
|
||||
SECTION_REFERENCE_TABLE_.has(SECTION)
|
||||
or ELEMENT_PANEL_REFERENCE_TABLE_.has(SECTION)
|
||||
):
|
||||
return true
|
||||
|
||||
# Add the invalid section to the invalid entries list
|
||||
invalidEntries_[SECTION] = []
|
||||
push_warning("Invalid section '", SECTION, "' found.")
|
||||
return false
|
||||
|
||||
|
||||
## Used by the verify_settings_data() function to verify the elements inside of the retrieved sections.
|
||||
func verify_elements(
|
||||
data_: Dictionary,
|
||||
invalidEntries_: Dictionary,
|
||||
SECTION: String
|
||||
) -> void:
|
||||
# Array of all elements under the section
|
||||
var VALID_SECTION_ELEMENTS: Array = get_valid_elements(SECTION)
|
||||
|
||||
# Itterate through all the elements in the section
|
||||
for element in data_[SECTION]:
|
||||
# Check for invalid elements
|
||||
if not VALID_SECTION_ELEMENTS.has(element):
|
||||
# Check if the element is in a valid section
|
||||
if not invalidEntries_.has(SECTION):
|
||||
# Add the section to the invalid entries list
|
||||
invalidEntries_[SECTION] = []
|
||||
|
||||
# Add the invalid element to the invalid entries list
|
||||
invalidEntries_[SECTION].append(element)
|
||||
push_warning(
|
||||
"Invalid element '"
|
||||
+ element
|
||||
+ "' found in section '"
|
||||
+ SECTION
|
||||
+ "'."
|
||||
)
|
||||
|
||||
|
||||
## Used by the verify_elements() function to retrieve the valid elements for the retrieved section.
|
||||
func get_valid_elements(SECTION: String) -> Array:
|
||||
# Check if the section is a settings section
|
||||
if SECTION_REFERENCE_TABLE_.has(SECTION):
|
||||
return SECTION_REFERENCE_TABLE_[SECTION].ELEMENT_REFERENCE_TABLE_.keys()
|
||||
|
||||
# Check if the section is an element panel
|
||||
if ELEMENT_PANEL_REFERENCE_TABLE_.has(SECTION):
|
||||
return ELEMENT_PANEL_REFERENCE_TABLE_[SECTION].ELEMENT_REFERENCE_TABLE_.keys()
|
||||
|
||||
return []
|
||||
|
||||
|
||||
## Used by the verify_settings_data() function to check if any expected sections are missing.
|
||||
func check_for_missing_sections(data_: Dictionary, validEntries_: Dictionary) -> void:
|
||||
# Itterate through all valid sections
|
||||
for section in validEntries_:
|
||||
# Check if the section is missing from the loaded data_
|
||||
if not data_.has(section):
|
||||
# Add an empty entry for the section
|
||||
data_[section] = {}
|
||||
# Set the invalid save file flag to true
|
||||
invalidSaveFile = true
|
||||
push_warning("Settings section is missing: ", section)
|
||||
|
||||
|
||||
## Used by the verify_settings_data() function to remove invalid entires from the retrieved data.
|
||||
func remove_invalid_entries(
|
||||
data_: Dictionary,
|
||||
invalidEntries_: Dictionary,
|
||||
validEntries_: Dictionary
|
||||
) -> void:
|
||||
# Itterate through the sections in the invalid entries list
|
||||
for section in invalidEntries_:
|
||||
# Check if the section is valid
|
||||
if validEntries_.has(section):
|
||||
# Itterate through the invalid elements
|
||||
for element in invalidEntries_[section]:
|
||||
# Remove the invalid element
|
||||
data_[section].erase(element)
|
||||
else:
|
||||
# Remove the invalid section
|
||||
data_.erase(section)
|
||||
@@ -0,0 +1 @@
|
||||
uid://c70d4w5cws2at
|
||||
Reference in New Issue
Block a user