diff options
author | kobewi <kobewi4e@gmail.com> | 2022-08-19 18:14:57 +0200 |
---|---|---|
committer | kobewi <kobewi4e@gmail.com> | 2023-05-10 14:03:10 +0200 |
commit | 04317e9cedea324c467bf9d619942e31eabf51a5 (patch) | |
tree | 82624c119ebf0b6e1b37b88dc723134aeefa26a3 /editor/editor_resource_preview.cpp | |
parent | 74c34aed38cecf502c257938d268d5f522557a0e (diff) | |
download | redot-engine-04317e9cedea324c467bf9d619942e31eabf51a5.tar.gz |
Add metadata to resource previews
Diffstat (limited to 'editor/editor_resource_preview.cpp')
-rw-r--r-- | editor/editor_resource_preview.cpp | 115 |
1 files changed, 63 insertions, 52 deletions
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index 6eef4e5a5a..7dea1a7e01 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -35,6 +35,7 @@ #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "core/object/message_queue.h" +#include "core/variant/variant_utility.cpp" #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_scale.h" @@ -48,17 +49,17 @@ bool EditorResourcePreviewGenerator::handles(const String &p_type) const { ERR_FAIL_V_MSG(false, "EditorResourcePreviewGenerator::_handles needs to be overridden."); } -Ref<Texture2D> EditorResourcePreviewGenerator::generate(const Ref<Resource> &p_from, const Size2 &p_size) const { +Ref<Texture2D> EditorResourcePreviewGenerator::generate(const Ref<Resource> &p_from, const Size2 &p_size, Dictionary &p_metadata) const { Ref<Texture2D> preview; - if (GDVIRTUAL_CALL(_generate, p_from, p_size, preview)) { + if (GDVIRTUAL_CALL(_generate, p_from, p_size, p_metadata, preview)) { return preview; } ERR_FAIL_V_MSG(Ref<Texture2D>(), "EditorResourcePreviewGenerator::_generate needs to be overridden."); } -Ref<Texture2D> EditorResourcePreviewGenerator::generate_from_path(const String &p_path, const Size2 &p_size) const { +Ref<Texture2D> EditorResourcePreviewGenerator::generate_from_path(const String &p_path, const Size2 &p_size, Dictionary &p_metadata) const { Ref<Texture2D> preview; - if (GDVIRTUAL_CALL(_generate_from_path, p_path, p_size, preview)) { + if (GDVIRTUAL_CALL(_generate_from_path, p_path, p_size, p_metadata, preview)) { return preview; } @@ -66,7 +67,7 @@ Ref<Texture2D> EditorResourcePreviewGenerator::generate_from_path(const String & if (!res.is_valid()) { return res; } - return generate(res, p_size); + return generate(res, p_size, p_metadata); } bool EditorResourcePreviewGenerator::generate_small_preview_automatically() const { @@ -83,8 +84,8 @@ bool EditorResourcePreviewGenerator::can_generate_small_preview() const { void EditorResourcePreviewGenerator::_bind_methods() { GDVIRTUAL_BIND(_handles, "type"); - GDVIRTUAL_BIND(_generate, "resource", "size"); - GDVIRTUAL_BIND(_generate_from_path, "path", "size"); + GDVIRTUAL_BIND(_generate, "resource", "size", "metadata"); + GDVIRTUAL_BIND(_generate_from_path, "path", "size", "metadata"); GDVIRTUAL_BIND(_generate_small_preview_automatically); GDVIRTUAL_BIND(_can_generate_small_preview); } @@ -99,35 +100,31 @@ void EditorResourcePreview::_thread_func(void *ud) { erp->_thread(); } -void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Texture2D> &p_texture, const Ref<Texture2D> &p_small_texture, ObjectID id, const StringName &p_func, const Variant &p_ud) { - String path = p_str; +void EditorResourcePreview::_preview_ready(const String &p_path, int p_hash, const Ref<Texture2D> &p_texture, const Ref<Texture2D> &p_small_texture, ObjectID id, const StringName &p_func, const Variant &p_ud, const Dictionary &p_metadata) { { MutexLock lock(preview_mutex); - uint32_t hash = 0; uint64_t modified_time = 0; - if (p_str.begins_with("ID:")) { - hash = uint32_t(p_str.get_slicec(':', 2).to_int()); - path = "ID:" + p_str.get_slicec(':', 1); - } else { - modified_time = FileAccess::get_modified_time(path); + if (!p_path.begins_with("ID:")) { + modified_time = FileAccess::get_modified_time(p_path); } Item item; item.order = order++; item.preview = p_texture; item.small_preview = p_small_texture; - item.last_hash = hash; + item.last_hash = p_hash; item.modified_time = modified_time; + item.preview_metadata = p_metadata; - cache[path] = item; + cache[p_path] = item; } - MessageQueue::get_singleton()->push_call(id, p_func, path, p_texture, p_small_texture, p_ud); + MessageQueue::get_singleton()->push_call(id, p_func, p_path, p_texture, p_small_texture, p_ud); } -void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<ImageTexture> &r_small_texture, const QueueItem &p_item, const String &cache_base) { +void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<ImageTexture> &r_small_texture, const QueueItem &p_item, const String &cache_base, Dictionary &p_metadata) { String type; if (p_item.resource.is_valid()) { @@ -155,9 +152,9 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref< Ref<Texture2D> generated; if (p_item.resource.is_valid()) { - generated = preview_generators[i]->generate(p_item.resource, Vector2(thumbnail_size, thumbnail_size)); + generated = preview_generators.write[i]->generate(p_item.resource, Vector2(thumbnail_size, thumbnail_size), p_metadata); } else { - generated = preview_generators[i]->generate_from_path(p_item.path, Vector2(thumbnail_size, thumbnail_size)); + generated = preview_generators.write[i]->generate_from_path(p_item.path, Vector2(thumbnail_size, thumbnail_size), p_metadata); } r_texture = generated; @@ -165,10 +162,11 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref< if (preview_generators[i]->can_generate_small_preview()) { Ref<Texture2D> generated_small; + Dictionary d; if (p_item.resource.is_valid()) { - generated_small = preview_generators[i]->generate(p_item.resource, Vector2(small_thumbnail_size, small_thumbnail_size)); + generated_small = preview_generators.write[i]->generate(p_item.resource, Vector2(small_thumbnail_size, small_thumbnail_size), d); } else { - generated_small = preview_generators[i]->generate_from_path(p_item.path, Vector2(small_thumbnail_size, small_thumbnail_size)); + generated_small = preview_generators.write[i]->generate_from_path(p_item.path, Vector2(small_thumbnail_size, small_thumbnail_size), d); } r_small_texture = generated_small; } @@ -185,9 +183,9 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref< } if (!p_item.resource.is_valid()) { - // cache the preview in case it's a resource on disk + // Cache the preview in case it's a resource on disk. if (r_texture.is_valid()) { - //wow it generated a preview... save cache + // Wow it generated a preview... save cache. bool has_small_texture = r_small_texture.is_valid(); ResourceSaver::save(r_texture, cache_base + ".png"); if (has_small_texture) { @@ -195,14 +193,16 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref< } Ref<FileAccess> f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE); ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + cache_base + ".txt'. Check user write permissions."); - f->store_line(itos(thumbnail_size)); - f->store_line(itos(has_small_texture)); - f->store_line(itos(FileAccess::get_modified_time(p_item.path))); - f->store_line(FileAccess::get_md5(p_item.path)); + _write_preview_cache(f, thumbnail_size, has_small_texture, FileAccess::get_modified_time(p_item.path), FileAccess::get_md5(p_item.path), p_metadata); } } } +Variant EditorResourcePreview::get_preview_metadata(const String &p_path, const String &p_meta) const { + ERR_FAIL_COND_V(!cache.has(p_path), Variant()); + return cache[p_path].preview_metadata.get(p_meta, Variant()); +} + void EditorResourcePreview::_iterate() { preview_mutex.lock(); @@ -211,13 +211,8 @@ void EditorResourcePreview::_iterate() { queue.pop_front(); if (cache.has(item.path)) { - //already has it because someone loaded it, just let it know it's ready - String path = item.path; - if (item.resource.is_valid()) { - path += ":" + itos(cache[item.path].last_hash); //keep last hash (see description of what this is in condition below) - } - - _preview_ready(path, cache[item.path].preview, cache[item.path].small_preview, item.id, item.function, item.userdata); + // Already has it because someone loaded it, just let it know it's ready. + _preview_ready(item.path, cache[item.path].last_hash, cache[item.path].preview, cache[item.path].small_preview, item.id, item.function, item.userdata, cache[item.path].preview_metadata); preview_mutex.unlock(); } else { @@ -230,28 +225,31 @@ void EditorResourcePreview::_iterate() { thumbnail_size *= EDSCALE; if (item.resource.is_valid()) { - _generate_preview(texture, small_texture, item, String()); + Dictionary preview_metadata; + _generate_preview(texture, small_texture, item, String(), preview_metadata); - //adding hash to the end of path (should be ID:<objid>:<hash>) because of 5 argument limit to call_deferred - _preview_ready(item.path + ":" + itos(item.resource->hash_edited_version()), texture, small_texture, item.id, item.function, item.userdata); + _preview_ready(item.path, item.resource->hash_edited_version(), texture, small_texture, item.id, item.function, item.userdata, preview_metadata); } else { + Dictionary preview_metadata; String temp_path = EditorPaths::get_singleton()->get_cache_dir(); String cache_base = ProjectSettings::get_singleton()->globalize_path(item.path).md5_text(); cache_base = temp_path.path_join("resthumb-" + cache_base); - //does not have it, try to load a cached thumbnail + // Does not have it, try to load a cached thumbnail. String file = cache_base + ".txt"; Ref<FileAccess> f = FileAccess::open(file, FileAccess::READ); if (f.is_null()) { - // No cache found, generate - _generate_preview(texture, small_texture, item, cache_base); + // No cache found, generate. + _generate_preview(texture, small_texture, item, cache_base, preview_metadata); } else { uint64_t modtime = FileAccess::get_modified_time(item.path); - int tsize = f->get_line().to_int(); - bool has_small_texture = f->get_line().to_int(); - uint64_t last_modtime = f->get_line().to_int(); + int tsize; + bool has_small_texture; + uint64_t last_modtime; + String hash; + _read_preview_cache(f, &tsize, &has_small_texture, &last_modtime, &hash, &preview_metadata); bool cache_valid = true; @@ -266,7 +264,7 @@ void EditorResourcePreview::_iterate() { if (last_md5 != md5) { cache_valid = false; } else { - //update modified time + // Update modified time. Ref<FileAccess> f2 = FileAccess::open(file, FileAccess::WRITE); if (f2.is_null()) { @@ -274,10 +272,7 @@ void EditorResourcePreview::_iterate() { // some proper cleanup/disabling of resource preview generation. ERR_PRINT("Cannot create file '" + file + "'. Check user write permissions."); } else { - f2->store_line(itos(thumbnail_size)); - f2->store_line(itos(has_small_texture)); - f2->store_line(itos(modtime)); - f2->store_line(md5); + _write_preview_cache(f2, thumbnail_size, has_small_texture, modtime, md5, preview_metadata); } } } else { @@ -308,10 +303,10 @@ void EditorResourcePreview::_iterate() { } if (!cache_valid) { - _generate_preview(texture, small_texture, item, cache_base); + _generate_preview(texture, small_texture, item, cache_base, preview_metadata); } } - _preview_ready(item.path, texture, small_texture, item.id, item.function, item.userdata); + _preview_ready(item.path, 0, texture, small_texture, item.id, item.function, item.userdata, preview_metadata); } } @@ -320,6 +315,22 @@ void EditorResourcePreview::_iterate() { } } +void EditorResourcePreview::_write_preview_cache(Ref<FileAccess> p_file, int p_thumbnail_size, bool p_has_small_texture, uint64_t p_modified_time, String p_hash, const Dictionary &p_metadata) { + p_file->store_line(itos(p_thumbnail_size)); + p_file->store_line(itos(p_has_small_texture)); + p_file->store_line(itos(p_modified_time)); + p_file->store_line(p_hash); + p_file->store_line(VariantUtilityFunctions::var_to_str(p_metadata).replace("\n", " ")); +} + +void EditorResourcePreview::_read_preview_cache(Ref<FileAccess> p_file, int *r_thumbnail_size, bool *r_has_small_texture, uint64_t *r_modified_time, String *r_hash, Dictionary *r_metadata) { + *r_thumbnail_size = p_file->get_line().to_int(); + *r_has_small_texture = p_file->get_line().to_int(); + *r_modified_time = p_file->get_line().to_int(); + *r_hash = p_file->get_line(); + *r_metadata = VariantUtilityFunctions::str_to_var(p_file->get_line()); +} + void EditorResourcePreview::_thread() { exited.clear(); while (!exit.is_set()) { |