Files
Factory47/addons/savekit/resource.gd
2026-06-04 16:53:41 -05:00

72 lines
2.6 KiB
GDScript

@abstract
class_name SaveKitResource
extends Resource
## Base class for user-defined resources that can be saved and loaded.
##
## [code]SaveKitResource[/code]s are used instead of the base [Resource] class to clearly identify data that is meant for persistence in save files, versus resource data that is part of the game's PCK.
## Emitted whenever this resource is saved.
signal saved
## Emitted whenever this resource is loaded.
signal loaded
const ReflectionUtils := preload("reflection_utils.gd")
const Serializer := preload("serializer.gd")
const Deserializer := preload("deserializer.gd")
## Saves data for this resource into a dictionary, suitable for persisting. This will serialize all of the resource's exported properties that have a non-default value.
##
## This method can be overridden to implement custom saving behavior.
func save_to_dict(s: Serializer) -> Dictionary:
var script: Script = get_script()
var script_property_default_values: Dictionary[String, Variant]
ReflectionUtils.get_script_default_property_values(script, script_property_default_values)
var save_dict := {}
for property in script.get_script_property_list():
var name: String = property["name"]
var usage: PropertyUsageFlags = property["usage"]
if usage & PROPERTY_USAGE_STORAGE == 0:
continue
var value: Variant = get(name)
# Don't save default values
if name in script_property_default_values and value == script_property_default_values[name]:
continue
save_dict[name] = s.encode_var(value)
saved.emit()
return save_dict
## Loads data into this resource from the given dictionary. This will set the resource's properties to the decoded values of [param data].
##
## This method can be overridden to implement custom loading behavior.
func load_from_dict(s: Deserializer, data: Dictionary) -> void:
var properties_by_name: Dictionary[String, Dictionary]
for property: Dictionary in self.get_property_list():
properties_by_name[property.name] = property
for name: String in data:
if name not in properties_by_name:
push_warning("Cannot load saved property ", name, " not currently found on resource ", self )
continue
var property := properties_by_name[name]
var usage_flags: PropertyUsageFlags = property["usage"]
if usage_flags & PROPERTY_USAGE_STORAGE == 0:
push_warning("Not loading property ", name, " with storage disabled")
continue
var encoded_value: Variant = data[name]
var type: Variant.Type = property["type"]
var classname: StringName = property.get("class_name", &"")
var decoded_value: Variant = s.decode_var(encoded_value, type, classname)
set(name, decoded_value)
loaded.emit()
emit_changed()