Skip to content

Commit

Permalink
Fix loading of cyclic scenes from GDScript
Browse files Browse the repository at this point in the history
  • Loading branch information
adamscott committed Jun 18, 2024
1 parent 7b63ac4 commit d8169fd
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 4 deletions.
19 changes: 19 additions & 0 deletions core/io/resource_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,25 @@ Ref<Resource> ResourceLoader::load(const String &p_path, const String &p_type_hi
return res;
}

// Returns a shallow reference of the loading resource.
// Will fail if the resource is not loading.
Ref<Resource> ResourceLoader::get_loading_resource(const String &p_path, Error *r_error) {
ERR_FAIL_COND_V(r_error == nullptr, nullptr);
*r_error = OK;

String local_path = _validate_local_path(p_path);
{
MutexLock thread_load_lock(thread_load_mutex);

if (!thread_load_tasks.has(local_path)) {
*r_error = FAILED;
return nullptr;
}

return thread_load_tasks[local_path].resource;
}
}

Ref<ResourceLoader::LoadToken> ResourceLoader::_load_start(const String &p_path, const String &p_type_hint, LoadThreadMode p_thread_mode, ResourceFormatLoader::CacheMode p_cache_mode) {
String local_path = _validate_local_path(p_path);

Expand Down
1 change: 1 addition & 0 deletions core/io/resource_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ class ResourceLoader {
static bool is_within_load() { return load_nesting > 0; };

static Ref<Resource> load(const String &p_path, const String &p_type_hint = "", ResourceFormatLoader::CacheMode p_cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE, Error *r_error = nullptr);
static Ref<Resource> get_loading_resource(const String &p_path, Error *r_error);
static bool exists(const String &p_path, const String &p_type_hint = "");

static void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions);
Expand Down
16 changes: 12 additions & 4 deletions modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4296,20 +4296,28 @@ void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) {
}
} else {
// TODO: Don't load if validating: use completion cache.
String resource_type = ResourceLoader::get_resource_type(p_preload->resolved_path);

// Must load GDScript separately to permit cyclic references
// as ResourceLoader::load() detects and rejects those.
if (ResourceLoader::get_resource_type(p_preload->resolved_path) == "GDScript") {
if (resource_type == "GDScript") {
Error err = OK;
Ref<GDScript> res = GDScriptCache::get_shallow_script(p_preload->resolved_path, err, parser->script_path);
p_preload->resource = res;
if (err != OK) {
push_error(vformat(R"(Could not preload resource script "%s".)", p_preload->resolved_path), p_preload->path);
}
} else {
p_preload->resource = ResourceLoader::load(p_preload->resolved_path);
if (p_preload->resource.is_null()) {
push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path);
// Permit cyclic loading if `ResourceLoader` is currently loading that resource.
Error err = OK;
Ref<PackedScene> res = ResourceLoader::get_loading_resource(p_preload->resolved_path, &err);
if (err == OK) {
p_preload->resource = res;
} else {
p_preload->resource = ResourceLoader::load(p_preload->resolved_path);
if (p_preload->resource.is_null()) {
push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path);
}
}
}
}
Expand Down

0 comments on commit d8169fd

Please sign in to comment.