void EditorResourcePreview::_thread() { while (!exit) { preview_sem->wait(); preview_mutex->lock(); if (queue.size()) { QueueItem item = queue.front()->get(); 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); preview_mutex->unlock(); } else { preview_mutex->unlock(); Ref<ImageTexture> texture; Ref<ImageTexture> small_texture; int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); thumbnail_size *= EDSCALE; if (item.resource.is_valid()) { _generate_preview(texture, small_texture, item, String()); //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); } else { String temp_path = EditorSettings::get_singleton()->get_cache_dir(); String cache_base = ProjectSettings::get_singleton()->globalize_path(item.path).md5_text(); cache_base = temp_path.plus_file("resthumb-" + cache_base); //does not have it, try to load a cached thumbnail String file = cache_base + ".txt"; FileAccess *f = FileAccess::open(file, FileAccess::READ); if (!f) { // No cache found, generate _generate_preview(texture, small_texture, item, cache_base); } else { uint64_t modtime = FileAccess::get_modified_time(item.path); int tsize = f->get_line().to_int64(); bool has_small_texture = f->get_line().to_int(); uint64_t last_modtime = f->get_line().to_int64(); bool cache_valid = true; if (tsize != thumbnail_size) { cache_valid = false; memdelete(f); } else if (last_modtime != modtime) { String last_md5 = f->get_line(); String md5 = FileAccess::get_md5(item.path); memdelete(f); if (last_md5 != md5) { cache_valid = false; } else { //update modified time f = FileAccess::open(file, FileAccess::WRITE); f->store_line(itos(modtime)); f->store_line(itos(has_small_texture)); f->store_line(md5); memdelete(f); } } else { memdelete(f); } if (cache_valid) { Ref<Image> img; img.instance(); Ref<Image> small_img; small_img.instance(); if (img->load(cache_base + ".png") != OK) { cache_valid = false; } else { texture.instance(); texture->create_from_image(img, Texture::FLAG_FILTER); if (has_small_texture) { if (small_img->load(cache_base + "_small.png") != OK) { cache_valid = false; } else { small_texture.instance(); small_texture->create_from_image(small_img, Texture::FLAG_FILTER); } } } } if (!cache_valid) { _generate_preview(texture, small_texture, item, cache_base); } } _preview_ready(item.path, texture, small_texture, item.id, item.function, item.userdata); } } } else { preview_mutex->unlock(); } } }
void EditorResourcePreview::_thread() { //print_line("begin thread"); while (!exit) { //print_line("wait for semaphore"); preview_sem->wait(); preview_mutex->lock(); //print_line("blue team go"); if (queue.size()) { QueueItem item = queue.front()->get(); queue.pop_front(); if (cache.has(item.path)) { //already has it because someone loaded it, just let it know it's ready if (item.resource.is_valid()) { item.path += ":" + itos(cache[item.path].last_hash); //keep last hash (see description of what this is in condition below) } _preview_ready(item.path, cache[item.path].preview, item.id, item.function, item.userdata); preview_mutex->unlock(); } else { preview_mutex->unlock(); Ref<Texture> texture; //print_line("pop from queue "+item.path); int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size"); thumbnail_size *= EDSCALE; if (item.resource.is_valid()) { texture = _generate_preview(item, String()); //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, item.id, item.function, item.userdata); } else { String temp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp"); String cache_base = Globals::get_singleton()->globalize_path(item.path).md5_text(); cache_base = temp_path.plus_file("resthumb-" + cache_base); //does not have it, try to load a cached thumbnail String file = cache_base + ".txt"; //print_line("cachetxt at "+file); FileAccess *f = FileAccess::open(file, FileAccess::READ); if (!f) { //print_line("generate because not cached"); //generate texture = _generate_preview(item, cache_base); } else { uint64_t modtime = FileAccess::get_modified_time(item.path); int tsize = f->get_line().to_int64(); uint64_t last_modtime = f->get_line().to_int64(); bool cache_valid = true; if (tsize != thumbnail_size) { cache_valid = false; memdelete(f); } else if (last_modtime != modtime) { String last_md5 = f->get_line(); String md5 = FileAccess::get_md5(item.path); memdelete(f); if (last_md5 != md5) { cache_valid = false; } else { //update modified time f = FileAccess::open(file, FileAccess::WRITE); f->store_line(itos(modtime)); f->store_line(md5); memdelete(f); } } else { memdelete(f); } if (cache_valid) { texture = ResourceLoader::load(cache_base + ".png", "ImageTexture", true); if (!texture.is_valid()) { //well f**k cache_valid = false; } } if (!cache_valid) { texture = _generate_preview(item, cache_base); } } //print_line("notify of preview ready"); _preview_ready(item.path, texture, item.id, item.function, item.userdata); } } } else { preview_mutex->unlock(); } } }