浏览代码

Added proper resource preview cache invalidation, fixes #5342

Juan Linietsky 9 年之前
父节点
当前提交
6442dfb73b

+ 7 - 0
tools/editor/editor_file_system.cpp

@@ -34,6 +34,7 @@
 #include "editor_node.h"
 #include "io/resource_saver.h"
 #include "editor_settings.h"
+#include "editor_resource_preview.h"
 
 EditorFileSystem *EditorFileSystem::singleton=NULL;
 
@@ -848,6 +849,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const S
 			continue;
 
 		}
+
 		if (_check_meta_sources(p_dir->files[i]->meta)) {
 			ItemAction ia;
 			ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED;
@@ -858,6 +860,8 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const S
 		} else {
 			p_dir->files[i]->meta.sources_changed=false;
 		}
+
+		EditorResourcePreview::get_singleton()->check_for_invalidation(p_dir->get_file_path(i));
 	}
 
 	for(int i=0;i<p_dir->subdirs.size();i++) {
@@ -1328,6 +1332,7 @@ void EditorFileSystem::update_file(const String& p_file) {
 	fs->files[cpos]->modified_time=FileAccess::get_modified_time(p_file);
 	fs->files[cpos]->meta=_get_meta(p_file);
 
+	EditorResourcePreview::get_singleton()->call_deferred("check_for_invalidation",p_file);
 	call_deferred("emit_signal","filesystem_changed"); //update later
 
 }
@@ -1341,6 +1346,8 @@ void EditorFileSystem::_bind_methods() {
 
 }
 
+
+
 EditorFileSystem::EditorFileSystem() {
 
 

+ 1 - 0
tools/editor/editor_file_system.h

@@ -236,6 +236,7 @@ public:
 	EditorFileSystemDirectory *get_path(const String& p_path);
 	String get_file_type(const String& p_file) const;
 	EditorFileSystemDirectory* find_file(const String& p_file,int* r_index) const;
+
 	EditorFileSystem();
 	~EditorFileSystem();
 };

+ 1 - 0
tools/editor/editor_node.cpp

@@ -2846,6 +2846,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 				if (mt!=E->get()->get_last_modified_time()) {
 					E->get()->reload_from_file();
 				}
+
 			}
 
 

+ 34 - 0
tools/editor/editor_resource_preview.cpp

