Prechádzať zdrojové kódy

Lot of work in new importer, importing textures now works.

Juan Linietsky 8 rokov pred
rodič
commit
2cd2ca7bbc

+ 1 - 1
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

+ 1 - 1
core/image.cpp

@@ -2155,7 +2155,7 @@ void Image::fix_alpha_edges() {
 		return; //not needed
 
 	PoolVector<uint8_t> dcopy = data;
-	PoolVector<uint8_t>::Read rp = data.read();
+	PoolVector<uint8_t>::Read rp = dcopy.read();
 	const uint8_t *srcptr=rp.ptr();
 
 	PoolVector<uint8_t>::Write wp = data.write();

+ 5 - 0
core/io/config_file.cpp

@@ -119,7 +119,10 @@ void ConfigFile::get_section_keys(const String& p_section,List<String> *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);
 

+ 2 - 0
core/io/config_file.h

@@ -54,6 +54,8 @@ public:
 	void get_sections(List<String> *r_sections) const;
 	void get_section_keys(const String& p_section,List<String> *r_keys) const;
 
+	void erase_section(const String& p_section);
+
 	Error save(const String& p_path);
 	Error load(const String& p_path);
 

+ 82 - 5
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<String> *p_extensions) const{
 
+	print_line("getting exts from: "+itos(importers.size()));
 	Set<String> found;
 
 	for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) {
@@ -84,6 +92,7 @@ void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extension
 		E->get()->get_recognized_extensions(&local_exts);
 		for (List<String>::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<String> *p_extension
 
 void ResourceFormatImporter::get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const{
 
+	if (p_type=="") {
+		return get_recognized_extensions(p_extensions);
+	}
+
 	Set<String> found;
 
 	for (Set< Ref<ResourceImporter> >::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<String> 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<ResourceImporter> >::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<String>
 	return ResourceLoader::get_dependencies(pat.path,p_dependencies,p_add_types);
 }
 
+Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String& p_name) {
+
+	for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) {
+		if (E->get()->get_importer_name()==p_name) {
+			return E->get();
+		}
+	}
+
+	return Ref<ResourceImporter>();
+}
+
+
+void ResourceFormatImporter::get_importers_for_extension(const String& p_extension,List<Ref<ResourceImporter> > *r_importers) {
+
+	for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) {
+		List<String> local_exts;
+		E->get()->get_recognized_extensions(&local_exts);
+		for (List<String>::Element *F=local_exts.front();F;F=F->next()) {
+			if (p_extension.to_lower()==F->get()) {
+				r_importers->push_back(E->get());
+			}
+		}
+	}
+}
+
+Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const String& p_extension) {
+
+
+	Ref<ResourceImporter> importer;
+	float priority=0;
+
+	for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) {
+
+		List<String> local_exts;
+		E->get()->get_recognized_extensions(&local_exts);
+		for (List<String>::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;
+}

+ 33 - 7
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<ResourceImporter> > 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<String> *p_extensions) const;
 	virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *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<String> *p_dependencies,bool p_add_types=false);
 
+	virtual bool can_be_imported(const String& p_path) const;
+
+
+	void add_importer(const Ref<ResourceImporter>& p_importer) { importers.insert(p_importer); }
+	Ref<ResourceImporter> get_importer_by_name(const String& p_name);
+	Ref<ResourceImporter> get_importer_by_extension(const String& p_extension);
+	void get_importers_for_extension(const String& p_extension,List<Ref<ResourceImporter> > *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<String> *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<ImportOption> *r_options)=0;
 
-	virtual RES import(const String& p_path,const Map<StringName,Variant>& 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<ImportOption> *r_options,int p_preset=0) const=0;
+	virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const=0;
+
+
+	virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants)=0;
 
 };
 

+ 1 - 1
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<String> *p_extensions) const=0;
 	virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *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<String> *p_dependencies,bool p_add_types=false);

+ 1 - 0
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,

+ 9 - 0
core/pair.h

@@ -39,4 +39,13 @@ struct Pair {
 	Pair( F p_first,  S p_second) { first=p_first; second=p_second; }
 };
 
+template<class F,class S>
+struct PairSort {
+
+	bool operator()(const Pair<F,S>& A, const Pair<F,S>& B) const {
+		return A.first < B.first;
+	}
+};
+
+
 #endif // PAIR_H

+ 7 - 2
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<Object>();
 
 
@@ -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 );

+ 1 - 0
core/resource.cpp

@@ -353,6 +353,7 @@ Resource::Resource() {
 
 #ifdef TOOLS_ENABLED
 	last_modified_time=0;
+	import_last_modified_time=0;
 #endif
 
 	subindex=0;

+ 8 - 0
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

+ 0 - 31
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);
 

+ 3 - 0
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

+ 3 - 0
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

+ 7 - 5
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<Texture>();
 	ClassDB::register_virtual_class<SkyBox>();
 	ClassDB::register_class<ImageSkyBox>();
+	ClassDB::register_class<StreamTexture>();
 	ClassDB::register_class<ImageTexture>();
 	ClassDB::register_class<AtlasTexture>();
 	ClassDB::register_class<LargeTexture>();
@@ -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

