Browse Source

Fix issues regarding reload of resources in imported scenes. Closes #10017

Juan Linietsky 8 years ago
parent
commit
d39e79e7ec

+ 3 - 2
core/io/resource_format_binary.cpp

@@ -1005,7 +1005,7 @@ ResourceInteractiveLoaderBinary::~ResourceInteractiveLoaderBinary() {
 		memdelete(f);
 }
 
-Ref<ResourceInteractiveLoader> ResourceFormatLoaderBinary::load_interactive(const String &p_path, Error *r_error) {
+Ref<ResourceInteractiveLoader> 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<ResourceInteractiveLoader> ResourceFormatLoaderBinary::load_interactive(cons
 	}
 
 	Ref<ResourceInteractiveLoaderBinary> 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);

+ 1 - 1
core/io/resource_format_binary.h

@@ -101,7 +101,7 @@ public:
 
 class ResourceFormatLoaderBinary : public ResourceFormatLoader {
 public:
-	virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, Error *r_error = NULL);
+	virtual Ref<ResourceInteractiveLoader> 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<String> *p_extensions) const;
 	virtual void get_recognized_extensions(List<String> *p_extensions) const;
 	virtual bool handles_type(const String &p_type) const;

+ 1 - 1
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()) {

+ 47 - 35
core/io/resource_loader.cpp

@@ -109,10 +109,10 @@ public:
 	ResourceInteractiveLoaderDefault() {}
 };
 
-Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const String &p_path, Error *r_error) {
+Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const String &p_path, const String &p_original_path, Error *r_error) {
 
 	//either this
-	Ref<Resource> res = load(p_path, p_path, r_error);
+	Ref<Resource> res = load(p_path, p_original_path, r_error);
 	if (res.is_null())
 		return Ref<ResourceInteractiveLoader>();
 
@@ -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<ResourceInteractiveLoader> ril = load_interactive(p_path, r_error);
+	Ref<ResourceInteractiveLoader> 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<String> *
 
 ///////////////////////////////////
 
+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);
-		}
-#endif
-
-		return res;
+	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
 
-	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<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) {
@@ -262,7 +274,7 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_
 		if (!loader[i]->recognize_path(path, p_type_hint))
 			continue;
 		found = true;
-		Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(path, r_error);
+		Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(path, local_path, r_error);
 		if (ril.is_null())
 			continue;
 		if (!p_no_cache)

+ 5 - 1
core/io/resource_loader.h

@@ -57,7 +57,7 @@ public:
 
 class ResourceFormatLoader {
 public:
-	virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, Error *r_error = NULL);
+	virtual Ref<ResourceInteractiveLoader> 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<String> *p_extensions) const = 0;
 	virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
@@ -96,6 +96,10 @@ class ResourceLoader {
 
 	static SelfList<Resource>::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<ResourceInteractiveLoader> 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);

+ 3 - 0
editor/editor_file_system.cpp

@@ -1509,6 +1509,8 @@ void EditorFileSystem::reimport_files(const Vector<String> &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() {

+ 49 - 19
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<String> &p_resources) {
+	print_line("reimporting");
+	List<String> 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<String>::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<PackedScene> 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<Ref<Resource> > cached;
 	ResourceCache::get_cached_resources(&cached);
 	List<Ref<Resource> > to_clear; //clear internal resources from previous scene from being used
 	for (List<Ref<Resource> >::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<Texture>(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<StringName> tl;

+ 1 - 0
editor/editor_node.h

@@ -422,6 +422,7 @@ private:
 	void _prepare_history();
 
 	void _fs_changed();
+	void _resources_reimported(const Vector<String> &p_resources);
 	void _sources_changed(bool p_exist);
 
 	void _node_renamed();

+ 2 - 1
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;
 }

+ 3 - 2
scene/resources/scene_format_text.cpp

@@ -891,7 +891,7 @@ String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) {
 
 /////////////////////
 
-Ref<ResourceInteractiveLoader> ResourceFormatLoaderText::load_interactive(const String &p_path, Error *r_error) {
+Ref<ResourceInteractiveLoader> 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<ResourceInteractiveLoader> ResourceFormatLoaderText::load_interactive(const
 	}
 
 	Ref<ResourceInteractiveLoaderText> 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);

+ 1 - 1
scene/resources/scene_format_text.h

@@ -108,7 +108,7 @@ public:
 
 class ResourceFormatLoaderText : public ResourceFormatLoader {
 public:
-	virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, Error *r_error = NULL);
+	virtual Ref<ResourceInteractiveLoader> 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<String> *p_extensions) const;
 	virtual void get_recognized_extensions(List<String> *p_extensions) const;
 	virtual bool handles_type(const String &p_type) const;