From 2cd2ca7bbc892eccc635b1c4aea80c956c9b92dc Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 1 Feb 2017 09:45:45 -0300 Subject: Lot of work in new importer, importing textures now works. --- core/dvector.h | 2 +- core/image.cpp | 2 +- core/io/config_file.cpp | 5 + core/io/config_file.h | 2 + core/io/resource_import.cpp | 87 +++- core/io/resource_import.h | 40 +- core/io/resource_loader.h | 2 +- core/object.h | 1 + core/pair.h | 9 + core/register_core_types.cpp | 9 +- core/resource.cpp | 1 + core/resource.h | 8 + main/main.cpp | 31 -- scene/io/resource_format_image.cpp | 3 + scene/io/resource_format_image.h | 3 + scene/register_scene_types.cpp | 12 +- scene/resources/texture.cpp | 329 +++++++++++++ scene/resources/texture.h | 71 +++ tools/editor/SCsub | 1 + tools/editor/editor_file_system.cpp | 517 +++++++++++---------- tools/editor/editor_file_system.h | 53 +-- tools/editor/editor_node.cpp | 440 +++--------------- tools/editor/editor_node.h | 13 +- tools/editor/filesystem_dock.cpp | 117 ++--- tools/editor/filesystem_dock.h | 5 + tools/editor/import/resource_import_texture.cpp | 274 +++++++++++ tools/editor/import/resource_import_texture.h | 43 ++ tools/editor/import_dock.cpp | 331 +++++++++++++ tools/editor/import_dock.h | 42 ++ .../io_plugins/editor_texture_import_plugin.h | 5 + tools/editor/property_editor.cpp | 40 +- tools/editor/property_editor.h | 4 +- 32 files changed, 1705 insertions(+), 797 deletions(-) create mode 100644 tools/editor/import/resource_import_texture.cpp create mode 100644 tools/editor/import/resource_import_texture.h create mode 100644 tools/editor/import_dock.cpp create mode 100644 tools/editor/import_dock.h diff --git a/core/dvector.h b/core/dvector.h index cac9e8ef85..53a29738f7 100644 --- a/core/dvector.h +++ b/core/dvector.h @@ -89,7 +89,7 @@ class PoolVector { if (!alloc) return; - ERR_FAIL_COND(alloc->lock>0); +// ERR_FAIL_COND(alloc->lock>0); should not be illegal to lock this for copy on write, as it's a copy on write after all if (alloc->refcount.get()==1) return; //nothing to do diff --git a/core/image.cpp b/core/image.cpp index ed505b0f77..2d038691f2 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -2155,7 +2155,7 @@ void Image::fix_alpha_edges() { return; //not needed PoolVector dcopy = data; - PoolVector::Read rp = data.read(); + PoolVector::Read rp = dcopy.read(); const uint8_t *srcptr=rp.ptr(); PoolVector::Write wp = data.write(); diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index a9de740806..b944906e78 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -119,7 +119,10 @@ void ConfigFile::get_section_keys(const String& p_section,List *r_keys) } +void ConfigFile::erase_section(const String& p_section) { + values.erase(p_section); +} Error ConfigFile::save(const String& p_path){ @@ -215,6 +218,8 @@ void ConfigFile::_bind_methods(){ ClassDB::bind_method(_MD("get_sections"),&ConfigFile::_get_sections); ClassDB::bind_method(_MD("get_section_keys","section"),&ConfigFile::_get_section_keys); + ClassDB::bind_method(_MD("erase_section","section"),&ConfigFile::erase_section); + ClassDB::bind_method(_MD("load:Error","path"),&ConfigFile::load); ClassDB::bind_method(_MD("save:Error","path"),&ConfigFile::save); diff --git a/core/io/config_file.h b/core/io/config_file.h index 397342f90f..c9c4a9fbc0 100644 --- a/core/io/config_file.h +++ b/core/io/config_file.h @@ -54,6 +54,8 @@ public: void get_sections(List *r_sections) const; void get_section_keys(const String& p_section,List *r_keys) const; + void erase_section(const String& p_section); + Error save(const String& p_path); Error load(const String& p_path); diff --git a/core/io/resource_import.cpp b/core/io/resource_import.cpp index 92b5d1de40..18fd8d25e7 100644 --- a/core/io/resource_import.cpp +++ b/core/io/resource_import.cpp @@ -30,7 +30,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String& p_path, PathAndTy return OK; } else if (err!=OK) { - ERR_PRINTS("ResourceFormatImporter::load - "+p_path+":"+itos(lines)+" error: "+error_text); + ERR_PRINTS("ResourceFormatImporter::load - "+p_path+".import:"+itos(lines)+" error: "+error_text); memdelete(f); return err; } @@ -71,12 +71,20 @@ RES ResourceFormatImporter::load(const String &p_path,const String& p_original_p } - return ResourceLoader::load(pat.path,pat.type,false,r_error); + RES res = ResourceLoader::load(pat.path,pat.type,false,r_error); + +#ifdef TOOLS_ENABLED + res->set_import_last_modified_time( res->get_last_modified_time() ); //pass this, if used + res->set_import_path(pat.path); +#endif + + return res; } void ResourceFormatImporter::get_recognized_extensions(List *p_extensions) const{ + print_line("getting exts from: "+itos(importers.size())); Set found; for (Set< Ref >::Element *E=importers.front();E;E=E->next()) { @@ -84,6 +92,7 @@ void ResourceFormatImporter::get_recognized_extensions(List *p_extension E->get()->get_recognized_extensions(&local_exts); for (List::Element *F=local_exts.front();F;F=F->next()) { if (!found.has(F->get())) { + print_line("adding ext "+String(F->get())); p_extensions->push_back(F->get()); found.insert(F->get()); } @@ -93,10 +102,14 @@ void ResourceFormatImporter::get_recognized_extensions(List *p_extension void ResourceFormatImporter::get_recognized_extensions_for_type(const String& p_type,List *p_extensions) const{ + if (p_type=="") { + return get_recognized_extensions(p_extensions); + } + Set found; for (Set< Ref >::Element *E=importers.front();E;E=E->next()) { - if (!ClassDB::is_parent_class(p_type,E->get()->get_resource_type())) + if (!ClassDB::is_parent_class(E->get()->get_resource_type(),p_type)) continue; List local_exts; @@ -112,13 +125,21 @@ void ResourceFormatImporter::get_recognized_extensions_for_type(const String& p_ bool ResourceFormatImporter::recognize_path(const String& p_path,const String& p_for_type) const{ - return (p_path.get_extension().to_lower()=="import"); + return FileAccess::exists(p_path+".import"); + +} + +bool ResourceFormatImporter::can_be_imported(const String& p_path) const { + + return ResourceFormatLoader::recognize_path(p_path); } + bool ResourceFormatImporter::handles_type(const String& p_type) const { for (Set< Ref >::Element *E=importers.front();E;E=E->next()) { - if (ClassDB::is_parent_class(p_type,E->get()->get_resource_type())) + print_line("handles "+p_type+" base is "+E->get()->get_resource_type()); + if (ClassDB::is_parent_class(E->get()->get_resource_type(),p_type)) return true; } @@ -152,3 +173,59 @@ void ResourceFormatImporter::get_dependencies(const String& p_path,List return ResourceLoader::get_dependencies(pat.path,p_dependencies,p_add_types); } +Ref ResourceFormatImporter::get_importer_by_name(const String& p_name) { + + for (Set< Ref >::Element *E=importers.front();E;E=E->next()) { + if (E->get()->get_importer_name()==p_name) { + return E->get(); + } + } + + return Ref(); +} + + +void ResourceFormatImporter::get_importers_for_extension(const String& p_extension,List > *r_importers) { + + for (Set< Ref >::Element *E=importers.front();E;E=E->next()) { + List local_exts; + E->get()->get_recognized_extensions(&local_exts); + for (List::Element *F=local_exts.front();F;F=F->next()) { + if (p_extension.to_lower()==F->get()) { + r_importers->push_back(E->get()); + } + } + } +} + +Ref ResourceFormatImporter::get_importer_by_extension(const String& p_extension) { + + + Ref importer; + float priority=0; + + for (Set< Ref >::Element *E=importers.front();E;E=E->next()) { + + List local_exts; + E->get()->get_recognized_extensions(&local_exts); + for (List::Element *F=local_exts.front();F;F=F->next()) { + if (p_extension.to_lower()==F->get() && E->get()->get_priority() > priority) { + importer=E->get(); + priority=E->get()->get_priority(); + } + } + } + + return importer; +} + +String ResourceFormatImporter::get_import_base_path(const String& p_for_file) const { + + return "res://.import/"+p_for_file.get_file()+"-"+p_for_file.md5_text(); +} + +ResourceFormatImporter *ResourceFormatImporter::singleton=NULL; + +ResourceFormatImporter::ResourceFormatImporter() { + singleton=this; +} diff --git a/core/io/resource_import.h b/core/io/resource_import.h index d4b80030b2..d54308b6ed 100644 --- a/core/io/resource_import.h +++ b/core/io/resource_import.h @@ -15,35 +15,61 @@ class ResourceFormatImporter : public ResourceFormatLoader { Error _get_path_and_type(const String& p_path,PathAndType & r_path_and_type) const; + static ResourceFormatImporter *singleton; + Set< Ref > importers; public: + static ResourceFormatImporter *get_singleton() { return singleton; } 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; virtual void get_recognized_extensions_for_type(const String& p_type,List *p_extensions) const; - bool recognize_path(const String& p_path,const String& p_for_type=String()) const; - virtual bool handles_type(const String& p_type) const=0; - virtual String get_resource_type(const String &p_path) const=0; + virtual bool recognize_path(const String& p_path,const String& p_for_type=String()) const; + virtual bool handles_type(const String& p_type) const; + virtual String get_resource_type(const String &p_path) const; virtual void get_dependencies(const String& p_path,List *p_dependencies,bool p_add_types=false); + virtual bool can_be_imported(const String& p_path) const; + + + void add_importer(const Ref& p_importer) { importers.insert(p_importer); } + Ref get_importer_by_name(const String& p_name); + Ref get_importer_by_extension(const String& p_extension); + void get_importers_for_extension(const String& p_extension,List > *r_importers); + + String get_import_base_path(const String& p_for_file) const; + ResourceFormatImporter(); }; -class ResourceImporter { +class ResourceImporter : public Reference { + + GDCLASS(ResourceImporter,Reference) public: - virtual String get_name() const=0; + virtual String get_importer_name() const=0; virtual String get_visible_name() const=0; virtual void get_recognized_extensions(List *p_extensions) const=0; + virtual String get_save_extension() const=0; virtual String get_resource_type() const=0; + virtual float get_priority() const { return 1.0; } struct ImportOption { PropertyInfo option; Variant default_value; + + ImportOption(const PropertyInfo& p_info,const Variant& p_default) { option=p_info; default_value=p_default; } + ImportOption() {} }; - virtual void get_import_options(List *r_options)=0; - virtual RES import(const String& p_path,const Map& p_options)=0; + virtual int get_preset_count() const { return 0; } + virtual String get_preset_name(int p_idx) const { return String(); } + + virtual void get_import_options(List *r_options,int p_preset=0) const=0; + virtual bool get_option_visibility(const String& p_option,const Map& p_options) const=0; + + + virtual Error import(const String& p_source_file,const String& p_save_path,const Map& p_options,List* r_platform_variants)=0; }; diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 05a4d98d83..f464415e12 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -61,7 +61,7 @@ public: 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; - bool recognize_path(const String& p_path,const String& p_for_type=String()) const; + virtual bool recognize_path(const String& p_path,const String& p_for_type=String()) const; virtual bool handles_type(const String& p_type) const=0; virtual String get_resource_type(const String &p_path) const=0; virtual void get_dependencies(const String& p_path,List *p_dependencies,bool p_add_types=false); diff --git a/core/object.h b/core/object.h index b9a800afc4..3032452ccf 100644 --- a/core/object.h +++ b/core/object.h @@ -103,6 +103,7 @@ enum PropertyUsageFlags { PROPERTY_USAGE_SCRIPT_VARIABLE=8192, PROPERTY_USAGE_STORE_IF_NULL=16384, PROPERTY_USAGE_ANIMATE_AS_TRIGGER=32768, + PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED=65536, PROPERTY_USAGE_DEFAULT=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK, PROPERTY_USAGE_DEFAULT_INTL=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK|PROPERTY_USAGE_INTERNATIONALIZED, diff --git a/core/pair.h b/core/pair.h index d75cbed642..174ffb3883 100644 --- a/core/pair.h +++ b/core/pair.h @@ -39,4 +39,13 @@ struct Pair { Pair( F p_first, S p_second) { first=p_first; second=p_second; } }; +template +struct PairSort { + + bool operator()(const Pair& A, const Pair& B) const { + return A.first < B.first; + } +}; + + #endif // PAIR_H diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 8cbfdf0b01..ab94b56cdc 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -45,6 +45,7 @@ #include "compressed_translation.h" #include "io/translation_loader_po.h" #include "io/resource_format_binary.h" +#include "io/resource_import.h" #include "io/stream_peer_ssl.h" #include "os/input.h" #include "core/io/xml_parser.h" @@ -57,7 +58,7 @@ static ResourceFormatSaverBinary *resource_saver_binary=NULL; static ResourceFormatLoaderBinary *resource_loader_binary=NULL; - +static ResourceFormatImporter *resource_format_importer=NULL; static _ResourceLoader *_resource_loader=NULL; static _ResourceSaver *_resource_saver=NULL; @@ -105,6 +106,9 @@ void register_core_types() { resource_loader_binary = memnew( ResourceFormatLoaderBinary ); ResourceLoader::add_resource_format_loader(resource_loader_binary); + resource_format_importer = memnew( ResourceFormatImporter ); + ResourceLoader::add_resource_format_loader(resource_format_importer); + ClassDB::register_class(); @@ -183,7 +187,6 @@ void register_core_singletons() { GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("ClassDB",_classdb ) ); GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("Marshalls",_Marshalls::get_singleton() ) ); GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("TranslationServer",TranslationServer::get_singleton() ) ); - GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("TS",TranslationServer::get_singleton() ) ); GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("Input",Input::get_singleton() ) ); GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("InputMap",InputMap::get_singleton() ) ); @@ -207,6 +210,8 @@ void unregister_core_types() { memdelete(resource_saver_binary); if (resource_loader_binary) memdelete(resource_loader_binary); + if (resource_format_importer) + memdelete(resource_format_importer); memdelete( resource_format_po ); diff --git a/core/resource.cpp b/core/resource.cpp index 765000d662..9b5bac5f32 100644 --- a/core/resource.cpp +++ b/core/resource.cpp @@ -353,6 +353,7 @@ Resource::Resource() { #ifdef TOOLS_ENABLED last_modified_time=0; + import_last_modified_time=0; #endif subindex=0; diff --git a/core/resource.h b/core/resource.h index b2873e4866..b29077a3b8 100644 --- a/core/resource.h +++ b/core/resource.h @@ -66,6 +66,8 @@ friend class ResourceCache; #ifdef TOOLS_ENABLED uint64_t last_modified_time; + uint64_t import_last_modified_time; + String import_path; #endif bool local_to_scene; @@ -118,6 +120,12 @@ public: virtual void set_last_modified_time(uint64_t p_time) { last_modified_time=p_time; } uint64_t get_last_modified_time() const { return last_modified_time; } + virtual void set_import_last_modified_time(uint64_t p_time) { import_last_modified_time=p_time; } + uint64_t get_import_last_modified_time() const { return import_last_modified_time; } + + void set_import_path(const String& p_path) { import_path=p_path; } + String get_import_path() const { return import_path; } + #endif virtual RID get_rid() const; // some resources may offer conversion to RID diff --git a/main/main.cpp b/main/main.cpp index 6dde1e521c..094b6aedae 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -183,8 +183,6 @@ void Main::print_help(const char* p_binary) { #ifdef TOOLS_ENABLED OS::get_singleton()->print("\t-doctool FILE: Dump the whole engine api to FILE in XML format. If FILE exists, it will be merged.\n"); OS::get_singleton()->print("\t-nodocbase: Disallow dump the base types (used with -doctool).\n"); - OS::get_singleton()->print("\t-optimize FILE Save an optimized copy of scene to FILE.\n"); - OS::get_singleton()->print("\t-optimize_preset [preset] Use a given preset for optimization.\n"); OS::get_singleton()->print("\t-export [target] Export the project using given export target.\n"); #endif } @@ -1074,12 +1072,9 @@ bool Main::start() { String script; String test; String screen; - String optimize; - String optimize_preset; String _export_platform; String _import; String _import_script; - String dumpstrings; bool noquit=false; bool export_debug=false; bool project_manager_request = false; @@ -1108,10 +1103,6 @@ bool Main::start() { Engine::get_singleton()->_custom_level=args[i+1]; } else if (args[i]=="-test") { test=args[i+1]; - } else if (args[i]=="-optimize") { - optimize=args[i+1]; - } else if (args[i]=="-optimize_preset") { - optimize_preset=args[i+1]; } else if (args[i]=="-export") { editor=true; //needs editor _export_platform=args[i+1]; @@ -1125,9 +1116,6 @@ bool Main::start() { } else if (args[i]=="-import_script") { editor=true; //needs editor _import_script=args[i+1]; - } else if (args[i]=="-dumpstrings") { - editor=true; //needs editor - dumpstrings=args[i+1]; } else { // The parameter does not match anything known, don't skip the next argument parsed_pair=false; @@ -1162,10 +1150,6 @@ bool Main::start() { return false; } - if (optimize!="") - editor=true; //need editor - - #endif @@ -1399,22 +1383,7 @@ bool Main::start() { Error serr = editor_node->load_scene(local_game_path); - if (serr==OK) { - if (optimize!="") { - - editor_node->save_optimized_copy(optimize,optimize_preset); - if (!noquit) - sml->quit(); - } - - if (dumpstrings!="") { - - editor_node->save_translatable_strings(dumpstrings); - if (!noquit) - sml->quit(); - } - } } OS::get_singleton()->set_context(OS::CONTEXT_EDITOR); diff --git a/scene/io/resource_format_image.cpp b/scene/io/resource_format_image.cpp index 2d098d01f5..4d15ab86fd 100644 --- a/scene/io/resource_format_image.cpp +++ b/scene/io/resource_format_image.cpp @@ -27,6 +27,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "resource_format_image.h" + +#if 0 #include "scene/resources/texture.h" #include "io/image_loader.h" #include "globals.h" @@ -260,3 +262,4 @@ ResourceFormatLoaderImage::ResourceFormatLoaderImage() { GLOBAL_DEF("rendering/image_loader/repeat",false); } +#endif diff --git a/scene/io/resource_format_image.h b/scene/io/resource_format_image.h index 6e4ead2a0b..0638e97787 100644 --- a/scene/io/resource_format_image.h +++ b/scene/io/resource_format_image.h @@ -29,6 +29,8 @@ #ifndef RESOURCE_FORMAT_IMAGE_H #define RESOURCE_FORMAT_IMAGE_H +#if 0 + #include "io/resource_loader.h" #include "io/resource_saver.h" /** @@ -49,3 +51,4 @@ public: }; #endif +#endif diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 7e8a033c40..0ad140f7c3 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -230,7 +230,6 @@ #include "scene/resources/scene_format_text.h" -static ResourceFormatLoaderImage *resource_loader_image=NULL; //static ResourceFormatLoaderWAV *resource_loader_wav=NULL; @@ -245,6 +244,8 @@ static ResourceFormatLoaderText *resource_loader_text=NULL; static ResourceFormatLoaderDynamicFont *resource_loader_dynamic_font=NULL; +static ResourceFormatLoaderStreamTexture *resource_loader_stream_texture=NULL; + //static SceneStringNames *string_names; void register_scene_types() { @@ -255,14 +256,14 @@ void register_scene_types() { Node::init_node_hrcr(); - resource_loader_image = memnew( ResourceFormatLoaderImage ); - ResourceLoader::add_resource_format_loader( resource_loader_image ); - //resource_loader_wav = memnew( ResourceFormatLoaderWAV ); //ResourceLoader::add_resource_format_loader( resource_loader_wav ); resource_loader_dynamic_font = memnew( ResourceFormatLoaderDynamicFont ); ResourceLoader::add_resource_format_loader( resource_loader_dynamic_font ); + resource_loader_stream_texture = memnew( ResourceFormatLoaderStreamTexture); + ResourceLoader::add_resource_format_loader( resource_loader_stream_texture ); + #ifdef TOOLS_ENABLED //scene first! @@ -570,6 +571,7 @@ void register_scene_types() { ClassDB::register_virtual_class(); ClassDB::register_virtual_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); @@ -643,9 +645,9 @@ void unregister_scene_types() { clear_default_theme(); - memdelete( resource_loader_image ); // memdelete( resource_loader_wav ); memdelete( resource_loader_dynamic_font ); + memdelete( resource_loader_stream_texture ); #ifdef TOOLS_ENABLED diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index a1ad5d8237..a853b62254 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -453,6 +453,335 @@ ImageTexture::~ImageTexture() { VisualServer::get_singleton()->free( texture ); } +////////////////////////////////////////// + + + +uint32_t StreamTexture::get_flags() const { + + return flags; +} +Image::Format StreamTexture::get_format() const { + + return format; +} + + +Error StreamTexture::_load_data(const String& p_path,int &tw,int &th,int& flags,Image& image,int p_size_limit) { + + + FileAccess *f = FileAccess::open(p_path,FileAccess::READ); + ERR_FAIL_COND_V(!f,ERR_CANT_OPEN); + + uint8_t header[4]; + f->get_buffer(header,4); + if (header[0]!='G' || header[1]!='D' || header[2]!='S' || header[3]!='T') { + memdelete(f); + ERR_FAIL_COND_V(header[0]!='G' || header[1]!='D' || header[2]!='S' || header[3]!='T',ERR_FILE_CORRUPT); + } + + tw = f->get_32(); + th = f->get_32(); + flags= f->get_32(); //texture flags! + uint32_t df = f->get_32(); //data format + + print_line("width: "+itos(tw)); + print_line("height: "+itos(th)); + print_line("flags: "+itos(flags)); + print_line("df: "+itos(df)); + + if (!(df&FORMAT_BIT_STREAM)) { + p_size_limit=0; + } + + + if (df&FORMAT_BIT_LOSSLESS || df&FORMAT_BIT_LOSSY) { + //look for a PNG or WEBP file inside + + int sw=tw; + int sh=th; + + uint32_t mipmaps = f->get_32(); + uint32_t size = f->get_32(); + + print_line("mipmaps: "+itos(mipmaps)); + + while(mipmaps>1 && p_size_limit>0 && (sw>p_size_limit || sh>p_size_limit)) { + + f->seek(f->get_pos()+size); + mipmaps = f->get_32(); + size = f->get_32(); + + sw=MAX(sw>>1,1); + sh=MAX(sh>>1,1); + mipmaps--; + } + + //mipmaps need to be read independently, they will be later combined + Vector mipmap_images; + int total_size=0; + + for(int i=0;i pv; + pv.resize(size); + { + PoolVector::Write w = pv.write(); + f->get_buffer(w.ptr(),size); + } + + Image img; + if (df&FORMAT_BIT_LOSSLESS) { + img = Image::lossless_unpacker(pv); + } else { + img = Image::lossy_unpacker(pv); + } + + if (img.empty()) { + memdelete(f); + ERR_FAIL_COND_V(img.empty(),ERR_FILE_CORRUPT); + } + total_size+=img.get_data().size(); + + mipmap_images.push_back(img); + } + + print_line("mipmap read total: "+itos(mipmap_images.size())); + + + memdelete(f); //no longer needed + + if (mipmap_images.size()==1) { + + image=mipmap_images[0]; + return OK; + + } else { + PoolVector img_data; + img_data.resize(total_size); + + { + PoolVector::Write w=img_data.write(); + + int ofs=0; + for(int i=0;i id = mipmap_images[i].get_data(); + int len = id.size(); + PoolVector::Read r = id.read(); + copymem(&w[ofs],r.ptr(),len); + ofs+=len; + } + } + + image = Image(sw,sh,true,mipmap_images[0].get_format(),img_data); + return OK; + } + + } else { + + //look for regular format + Image::Format format = (Image::Format)(df&FORMAT_MASK_IMAGE_FORMAT); + bool mipmaps = df&FORMAT_BIT_HAS_MIPMAPS; + + if (!mipmaps) { + int size = Image::get_image_data_size(tw,th,format,0); + + PoolVector img_data; + img_data.resize(size); + + { + PoolVector::Write w=img_data.write(); + f->get_buffer(w.ptr(),size); + } + + memdelete(f); + + image = Image(tw,th,false,format,img_data); + return OK; + } else { + + int sw=tw; + int sh=th; + + int mipmaps = Image::get_image_required_mipmaps(tw,th,format); + int total_size = Image::get_image_data_size(tw,th,format,mipmaps); + int idx=0; + int ofs=0; + + + while(mipmaps>1 && p_size_limit>0 && (sw>p_size_limit || sh>p_size_limit)) { + + sw=MAX(sw>>1,1); + sh=MAX(sh>>1,1); + mipmaps--; + idx++; + } + + if (idx>0) { + ofs=Image::get_image_data_size(tw,th,format,idx-1); + } + + if (total_size - ofs <=0) { + memdelete(f); + ERR_FAIL_V(ERR_FILE_CORRUPT); + } + + f->seek(f->get_pos()+ofs); + + + PoolVector img_data; + img_data.resize(total_size - ofs); + + { + PoolVector::Write w=img_data.write(); + int bytes = f->get_buffer(w.ptr(),total_size - ofs); + + memdelete(f); + + if (bytes != total_size - ofs) { + ERR_FAIL_V(ERR_FILE_CORRUPT); + } + } + + image = Image(sw,sh,true,format,img_data); + + return OK; + } + } + + return ERR_BUG; //unreachable +} + +Error StreamTexture::load(const String& p_path) { + + + int lw,lh,lflags; + Image image; + Error err = _load_data(p_path,lw,lh,lflags,image); + if (err) + return err; + + VS::get_singleton()->texture_allocate(texture,image.get_width(),image.get_height(),image.get_format(),lflags); + VS::get_singleton()->texture_set_data(texture,image); + + w=lw; + h=lh; + flags=lflags; + path_to_file=p_path; + format=image.get_format(); + + return OK; +} +String StreamTexture::get_load_path() const { + + return path_to_file; +} + +int StreamTexture::get_width() const { + + return w; +} +int StreamTexture::get_height() const { + + return h; +} +RID StreamTexture::get_rid() const { + + return texture; +} + + +void StreamTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const { + + if ((w|h)==0) + return; + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,Rect2( p_pos, Size2(w,h)),texture,false,p_modulate,p_transpose); + +} +void StreamTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const { + + if ((w|h)==0) + return; + VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,p_rect,texture,p_tile,p_modulate,p_transpose); + +} +void StreamTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate, bool p_transpose) const{ + + if ((w|h)==0) + return; + VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,texture,p_src_rect,p_modulate,p_transpose); +} + +bool StreamTexture::has_alpha() const { + + return false; +} +void StreamTexture::set_flags(uint32_t p_flags){ + +} + +void StreamTexture::reload_from_file() { + + load(path_to_file); +} + +void StreamTexture::_bind_methods() { + + ClassDB::bind_method(_MD("load","path"),&StreamTexture::load); + ClassDB::bind_method(_MD("get_load_path"),&StreamTexture::get_load_path); + + ADD_PROPERTY( PropertyInfo(Variant::STRING,"load_path",PROPERTY_HINT_FILE,"*.stex"),_SCS("load"),_SCS("get_load_path")); +} + + +StreamTexture::StreamTexture() { + + format=Image::FORMAT_MAX; + flags=0; + w=0; + h=0; + + texture = VS::get_singleton()->texture_create(); +} + +StreamTexture::~StreamTexture() { + + VS::get_singleton()->free(texture); +} + + + +RES ResourceFormatLoaderStreamTexture::load(const String &p_path,const String& p_original_path,Error *r_error) { + + Ref st; + st.instance(); + Error err = st->load(p_path); + if (r_error) + *r_error=err; + if (err!=OK) + return RES(); + + return st; +} + +void ResourceFormatLoaderStreamTexture::get_recognized_extensions(List *p_extensions) const{ + + p_extensions->push_back("stex"); +} +bool ResourceFormatLoaderStreamTexture::handles_type(const String& p_type) const{ + return p_type=="StreamTexture"; + +} +String ResourceFormatLoaderStreamTexture::get_resource_type(const String &p_path) const{ + + if (p_path.get_extension().to_lower()=="stex") + return "StreamTexture"; + return ""; +} + + + + ////////////////////////////////////////// diff --git a/scene/resources/texture.h b/scene/resources/texture.h index aac3514af3..919c588894 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -31,6 +31,7 @@ #include "resource.h" #include "servers/visual_server.h" +#include "io/resource_loader.h" #include "math_2d.h" /** @@ -160,6 +161,76 @@ public: }; + +class StreamTexture : public Texture { + + GDCLASS( StreamTexture, Texture ); +public: + enum DataFormat { + DATA_FORMAT_IMAGE, + DATA_FORMAT_LOSSLESS, + DATA_FORMAT_LOSSY + }; + + enum FormatBits { + FORMAT_MASK_IMAGE_FORMAT=(1<<20)-1, + FORMAT_BIT_LOSSLESS=1<<20, + FORMAT_BIT_LOSSY=1<<21, + FORMAT_BIT_STREAM=1<<22, + FORMAT_BIT_HAS_MIPMAPS=1<<23, + }; + +private: + + Error _load_data(const String &p_path, int &tw, int &th, int& flags, Image& image, int p_size_limit=0); + String path_to_file; + RID texture; + Image::Format format; + uint32_t flags; + int w,h; + + virtual void reload_from_file(); + +protected: + + static void _bind_methods(); + +public: + + + uint32_t get_flags() const; + Image::Format get_format() const; + Error load(const String& p_path); + String get_load_path() const; + + int get_width() const; + int get_height() const; + virtual RID get_rid() const; + + virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const; + + virtual bool has_alpha() const; + virtual void set_flags(uint32_t p_flags); + + StreamTexture(); + ~StreamTexture(); + +}; + + +class ResourceFormatLoaderStreamTexture : public ResourceFormatLoader { +public: + 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; + virtual bool handles_type(const String& p_type) const; + virtual String get_resource_type(const String &p_path) const; + +}; + + + VARIANT_ENUM_CAST( ImageTexture::Storage ); class AtlasTexture : public Texture { diff --git a/tools/editor/SCsub b/tools/editor/SCsub index 85d4d11073..a0e6802348 100644 --- a/tools/editor/SCsub +++ b/tools/editor/SCsub @@ -78,3 +78,4 @@ if (env["tools"] == "yes"): SConscript('plugins/SCsub') SConscript('fileserver/SCsub') SConscript('io_plugins/SCsub') + SConscript('import/SCsub') diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp index 120cbb9712..f05aaa683c 100644 --- a/tools/editor/editor_file_system.cpp +++ b/tools/editor/editor_file_system.cpp @@ -34,8 +34,10 @@ #include "os/file_access.h" #include "editor_node.h" #include "io/resource_saver.h" +#include "io/resource_import.h" #include "editor_settings.h" #include "editor_resource_preview.h" +#include "variant_parser.h" EditorFileSystem *EditorFileSystem::singleton=NULL; @@ -115,75 +117,13 @@ String EditorFileSystemDirectory::get_file_path(int p_idx) const { return "res://"+file; } -bool EditorFileSystemDirectory::get_file_meta(int p_idx) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),""); - return files[p_idx]->meta.enabled; -} Vector EditorFileSystemDirectory::get_file_deps(int p_idx) const { ERR_FAIL_INDEX_V(p_idx,files.size(),Vector()); - return files[p_idx]->meta.deps; + return files[p_idx]->deps; } -Vector EditorFileSystemDirectory::get_missing_sources(int p_idx) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),Vector()); - Vector missing; - for(int i=0;imeta.sources.size();i++) { - if (files[p_idx]->meta.sources[i].missing) - missing.push_back(files[p_idx]->meta.sources[i].path); - } - - return missing; - - -} -bool EditorFileSystemDirectory::is_missing_sources(int p_idx) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),false); - for(int i=0;imeta.sources.size();i++) { - if (files[p_idx]->meta.sources[i].missing) - return true; - } - - return false; -} - -bool EditorFileSystemDirectory::have_sources_changed(int p_idx) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),false); - return files[p_idx]->meta.sources_changed; - -} - -int EditorFileSystemDirectory::get_source_count(int p_idx) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),0); - if (!files[p_idx]->meta.enabled) - return 0; - return files[p_idx]->meta.sources.size(); -} -String EditorFileSystemDirectory::get_source_file(int p_idx,int p_source) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),String()); - ERR_FAIL_INDEX_V(p_source,files[p_idx]->meta.sources.size(),String()); - if (!files[p_idx]->meta.enabled) - return String(); - - return files[p_idx]->meta.sources[p_source].path; - -} -bool EditorFileSystemDirectory::is_source_file_missing(int p_idx,int p_source) const { - - ERR_FAIL_INDEX_V(p_idx,files.size(),false); - ERR_FAIL_INDEX_V(p_source,files[p_idx]->meta.sources.size(),false); - if (!files[p_idx]->meta.enabled) - return false; - - return files[p_idx]->meta.sources[p_source].missing; -} StringName EditorFileSystemDirectory::get_file_type(int p_idx) const { @@ -210,7 +150,6 @@ void EditorFileSystemDirectory::_bind_methods() { ClassDB::bind_method(_MD("get_file","idx"),&EditorFileSystemDirectory::get_file); ClassDB::bind_method(_MD("get_file_path","idx"),&EditorFileSystemDirectory::get_file_path); ClassDB::bind_method(_MD("get_file_type","idx"),&EditorFileSystemDirectory::get_file_type); - ClassDB::bind_method(_MD("is_missing_sources","idx"),&EditorFileSystemDirectory::is_missing_sources); ClassDB::bind_method(_MD("get_name"),&EditorFileSystemDirectory::get_name); ClassDB::bind_method(_MD("get_path"),&EditorFileSystemDirectory::get_path); ClassDB::bind_method(_MD("get_parent:EditorFileSystemDirectory"),&EditorFileSystemDirectory::get_parent); @@ -244,42 +183,6 @@ EditorFileSystemDirectory::~EditorFileSystemDirectory() { - -EditorFileSystemDirectory::ImportMeta EditorFileSystem::_get_meta(const String& p_path) { - - return EditorFileSystemDirectory::ImportMeta(); -#if 0 - Ref imd = ResourceLoader::load_import_metadata(p_path); - EditorFileSystemDirectory::ImportMeta m; - if (imd.is_null()) { - m.enabled=false; - m.sources_changed=false; - } else { - m.enabled=true; - m.sources_changed=false; - - for(int i=0;iget_source_count();i++) { - EditorFileSystemDirectory::ImportMeta::Source s; - s.path=imd->get_source_path(i); - s.md5=imd->get_source_md5(i); - s.modified_time=0; - s.missing=false; - m.sources.push_back(s); - } - m.import_editor=imd->get_editor(); - } - - List deps; - ResourceLoader::get_dependencies(p_path,&deps); - for(List::Element *E=deps.front();E;E=E->next()) { - m.deps.push_back(E->get()); - } - - return m; -#endif -} - - void EditorFileSystem::_scan_filesystem() { ERR_FAIL_COND(!scanning || new_filesystem); @@ -292,7 +195,7 @@ void EditorFileSystem::_scan_filesystem() { String project=GlobalConfig::get_singleton()->get_resource_path(); - String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache"); + String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache2"); FileAccess *f =FileAccess::open(fscache,FileAccess::READ); if (f) { @@ -322,30 +225,14 @@ void EditorFileSystem::_scan_filesystem() { FileCache fc; fc.type=split[1]; fc.modification_time=split[2].to_int64(); - String meta = split[3].strip_edges(); - fc.meta.enabled=false; - if (meta.find("<>")!=-1){ - Vector spl = meta.split("<>"); - int sc = spl.size()-1; - if (sc%3==0){ - fc.meta.enabled=true; - fc.meta.import_editor=spl[0]; - fc.meta.sources.resize(sc/3); - for(int i=0;i dp = deps.split("<>"); for(int i=0;iget_project_settings_path().plus_file("filesystem_cache2"); + FileAccess *f=FileAccess::open(fscache,FileAccess::WRITE); + _save_filesystem_cache(filesystem,f); + f->close(); + memdelete(f); +} void EditorFileSystem::_thread_func(void *_userdata) { @@ -408,6 +302,8 @@ bool EditorFileSystem::_update_scan_actions() { bool fs_changed=false; + Vector reimports; + for (List::Element *E=scan_actions.front();E;E=E->next()) { ItemAction&ia = E->get(); @@ -472,18 +368,25 @@ bool EditorFileSystem::_update_scan_actions() { //print_line("*ACTION REMOVE FILE: "+ia.file); } break; - case ItemAction::ACTION_FILE_SOURCES_CHANGED: { + case ItemAction::ACTION_FILE_REIMPORT: { + int idx = ia.dir->find_file_index(ia.file); ERR_CONTINUE(idx==-1); String full_path = ia.dir->get_file_path(idx); - sources_changed.push_back(full_path); + reimports.push_back(full_path); + fs_changed=true; } break; } } + + if (reimports.size()) { + reimport_files(reimports); + + } scan_actions.clear(); return fs_changed; @@ -495,9 +398,10 @@ void EditorFileSystem::scan() { if (false /*&& bool(Globals::get_singleton()->get("debug/disable_scan"))*/) return; - if (scanning || scanning_sources|| thread) + if (scanning || scanning_changes|| thread) return; + _update_extensions(); abort_scan=false; if (!use_threads) { @@ -532,43 +436,6 @@ void EditorFileSystem::scan() { } -bool EditorFileSystem::_check_meta_sources(EditorFileSystemDirectory::ImportMeta & p_meta) { - - if (p_meta.enabled) { - - for(int j=0;j dirs; @@ -675,9 +540,11 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess for (List::Element*E=files.front();E;E=E->next(),idx++) { + String ext = E->get().get_extension().to_lower(); - if (!valid_extensions.has(ext)) + if (!valid_extensions.has(ext)) { continue; //invalid + } EditorFileSystemDirectory::FileInfo *fi = memnew( EditorFileSystemDirectory::FileInfo ); fi->file=E->get(); @@ -687,32 +554,45 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess FileCache *fc = file_cache.getptr(path); uint64_t mt = FileAccess::get_modified_time(path); - if (fc && fc->modification_time == mt) { + if (import_extensions.has(ext)) { - fi->meta=fc->meta; - fi->type=fc->type; - fi->modified_time=fc->modification_time; - } else { - fi->meta=_get_meta(path); - fi->type=ResourceLoader::get_resource_type(path); - fi->modified_time=mt; + //is imported + uint64_t import_mt=0; + if (FileAccess::exists(path+".import")) { + import_mt=FileAccess::get_modified_time(path+".import"); + } - } + if (fc && fc->modification_time==mt && fc->import_modification_time==import_mt) { + + fi->type=fc->type; + fi->modified_time=fc->modification_time; + fi->import_modified_time=fc->import_modification_time; + + } else { + + print_line("REIMPORT BECAUSE: time changed"); + fi->type=ResourceFormatImporter::get_singleton()->get_resource_type(path); + fi->modified_time=0; + fi->import_modified_time=0; - if (fi->meta.enabled) { - if (_check_meta_sources(fi->meta)) { ItemAction ia; - ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED; + ia.action=ItemAction::ACTION_FILE_REIMPORT; ia.dir=p_dir; ia.file=E->get(); scan_actions.push_back(ia); - fi->meta.sources_changed=true; - } else { - fi->meta.sources_changed=false; } - } else { - fi->meta.sources_changed=true; + //not imported, so just update type if changed + if (fc && fc->modification_time == mt) { + + fi->type=fc->type; + fi->modified_time=fc->modification_time; + fi->import_modified_time=0; + } else { + fi->type=ResourceLoader::get_resource_type(path); + fi->modified_time=mt; + fi->import_modified_time=0; + } } p_dir->files.push_back(fi); @@ -722,11 +602,13 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess } + void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const ScanProgress& p_progress) { uint64_t current_mtime = FileAccess::get_modified_time(p_dir->get_path()); bool updated_dir=false; + String cd = p_dir->get_path(); //print_line("dir: "+p_dir->get_path()+" MODTIME: "+itos(p_dir->modified_time)+" CTIME: "+itos(current_mtime)); @@ -751,7 +633,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const S //then scan files and directories and check what's different DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); - String cd = p_dir->get_path(); + da->change_dir(cd); da->list_dir_begin(); while (true) { @@ -807,7 +689,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const S String path = cd.plus_file(fi->file); fi->modified_time=FileAccess::get_modified_time(path); - fi->meta=_get_meta(path); + fi->import_modified_time=0; fi->type=ResourceLoader::get_resource_type(path); { @@ -817,19 +699,18 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const S ia.file=f; ia.new_file=fi; scan_actions.push_back(ia); - } - //take the chance and scan sources - if (_check_meta_sources(fi->meta)) { + } + + if (import_extensions.has(ext)) { + //if it can be imported, and it was added, it needs to be reimported + print_line("REIMPORT: file was not found before, reimport"); ItemAction ia; - ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED; + ia.action=ItemAction::ACTION_FILE_REIMPORT; ia.dir=p_dir; ia.file=f; scan_actions.push_back(ia); - fi->meta.sources_changed=true; - } else { - fi->meta.sources_changed=false; } } else { @@ -859,15 +740,39 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const S } - if (_check_meta_sources(p_dir->files[i]->meta)) { - ItemAction ia; - ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED; - ia.dir=p_dir; - ia.file=p_dir->files[i]->file; - scan_actions.push_back(ia); - p_dir->files[i]->meta.sources_changed=true; - } else { - p_dir->files[i]->meta.sources_changed=false; + if (import_extensions.has(p_dir->files[i]->file.get_extension().to_lower())) { + //check here if file must be imported or not + + String path = cd.plus_file(p_dir->files[i]->file); + + uint64_t mt = FileAccess::get_modified_time(path); + + bool reimport=false; + + if (mt!=p_dir->files[i]->modified_time) { + print_line("REIMPORT: modified time changed, reimport"); + reimport=true; //it was modified, must be reimported. + } else if (!FileAccess::exists(path+".import")) { + print_line("REIMPORT: no .import exists, reimport"); + reimport=true; //no .import file, obviously reimport + } else { + + uint64_t import_mt=FileAccess::get_modified_time(path+".import"); + if (import_mt!=p_dir->files[i]->import_modified_time) { + print_line("REIMPORT: import modified changed, reimport"); + reimport=true; + } + } + + if (reimport) { + + ItemAction ia; + ia.action=ItemAction::ACTION_FILE_REIMPORT; + ia.dir=p_dir; + ia.file=p_dir->files[i]->file; + scan_actions.push_back(ia); + } + } EditorResourcePreview::get_singleton()->check_for_invalidation(p_dir->get_file_path(i)); @@ -900,7 +805,7 @@ void EditorFileSystem::_thread_func_sources(void *_userdata) { sp.low=0; efs->_scan_fs_changes(efs->filesystem,sp); } - efs->scanning_sources_done=true; + efs->scanning_changes_done=true; } void EditorFileSystem::get_changed_sources(List *r_changed) { @@ -908,14 +813,15 @@ void EditorFileSystem::get_changed_sources(List *r_changed) { *r_changed=sources_changed; } -void EditorFileSystem::scan_sources() { +void EditorFileSystem::scan_changes() { - if (scanning || scanning_sources|| thread) + if (scanning || scanning_changes|| thread) return; + _update_extensions(); sources_changed.clear(); - scanning_sources=true; - scanning_sources_done=false; + scanning_changes=true; + scanning_changes_done=false; abort_scan=false; @@ -931,8 +837,8 @@ void EditorFileSystem::scan_sources() { if (_update_scan_actions()) emit_signal("filesystem_changed"); } - scanning_sources=false; - scanning_sources_done=true; + scanning_changes=false; + scanning_changes_done=true; emit_signal("sources_changed",sources_changed.size()>0); } else { @@ -987,11 +893,11 @@ void EditorFileSystem::_notification(int p_what) { if (use_threads) { - if (scanning_sources) { + if (scanning_changes) { - if (scanning_sources_done) { + if (scanning_changes_done) { - scanning_sources=false; + scanning_changes=false; set_process(false); @@ -1053,22 +959,13 @@ void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory*p_dir,Fi for(int i=0;ifiles.size();i++) { - String s=p_dir->files[i]->file+"::"+p_dir->files[i]->type+"::"+String::num(p_dir->files[i]->modified_time)+"::"; - if (p_dir->files[i]->meta.enabled) { - s+=p_dir->files[i]->meta.import_editor; - for(int j=0;jfiles[i]->meta.sources.size();j++){ - s+="<>"+p_dir->files[i]->meta.sources[j].path; - s+="<>"+p_dir->files[i]->meta.sources[j].md5; - s+="<>"+String::num(p_dir->files[i]->meta.sources[j].modified_time); - - } - } + String s=p_dir->files[i]->file+"::"+p_dir->files[i]->type+"::"+itos(p_dir->files[i]->modified_time)+"::"+itos(p_dir->files[i]->import_modified_time); s+="::"; - for(int j=0;jfiles[i]->meta.deps.size();j++) { + for(int j=0;jfiles[i]->deps.size();j++) { if (j>0) s+="<>"; - s+=p_dir->files[i]->meta.deps[j]; + s+=p_dir->files[i]->deps[j]; } p_file->store_line(s); @@ -1261,34 +1158,8 @@ void EditorFileSystem::_resource_saved(const String& p_path){ } -String EditorFileSystem::_find_first_from_source(EditorFileSystemDirectory* p_dir,const String &p_src) const { - - for(int i=0;ifiles.size();i++) { - for(int j=0;jfiles[i]->meta.sources.size();j++) { - - if (p_dir->files[i]->meta.sources[j].path==p_src) - return p_dir->get_file_path(i); - } - } - - for(int i=0;isubdirs.size();i++) { - - String ret = _find_first_from_source(p_dir->subdirs[i],p_src); - if (ret.length()>0) - return ret; - } - - return String(); -} -String EditorFileSystem::find_resource_from_source(const String& p_path) const { - - - if (filesystem) - return _find_first_from_source(filesystem,p_path); - return String(); -} void EditorFileSystem::update_file(const String& p_file) { @@ -1339,7 +1210,7 @@ void EditorFileSystem::update_file(const String& p_file) { //print_line("UPDATING: "+p_file); fs->files[cpos]->type=type; fs->files[cpos]->modified_time=FileAccess::get_modified_time(p_file); - fs->files[cpos]->meta=_get_meta(p_file); + fs->files[cpos]->import_modified_time=0; EditorResourcePreview::get_singleton()->call_deferred("check_for_invalidation",p_file); call_deferred("emit_signal","filesystem_changed"); //update later @@ -1347,6 +1218,128 @@ void EditorFileSystem::update_file(const String& p_file) { } +void EditorFileSystem::_reimport_file(const String& p_file) { + + print_line("REIMPORTING: "+p_file); + + EditorFileSystemDirectory *fs=NULL; + int cpos=-1; + bool found = _find_file(p_file,&fs,cpos); + ERR_FAIL_COND(!found); + + //try to obtain existing params + + Map params; + String importer_name; + + if (FileAccess::exists(p_file+".import")) { + + Ref cf; + cf.instance(); + Error err = cf->load(p_file+".import"); + if (err==OK) { + List sk; + cf->get_section_keys("params",&sk); + for(List::Element *E=sk.front();E;E=E->next()) { + params[E->get()]=cf->get_value("params",E->get()); + } + importer_name = cf->get_value("remap","importer"); + } + } + + Ref importer; + //find the importer + if (importer_name!="") { + importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name); + } + + if (importer.is_null()) { + //not found by name, find by extension + importer = ResourceFormatImporter::get_singleton()->get_importer_by_extension(p_file.get_extension()); + if (importer.is_null()) { + ERR_PRINT("BUG: File queued for import, but can't be imported!"); + ERR_FAIL(); + + } + } + + //mix with default params, in case a parameter is missing + + List opts; + importer->get_import_options(&opts); + for (List::Element *E=opts.front();E;E=E->next()) { + if (!params.has(E->get().option.name)) { //this one is not present + params[E->get().option.name]=E->get().default_value; + } + } + + //finally, perform import!! + String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(p_file); + + List import_variants; + + Error err = importer->import(p_file,base_path,params,&import_variants); + + ERR_EXPLAIN("Error importing: "+p_file); + ERR_FAIL_COND(err!=OK); + + //as import is complete, save the .import file + + FileAccess *f = FileAccess::open(p_file+".import",FileAccess::WRITE); + ERR_FAIL_COND(!f); + + //write manually, as order matters ([remap] has to go first for performance). + f->store_line("[remap]"); + f->store_line(""); + f->store_line("importer=\""+importer->get_importer_name()+"\""); + f->store_line("type=\""+importer->get_resource_type()+"\""); + + if (import_variants.size()) { + //import with variants + for(List::Element *E=import_variants.front();E;E=E->next()) { + + + f->store_line("path."+E->get()+"=\""+base_path.c_escape()+"."+E->get()+"."+importer->get_save_extension()+"\""); + } + } else { + + f->store_line("path=\""+base_path+"."+importer->get_save_extension()+"\""); + } + + f->store_line(""); + f->store_line("[params]"); + f->store_line(""); + + //store options in provided order, to avoid file changing + for (List::Element *E=opts.front();E;E=E->next()) { + + String base = E->get().option.name; + String value; + VariantWriter::write_to_string(params[base],value); + f->store_line(base+"="+value); + + + } + + memdelete(f); + + //update modified times, to avoid reimport + fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file); + fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file+".import"); +} + +void EditorFileSystem::reimport_files(const Vector& p_files) { + + + EditorProgress pr("reimport",TTR("(Re)Importing Assets"),p_files.size()); + for(int i=0;i extensionsl; + ResourceLoader::get_recognized_extensions_for_type("",&extensionsl); + for(List::Element *E = extensionsl.front();E;E=E->next()) { + + valid_extensions.insert(E->get()); + } + + extensionsl.clear(); + ResourceFormatImporter::get_singleton()->get_recognized_extensions(&extensionsl); + for(List::Element *E = extensionsl.front();E;E=E->next()) { + import_extensions.insert(E->get()); + } +} EditorFileSystem::EditorFileSystem() { @@ -1379,16 +1390,14 @@ EditorFileSystem::EditorFileSystem() { thread_sources=NULL; new_filesystem=NULL; - scanning_sources=false; + scanning_changes=false; ResourceSaver::set_save_callback(_resource_saved); - List extensionsl; - ResourceLoader::get_recognized_extensions_for_type("",&extensionsl); - for(List::Element *E = extensionsl.front();E;E=E->next()) { - - valid_extensions.insert(E->get()); + DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (da->change_dir("res://.import")!=OK) { + da->make_dir("res://.import"); } - + memdelete(da); scan_total=0; } diff --git a/tools/editor/editor_file_system.h b/tools/editor/editor_file_system.h index 3a26f46aa9..3ad739ae9d 100644 --- a/tools/editor/editor_file_system.h +++ b/tools/editor/editor_file_system.h @@ -48,30 +48,13 @@ class EditorFileSystemDirectory : public Object { EditorFileSystemDirectory *parent; Vector subdirs; - struct ImportMeta { - - struct Source { - - String path; - String md5; - uint64_t modified_time; - bool missing; - - }; - - Vector sources; - String import_editor; - Vector deps; - bool enabled; - bool sources_changed; - - }; struct FileInfo { String file; StringName type; uint64_t modified_time; - ImportMeta meta; + uint64_t import_modified_time; + Vector deps; bool verified; //used for checking changes }; @@ -101,14 +84,7 @@ public: String get_file(int p_idx) const; String get_file_path(int p_idx) const; StringName get_file_type(int p_idx) const; - bool get_file_meta(int p_idx) const; - bool is_missing_sources(int p_idx) const; - bool have_sources_changed(int p_idx) const; - Vector get_missing_sources(int p_idx) const; Vector get_file_deps(int p_idx) const; - int get_source_count(int p_idx) const; - String get_source_file(int p_idx,int p_source) const; - bool is_source_file_missing(int p_idx,int p_source) const; EditorFileSystemDirectory *get_parent(); @@ -136,7 +112,7 @@ class EditorFileSystem : public Node { ACTION_DIR_REMOVE, ACTION_FILE_ADD, ACTION_FILE_REMOVE, - ACTION_FILE_SOURCES_CHANGED + ACTION_FILE_REIMPORT }; Action action; @@ -171,7 +147,7 @@ class EditorFileSystem : public Node { String type; uint64_t modification_time; - EditorFileSystemDirectory::ImportMeta meta; + uint64_t import_modification_time; Vector deps; }; @@ -186,25 +162,25 @@ class EditorFileSystem : public Node { ScanProgress get_sub(int p_current,int p_total) const; }; - static EditorFileSystemDirectory::ImportMeta _get_meta(const String& p_path); - - bool _check_meta_sources(EditorFileSystemDirectory::ImportMeta & p_meta); + void _save_filesystem_cache(); void _save_filesystem_cache(EditorFileSystemDirectory *p_dir,FileAccess *p_file); bool _find_file(const String& p_file,EditorFileSystemDirectory ** r_d, int &r_file_pos) const; void _scan_fs_changes(EditorFileSystemDirectory *p_dir, const ScanProgress &p_progress); + int md_count; Set valid_extensions; + Set import_extensions; void _scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess *da,const ScanProgress& p_progress); Thread *thread_sources; - bool scanning_sources; - bool scanning_sources_done; + bool scanning_changes; + bool scanning_changes_done; static void _thread_func_sources(void *_userdata); @@ -214,7 +190,10 @@ class EditorFileSystem : public Node { bool _update_scan_actions(); static void _resource_saved(const String& p_path); - String _find_first_from_source(EditorFileSystemDirectory* p_dir,const String &p_src) const; + + void _update_extensions(); + + void _reimport_file(const String &p_file); protected: @@ -229,14 +208,16 @@ public: bool is_scanning() const; float get_scanning_progress() const; void scan(); - void scan_sources(); + void scan_changes(); void get_changed_sources(List *r_changed); void update_file(const String& p_file); - String find_resource_from_source(const String& p_path) const; + EditorFileSystemDirectory *get_filesystem_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; + void reimport_files(const Vector& p_files); + EditorFileSystem(); ~EditorFileSystem(); }; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 4bbef01acf..56384fb32d 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -99,7 +99,7 @@ #include "plugins/color_ramp_editor_plugin.h" #include "plugins/collision_shape_2d_editor_plugin.h" #include "plugins/gi_probe_editor_plugin.h" - +#include "import/resource_import_texture.h" // end #include "editor_settings.h" #include "io_plugins/editor_texture_import_plugin.h" @@ -333,21 +333,6 @@ void EditorNode::_notification(int p_what) { _editor_select(EDITOR_3D); - if (defer_load_scene!="") { - - load_scene(defer_load_scene); - defer_load_scene=""; - } - - if (defer_translatable!="") { - - Error ok = save_translatable_strings(defer_translatable); - if (ok!=OK) - OS::get_singleton()->set_exit_code(255); - defer_translatable=""; - get_tree()->quit(); - } - /* if (defer_optimize!="") { Error ok = save_optimized_copy(defer_optimize,defer_optimize_preset); @@ -370,40 +355,7 @@ void EditorNode::_notification(int p_what) { if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) { - /* - List > cached; - ResourceCache::get_cached_resources(&cached); - - bool changes=false; - for(List >::Element *E=cached.front();E;E=E->next()) { - - if (!E->get()->can_reload_from_file()) - continue; - if (E->get()->get_path().find("::")!=-1) - continue; - uint64_t mt = FileAccess::get_modified_time(E->get()->get_path()); - if (mt!=E->get()->get_last_modified_time()) { - changes=true; - break; - } - } - - - - sources_button->get_popup()->set_item_disabled(sources_button->get_popup()->get_item_index(DEPENDENCY_UPDATE_LOCAL),!changes); - if (changes && sources_button->get_popup()->is_item_disabled(sources_button->get_popup()->get_item_index(DEPENDENCY_UPDATE_IMPORTED))) { - sources_button->set_icon(gui_base->get_icon("DependencyLocalChanged","EditorIcons")); - } -*/ - - if (bool(EDITOR_DEF("filesystem/resources/auto_reload_modified_images",true))) { - - _menu_option_confirm(DEPENDENCY_LOAD_CHANGED_IMAGES,true); - } - - waiting_for_sources_changed=true; - EditorFileSystem::get_singleton()->scan_sources(); - + EditorFileSystem::get_singleton()->scan_changes(); } if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) { @@ -435,59 +387,69 @@ void EditorNode::_fs_changed() { export_defer.platform=""; } -} + { -void EditorNode::_sources_changed(bool p_exist) { + //reload changed resources + List > changed; - if (p_exist && bool(EditorSettings::get_singleton()->get("filesystem/import/automatic_reimport_on_sources_changed"))) { - p_exist=false; + List > cached; + ResourceCache::get_cached_resources(&cached); + //this should probably be done in a thread.. + for(List >::Element *E=cached.front();E;E=E->next()) { - List changed_sources; - EditorFileSystem::get_singleton()->get_changed_sources(&changed_sources); + if (!E->get()->editor_can_reload_from_file()) + 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; + if (E->get()->get_import_path()!=String()) { + //imported resource + uint64_t mt = FileAccess::get_modified_time(E->get()->get_import_path()); - EditorProgress ep("reimport",TTR("Re-Importing"),changed_sources.size()); - int step_idx=0; -#if 0 - for(List::Element *E=changed_sources.front();E;E=E->next()) { + if (mt!=E->get()->get_import_last_modified_time()) { + changed.push_back(E->get()); + } - ep.step(TTR("Importing:")+" "+E->get(),step_idx++); + } else { + uint64_t mt = FileAccess::get_modified_time(E->get()->get_path()); - Ref rimd = ResourceLoader::load_import_metadata(E->get()); - ERR_CONTINUE(rimd.is_null()); - String editor = rimd->get_editor(); - if (editor.begins_with("texture_")) { - editor="texture"; //compatibility fix for old versions - } - Ref eip = EditorImportExport::get_singleton()->get_import_plugin_by_name(editor); - ERR_CONTINUE(eip.is_null()); - Error err = eip->import(E->get(),rimd); - if (err!=OK) { - EditorNode::add_io_error("Error Re Importing:\n "+E->get()); + if (mt!=E->get()->get_last_modified_time()) { + changed.push_back(E->get()); + } } + } + if (changed.size()) { + EditorProgress ep("reload_res","Reload Modified Resources",changed.size()); + int idx=0; + for(List >::Element *E=changed.front();E;E=E->next()) { + + ep.step(E->get()->get_path(),idx++); + E->get()->reload_from_file(); + } } -#endif - EditorFileSystem::get_singleton()->scan_sources(); - waiting_for_sources_changed=false; - return; + } +} - if (p_exist) { +void EditorNode::_sources_changed(bool p_exist) { - sources_button->set_icon(gui_base->get_icon("DependencyChanged","EditorIcons")); - sources_button->set_disabled(false); + if (waiting_for_first_scan) { - } else { + if (defer_load_scene!="") { - sources_button->set_icon(gui_base->get_icon("DependencyOk","EditorIcons")); - sources_button->set_disabled(true); + print_line("loading scene DEFERED"); + load_scene(defer_load_scene); + defer_load_scene=""; + } + waiting_for_first_scan=false; } - waiting_for_sources_changed=false; } @@ -1206,12 +1168,6 @@ void EditorNode::_dialog_action(String p_file) { get_undo_redo()->clear_history(); } break; - case FILE_DUMP_STRINGS: { - - save_translatable_strings(p_file); - - } break; - case FILE_SAVE_SCENE: case FILE_SAVE_AS_SCENE: { @@ -2203,46 +2159,6 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { _menu_option_confirm(FILE_SAVE_AND_RUN, true); } break; - case FILE_DUMP_STRINGS: { - - Node *scene = editor_data.get_edited_scene_root(); - - if (!scene) { - - current_option=-1; - //confirmation->get_cancel()->hide(); - accept->get_ok()->set_text(TTR("I see..")); - accept->set_text("This operation can't be done without a tree root."); - accept->popup_centered_minsize(); - break; - } - - String cpath; - if (scene->get_filename()!="") { - cpath = scene->get_filename(); - - String fn = cpath.substr(0,cpath.length() - cpath.get_extension().size()); - String ext=cpath.get_extension(); - cpath=fn+".pot"; - - - } else { - current_option=-1; - //confirmation->get_cancel()->hide(); - accept->get_ok()->set_text(TTR("I see..")); - accept->set_text(TTR("Please save the scene first.")); - accept->popup_centered_minsize(); - break; - - } - - file->set_mode(EditorFileDialog::MODE_SAVE_FILE); - - file->set_current_path(cpath); - file->set_title(TTR("Save Translatable Strings")); - file->popup_centered_ratio(); - - } break; case FILE_SAVE_OPTIMIZED: { #if 0 Node *scene = editor_data.get_edited_scene_root(); @@ -2867,24 +2783,6 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { case DEPENDENCY_LOAD_CHANGED_IMAGES: { - List > cached; - ResourceCache::get_cached_resources(&cached); - //this should probably be done in a thread.. - for(List >::Element *E=cached.front();E;E=E->next()) { - - if (!E->get()->editor_can_reload_from_file()) - 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(); - } - - } - } break; case DEPENDENCY_UPDATE_IMPORTED: { @@ -3211,232 +3109,6 @@ void EditorNode::set_edited_scene(Node *p_scene) { } -void EditorNode::_fetch_translatable_strings(const Object *p_object,Set& strings) { - - - List tstrings; - p_object->get_translatable_strings(&tstrings); - for(List::Element *E=tstrings.front();E;E=E->next()) - strings.insert(E->get()); - - - - const Node * node = p_object->cast_to(); - - if (!node) - return; - - Ref