From d39e79e7ec8e010c251d9df3ece7cb7675a2c7a5 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Thu, 31 Aug 2017 18:57:03 -0300 Subject: [PATCH] Fix issues regarding reload of resources in imported scenes. Closes #10017 --- core/io/resource_format_binary.cpp | 5 +- core/io/resource_format_binary.h | 2 +- core/io/resource_import.cpp | 2 +- core/io/resource_loader.cpp | 82 +++++++++++++---------- core/io/resource_loader.h | 6 +- editor/editor_file_system.cpp | 3 + editor/editor_node.cpp | 68 +++++++++++++------ editor/editor_node.h | 1 + editor/import/resource_importer_scene.cpp | 3 +- scene/resources/scene_format_text.cpp | 5 +- scene/resources/scene_format_text.h | 2 +- 11 files changed, 116 insertions(+), 63 deletions(-) diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 965d11e4147..f44492248ec 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -1005,7 +1005,7 @@ ResourceInteractiveLoaderBinary::~ResourceInteractiveLoaderBinary() { memdelete(f); } -Ref ResourceFormatLoaderBinary::load_interactive(const String &p_path, Error *r_error) { +Ref ResourceFormatLoaderBinary::load_interactive(const String &p_path, const String &p_original_path, Error *r_error) { if (r_error) *r_error = ERR_FILE_CANT_OPEN; @@ -1019,7 +1019,8 @@ Ref ResourceFormatLoaderBinary::load_interactive(cons } Ref ria = memnew(ResourceInteractiveLoaderBinary); - ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path); + String path = p_original_path != "" ? p_original_path : p_path; + ria->local_path = ProjectSettings::get_singleton()->localize_path(path); ria->res_path = ria->local_path; //ria->set_local_path( Globals::get_singleton()->localize_path(p_path) ); ria->open(f); diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 1bd0d333c66..ab77c2c9d34 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -101,7 +101,7 @@ public: class ResourceFormatLoaderBinary : public ResourceFormatLoader { public: - virtual Ref load_interactive(const String &p_path, Error *r_error = NULL); + virtual Ref load_interactive(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); virtual void get_recognized_extensions_for_type(const String &p_type, List *p_extensions) const; virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String &p_type) const; diff --git a/core/io/resource_import.cpp b/core/io/resource_import.cpp index 69ff791a3ad..be486a86a3c 100644 --- a/core/io/resource_import.cpp +++ b/core/io/resource_import.cpp @@ -119,7 +119,7 @@ RES ResourceFormatImporter::load(const String &p_path, const String &p_original_ return RES(); } - RES res = ResourceLoader::load(pat.path, pat.type, false, r_error); + RES res = ResourceLoader::_load(pat.path, p_path, pat.type, false, r_error); #ifdef TOOLS_ENABLED if (res.is_valid()) { diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 30ae9f5681e..4f266df43e9 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -109,10 +109,10 @@ public: ResourceInteractiveLoaderDefault() {} }; -Ref ResourceFormatLoader::load_interactive(const String &p_path, Error *r_error) { +Ref ResourceFormatLoader::load_interactive(const String &p_path, const String &p_original_path, Error *r_error) { //either this - Ref res = load(p_path, p_path, r_error); + Ref res = load(p_path, p_original_path, r_error); if (res.is_null()) return Ref(); @@ -126,7 +126,7 @@ RES ResourceFormatLoader::load(const String &p_path, const String &p_original_pa String path = p_path; //or this must be implemented - Ref ril = load_interactive(p_path, r_error); + Ref ril = load_interactive(p_path, p_original_path, r_error); if (!ril.is_valid()) return RES(); ril->set_local_path(p_original_path); @@ -157,6 +157,34 @@ void ResourceFormatLoader::get_dependencies(const String &p_path, List * /////////////////////////////////// +RES ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, bool p_no_cache, Error *r_error) { + + bool found = false; + + // Try all loaders and pick the first match for the type hint + for (int i = 0; i < loader_count; i++) { + + if (!loader[i]->recognize_path(p_path, p_type_hint)) { + continue; + } + found = true; + RES res = loader[i]->load(p_path, p_original_path != String() ? p_original_path : p_path, r_error); + if (res.is_null()) { + continue; + } + + return res; + } + + if (found) { + ERR_EXPLAIN("Failed loading resource: " + p_path); + } else { + ERR_EXPLAIN("No loader found for resource: " + p_path); + } + ERR_FAIL_V(RES()); + return RES(); +} + RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) { if (r_error) @@ -183,45 +211,29 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p if (OS::get_singleton()->is_stdout_verbose()) print_line("load resource: " + path); - bool found = false; - // Try all loaders and pick the first match for the type hint - for (int i = 0; i < loader_count; i++) { + RES res = _load(path, local_path, p_type_hint, p_no_cache, r_error); - if (!loader[i]->recognize_path(path, p_type_hint)) { - continue; - } - found = true; - RES res = loader[i]->load(path, path, r_error); - if (res.is_null()) { - continue; - } - if (!p_no_cache) - res->set_path(local_path); + if (res.is_null()) { + return RES(); + } + if (!p_no_cache) + res->set_path(local_path); - if (xl_remapped) - res->set_as_translation_remapped(true); + if (xl_remapped) + res->set_as_translation_remapped(true); #ifdef TOOLS_ENABLED - res->set_edited(false); - if (timestamp_on_load) { - uint64_t mt = FileAccess::get_modified_time(path); - //printf("mt %s: %lli\n",remapped_path.utf8().get_data(),mt); - res->set_last_modified_time(mt); - } + res->set_edited(false); + if (timestamp_on_load) { + uint64_t mt = FileAccess::get_modified_time(path); + //printf("mt %s: %lli\n",remapped_path.utf8().get_data(),mt); + res->set_last_modified_time(mt); + } #endif - return res; - } - - if (found) { - ERR_EXPLAIN("Failed loading resource: " + path); - } else { - ERR_EXPLAIN("No loader found for resource: " + path); - } - ERR_FAIL_V(RES()); - return RES(); + return res; } Ref ResourceLoader::load_interactive(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) { @@ -262,7 +274,7 @@ Ref ResourceLoader::load_interactive(const String &p_ if (!loader[i]->recognize_path(path, p_type_hint)) continue; found = true; - Ref ril = loader[i]->load_interactive(path, r_error); + Ref ril = loader[i]->load_interactive(path, local_path, r_error); if (ril.is_null()) continue; if (!p_no_cache) diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 91f0c939bf1..a71a5685695 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -57,7 +57,7 @@ public: class ResourceFormatLoader { public: - virtual Ref load_interactive(const String &p_path, Error *r_error = NULL); + virtual Ref load_interactive(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); virtual void get_recognized_extensions(List *p_extensions) const = 0; virtual void get_recognized_extensions_for_type(const String &p_type, List *p_extensions) const; @@ -96,6 +96,10 @@ class ResourceLoader { static SelfList::List remapped_list; + friend class ResourceFormatImporter; + //internal load function + static RES _load(const String &p_path, const String &p_original_path, const String &p_type_hint, bool p_no_cache, Error *r_error); + public: static Ref load_interactive(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL); static RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index c175886d14e..3f4d466086d 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -1509,6 +1509,8 @@ void EditorFileSystem::reimport_files(const Vector &p_files) { if (!is_scanning()) { emit_signal("filesystem_changed"); } + + emit_signal("resources_reimported", p_files); } void EditorFileSystem::_bind_methods() { @@ -1524,6 +1526,7 @@ void EditorFileSystem::_bind_methods() { ADD_SIGNAL(MethodInfo("filesystem_changed")); ADD_SIGNAL(MethodInfo("sources_changed", PropertyInfo(Variant::BOOL, "exist"))); + ADD_SIGNAL(MethodInfo("resources_reimported", PropertyInfo(Variant::POOL_STRING_ARRAY, "resources"))); } void EditorFileSystem::_update_extensions() { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 15de8206aad..8575cd164fa 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -382,20 +382,23 @@ void EditorNode::_fs_changed() { continue; if (E->get()->get_import_path() != String()) { - //imported resource +//this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback +//imported resource +#if 0 uint64_t mt = FileAccess::get_modified_time(E->get()->get_import_path()); if (mt != E->get()->get_import_last_modified_time()) { print_line("success"); changed.push_back(E->get()); } +#endif + continue; + } - } else { - uint64_t mt = FileAccess::get_modified_time(E->get()->get_path()); + uint64_t mt = FileAccess::get_modified_time(E->get()->get_path()); - if (mt != E->get()->get_last_modified_time()) { - changed.push_back(E->get()); - } + if (mt != E->get()->get_last_modified_time()) { + changed.push_back(E->get()); } } @@ -410,6 +413,33 @@ void EditorNode::_fs_changed() { _mark_unsaved_scenes(); } +void EditorNode::_resources_reimported(const Vector &p_resources) { + print_line("reimporting"); + List scenes; //will load later + + for (int i = 0; i < p_resources.size(); i++) { + String file_type = ResourceLoader::get_resource_type(p_resources[i]); + if (file_type == "PackedScene") { + scenes.push_back(p_resources[i]); + //reload later if needed, first go with normal resources + continue; + } + + if (!ResourceCache::has(p_resources[i])) { + continue; //not loaded, no need to reload + } + //reload normally + Resource *resource = ResourceCache::get(p_resources[i]); + if (resource) { + resource->reload_from_file(); + } + } + + for (List::Element *E = scenes.front(); E; E = E->next()) { + reload_scene(E->get()); + } +} + void EditorNode::_sources_changed(bool p_exist) { if (waiting_for_first_scan) { @@ -2857,6 +2887,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b dependency_errors.clear(); + print_line("actually loading it"); Error err; Ref sdata = ResourceLoader::load(lpath, "", true, &err); if (!sdata.is_valid()) { @@ -4179,30 +4210,25 @@ void EditorNode::_file_access_close_error_notify(const String &p_str) { void EditorNode::reload_scene(const String &p_path) { - //first of all, reload textures as they might have changed on disk + //first of all, reload internal textures, materials, meshes, etc. as they might have changed on disk + print_line("reloading: " + p_path); List > cached; ResourceCache::get_cached_resources(&cached); List > to_clear; //clear internal resources from previous scene from being used for (List >::Element *E = cached.front(); E; E = E->next()) { - if (E->get()->get_path().begins_with(p_path + "::")) //subresources of existing scene + if (E->get()->get_path().find("::") != -1) { + print_line(E->get()->get_path()); + } + if (E->get()->get_path().begins_with(p_path + "::")) { //subresources of existing scene to_clear.push_back(E->get()); - - if (!cast_to(E->get().ptr())) - continue; - if (!E->get()->get_path().is_resource_file() && !E->get()->get_path().is_abs_path()) - continue; - if (!FileAccess::exists(E->get()->get_path())) - continue; - uint64_t mt = FileAccess::get_modified_time(E->get()->get_path()); - if (mt != E->get()->get_last_modified_time()) { - E->get()->reload_from_file(); } } //so reload reloads everything, clear subresources of previous scene while (to_clear.front()) { + print_line("bye bye: " + to_clear.front()->get()->get_path()); to_clear.front()->get()->set_path(""); to_clear.pop_front(); } @@ -4234,7 +4260,8 @@ void EditorNode::reload_scene(const String &p_path) { //remove scene _remove_scene(scene_idx); //reload scene - load_scene(p_path); + + load_scene(p_path, true, false, true, true); //adjust index so tab is back a the previous position editor_data.move_edited_scene_to_index(scene_idx); get_undo_redo()->clear_history(); @@ -4426,6 +4453,8 @@ void EditorNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_dim_timeout"), &EditorNode::_dim_timeout); ClassDB::bind_method(D_METHOD("_check_gui_base_size"), &EditorNode::_check_gui_base_size); + ClassDB::bind_method(D_METHOD("_resources_reimported"), &EditorNode::_resources_reimported); + ADD_SIGNAL(MethodInfo("play_pressed")); ADD_SIGNAL(MethodInfo("pause_pressed")); ADD_SIGNAL(MethodInfo("stop_pressed")); @@ -5454,6 +5483,7 @@ EditorNode::EditorNode() { EditorFileSystem::get_singleton()->connect("sources_changed", this, "_sources_changed"); EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_fs_changed"); + EditorFileSystem::get_singleton()->connect("resources_reimported", this, "_resources_reimported"); { List tl; diff --git a/editor/editor_node.h b/editor/editor_node.h index 445ef4922ee..c3ceee350a0 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -422,6 +422,7 @@ private: void _prepare_history(); void _fs_changed(); + void _resources_reimported(const Vector &p_resources); void _sources_changed(bool p_exist); void _node_renamed(); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 7fa76713f3e..594728d2e0d 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -1167,7 +1167,8 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p memdelete(scene); - EditorNode::get_singleton()->reload_scene(p_source_file); + //this is not the time to reimport, wait until import process is done, import file is saved, etc. + //EditorNode::get_singleton()->reload_scene(p_source_file); return OK; } diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index fea5c11dec6..14e2ef83f82 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -891,7 +891,7 @@ String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) { ///////////////////// -Ref ResourceFormatLoaderText::load_interactive(const String &p_path, Error *r_error) { +Ref ResourceFormatLoaderText::load_interactive(const String &p_path, const String &p_original_path, Error *r_error) { if (r_error) *r_error = ERR_CANT_OPEN; @@ -905,7 +905,8 @@ Ref ResourceFormatLoaderText::load_interactive(const } Ref ria = memnew(ResourceInteractiveLoaderText); - ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path); + String path = p_original_path != "" ? p_original_path : p_path; + ria->local_path = ProjectSettings::get_singleton()->localize_path(path); ria->res_path = ria->local_path; //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); ria->open(f); diff --git a/scene/resources/scene_format_text.h b/scene/resources/scene_format_text.h index 193bcf71126..a72a62037cc 100644 --- a/scene/resources/scene_format_text.h +++ b/scene/resources/scene_format_text.h @@ -108,7 +108,7 @@ public: class ResourceFormatLoaderText : public ResourceFormatLoader { public: - virtual Ref load_interactive(const String &p_path, Error *r_error = NULL); + virtual Ref load_interactive(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); virtual void get_recognized_extensions_for_type(const String &p_type, List *p_extensions) const; virtual void get_recognized_extensions(List *p_extensions) const; virtual bool handles_type(const String &p_type) const;