Archmage.AtlasLoader
Loads a generated ConfigAtlas from atlas.json and the config files it lists.
Inherits: RefCounted
var atlas := ConfigAtlas.new()var loader := Archmage.AtlasLoader.new()var opts := Archmage.AtlasOptions.new().with_blacklist(["balance"])var err := loader.load_atlas("res://configs/atlas.json", "res://configs", atlas, opts)if err != OK: push_error(loader.get_error_message())The loader reads atlas.json, applies the atlas modifier, loads each item that is not skipped, merges the override files into it, resolves the references between entries, and calls Archmage.Atlas.on_loaded(). Create a new atlas for each load.
load_atlas_async() does the same work without blocking the main thread:
var err := await loader.load_atlas_async("res://configs/atlas.json", "res://configs", atlas, opts)The progress signal reports the items loaded so far, such as for a loading screen:
loader.progress.connect(_on_load_progress)
func _on_load_progress(loaded: int, total: int, _key: String) -> void: progress_bar.max_value = total progress_bar.value = loadedcancel() stops a running load before its next item. The load then returns ERR_SKIP, and the atlas is partly filled: do not use it.
load_atlas() and load_atlas_async() return one of these codes:
OKon success.ERR_INVALID_PARAMETER: an invalid option, such as an unknown key in the whitelist, an empty variant, or an override root that is not a directory.- The code of the file system, such as
ERR_FILE_NOT_FOUND, when a file cannot be read. ERR_PARSE_ERROR: a file is not valid JSON, atlas.json does not have its expected shape, or theload_jsonof an item returned an error message: a value has the wrong JSON type, such as a string for an int field, or a value is invalid, such as a duration.ERR_DOES_NOT_EXIST: atlas.json has no file for an item that is loaded.ERR_INVALID_DATA: a reference has no entry (Archmage.Atlas.bind_refs()failed), or an item has an unknown mapping.FAILED:AtlasExtension.on_loaded()returned an error message.ERR_BUSY: another loader is loading the same atlas, or this loader has not finished an earlier load. In the second case,get_error_message()keeps the message of the earlier load.ERR_SKIP:cancel()was called during the load.
Signals
Section titled “Signals”progress
Section titled “progress”signal progress(loaded: int, total: int, key: String)Emitted when the items to load are known, with loaded 0 and an empty key, and after each item is loaded, with the number of items loaded so far and the key of that item. total is the number of items to load, which does not include the items that the whitelist or the blacklist skips. load_atlas() emits it on the calling thread, and load_atlas_async() on the main thread.
Methods
Section titled “Methods”get_error_message()
Section titled “get_error_message()”func get_error_message() -> StringReturns the message of the last failed load, or an empty string when it succeeded. The message starts with <archmage> and includes context such as the item key and the file path. A message from AtlasExtension.on_loaded() is returned unchanged.
load_atlas()
Section titled “load_atlas()”func load_atlas(atlas_file: String, cfg_root: String, atlas: Archmage.Atlas, options: Archmage.AtlasOptions = null) -> ErrorLoads atlas from atlas_file on the calling thread. The file paths in atlas.json are relative to cfg_root. Returns OK or an error code (see the class description); get_error_message() then returns the message.
load_atlas_async()
Section titled “load_atlas_async()”func load_atlas_async(atlas_file: String, cfg_root: String, atlas: Archmage.Atlas, options: Archmage.AtlasOptions = null) -> ErrorLoads atlas as load_atlas() does, without blocking the main thread, and returns the same codes. Call it on the main thread with await.
Threads of the WorkerThreadPool read and parse the files of the items and fill their objects, for at most Archmage.AtlasOptions.with_max_concurrency() items at a time; the Archmage.FS methods that read files are called on these threads. The atlas modifier, the logger, Archmage.Atlas.bind_refs() and Archmage.Atlas.on_loaded() run on the main thread. Without thread support, as in a Web export without threads, the items are loaded on the main thread, one per frame.
Do not use atlas until the load finishes, because its objects are filled over several frames. To keep using the loaded configs during a reload, load into a new atlas and replace the old one when the load succeeds.
cancel()
Section titled “cancel()”func cancel() -> voidStops the running load before it starts its next item, or before it resolves the references when all items are loaded. The load then returns ERR_SKIP, and get_error_message() returns <archmage> load canceled. load_atlas_async() still waits for the items that are being loaded on worker threads. A canceled load does not call Archmage.Atlas.bind_refs() or Archmage.Atlas.on_loaded(), and the atlas is partly filled: do not use it.
Call it on the thread that runs the load: during load_atlas_async(), on the main thread, such as from a button; during load_atlas(), from a handler of progress. It has no effect when no load is running.
merge_json()
Section titled “merge_json()”static func merge_json(target: Variant, patch: Variant) -> VariantMerges patch into target and returns the result. This is how the files of a Archmage.AtlasItem.MAPPING_MANY item and the override files are combined:
- Two objects (Dictionary) are merged key by key: a key of
patchthattargetlacks is added, and the values of a key in both are merged by these rules. Keys only intargetare kept. - Otherwise,
patchreplacestarget, also when it is an array ornull.
null is a value, not a deletion: a key whose value in patch is null is set to null in the result, not removed. The generated code then sets a null field to its default value, and a null config entry stays null. target is changed in place when both are objects.