+ 329 - 0
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<Image> mipmap_images;
+		int total_size=0;
+
+		for(int i=0;i<mipmaps;i++) {
+			PoolVector<uint8_t> pv;
+			pv.resize(size);
+			{
+				PoolVector<uint8_t>::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<uint8_t> img_data;
+			img_data.resize(total_size);
+
+			{
+				PoolVector<uint8_t>::Write w=img_data.write();
+
+				int ofs=0;
+				for(int i=0;i<mipmap_images.size();i++) {
+
+					PoolVector<uint8_t> id = mipmap_images[i].get_data();
+					int len = id.size();
+					PoolVector<uint8_t>::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<uint8_t> img_data;
+			img_data.resize(size);
+
+			{
+				PoolVector<uint8_t>::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<uint8_t> img_data;
+			img_data.resize(total_size - ofs);
+
+			{
+				PoolVector<uint8_t>::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<StreamTexture> 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<String> *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 "";
+}
+
+
+
+
 
 //////////////////////////////////////////
 

+ 71 - 0
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<String> *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 {

+ 1 - 0
tools/editor/SCsub

@@ -78,3 +78,4 @@ if (env["tools"] == "yes"):
     SConscript('plugins/SCsub')
     SConscript('fileserver/SCsub')
     SConscript('io_plugins/SCsub')
+    SConscript('import/SCsub')

+ 263 - 254
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<String> EditorFileSystemDirectory::get_file_deps(int p_idx) const {
 
 	ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>());
-	return files[p_idx]->meta.deps;
+	return files[p_idx]->deps;
 
 }
-Vector<String> EditorFileSystemDirectory::get_missing_sources(int p_idx) const {
-
-	ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>());
-	Vector<String> missing;
-	for(int i=0;i<files[p_idx]->meta.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;i<files[p_idx]->meta.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<ResourceImportMetadata> 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;i<imd->get_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<String> deps;
-	ResourceLoader::get_dependencies(p_path,&deps);
-	for(List<String>::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<String> 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<fc.meta.sources.size();i++) {
-							fc.meta.sources[i].path=spl[1+i*3+0];
-							fc.meta.sources[i].md5=spl[1+i*3+1];
-							fc.meta.sources[i].modified_time=spl[1+i*3+2].to_int64();
-						}
+				fc.import_modification_time = split[3].to_int64();
 
-					}
-
-				}
 				String deps = split[4].strip_edges();
 				if (deps.length()) {
 					Vector<String> dp = deps.split("<>");
 					for(int i=0;i<dp.size();i++) {
 						String path=dp[i];
-						fc.meta.deps.push_back(path);
+						fc.deps.push_back(path);
 					}
 				}
 
@@ -393,7 +280,14 @@ void EditorFileSystem::_scan_filesystem() {
 
 }
 
+void EditorFileSystem::_save_filesystem_cache() {
+	String fscache = EditorSettings::get_singleton()->get_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<String> reimports;
+
 	for (List<ItemAction>::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<p_meta.sources.size();j++) {
-
-#if 0
-			String src = EditorImportPlugin::expand_source_path(p_meta.sources[j].path);
-
-			if (!FileAccess::exists(src)) {
-				p_meta.sources[j].missing=true;
-				continue;
-			}
-
-			p_meta.sources[j].missing=false;
-
-			uint64_t mt = FileAccess::get_modified_time(src);
-
-			if (mt!=p_meta.sources[j].modified_time) {
-				//scan
-				String md5 = FileAccess::get_md5(src);
-				//print_line("checking: "+src);
-				//print_line("md5: "+md5);
-				//print_line("vs: "+p_meta.sources[j].md5);
-				if (md5!=p_meta.sources[j].md5) {
-					//really changed
-					return true;
-				}
-				p_meta.sources[j].modified_time=mt;
-			}
-#endif
-		}
-	}
-
-	return false;
-}
-
 void EditorFileSystem::ScanProgress::update(int p_current,int p_total) const {
 
 	float ratio = low + ((hi-low)/p_total)*p_current;
@@ -586,8 +453,6 @@ EditorFileSystem::ScanProgress EditorFileSystem::ScanProgress::get_sub(int p_cur
 
 
 }
-
-
 void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess *da,const ScanProgress& p_progress) {
 
 	List<String> dirs;
@@ -675,9 +540,11 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess
 
 	for (List<String>::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<String> *r_changed) {
@@ -908,14 +813,15 @@ void EditorFileSystem::get_changed_sources(List<String> *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;i<p_dir->files.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;j<p_dir->files[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;j<p_dir->files[i]->meta.deps.size();j++) {
+		for(int j=0;j<p_dir->files[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;i<p_dir->files.size();i++) {
-		for(int j=0;j<p_dir->files[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;i<p_dir->subdirs.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<StringName,Variant> params;
+	String importer_name;
+
+	if (FileAccess::exists(p_file+".import")) {
+
+		Ref<ConfigFile> cf;
+		cf.instance();
+		Error err = cf->load(p_file+".import");
+		if (err==OK) {
+			List<String> sk;
+			cf->get_section_keys("params",&sk);
+			for(List<String>::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<ResourceImporter> 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<ResourceImporter::ImportOption> opts;
+	importer->get_import_options(&opts);
+	for (List<ResourceImporter::ImportOption>::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<String> 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<String>::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<ResourceImporter::ImportOption>::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<String>& p_files) {
+
+
+	EditorProgress pr("reimport",TTR("(Re)Importing Assets"),p_files.size());
+	for(int i=0;i<p_files.size();i++) {
+		pr.step(p_files[i].get_file(),i);
+
+		_reimport_file(p_files[i]);
+	}
+
+	_save_filesystem_cache();
+}
 
 void EditorFileSystem::_bind_methods() {
 
@@ -1355,7 +1348,7 @@ void EditorFileSystem::_bind_methods() {
 	ClassDB::bind_method(_MD("is_scanning"),&EditorFileSystem::is_scanning);
 	ClassDB::bind_method(_MD("get_scanning_progress"),&EditorFileSystem::get_scanning_progress);
 	ClassDB::bind_method(_MD("scan"),&EditorFileSystem::scan);
-	ClassDB::bind_method(_MD("scan_sources"),&EditorFileSystem::scan_sources);
+	ClassDB::bind_method(_MD("scan_sources"),&EditorFileSystem::scan_changes);
 	ClassDB::bind_method(_MD("update_file","path"),&EditorFileSystem::update_file);
 	ClassDB::bind_method(_MD("get_filesystem_path:EditorFileSystemDirectory","path"),&EditorFileSystem::get_filesystem_path);
 	ClassDB::bind_method(_MD("get_file_type","path"),&EditorFileSystem::get_file_type);
@@ -1365,7 +1358,25 @@ void EditorFileSystem::_bind_methods() {
 
 }
 
+void EditorFileSystem::_update_extensions() {
+
+	valid_extensions.clear();
+	import_extensions.clear();
+
+	List<String> extensionsl;
+	ResourceLoader::get_recognized_extensions_for_type("",&extensionsl);
+	for(List<String>::Element *E = extensionsl.front();E;E=E->next()) {
+
+		valid_extensions.insert(E->get());
+	}
+
+	extensionsl.clear();
+	ResourceFormatImporter::get_singleton()->get_recognized_extensions(&extensionsl);
+	for(List<String>::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<String> extensionsl;
-	ResourceLoader::get_recognized_extensions_for_type("",&extensionsl);
-	for(List<String>::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;
 }

+ 17 - 36
tools/editor/editor_file_system.h

@@ -48,30 +48,13 @@ class EditorFileSystemDirectory : public Object {
 	EditorFileSystemDirectory *parent;
 	Vector<EditorFileSystemDirectory*> subdirs;
 
-	struct ImportMeta {
-
-		struct Source {
-
-			String path;
-			String md5;
-			uint64_t modified_time;
-			bool missing;			
-
-		};
-
-		Vector<Source> sources;
-		String import_editor;
-		Vector<String> deps;
-		bool enabled;
-		bool sources_changed;
-
-	};
 
 	struct FileInfo {
 		String file;
 		StringName type;
 		uint64_t modified_time;
-		ImportMeta meta;
+		uint64_t import_modified_time;
+		Vector<String> 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<String> get_missing_sources(int p_idx) const;
 	Vector<String> 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<String> 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<String> valid_extensions;
+	Set<String> 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<String> *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<String>& p_files);
+
 	EditorFileSystem();
 	~EditorFileSystem();
 };

+ 65 - 375
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<Ref<Resource> > cached;
-		ResourceCache::get_cached_resources(&cached);
-
-		bool changes=false;
-		for(List<Ref<Resource> >::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<Ref<Resource> > changed;
 
-	if (p_exist && bool(EditorSettings::get_singleton()->get("filesystem/import/automatic_reimport_on_sources_changed"))) {
-		p_exist=false;
+		List<Ref<Resource> > cached;
+		ResourceCache::get_cached_resources(&cached);
+		//this should probably be done in a thread..
+		for(List<Ref<Resource> >::Element *E=cached.front();E;E=E->next()) {
 
-		List<String> 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<String>::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<ResourceImportMetadata> 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<EditorImportPlugin> 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<Ref<Resource> >::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<Ref<Resource> > cached;
-			ResourceCache::get_cached_resources(&cached);
-			//this should probably be done in a thread..
-			for(List<Ref<Resource> >::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<StringName>& strings) {
-
-
-	List<String> tstrings;
-	p_object->get_translatable_strings(&tstrings);
-	for(List<String>::Element *E=tstrings.front();E;E=E->next())
-		strings.insert(E->get());
-
-
-
-	const Node * node = p_object->cast_to<Node>();
-
-	if (!node)
-		return;
-
-	Ref<Script> script = node->get_script();
-	if (script.is_valid())
-		_fetch_translatable_strings(script.ptr(),strings);
-
-	for(int i=0;i<node->get_child_count();i++) {
-
-		Node *c=node->get_child(i);
-		if (c->get_owner()!=get_edited_scene())
-			continue;
-
-		_fetch_translatable_strings(c,strings);
-	}
-
-}
-
-
-Error EditorNode::save_translatable_strings(const String& p_to_file) {
-
-	if (!is_inside_tree()) {
-		defer_translatable=p_to_file;
-		return OK;
-	}
-
-	ERR_FAIL_COND_V(!get_edited_scene(),ERR_INVALID_DATA);
-
-	Set<StringName> strings;
-	_fetch_translatable_strings(get_edited_scene(),strings);
-
-	Error err;
-	FileAccess *f = FileAccess::open(p_to_file,FileAccess::WRITE,&err);
-	ERR_FAIL_COND_V(err,err);
-
-	OS::Date date = OS::get_singleton()->get_date();
-	OS::Time time = OS::get_singleton()->get_time();
-	f->store_line("# Translation Strings Dump.");
-	f->store_line("# Created By.");
-	f->store_line("# \t" VERSION_FULL_NAME " (c) 2008-2017 Juan Linietsky, Ariel Manzur.");
-	f->store_line("# From Scene: ");
-	f->store_line("# \t"+get_edited_scene()->get_filename());
-	f->store_line("");
-	f->store_line("msgid \"\"");
-	f->store_line("msgstr \"\"");
-	f->store_line("\"Report-Msgid-Bugs-To: <define>\\n\"");
-	f->store_line("\"POT-Creation-Date: "+itos(date.year)+"-"+itos(date.month)+"-"+itos(date.day)+" "+itos(time.hour)+":"+itos(time.min)+"0000\\n\"");
-	//f->store_line("\"PO-Revision-Date: 2006-08-30 13:56-0700\\n\"");
-	//f->store_line("\"Last-Translator: Rubén C. Díaz Alonso <[email protected]>\\n\"");
-	f->store_line("\"Language-Team: <define>\\n\"");
-	f->store_line("\"MIME-Version: 1.0\\n\"");
-	f->store_line("\"Content-Type: text/plain; charset=UTF-8\\n\"");
-	f->store_line("\"Content-Transfer-Encoding: 8bit\\n\"");
-	f->store_line("");
-
-	for(Set<StringName>::Element *E=strings.front();E;E=E->next()) {
-
-		String s = E->get();
-		if (s=="" || s.strip_edges()=="")
-			continue;
-		Vector<String> substr = s.split("\n");
-		ERR_CONTINUE(substr.size()==0);
-
-		f->store_line("");
-
-		if (substr.size()==1) {
-
-			f->store_line("msgid \""+substr[0].c_escape()+"\"");
-		} else {
-
-			f->store_line("msgid \"\"");
-			for(int i=0;i<substr.size();i++) {
-
-				String s = substr[i];
-				if (i!=substr.size()-1)
-					s+="\n";
-				f->store_line("\""+s.c_escape()+"\"");
-			}
-		}
-
-		f->store_line("msgstr \"\"");
-
-	}
-
-
-	f->close();
-	memdelete(f);
-
-	return OK;
-
-}
-
-Error EditorNode::save_optimized_copy(const String& p_scene,const String& p_preset) {
-
-#if 0
-
-	if (!is_inside_scene()) {
-		defer_optimize=p_scene;
-		defer_optimize_preset=p_preset;
-		return OK;
-	}
-
-
-	if (!get_edited_scene()) {
-
-		get_scene()->quit();
-		ERR_EXPLAIN("No scene to optimize (loading failed?)");
-		ERR_FAIL_V(ERR_FILE_NOT_FOUND);
-	}
-
-
-	String src_scene=GlobalConfig::get_singleton()->localize_path(get_edited_scene()->get_filename());
-
-
-	String path=p_scene;
-	print_line("p_path: "+p_scene);
-	print_line("src_scene: "+p_scene);
-
-	if (path.is_rel_path()) {
-		print_line("rel path!?");
-		path=src_scene.get_base_dir()+"/"+path;
-	}
-	path = GlobalConfig::get_singleton()->localize_path(path);
-
-	print_line("path: "+path);
-
-
-	String preset = "optimizer_presets/"+p_preset;
-	if (!GlobalConfig::get_singleton()->has(preset)) {
-
-		//accept->"()->hide();
-		accept->get_ok()->set_text("I see..");
-		accept->set_text("Optimizer preset not found: "+p_preset);
-		accept->popup_centered(Size2(300,70));
-		ERR_EXPLAIN("Optimizer preset not found: "+p_preset);
-		ERR_FAIL_V(ERR_INVALID_PARAMETER);
-
-	}
-
-	Dictionary d = GlobalConfig::get_singleton()->get(preset);
-
-	ERR_FAIL_COND_V(!d.has("__type__"),ERR_INVALID_DATA);
-	String type=d["__type__"];
-
-	Ref<EditorOptimizedSaver> saver;
-
-	for(int i=0;i<editor_data.get_optimized_saver_count();i++) {
-
-		print_line(type+" vs "+editor_data.get_optimized_saver(i)->get_target_name());
-		if (editor_data.get_optimized_saver(i)->get_target_name()==type) {
-			saver=editor_data.get_optimized_saver(i);
-		}
-	}
-
-	ERR_EXPLAIN("Preset '"+p_preset+"' references nonexistent saver: "+type);
-	ERR_FAIL_COND_V(saver.is_null(),ERR_INVALID_DATA);
-
-	List<Variant> keys;
-	d.get_key_list(&keys);
-
-	saver->clear();
-
-	for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
-
-		saver->set(E->get(),d[E->get()]);
-	}
-
-	uint32_t flags=0;
-
-	/*
-	if (saver->is_bundle_scenes_enabled())
-		flags|=ResourceSaver::FLAG_BUNDLE_INSTANCED_SCENES;
-	*/
-	if (saver->is_bundle_resources_enabled())
-		flags|=ResourceSaver::FLAG_BUNDLE_RESOURCES;
-	if (saver->is_remove_editor_data_enabled())
-		flags|=ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES;
-	if (saver->is_big_endian_data_enabled())
-		flags|=ResourceSaver::FLAG_SAVE_BIG_ENDIAN;
-
-	String platform=saver->get_target_platform();
-	if (platform=="")
-		platform="all";
-
-	Ref<PackedScene> sdata = memnew( PackedScene );
-	Error err = sdata->pack(get_edited_scene());
-
-	if (err) {
-
-		current_option=-1;
-		//accept->get_cancel()->hide();
-		accept->get_ok()->set_text("I see..");
-		accept->set_text("Couldn't save scene. Likely dependencies (instances) couldn't be satisfied.");
-		accept->popup_centered(Size2(300,70));
-		return ERR_INVALID_DATA;
-
-	}
-	err = ResourceSaver::save(path,sdata,flags); //todo, saverSceneSaver::save(path,get_edited_scene(),flags,saver);
-
-	if (err) {
-
-		//accept->"()->hide();
-		accept->get_ok()->set_text("I see..");
-		accept->set_text("Error saving optimized scene: "+path);
-		accept->popup_centered(Size2(300,70));
-
-		ERR_FAIL_COND_V(err,err);
-
-	}
-
-	project_settings->add_remapped_path(src_scene,path,platform);
-#endif
-	return OK;
-}
 
 
 int EditorNode::_get_current_main_editor() {
@@ -3834,6 +3506,10 @@ void EditorNode::request_instance_scenes(const Vector<String>& p_files) {
 	scene_tree_dock->instance_scenes(p_files);
 }
 
+ImportDock *EditorNode::get_import_dock() {
+	return import_dock;
+}
+
 FileSystemDock *EditorNode::get_filesystem_dock() {
 
 	return filesystem_dock;
@@ -5063,7 +4739,6 @@ Variant EditorNode::drag_resource(const Ref<Resource>& p_res,Control* p_from) {
 	TextureRect *drag_preview = memnew( TextureRect );
 	Label* label=memnew( Label );
 
-	waiting_for_sources_changed=true; //
 	Ref<Texture> preview;
 
 	{
@@ -5440,6 +5115,13 @@ EditorNode::EditorNode() {
 	ResourceLoader::set_timestamp_on_load(true);
 	ResourceSaver::set_timestamp_on_save(true);
 
+
+	{  //register importers at the begining, so dialogs are created with the right extensions
+		Ref<ResourceImporterTexture> import_texture;
+		import_texture.instance();
+		ResourceFormatImporter::get_singleton()->add_importer(import_texture);
+	}
+
 	_pvrtc_register_compressors();
 
 	editor_selection = memnew( EditorSelection );
@@ -5765,7 +5447,6 @@ EditorNode::EditorNode() {
 	pm_export->set_name("Export");
 	p->add_child(pm_export);
 	p->add_submenu_item(TTR("Convert To.."),"Export");
-	pm_export->add_item(TTR("Translatable Strings.."),FILE_DUMP_STRINGS);
 	pm_export->add_separator();
 	pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_MeshLibrary", TTR("MeshLibrary..")), FILE_EXPORT_MESH_LIBRARY);
 	pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_TileSet", TTR("TileSet..")), FILE_EXPORT_TILESET);
@@ -6248,6 +5929,11 @@ EditorNode::EditorNode() {
 	property_editor->set_undo_redo(&editor_data.get_undo_redo());
 
 
+	import_dock = memnew( ImportDock );
+	dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(import_dock);
+	import_dock->set_name(TTR("Import"));
+
+
 	node_dock = memnew( NodeDock );
 	//node_dock->set_undoredo(&editor_data.get_undo_redo());
 	if (use_single_dock_column) {
@@ -6584,6 +6270,9 @@ EditorNode::EditorNode() {
 		plugin_init_callbacks[i]();
 	}
 
+
+
+
 	/*resource_preview->add_preview_generator( Ref<EditorTexturePreviewPlugin>( memnew(EditorTexturePreviewPlugin )));
 	resource_preview->add_preview_generator( Ref<EditorPackedScenePreviewPlugin>( memnew(EditorPackedScenePreviewPlugin )));
 	resource_preview->add_preview_generator( Ref<EditorMaterialPreviewPlugin>( memnew(EditorMaterialPreviewPlugin )));
@@ -6730,6 +6419,7 @@ EditorNode::EditorNode() {
 
 	FileAccess::set_file_close_fail_notify_callback(_file_access_close_error_notify);
 
+	waiting_for_first_scan=true;
 
 }
 

+ 4 - 9
tools/editor/editor_node.h

@@ -50,6 +50,7 @@
 #include "tools/editor/reparent_dialog.h"
 #include "tools/editor/connections_dialog.h"
 #include "tools/editor/node_dock.h"
+#include "tools/editor/import_dock.h"
 #include "tools/editor/settings_config_dialog.h"
 #include "tools/editor/groups_editor.h"
 #include "tools/editor/editor_data.h"
@@ -134,7 +135,6 @@ private:
 		FILE_EXPORT_MESH_LIBRARY,
 		FILE_EXPORT_TILESET,
 		FILE_SAVE_OPTIMIZED,
-		FILE_DUMP_STRINGS,
 		FILE_OPEN_RECENT,
 		FILE_OPEN_OLD_SCENE,
 		FILE_QUICK_OPEN_SCENE,
@@ -278,6 +278,7 @@ private:
 	//ResourcesDock *resources_dock;
 	PropertyEditor *property_editor;
 	NodeDock *node_dock;
+	ImportDock *import_dock;
 	VBoxContainer *prop_editor_vb;
 	FileSystemDock *filesystem_dock;
 	EditorRunNative *run_native;
@@ -318,9 +319,6 @@ private:
 	//TabContainer *prop_pallete;
 	//TabContainer *top_pallete;
 	String defer_load_scene;
-	String defer_translatable;
-	String defer_optimize;
-	String defer_optimize_preset;
 	String defer_export;
 	String defer_export_platform;
 	bool defer_export_debug;
@@ -376,6 +374,7 @@ private:
 	bool unsaved_cache;
 	String open_navigate;
 	bool changing_scene;
+	bool waiting_for_first_scan;
 
 	bool waiting_for_sources_changed;
 
@@ -488,7 +487,6 @@ private:
 	static void _load_error_notify(void* p_ud,const String& p_text);
 
 	bool has_main_screen() const { return true; }
-	void _fetch_translatable_strings(const Object *p_object,Set<StringName>& strings);
 
 	bool _find_editing_changed_scene(Node *p_from);
 
@@ -683,7 +681,6 @@ public:
 	Node *get_edited_scene() { return editor_data.get_edited_scene_root(); }
 
 	Viewport *get_scene_root() { return scene_root; } //root of the scene being edited
-	Error save_optimized_copy(const String& p_scene,const String& p_preset);
 
 	void fix_dependencies(const String& p_for_file);
 	void clear_scene() { _cleanup_scene(); }
@@ -703,13 +700,12 @@ public:
 	void request_instance_scene(const String &p_path);
 	void request_instance_scenes(const Vector<String>& p_files);
 	FileSystemDock *get_filesystem_dock();
+	ImportDock *get_import_dock();
 	SceneTreeDock *get_scene_tree_dock();
 	static UndoRedo* get_undo_redo() { return &singleton->editor_data.get_undo_redo(); }
 
 	EditorSelection *get_editor_selection() { return editor_selection; }
 
-	Error save_translatable_strings(const String& p_to_file);
-
 	void set_convert_old_scene(bool p_old) { convert_old=p_old; }
 
 	void notify_child_process_exited();
@@ -784,7 +780,6 @@ public:
 
 };
 
-
 struct EditorProgress {
 
 	String task;

+ 59 - 58
tools/editor/filesystem_dock.cpp

@@ -350,25 +350,9 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path,List<FileInfo>* m
 			FileInfo fi;
 			fi.name=file;
 			fi.type=p_path->get_file_type(i);
-			fi.path=p_path->get_file_path(i);
-			if (p_path->get_file_meta(i)) {
-				if (p_path->is_missing_sources(i)) {
-					fi.import_status=3;
-				} else if (p_path->have_sources_changed(i)) {
-					fi.import_status=2;
-				} else {
-					fi.import_status=1;
-				}
-			} else {
-				fi.import_status=0;
-			}
-			for(int j=0;j<p_path->get_source_count(i);j++) {
-				/*String s = EditorImportPlugin::expand_source_path(p_path->get_source_file(i,j));
-				if (p_path->is_source_file_missing(i,j)) {
-					s+=" (Missing)";
-				}
-				fi.sources.push_back(s);*/
-			}
+			fi.path=p_path->get_file_path(i);			
+			fi.import_status=0;
+
 
 			matches->push_back(fi);
 			if (matches->size()>p_max_items)
@@ -500,25 +484,7 @@ void FileSystemDock::_update_files(bool p_keep_selection) {
 			fi.name=efd->get_file(i);
 			fi.path=path.plus_file(fi.name);
 			fi.type=efd->get_file_type(i);
-			if (efd->get_file_meta(i)) {
-				if (efd->is_missing_sources(i)) {
-					fi.import_status=3;
-				} else if (efd->have_sources_changed(i)) {
-					fi.import_status=2;
-				} else {
-					fi.import_status=1;
-				}
-
-				for(int j=0;j<efd->get_source_count(i);j++) {
-					/*String s = EditorImportPlugin::expand_source_path(efd->get_source_file(i,j));
-					if (efd->is_source_file_missing(i,j)) {
-						s+=" (Missing)";
-					}
-					fi.sources.push_back(s);*/
-				}
-			} else {
-				fi.import_status=0;
-			}
+			fi.import_status=0;
 
 
 
@@ -1538,26 +1504,6 @@ void FileSystemDock::_files_list_rmb_select(int p_item,const Vector2& p_pos) {
 		if (efsd) {
 
 
-			if (!efsd->get_file_meta(pos)) {
-				all_can_reimport=false;
-
-
-			} else {
-				/*
-				Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(path);
-				if (rimd.is_valid()) {
-
-					String editor=rimd->get_editor();
-					if (editor.begins_with("texture_")) { //compatibility fix for old texture format
-						editor="texture";
-					}
-					types.insert(editor);
-
-				} else {
-					all_can_reimport=false;
-
-				}*/
-			}
 		} else {
 			all_can_reimport=false;
 
@@ -1642,6 +1588,57 @@ void FileSystemDock::select_file(const String& p_file) {
 
 }
 
+void FileSystemDock::_file_multi_selected(int p_index,bool p_selected) {
+
+
+	_file_selected();
+}
+
+void FileSystemDock::_file_selected() {
+
+	//check import
+	Vector<String> imports;
+	String import_type;
+
+	for(int i=0;i<files->get_item_count();i++) {
+		if (!files->is_selected(i))
+			continue;
+
+		String p = files->get_item_metadata(i);
+		if (!FileAccess::exists(p+".import")) {
+			imports.clear();
+			break;
+		}
+		Ref<ConfigFile> cf;
+		cf.instance();
+		Error err = cf->load(p+".import");
+		if (err!=OK) {
+			imports.clear();
+			break;
+		}
+
+		String type = cf->get_value("remap","type");
+		if (import_type=="") {
+			import_type=type;
+		} else if (import_type!=type) {
+			//all should be the same type
+			imports.clear();
+			break;
+		}
+		imports.push_back(p);
+	}
+
+
+	if (imports.size()==0) {
+		EditorNode::get_singleton()->get_import_dock()->clear();
+	} else if (imports.size()==1) {
+		EditorNode::get_singleton()->get_import_dock()->set_edit_path(imports[0]);
+	} else {
+		EditorNode::get_singleton()->get_import_dock()->set_edit_multiple_paths(imports);
+	}
+}
+
+
 void FileSystemDock::_bind_methods() {
 
 	ClassDB::bind_method(_MD("_update_tree"),&FileSystemDock::_update_tree);
@@ -1673,6 +1670,8 @@ void FileSystemDock::_bind_methods() {
 	ClassDB::bind_method(_MD("_files_list_rmb_select"),&FileSystemDock::_files_list_rmb_select);
 
 	ClassDB::bind_method(_MD("_preview_invalidated"),&FileSystemDock::_preview_invalidated);
+	ClassDB::bind_method(_MD("_file_selected"),&FileSystemDock::_file_selected);
+	ClassDB::bind_method(_MD("_file_multi_selected"),&FileSystemDock::_file_multi_selected);
 
 
 	ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::POOL_STRING_ARRAY, "files")));
@@ -1777,6 +1776,8 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
 	files->set_select_mode(ItemList::SELECT_MULTI);
 	files->set_drag_forwarding(this);
 	files->connect("item_rmb_selected",this,"_files_list_rmb_select");
+	files->connect("item_selected",this,"_file_selected");
+	files->connect("multi_selected",this,"_file_multi_selected");
 	files->set_allow_rmb_select(true);
 
 	file_list_vb = memnew( VBoxContainer );

+ 5 - 0
tools/editor/filesystem_dock.h

@@ -126,6 +126,11 @@ private:
 	Tree * tree; //directories
 	ItemList *files;
 
+
+	void _file_multi_selected(int p_index, bool p_selected);
+	void _file_selected();
+
+
 	void _go_to_tree();
 	void _go_to_dir(const String& p_dir);
 	void _select_file(int p_idx);

+ 274 - 0
tools/editor/import/resource_import_texture.cpp

@@ -0,0 +1,274 @@
+#include "resource_import_texture.h"
+#include "io/image_loader.h"
+#include "scene/resources/texture.h"
+
+String ResourceImporterTexture::get_importer_name() const {
+
+	return "texture";
+}
+
+String ResourceImporterTexture::get_visible_name() const{
+
+	return "Texture";
+}
+void ResourceImporterTexture::get_recognized_extensions(List<String> *p_extensions) const{
+
+	ImageLoader::get_recognized_extensions(p_extensions);
+}
+String ResourceImporterTexture::get_save_extension() const {
+	return "stex";
+}
+
+String ResourceImporterTexture::get_resource_type() const{
+
+	return "StreamTexture";
+}
+
+bool ResourceImporterTexture::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
+
+	if (p_option=="compress/lossy_quality" && int(p_options["compress/mode"])!=COMPRESS_LOSSY)
+		return false;
+
+	return true;
+}
+
+int ResourceImporterTexture::get_preset_count() const {
+	return 4;
+}
+String ResourceImporterTexture::get_preset_name(int p_idx) const {
+
+	static const char* preset_names[]={
+		"2D, Detect 3D",
+		"2D",
+		"2D Pixel",
+		"3D"
+	};
+
+	return preset_names[p_idx];
+}
+
+
+void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options,int p_preset) const {
+
+
+	r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Lossless,Lossy,Video RAM,Uncompressed",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED),p_preset==PRESET_3D?2:0));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"compress/lossy_quality",PROPERTY_HINT_RANGE,"0,1,0.01"),0.7));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"flags/repeat",PROPERTY_HINT_ENUM,"Disabled,Enabled,Mirrored"),p_preset==PRESET_3D?1:0));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/filter"),p_preset==PRESET_2D_PIXEL?false:true));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/mipmaps"),p_preset==PRESET_3D?true:false));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/anisotropic"),false));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/srgb",PROPERTY_HINT_ENUM,"Disable,Enable,Detect"),2));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"process/fix_alpha_border"),p_preset!=PRESET_3D?true:false));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"process/premult_alpha"),true));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"stream"),false));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"size_limit",PROPERTY_HINT_RANGE,"0,4096,1"),0));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"detect_3d"),p_preset==PRESET_DETECT));
+
+}
+
+
+void ResourceImporterTexture::_save_stex(const Image& p_image,const String& p_to_path,int p_compress_mode,float p_lossy_quality,Image::CompressMode p_vram_compression,bool p_mipmaps,int p_texture_flags,bool p_streamable) {
+
+
+	FileAccess *f = FileAccess::open(p_to_path,FileAccess::WRITE);
+	f->store_8('G');
+	f->store_8('D');
+	f->store_8('S');
+	f->store_8('T'); //godot streamable texture
+
+	f->store_32(p_image.get_width());
+	f->store_32(p_image.get_height());
+	f->store_32(p_texture_flags);
+
+	uint32_t format=0;
+
+	if (p_streamable)
+		format|=StreamTexture::FORMAT_BIT_STREAM;
+	if (p_mipmaps || p_compress_mode==COMPRESS_VIDEO_RAM) //VRAM always uses mipmaps
+		format|=StreamTexture::FORMAT_BIT_HAS_MIPMAPS; //mipmaps bit
+
+	switch (p_compress_mode) {
+		case COMPRESS_LOSSLESS: {
+
+			Image image = p_image;
+			if (p_mipmaps) {
+				image.generate_mipmaps();
+			} else {
+				image.clear_mipmaps();
+			}
+
+			int mmc = image.get_mipmap_count() + 1;
+
+			format=StreamTexture::FORMAT_BIT_LOSSLESS;
+			f->store_32(format);
+			f->store_32(mmc);
+
+			for(int i=0;i<mmc;i++) {
+
+				if (i>0) {
+					image.shrink_x2();
+				}
+
+				PoolVector<uint8_t> data = Image::lossless_packer(image);
+				int data_len = data.size();
+				f->store_32(data_len);
+
+				PoolVector<uint8_t>::Read r= data.read();
+				f->store_buffer(r.ptr(),data_len);
+
+			}
+
+
+		} break;
+		case COMPRESS_LOSSY: {
+			Image image = p_image;
+			if (p_mipmaps) {
+				image.generate_mipmaps();
+			} else {
+				image.clear_mipmaps();
+			}
+
+			int mmc = image.get_mipmap_count() + 1;
+
+			format=StreamTexture::FORMAT_BIT_LOSSY;
+			f->store_32(format);
+			f->store_32(mmc);
+
+			for(int i=0;i<mmc;i++) {
+
+				if (i>0) {
+					image.shrink_x2();
+				}
+
+				PoolVector<uint8_t> data = Image::lossy_packer(image,p_lossy_quality);
+				int data_len = data.size();
+				f->store_32(data_len);
+
+				PoolVector<uint8_t>::Read r = data.read();
+				f->store_buffer(r.ptr(),data_len);
+
+			}
+		} break;
+		case COMPRESS_VIDEO_RAM: {
+
+			Image image = p_image;
+			image.generate_mipmaps();
+			image.compress(p_vram_compression);
+
+			format |= image.get_format();
+
+			f->store_32(format);
+
+			PoolVector<uint8_t> data=image.get_data();
+			int dl = data.size();
+			PoolVector<uint8_t>::Read r = data.read();
+
+			f->store_buffer(r.ptr(),dl);
+
+		} break;
+		case COMPRESS_UNCOMPRESSED: {
+
+			Image image = p_image;
+			if (p_mipmaps) {
+				image.generate_mipmaps();
+			} else {
+				image.clear_mipmaps();
+			}
+
+			format |= image.get_format();
+			f->store_32(format);
+
+			PoolVector<uint8_t> data=image.get_data();
+			int dl = data.size();
+			PoolVector<uint8_t>::Read r = data.read();
+
+			f->store_buffer(r.ptr(),dl);
+
+		} break;
+	}
+
+	memdelete(f);
+}
+
+Error ResourceImporterTexture::import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants) {
+
+	int compress_mode = p_options["compress/mode"];
+	float lossy= p_options["compress/lossy_quality"];
+	int repeat= p_options["flags/repeat"];
+	bool filter= p_options["flags/filter"];
+	bool mipmaps= p_options["flags/mipmaps"];
+	bool anisotropic= p_options["flags/anisotropic"];
+	bool srgb= p_options["flags/srgb"];
+	bool fix_alpha_border= p_options["process/fix_alpha_border"];
+	bool premult_alpha= p_options["process/premult_alpha"];
+	bool stream = p_options["stream"];
+	int size_limit = p_options["size_limit"];
+
+
+	Image image;
+	Error err = ImageLoader::load_image(p_source_file,&image);
+	if (err!=OK)
+		return err;
+
+
+	int tex_flags=0;
+	if (repeat>0)
+		tex_flags|=Texture::FLAG_REPEAT;
+	if (repeat==2)
+		tex_flags|=Texture::FLAG_MIRRORED_REPEAT;
+	if (filter)
+		tex_flags|=Texture::FLAG_FILTER;
+	if (mipmaps || compress_mode==COMPRESS_VIDEO_RAM)
+		tex_flags|=Texture::FLAG_MIPMAPS;
+	if (anisotropic)
+		tex_flags|=Texture::FLAG_ANISOTROPIC_FILTER;
+	if (srgb)
+		tex_flags|=Texture::FLAG_CONVERT_TO_LINEAR;
+
+	if (size_limit >0 && (image.get_width()>size_limit || image.get_height()>size_limit )) {
+		//limit size
+		if (image.get_width() >= image.get_height()) {
+			int new_width = size_limit;
+			int new_height = image.get_height() * new_width / image.get_width();
+
+			image.resize(new_width,new_height,Image::INTERPOLATE_CUBIC);
+		} else {
+
+			int new_height = size_limit;
+			int new_width = image.get_width() * new_height / image.get_height();
+
+			image.resize(new_width,new_height,Image::INTERPOLATE_CUBIC);
+		}
+	}
+
+	if (fix_alpha_border) {
+		image.fix_alpha_edges();
+	}
+
+	if (premult_alpha) {
+		image.premultiply_alpha();
+	}
+
+
+	if (compress_mode==COMPRESS_VIDEO_RAM) {
+		//must import in all formats
+		//Android, GLES 2.x
+		_save_stex(image,p_save_path+".etc.stex",compress_mode,lossy,Image::COMPRESS_ETC,mipmaps,tex_flags,stream);
+		r_platform_variants->push_back("etc");
+		//_save_stex(image,p_save_path+".etc2.stex",compress_mode,lossy,Image::COMPRESS_ETC2,mipmaps,tex_flags,stream);
+		//r_platform_variants->push_back("etc2");
+		_save_stex(image,p_save_path+".s3tc.stex",compress_mode,lossy,Image::COMPRESS_S3TC,mipmaps,tex_flags,stream);
+		r_platform_variants->push_back("s3tc");
+
+	} else {
+		//import normally
+		_save_stex(image,p_save_path+".stex",compress_mode,lossy,Image::COMPRESS_16BIT /*this is ignored */,mipmaps,tex_flags,stream);
+	}
+
+	return OK;
+}
+
+ResourceImporterTexture::ResourceImporterTexture()
+{
+
+}

+ 43 - 0
tools/editor/import/resource_import_texture.h

@@ -0,0 +1,43 @@
+#ifndef RESOURCEIMPORTTEXTURE_H
+#define RESOURCEIMPORTTEXTURE_H
+
+#include "io/resource_import.h"
+
+class ResourceImporterTexture : public ResourceImporter {
+	GDCLASS(ResourceImporterTexture,ResourceImporter)
+public:
+	virtual String get_importer_name() const;
+	virtual String get_visible_name() const;
+	virtual void get_recognized_extensions(List<String> *p_extensions) const;
+	virtual String get_save_extension() const;
+	virtual String get_resource_type() const;
+
+
+	enum Preset {
+		PRESET_DETECT,
+		PRESET_2D,
+		PRESET_2D_PIXEL,
+		PRESET_3D,
+	};
+
+	enum CompressMode {
+		COMPRESS_LOSSLESS,
+		COMPRESS_LOSSY,
+		COMPRESS_VIDEO_RAM,
+		COMPRESS_UNCOMPRESSED
+	};
+
+	virtual int get_preset_count() const;
+	virtual String get_preset_name(int p_idx) const;
+
+	virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const;
+	virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const;
+
+	void _save_stex(const Image& p_image, const String& p_to_path, int p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags, bool p_streamable);
+
+	virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants);
+
+	ResourceImporterTexture();
+};
+
+#endif // RESOURCEIMPORTTEXTURE_H

+ 331 - 0
tools/editor/import_dock.cpp

@@ -0,0 +1,331 @@
+#include "import_dock.h"
+
+class ImportDockParameters : public Object {
+	GDCLASS(ImportDockParameters,Object)
+public:
+	Map<StringName,Variant> values;
+	List<PropertyInfo> properties;
+	Ref<ResourceImporter> importer;
+	Vector<String> paths;
+
+
+	bool _set(const StringName& p_name, const Variant& p_value) {
+
+		if (values.has(p_name)) {
+			values[p_name]=p_value;
+			return true;
+		}
+
+		return false;
+	}
+
+	bool _get(const StringName& p_name,Variant &r_ret) const {
+
+		if (values.has(p_name)) {
+			r_ret=values[p_name];
+			return true;
+		}
+
+		return false;
+
+	}
+	void _get_property_list( List<PropertyInfo> *p_list) const {
+
+		for (const List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
+			if (!importer->get_option_visibility(E->get().name,values))
+				continue;
+			p_list->push_back(E->get());
+		}
+	}
+
+	void update() {
+		_change_notify();
+	}
+};
+
+void ImportDock::set_edit_path(const String& p_path) {
+
+	Ref<ConfigFile> config;
+	config.instance();
+	Error err = config->load(p_path+".import");
+	if (err!=OK) {
+		clear();
+		return;
+	}
+
+
+	params->importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(config->get_value("remap","importer"));
+	if (params->importer.is_null()) {
+		clear();
+		return;
+	}
+
+	List<ResourceImporter::ImportOption> options;
+	params->importer->get_import_options(&options);
+
+	params->properties.clear();
+	params->values.clear();
+
+	for (List<ResourceImporter::ImportOption>::Element *E=options.front();E;E=E->next()) {
+
+		params->properties.push_back(E->get().option);
+		if (config->has_section_key("params",E->get().option.name)) {
+			params->values[E->get().option.name]=config->get_value("params",E->get().option.name);
+		} else {
+			params->values[E->get().option.name]=E->get().default_value;
+		}
+	}
+
+	params->update();
+
+	List<Ref<ResourceImporter> > importers;
+	ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_path.get_extension(),&importers);
+	List<Pair<String,String> > importer_names;
+
+	for (List<Ref<ResourceImporter> > ::Element *E=importers.front();E;E=E->next()) {
+		importer_names.push_back(Pair<String,String>(E->get()->get_visible_name(),E->get()->get_importer_name()));
+	}
+
+	importer_names.sort_custom<PairSort<String,String> >();
+
+	import_as->clear();
+
+	for (List<Pair<String,String> >::Element *E=importer_names.front();E;E=E->next()) {
+		import_as->add_item(E->get().first);
+		import_as->set_item_metadata(import_as->get_item_count()-1,E->get().second);
+		if (E->get().second==params->importer->get_importer_name()) {
+			import_as->select(import_as->get_item_count()-1);
+		}
+	}
+
+	preset->get_popup()->clear();
+
+	if (params->importer->get_preset_count()==0) {
+		preset->get_popup()->add_item(TTR("Default"));
+	} else {
+		for (int i=0;i<params->importer->get_preset_count();i++) {
+			preset->get_popup()->add_item(params->importer->get_preset_name(i));
+		}
+	}
+
+	params->paths.clear();
+	params->paths.push_back(p_path);
+	import->set_disabled(false);
+	import_as->set_disabled(false);
+
+	imported->set_text(p_path.get_file());
+}
+
+void ImportDock::set_edit_multiple_paths(const Vector<String>& p_paths) {
+
+	clear();
+
+	//use the value that is repeated the mot
+	Map<String,Dictionary> value_frequency;
+
+	for(int i=0;i<p_paths.size();i++) {
+
+		Ref<ConfigFile> config;
+		config.instance();
+		Error err = config->load(p_paths[i]+".import");
+		ERR_CONTINUE(err!=OK);
+
+		if (i==0) {
+			params->importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(config->get_value("remap","importer"));
+			if (params->importer.is_null()) {
+				clear();
+				return;
+			}
+		}
+
+		List<String> keys;
+		config->get_section_keys("params",&keys);
+
+
+		for (List<String>::Element *E=keys.front();E;E=E->next()) {
+
+			if (!value_frequency.has(E->get())) {
+				value_frequency[E->get()]=Dictionary();
+			}
+
+			Variant value = config->get_value("params",E->get());
+
+			if (value_frequency[E->get()].has(value)) {
+				value_frequency[E->get()][value]=int(value_frequency[E->get()][value])+1;
+			} else {
+				value_frequency[E->get()][value]=1;
+			}
+		}
+
+	}
+
+	ERR_FAIL_COND(params->importer.is_null());
+
+	List<ResourceImporter::ImportOption> options;
+	params->importer->get_import_options(&options);
+
+	params->properties.clear();
+	params->values.clear();
+
+	for (List<ResourceImporter::ImportOption>::Element *E=options.front();E;E=E->next()) {
+
+		params->properties.push_back(E->get().option);
+
+		if (value_frequency.has(E->get().option.name)) {
+
+			Dictionary d = value_frequency[E->get().option.name];
+			int freq=0;
+			List<Variant> v;
+			d.get_key_list(&v);
+			Variant value;
+			for (List<Variant>::Element *F=v.front();F;F=F->next()) {
+				int f = d[F->get()];
+				if (f>freq) {
+					value=F->get();
+				}
+			}
+
+			params->values[E->get().option.name]=value;
+		} else {
+			params->values[E->get().option.name]=E->get().default_value;
+		}
+	}
+
+	params->update();
+
+	List<Ref<ResourceImporter> > importers;
+	ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_paths[0].get_extension(),&importers);
+	List<Pair<String,String> > importer_names;
+
+	for (List<Ref<ResourceImporter> > ::Element *E=importers.front();E;E=E->next()) {
+		importer_names.push_back(Pair<String,String>(E->get()->get_visible_name(),E->get()->get_importer_name()));
+	}
+
+	importer_names.sort_custom<PairSort<String,String> >();
+
+	import_as->clear();
+
+	for (List<Pair<String,String> >::Element *E=importer_names.front();E;E=E->next()) {
+		import_as->add_item(E->get().first);
+		import_as->set_item_metadata(import_as->get_item_count()-1,E->get().second);
+		if (E->get().second==params->importer->get_importer_name()) {
+			import_as->select(import_as->get_item_count()-1);
+		}
+	}
+
+	preset->get_popup()->clear();
+
+	if (params->importer->get_preset_count()==0) {
+		preset->get_popup()->add_item(TTR("Default"));
+	} else {
+		for (int i=0;i<params->importer->get_preset_count();i++) {
+			preset->get_popup()->add_item(params->importer->get_preset_name(i));
+		}
+	}
+
+	params->paths=p_paths;
+	import->set_disabled(false);
+	import_as->set_disabled(false);
+
+	imported->set_text(itos(p_paths.size())+TTR(" Files"));
+}
+
+void ImportDock::_preset_selected(int p_idx) {
+
+	print_line("preset selected? "+p_idx);
+	List<ResourceImporter::ImportOption> options;
+
+	params->importer->get_import_options(&options,p_idx);
+
+	for (List<ResourceImporter::ImportOption>::Element *E=options.front();E;E=E->next()) {
+
+		params->values[E->get().option.name]=E->get().default_value;
+	}
+
+	params->update();
+
+}
+
+
+void ImportDock::clear() {
+
+	imported->set_text("");
+	import->set_disabled(true);
+	import_as->clear();
+	import_as->set_disabled(true);
+	params->values.clear();
+	params->properties.clear();
+	params->update();
+	preset->get_popup()->clear();
+
+}
+
+void ImportDock::_reimport() {
+
+	for(int i=0;i<params->paths.size();i++) {
+
+		Ref<ConfigFile> config;
+		config.instance();
+		Error err = config->load(params->paths[i]+".import");
+		ERR_CONTINUE(err!=OK);
+
+		config->erase_section("params");
+
+		for (List<PropertyInfo>::Element *E=params->properties.front();E;E=E->next()) {
+			config->set_value("params",E->get().name,params->values[E->get().name]);
+		}
+
+		config->save(params->paths[i]+".import");
+	}
+
+	EditorFileSystem::get_singleton()->reimport_files(params->paths);
+	EditorFileSystem::get_singleton()->emit_signal("filesystem_changed"); //it changed, so force emitting the signal
+
+}
+
+void ImportDock::_bind_methods() {
+
+	ClassDB::bind_method(_MD("_reimport"),&ImportDock::_reimport);
+	ClassDB::bind_method(_MD("_preset_selected"),&ImportDock::_preset_selected);
+}
+
+ImportDock::ImportDock() {
+
+
+	imported = memnew( LineEdit );
+	imported->set_editable(false);
+	add_child(imported);
+	HBoxContainer *hb = memnew(HBoxContainer);
+	add_margin_child(TTR("Import As:"),hb);
+	import_as = memnew( OptionButton );
+	hb->add_child(import_as);
+	import_as->set_h_size_flags(SIZE_EXPAND_FILL);
+	preset = memnew( MenuButton );
+	preset->set_text(TTR("Preset.."));
+	preset->get_popup()->connect("index_pressed",this,"_preset_selected");
+	hb->add_child(preset);
+
+	import_opts = memnew( PropertyEditor );
+	add_child(import_opts);
+	import_opts->set_v_size_flags(SIZE_EXPAND_FILL);
+	import_opts->hide_top_label();
+	import_opts->set_hide_script(true);
+
+	hb = memnew( HBoxContainer );
+	add_child(hb);
+	import = memnew( Button );
+	import->set_text(TTR("Reimport"));
+	import->connect("pressed",this,"_reimport");
+	hb->add_spacer();
+	hb->add_child(import);
+	hb->add_spacer();
+
+	params = memnew( ImportDockParameters );
+	import_opts->edit(params);
+
+}
+
+ImportDock::~ImportDock() {
+
+	memdelete(params);
+}

+ 42 - 0
tools/editor/import_dock.h

@@ -0,0 +1,42 @@
+#ifndef IMPORTDOCK_H
+#define IMPORTDOCK_H
+
+#include "io/resource_import.h"
+#include "editor_file_system.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/popup_menu.h"
+#include "property_editor.h"
+
+class ImportDockParameters;
+class ImportDock : public VBoxContainer {
+	GDCLASS(ImportDock,VBoxContainer)
+
+	LineEdit *imported;
+	OptionButton *import_as;
+	MenuButton *preset;
+	PropertyEditor *import_opts;
+
+	List<PropertyInfo> properties;
+	Map<StringName,Variant> property_values;
+
+	Button *import;
+
+	ImportDockParameters *params;
+
+	void _preset_selected(int p_idx);
+
+	void _reimport();
+protected:
+	static void _bind_methods();
+public:
+
+	void set_edit_path(const String& p_path);
+	void set_edit_multiple_paths(const Vector<String>& p_paths);
+	void clear();
+
+	ImportDock();
+	~ImportDock();
+};
+
+#endif // IMPORTDOCK_H

+ 5 - 0
tools/editor/io_plugins/editor_texture_import_plugin.h

@@ -29,6 +29,11 @@
 #ifndef EDITOR_TEXTURE_IMPORT_PLUGIN_H
 #define EDITOR_TEXTURE_IMPORT_PLUGIN_H
 
+
+
+
+
+
 #if 0
 #include "tools/editor/editor_import_export.h"
 #include "scene/gui/dialogs.h"

+ 29 - 11
tools/editor/property_editor.cpp

@@ -118,7 +118,7 @@ void CustomPropertyEditor::_menu_option(int p_which) {
 
 					Set<String> valid_extensions;
 					for (List<String>::Element *E=extensions.front();E;E=E->next()) {
-
+						print_line("found: "+E->get());
 						valid_extensions.insert(E->get());
 					}
 
@@ -3140,6 +3140,10 @@ void PropertyEditor::update_tree() {
 		} else  if ( ! (p.usage&PROPERTY_USAGE_EDITOR ) )
 			continue;
 
+
+		if (hide_script && p.name=="script/script")
+			continue;
+
 		String basename=p.name;
 		if (group!="") {
 			if (group_base!="") {
@@ -3886,7 +3890,7 @@ void PropertyEditor::_item_selected() {
 }
 
 
-void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value) {
+void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value, bool p_refresh_all) {
 
 	if (autoclear) {
 		TreeItem *item = tree->get_selected();
@@ -3899,7 +3903,11 @@ void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value) {
 	if (!undo_redo || obj->cast_to<MultiNodeEdit>() || obj->cast_to<ArrayPropertyEdit>()) { //kind of hacky
 
 		obj->set(p_name,p_value);
-		_changed_callbacks(obj,p_name);
+		if (p_refresh_all)
+			_changed_callbacks(obj,"");
+		else
+			_changed_callbacks(obj,p_name);
+
 		emit_signal(_prop_edited,p_name);
 
 
@@ -3909,9 +3917,14 @@ void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value) {
 		undo_redo->add_do_property(obj,p_name,p_value);
 		undo_redo->add_undo_property(obj,p_name,obj->get(p_name));
 
+		if (p_refresh_all) {
+			undo_redo->add_do_method(this,"_changed_callback",obj,"");
+			undo_redo->add_undo_method(this,"_changed_callback",obj,"");
+		} else {
 
-		undo_redo->add_do_method(this,"_changed_callback",obj,p_name);
-		undo_redo->add_undo_method(this,"_changed_callback",obj,p_name);
+			undo_redo->add_do_method(this,"_changed_callback",obj,p_name);
+			undo_redo->add_undo_method(this,"_changed_callback",obj,p_name);
+		}
 
 		Resource *r = obj->cast_to<Resource>();
 		if (r) {
@@ -3973,6 +3986,9 @@ void PropertyEditor::_item_edited() {
 
 	int type=d["type"];
 	int hint= d["hint"];
+	int usage = d["usage"];
+	bool refresh_all = usage&PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED;
+
 	String hint_text=d["hint_text"];
 	switch(type) {
 
@@ -3981,7 +3997,7 @@ void PropertyEditor::_item_edited() {
 		} break;
 		case Variant::BOOL: {
 
-			_edit_set(name,item->is_checked(1));
+			_edit_set(name,item->is_checked(1),refresh_all);
 			item->set_tooltip(1, item->is_checked(1) ? "True" : "False");
 		} break;
 		case Variant::INT:
@@ -3995,9 +4011,9 @@ void PropertyEditor::_item_edited() {
 				break;
 
 			if (type==Variant::INT)
-				_edit_set(name,int(item->get_range(1)));
+				_edit_set(name,int(item->get_range(1)),refresh_all);
 			else
-				_edit_set(name,item->get_range(1));
+				_edit_set(name,item->get_range(1),refresh_all);
 		} break;
 		case Variant::STRING: {
 
@@ -4012,9 +4028,9 @@ void PropertyEditor::_item_edited() {
 					txt=strings[idx];
 				}
 
-				_edit_set(name,txt);
+				_edit_set(name,txt,refresh_all);
 			} else {
-				_edit_set(name,item->get_text(1));
+				_edit_set(name,item->get_text(1),refresh_all);
 			}
 		} break;
 			// math types
@@ -4045,7 +4061,7 @@ void PropertyEditor::_item_edited() {
 
 		} break;
 		case Variant::NODE_PATH: {
-			_edit_set(name, NodePath(item->get_text(1)));
+			_edit_set(name, NodePath(item->get_text(1)),refresh_all);
 
 		} break;
 
@@ -4476,6 +4492,8 @@ PropertyEditor::PropertyEditor() {
 
 	_prop_edited="property_edited";
 
+	hide_script=false;
+
 	undo_redo=NULL;
 	obj=NULL;
 	search_box=NULL;

+ 3 - 1
tools/editor/property_editor.h

@@ -192,6 +192,7 @@ class PropertyEditor : public Control {
 	bool use_doc_hints;
 	bool use_filter;
 	bool subsection_selectable;
+	bool hide_script;
 
 	HashMap<String,String> pending;
 	String selected_property;
@@ -224,7 +225,7 @@ class PropertyEditor : public Control {
 	void _node_removed(Node *p_node);
 
 friend class ProjectExportDialog;
-	void _edit_set(const String& p_name, const Variant& p_value);
+	void _edit_set(const String& p_name, const Variant& p_value,bool p_refresh_all=false);
 	void _draw_flags(Object *ti,const Rect2& p_rect);
 
 	bool _might_be_in_instance();
@@ -276,6 +277,7 @@ public:
 
 	void set_show_categories(bool p_show);
 	void set_use_doc_hints(bool p_enable) { use_doc_hints=p_enable; }
+	void set_hide_script(bool p_hide) { hide_script=p_hide; }
 
 	void set_use_filter(bool p_use);
 	void register_text_enter(Node *p_line_edit);