@@ -66,16 +66,20 @@ void EditorResourcePreview::_preview_ready(const String& p_str,const Ref<Texture
 
 	String path = p_str;
 	uint32_t hash=0;
+	uint64_t modified_time=0;
 
 	if (p_str.begins_with("ID:")) {
 		hash=p_str.get_slicec(':',2).to_int();
 		path="ID:"+p_str.get_slicec(':',1);
+	} else {
+		modified_time = FileAccess::get_modified_time(path);
 	}
 
 	Item item;
 	item.order=order++;
 	item.preview=p_texture;
 	item.last_hash=hash;
+	item.modified_time=modified_time;
 
 	cache[path]=item;
 
@@ -263,6 +267,8 @@ void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource>& p
 	preview_mutex->lock();
 
 	String path_id = "ID:"+itos(p_res->get_instance_ID());
+
+
 	if (cache.has(path_id) && cache[path_id].last_hash==p_res->hash_edited_version()) {
 
 		cache[path_id].order=order++;
@@ -272,6 +278,8 @@ void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource>& p
 
 	}
 
+	cache.erase(path_id); //erase if exists, since it will be regen
+
 	//print_line("send to thread "+p_path);
 	QueueItem item;
 	item.function=p_receiver_func;
@@ -322,6 +330,32 @@ EditorResourcePreview* EditorResourcePreview::get_singleton() {
 void EditorResourcePreview::_bind_methods() {
 
 	ObjectTypeDB::bind_method("_preview_ready",&EditorResourcePreview::_preview_ready);
+	ObjectTypeDB::bind_method(_MD("check_for_invalidation","path"),&EditorResourcePreview::check_for_invalidation);
+
+
+	ADD_SIGNAL(MethodInfo("preview_invalidated",PropertyInfo(Variant::STRING,"path")));
+}
+
+bool EditorResourcePreview::check_for_invalidation(const String& p_path) {
+
+	preview_mutex->lock();
+
+	bool call_invalidated=false;
+	if (cache.has(p_path)) {
+
+		uint64_t modified_time = FileAccess::get_modified_time(p_path);
+		if (modified_time!=cache[p_path].modified_time) {
+			cache.erase(p_path);
+			call_invalidated=true;
+		}
+	}
+
+	preview_mutex->unlock();
+
+	if (call_invalidated) {//do outside mutex
+		call_deferred("emit_signal","preview_invalidated",p_path);
+	}
+
 }
 
 EditorResourcePreview::EditorResourcePreview() {

+ 4 - 0
tools/editor/editor_resource_preview.h

@@ -93,6 +93,7 @@ class EditorResourcePreview : public Node {
 		Ref<Texture> preview;
 		int order;
 		uint32_t last_hash;
+		uint64_t modified_time;
 	};
 
 	int order;
@@ -106,6 +107,8 @@ class EditorResourcePreview : public Node {
 	void _thread();
 
 	Vector<Ref<EditorResourcePreviewGenerator> > preview_generators;
+
+
 protected:
 
 	static void _bind_methods();
@@ -118,6 +121,7 @@ public:
 	void queue_edited_resource_preview(const Ref<Resource>& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata);
 
 	void add_preview_generator(const Ref<EditorResourcePreviewGenerator>& p_generator);
+	bool check_for_invalidation(const String& p_path);
 
 	EditorResourcePreview();
 	~EditorResourcePreview();

+ 25 - 0
tools/editor/scenes_dock.cpp

@@ -189,6 +189,7 @@ void ScenesDock::_notification(int p_what) {
 			initialized=true;
 
 			EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"_fs_changed");
+			EditorResourcePreview::get_singleton()->connect("preview_invalidated",this,"_preview_invalidated");
 
 			button_reload->set_icon( get_icon("Reload","EditorIcons"));
 			button_favorite->set_icon( get_icon("Favorites","EditorIcons"));
@@ -663,6 +664,27 @@ void ScenesDock::_go_to_dir(const String& p_dir){
 
 
 }
+
+void ScenesDock::_preview_invalidated(const String& p_path) {
+
+	if (p_path.get_base_dir()==path && search_box->get_text()==String() && file_list_vb->is_visible()) {
+
+
+		for(int i=0;i<files->get_item_count();i++) {
+
+			if (files->get_item_metadata(i)==p_path) {
+				//re-request preview
+				Array udata;
+				udata.resize(2);
+				udata[0]=i;
+				udata[1]=files->get_item_text(i);
+				EditorResourcePreview::get_singleton()->queue_resource_preview(p_path,this,"_thumbnail_done",udata);
+				break;
+			}
+		}
+	}
+}
+
 void ScenesDock::_fs_changed() {
 
 	button_hist_prev->set_disabled(history_pos==0);
@@ -1620,6 +1642,9 @@ void ScenesDock::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("drop_data_fw"), &ScenesDock::drop_data_fw);
 	ObjectTypeDB::bind_method(_MD("_files_list_rmb_select"),&ScenesDock::_files_list_rmb_select);
 
+	ObjectTypeDB::bind_method(_MD("_preview_invalidated"),&ScenesDock::_preview_invalidated);
+
+
 	ADD_SIGNAL(MethodInfo("instance"));
 	ADD_SIGNAL(MethodInfo("open"));
 

+ 2 - 0
tools/editor/scenes_dock.h

@@ -168,6 +168,8 @@ class ScenesDock : public VBoxContainer {
 	bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
 	void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
 
+	void _preview_invalidated(const String& p_path);
+
 protected:
 	void _notification(int p_what);
 	static void _bind_methods();