Last active
August 10, 2024 11:06
-
-
Save apples/63ecb59e0dadbb0ea60a710e618b6504 to your computer and use it in GitHub Desktop.
Shallow resource loader designed to load PackedScene files without loading their external resource dependencies.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@tool | |
extends RefCounted | |
## ShallowResourceLoader | |
## | |
## Shallowly loads a resource without loading external dependencies. | |
## Dependencies are replaced by an instance of PlaceholderExternalResource. | |
## Dependencies which have already been loaded and which are in the cache are not replaced. | |
## Placeholder resources will be stored in the cache using the resource_path they are replacing. | |
## | |
## For scenes, other instanced scenes are also loaded recursively, unless recursive_scenes is false. | |
## Each instanced scene is loaded shallowly, and will be cached using its original path. | |
## | |
## The returned resource itself will not be cached. | |
## | |
## The typical use case for this is to shallowly load a [class PackedScene], | |
## and then use [method PackedScene.get_state] to examine it, | |
## while avoiding loading all of its resource dependencies such as models and textures. | |
## You could use this method to load other Resource types, but may get type errors. | |
## Similar to load(), but does not load any additional external resources. | |
## [param resource_path]: The path of the Resource to load. | |
## [param recursive_scenes]: When true, external scenes are also loaded recursively. Note: these WILL be cached. | |
## Returns the loaded Resource. Note: the resource's resource_path will be empty, and it will not be cached. | |
func load_without_dependencies(resource_path: String, recursive_scenes: bool = true) -> Resource: | |
# We need to store the placeholders or they'll be removed from the cache. | |
var placeholder_instances: Array[Resource] = [] | |
# get_dependencies also performs a shallow load of the resource, but unfortunately there's no way to access the result. | |
for dep: String in ResourceLoader.get_dependencies(resource_path): | |
var dep_path := dep.get_slice("::", 2) | |
# If the resource is already loaded and cached, we can just use that. | |
if ResourceLoader.has_cached(dep_path): | |
continue | |
var placeholder: Resource | |
# Unfortunately we need to use EditorInterface in order to check if something is a scene. | |
# This means that this code cannot be used in an exported build. | |
# We could just check the file extension instead, it should generally be a .tscn, .scn, or .escn file. | |
if recursive_scenes and EditorInterface.get_resource_filesystem().get_file_type(dep_path) == "PackedScene": | |
placeholder = load_without_dependencies(dep_path) | |
else: | |
placeholder = PlaceholderExternalResource.new() | |
# take_over_path isn't really necessary here, since we know the resource isn't in the cache, | |
# but I figure it makes the intent clear: we want to add the placeholder to the cache. | |
placeholder.take_over_path(dep_path) | |
placeholder_instances.append(placeholder) | |
# Loading the resource with CACHE_MODE_IGNORE ensure that it doesn't get added to the cache. | |
# This is kind of a moot effort, since all the external resources (or their placeholders) are still cached. | |
return ResourceLoader.load(resource_path, "", ResourceLoader.CACHE_MODE_IGNORE) | |
## A placeholder representing an external resource. | |
class PlaceholderExternalResource extends Resource: | |
func _to_string() -> String: | |
return "<Placeholder for: %s>" % resource_path |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment