Files
frog/addons/dialogic/Core/Dialogic_Subsystem.gd
2026-09-03 09:43:13 +02:00

100 lines
3.7 KiB
GDScript

class_name DialogicSubsystem
extends Node
## A (mostly) standalone system inside Dialogic.
##
## Subclasses registered via a [class DialogicIndexer] will be instanced as children of the [class DialogicGameHandler].[br]
## These systems should provide easy access to methods and settings regarding their logic.[br]
## By overwriting the classes various methods, they should handle saving and loading of the system.[br]
## Exported variables on a subsystem will be considered relevant for the save-state, so on save they will be packed and
## unpacked on load before [method _load_state] is called.
## Additional state (e.g. from nodes in the scene, can be collected in [method _pack_extra_state].
## A reference to the [class DialogicGameHandler] this subsystem instance belongs to.
## Currently only the Dialogic autoload instance of DialogicGameHandler is supported.
var dialogic: DialogicGameHandler = null
enum LoadFlags {FULL_LOAD, ONLY_DNODES}
## Called once after every subsystem has been added to the tree.
## To be overriden by sub-classes.
func _post_install() -> void:
pass
## Reset the subsystem and clear all effects it has had on the scene tree.
## Called on DialogicGameHandler ready, clear and before loading a different state.
## To be overriden by sub-classes.
func _clear_state(_clear_flag:=DialogicGameHandler.ClearFlags.FULL_CLEAR) -> void:
pass
## Called when `DialogicGameHandler.paused` changes to `true`. Pause all systems.
## To be overriden by sub-classes.
func _pause() -> void:
pass
## Called when `DialogicGameHandler.paused` changes to `false`. Resume all paused systems.
## To be overriden by sub-classes.
func _resume() -> void:
pass
## Called when a state is loaded by the DialogicGameHandler.
## Calls [method _load_state].
## It should usually not be necessary to access this directly.
func load_state(load_flag:=LoadFlags.FULL_LOAD) -> void:
_load_state(load_flag)
## Make sure to recreate the state from the exported state variables (have been unpacked before this) and the "extra-state" which you can access with [method get_extra_state].
## To be overriden by sub-classes.
func _load_state(_load_flag:=LoadFlags.FULL_LOAD) -> void:
pass
## Called by DialogGameHandler to get the current state of the subsystem.
## Combines the result of [method pack_exported_state] and [method _get_extra_state].
func get_state() -> Dictionary:
return pack_exported_state().merged(pack_extra_state())
## Used by [method get_state]. Calls [method _pack_extra_state].
func pack_extra_state() -> Dictionary:
return _pack_extra_state()
## To be overriden by sub-classes.
## Return a dictionary with all the info you want to save (that isn't already represented by the exported state variables).
## This is especially useful for saving the state of elements in the scene tree.
## To get this state after a later load, use [method get_extra_state].
func _pack_extra_state() -> Dictionary:
return {}
## If called after a load, this will return the extra state dictionary that was packed by [method _pack_extra_state].
func get_extra_state() -> Dictionary:
return get_meta("extra_state", {})
## Packs all the exported variables into a dictionary.
func pack_exported_state() -> Dictionary:
var info := {}
for i in self.script.get_script_property_list():
if i.usage & PROPERTY_USAGE_EDITOR == PROPERTY_USAGE_EDITOR:
info[i.name] = self.get(i.name)
return info
## Unpacks the values from the given info dictionary into the exported variables.
func unpack_state(info:Dictionary) -> void:
var leftovers := info.duplicate()
for i in self.script.get_script_property_list():
if i.usage & PROPERTY_USAGE_EDITOR == PROPERTY_USAGE_EDITOR:
if i.name in info:
self.set(i.name, info[i.name])
leftovers.erase(i.name)
set_meta("extra_state", leftovers)