浏览代码

Merge branch 'master' of https://github.com/okamstudio/godot

Mariano Javier Suligoy 10 年之前
父节点
当前提交
54291c655d
共有 86 个文件被更改,包括 2892 次插入287 次删除
  1. 3 3
      SConstruct
  2. 1 0
      core/error_list.h
  3. 1 0
      core/global_constants.cpp
  4. 313 23
      core/io/resource_format_binary.cpp
  5. 9 5
      core/io/resource_format_binary.h
  6. 269 53
      core/io/resource_format_xml.cpp
  7. 18 7
      core/io/resource_format_xml.h
  8. 54 11
      core/io/resource_loader.cpp
  9. 16 6
      core/io/resource_loader.h
  10. 1 1
      core/io/resource_saver.h
  11. 8 1
      core/io/translation_loader_po.cpp
  12. 1 1
      core/io/translation_loader_po.h
  13. 12 1
      drivers/chibi/event_stream_chibi.cpp
  14. 1 1
      drivers/chibi/event_stream_chibi.h
  15. 9 1
      drivers/dds/texture_loader_dds.cpp
  16. 1 1
      drivers/dds/texture_loader_dds.h
  17. 3 2
      drivers/mpc/audio_stream_mpc.cpp
  18. 1 1
      drivers/mpc/audio_stream_mpc.h
  19. 8 1
      drivers/pvr/texture_loader_pvr.cpp
  20. 1 1
      drivers/pvr/texture_loader_pvr.h
  21. 4 1
      drivers/speex/audio_stream_speex.cpp
  22. 1 1
      drivers/speex/audio_stream_speex.h
  23. 1 1
      drivers/theora/video_stream_theora.h
  24. 3 1
      drivers/theoraplayer/video_stream_theoraplayer.cpp
  25. 1 1
      drivers/theoraplayer/video_stream_theoraplayer.h
  26. 3 1
      drivers/vorbis/audio_stream_ogg_vorbis.cpp
  27. 1 1
      drivers/vorbis/audio_stream_ogg_vorbis.h
  28. 6 1
      modules/gdscript/gd_script.cpp
  29. 1 1
      modules/gdscript/gd_script.h
  30. 3 1
      platform/x11/detect.py
  31. 1 1
      scene/gui/dialogs.cpp
  32. 25 12
      scene/gui/item_list.cpp
  33. 2 0
      scene/gui/item_list.h
  34. 132 0
      scene/gui/patch_9_frame.cpp
  35. 40 0
      scene/gui/patch_9_frame.h
  36. 5 0
      scene/gui/tree.cpp
  37. 11 2
      scene/io/resource_format_image.cpp
  38. 1 1
      scene/io/resource_format_image.h
  39. 9 1
      scene/io/resource_format_wav.cpp
  40. 1 1
      scene/io/resource_format_wav.h
  41. 2 0
      scene/register_scene_types.cpp
  42. 6 1
      scene/resources/bit_mask.cpp
  43. 1 1
      scene/resources/bit_mask.h
  44. 8 1
      scene/resources/shader.cpp
  45. 1 1
      scene/resources/shader.h
  46. 8 1
      scene/resources/theme.cpp
  47. 1 1
      scene/resources/theme.h
  48. 512 0
      tools/editor/dependency_editor.cpp
  49. 94 0
      tools/editor/dependency_editor.h
  50. 3 2
      tools/editor/editor_file_dialog.cpp
  51. 41 3
      tools/editor/editor_file_system.cpp
  52. 6 3
      tools/editor/editor_file_system.h
  53. 64 3
      tools/editor/editor_node.cpp
  54. 18 1
      tools/editor/editor_node.h
  55. 二进制
      tools/editor/icons/icon_anchor.png
  56. 二进制
      tools/editor/icons/icon_control_align_bottom_center.png
  57. 二进制
      tools/editor/icons/icon_control_align_bottom_left.png
  58. 二进制
      tools/editor/icons/icon_control_align_bottom_right.png
  59. 二进制
      tools/editor/icons/icon_control_align_bottom_wide.png
  60. 二进制
      tools/editor/icons/icon_control_align_center.png
  61. 二进制
      tools/editor/icons/icon_control_align_center_left.png
  62. 二进制
      tools/editor/icons/icon_control_align_center_right.png
  63. 二进制
      tools/editor/icons/icon_control_align_left_center.png
  64. 二进制
      tools/editor/icons/icon_control_align_left_wide.png
  65. 二进制
      tools/editor/icons/icon_control_align_right_center.png
  66. 二进制
      tools/editor/icons/icon_control_align_right_wide.png
  67. 二进制
      tools/editor/icons/icon_control_align_top_center.png
  68. 二进制
      tools/editor/icons/icon_control_align_top_left.png
  69. 二进制
      tools/editor/icons/icon_control_align_top_right.png
  70. 二进制
      tools/editor/icons/icon_control_align_top_wide.png
  71. 二进制
      tools/editor/icons/icon_control_align_wide.png
  72. 二进制
      tools/editor/icons/icon_control_hcenter_wide.png
  73. 二进制
      tools/editor/icons/icon_control_vcenter_wide.png
  74. 二进制
      tools/editor/icons/icon_file_list.png
  75. 二进制
      tools/editor/icons/icon_filesystem.png
  76. 二进制
      tools/editor/icons/icon_non_favorite.png
  77. 二进制
      tools/editor/icons/icon_patch_9_frame.png
  78. 120 0
      tools/editor/plugins/canvas_item_editor_plugin.cpp
  79. 20 0
      tools/editor/plugins/canvas_item_editor_plugin.h
  80. 3 1
      tools/editor/project_export.cpp
  81. 3 0
      tools/editor/project_export.h
  82. 36 6
      tools/editor/quick_open.cpp
  83. 7 3
      tools/editor/quick_open.h
  84. 869 62
      tools/editor/scenes_dock.cpp
  85. 84 46
      tools/editor/scenes_dock.h
  86. 4 3
      version.py

+ 3 - 3
SConstruct

@@ -220,14 +220,14 @@ if selected_platform in platform_list:
 
 
 	env.Append(LINKFLAGS=string.split(str(LINKFLAGS)))
 	env.Append(LINKFLAGS=string.split(str(LINKFLAGS)))
 
 
-	detect.configure(env)
-
-
 	flag_list = platform_flags[selected_platform]
 	flag_list = platform_flags[selected_platform]
 	for f in flag_list:
 	for f in flag_list:
 		if not (f[0] in ARGUMENTS): # allow command line to override platform flags
 		if not (f[0] in ARGUMENTS): # allow command line to override platform flags
 			env[f[0]] = f[1]
 			env[f[0]] = f[1]
 
 
+	#must happen after the flags, so when flags are used by configure, stuff happens (ie, ssl on x11)
+	detect.configure(env)
+
         #env['platform_libsuffix'] = env['LIBSUFFIX']
         #env['platform_libsuffix'] = env['LIBSUFFIX']
 
 
 	suffix="."+selected_platform
 	suffix="."+selected_platform

+ 1 - 0
core/error_list.h

@@ -54,6 +54,7 @@ enum Error {
 	ERR_FILE_CANT_READ,
 	ERR_FILE_CANT_READ,
 	ERR_FILE_UNRECOGNIZED, // (15)
 	ERR_FILE_UNRECOGNIZED, // (15)
 	ERR_FILE_CORRUPT,
 	ERR_FILE_CORRUPT,
+	ERR_FILE_MISSING_DEPENDENCIES,
 	ERR_FILE_EOF,
 	ERR_FILE_EOF,
 	ERR_CANT_OPEN, ///< Can't open a resource/socket/file
 	ERR_CANT_OPEN, ///< Can't open a resource/socket/file
 	ERR_CANT_CREATE,
 	ERR_CANT_CREATE,

+ 1 - 0
core/global_constants.cpp

@@ -422,6 +422,7 @@ static _GlobalConstant _global_constants[]={
 	BIND_GLOBAL_CONSTANT( ERR_FILE_CANT_READ ),
 	BIND_GLOBAL_CONSTANT( ERR_FILE_CANT_READ ),
 	BIND_GLOBAL_CONSTANT( ERR_FILE_UNRECOGNIZED ),
 	BIND_GLOBAL_CONSTANT( ERR_FILE_UNRECOGNIZED ),
 	BIND_GLOBAL_CONSTANT( ERR_FILE_CORRUPT ),
 	BIND_GLOBAL_CONSTANT( ERR_FILE_CORRUPT ),
+	BIND_GLOBAL_CONSTANT( ERR_FILE_MISSING_DEPENDENCIES),
 	BIND_GLOBAL_CONSTANT( ERR_FILE_EOF ),
 	BIND_GLOBAL_CONSTANT( ERR_FILE_EOF ),
 	BIND_GLOBAL_CONSTANT( ERR_CANT_OPEN ), ///< Can't open a resource/socket/file
 	BIND_GLOBAL_CONSTANT( ERR_CANT_OPEN ), ///< Can't open a resource/socket/file
 	BIND_GLOBAL_CONSTANT( ERR_CANT_CREATE ),
 	BIND_GLOBAL_CONSTANT( ERR_CANT_CREATE ),

+ 313 - 23
core/io/resource_format_binary.cpp

@@ -31,6 +31,7 @@
 #include "globals.h"
 #include "globals.h"
 #include "io/file_access_compressed.h"
 #include "io/file_access_compressed.h"
 #include "io/marshalls.h"
 #include "io/marshalls.h"
+#include "os/dir_access.h"
 //#define print_bl(m_what) print_line(m_what)
 //#define print_bl(m_what) print_line(m_what)
 #define print_bl(m_what)
 #define print_bl(m_what)
 
 
@@ -99,7 +100,9 @@ enum {
 	OBJECT_EMPTY=0,
 	OBJECT_EMPTY=0,
 	OBJECT_EXTERNAL_RESOURCE=1,
 	OBJECT_EXTERNAL_RESOURCE=1,
 	OBJECT_INTERNAL_RESOURCE=2,
 	OBJECT_INTERNAL_RESOURCE=2,
-	FORMAT_VERSION=0
+	OBJECT_EXTERNAL_RESOURCE_INDEX=3,
+	FORMAT_VERSION=1,
+	FORMAT_VERSION_CAN_RENAME_DEPS=1
 
 
 
 
 };
 };
@@ -375,7 +378,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v)  {
 				} break;
 				} break;
 				case OBJECT_INTERNAL_RESOURCE: {
 				case OBJECT_INTERNAL_RESOURCE: {
 					uint32_t index=f->get_32();
 					uint32_t index=f->get_32();
-					String path = res_path+"::"+itos(index);
+					String path = res_path+"::"+itos(index);					
 					RES res = ResourceLoader::load(path);
 					RES res = ResourceLoader::load(path);
 					if (res.is_null()) {
 					if (res.is_null()) {
 						WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data());
 						WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data());
@@ -384,6 +387,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v)  {
 
 
 				} break;
 				} break;
 				case OBJECT_EXTERNAL_RESOURCE: {
 				case OBJECT_EXTERNAL_RESOURCE: {
+					//old file format, still around for compatibility
 
 
 					String type = get_unicode_string();
 					String type = get_unicode_string();
 					String path = get_unicode_string();
 					String path = get_unicode_string();
@@ -394,6 +398,10 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v)  {
 
 
 					}
 					}
 
 
+					if (remaps.find(path)) {
+						path=remaps[path];
+					}
+
 					RES res=ResourceLoader::load(path,type);
 					RES res=ResourceLoader::load(path,type);
 
 
 					if (res.is_null()) {
 					if (res.is_null()) {
@@ -401,6 +409,34 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v)  {
 					}
 					}
 					r_v=res;
 					r_v=res;
 
 
+				} break;
+				case OBJECT_EXTERNAL_RESOURCE_INDEX: {
+					//new file format, just refers to an index in the external list
+					uint32_t erindex = f->get_32();
+
+					if (erindex>=external_resources.size()) {
+						WARN_PRINT("Broken external resource! (index out of size");
+						r_v=Variant();
+					} else {
+
+						String type = external_resources[erindex].type;
+						String path = external_resources[erindex].path;
+
+						if (path.find("://")==-1 && path.is_rel_path()) {
+							// path is relative to file being loaded, so convert to a resource path
+							path=Globals::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path));
+
+						}
+
+						RES res=ResourceLoader::load(path,type);
+
+						if (res.is_null()) {
+							WARN_PRINT(String("Couldn't load resource: "+path).utf8().get_data());
+						}
+						r_v=res;
+					}
+
+
 				} break;
 				} break;
 				default: {
 				default: {
 
 
@@ -628,17 +664,20 @@ Error ResourceInteractiveLoaderBinary::poll(){
 
 
 	if (s<external_resources.size()) {
 	if (s<external_resources.size()) {
 
 
-		RES res = ResourceLoader::load(external_resources[s].path,external_resources[s].type);
+		String path = external_resources[s].path;
+		if (remaps.has(path)) {
+			path=remaps[path];
+		}
+		RES res = ResourceLoader::load(path,external_resources[s].type);
 		if (res.is_null()) {
 		if (res.is_null()) {
 
 
 			if (!ResourceLoader::get_abort_on_missing_resources()) {
 			if (!ResourceLoader::get_abort_on_missing_resources()) {
 
 
-				ResourceLoader::notify_load_error("Resource Not Found: "+external_resources[s].path);
+				ResourceLoader::notify_dependency_error(local_path,path,external_resources[s].type);
 			} else {
 			} else {
 
 
-
-				error=ERR_FILE_CORRUPT;
-				ERR_EXPLAIN("Can't load dependency: "+external_resources[s].path);
+				error=ERR_FILE_MISSING_DEPENDENCIES;
+				ERR_EXPLAIN("Can't load dependency: "+path);
 				ERR_FAIL_V(error);
 				ERR_FAIL_V(error);
 			}
 			}
 
 
@@ -787,6 +826,27 @@ int ResourceInteractiveLoaderBinary::get_stage_count() const {
 	return external_resources.size()+internal_resources.size();
 	return external_resources.size()+internal_resources.size();
 }
 }
 
 
+
+static void save_ustring(FileAccess* f,const String& p_string) {
+
+
+	CharString utf8 = p_string.utf8();
+	f->store_32(utf8.length()+1);
+	f->store_buffer((const uint8_t*)utf8.get_data(),utf8.length()+1);
+}
+
+
+static String get_ustring(FileAccess *f) {
+
+	int len = f->get_32();
+	Vector<char> str_buf;
+	str_buf.resize(len);
+	f->get_buffer((uint8_t*)&str_buf[0],len);
+	String s;
+	s.parse_utf8(&str_buf[0]);
+	return s;
+}
+
 String ResourceInteractiveLoaderBinary::get_unicode_string() {
 String ResourceInteractiveLoaderBinary::get_unicode_string() {
 
 
 	int len = f->get_32();
 	int len = f->get_32();
@@ -801,7 +861,7 @@ String ResourceInteractiveLoaderBinary::get_unicode_string() {
 
 
 
 
 
 
-void ResourceInteractiveLoaderBinary::get_dependencies(FileAccess *p_f,List<String> *p_dependencies) {
+void ResourceInteractiveLoaderBinary::get_dependencies(FileAccess *p_f,List<String> *p_dependencies,bool p_add_types) {
 
 
 	open(p_f);
 	open(p_f);
 	if (error)
 	if (error)
@@ -814,6 +874,10 @@ void ResourceInteractiveLoaderBinary::get_dependencies(FileAccess *p_f,List<Stri
 			dep=ResourceLoader::guess_full_filename(dep,external_resources[i].type);
 			dep=ResourceLoader::guess_full_filename(dep,external_resources[i].type);
 		}
 		}
 
 
+		if (p_add_types && external_resources[i].type!=String()) {
+			dep+="::"+external_resources[i].type;
+		}
+
 		p_dependencies->push_back(dep);
 		p_dependencies->push_back(dep);
 	}
 	}
 
 
@@ -866,7 +930,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
 	print_bl("minor: "+itos(ver_minor));
 	print_bl("minor: "+itos(ver_minor));
 	print_bl("format: "+itos(ver_format));
 	print_bl("format: "+itos(ver_format));
 
 
-	if (ver_format<FORMAT_VERSION ||  ver_major>VERSION_MAJOR) {
+	if (ver_format>FORMAT_VERSION ||  ver_major>VERSION_MAJOR) {
 
 
 		f->close();
 		f->close();
 		ERR_EXPLAIN("File Format '"+itos(FORMAT_VERSION)+"."+itos(ver_major)+"."+itos(ver_minor)+"' is too new! Please upgrade to a a new engine version: "+local_path);
 		ERR_EXPLAIN("File Format '"+itos(FORMAT_VERSION)+"."+itos(ver_major)+"."+itos(ver_minor)+"' is too new! Please upgrade to a a new engine version: "+local_path);
@@ -903,6 +967,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
 	}
 	}
 
 
 	//see if the exporter has different set of external resources for more efficient loading
 	//see if the exporter has different set of external resources for more efficient loading
+	/*
 	String preload_depts = "deps/"+res_path.md5_text();
 	String preload_depts = "deps/"+res_path.md5_text();
 	if (Globals::get_singleton()->has(preload_depts)) {
 	if (Globals::get_singleton()->has(preload_depts)) {
 		external_resources.clear();
 		external_resources.clear();
@@ -913,7 +978,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
 			external_resources[i].path=depts.get_name(i);
 			external_resources[i].path=depts.get_name(i);
 		}
 		}
 		print_line(res_path+" - EXTERNAL RESOURCES: "+itos(external_resources.size()));
 		print_line(res_path+" - EXTERNAL RESOURCES: "+itos(external_resources.size()));
-	}
+	}*/
 
 
 	print_bl("ext resources: "+itos(ext_resources_size));
 	print_bl("ext resources: "+itos(ext_resources_size));
 	uint32_t int_resources_size=f->get_32();
 	uint32_t int_resources_size=f->get_32();
@@ -973,7 +1038,7 @@ String ResourceInteractiveLoaderBinary::recognize(FileAccess *p_f) {
 	uint32_t ver_minor=f->get_32();
 	uint32_t ver_minor=f->get_32();
 	uint32_t ver_format=f->get_32();
 	uint32_t ver_format=f->get_32();
 
 
-	if (ver_format<FORMAT_VERSION ||  ver_major>VERSION_MAJOR) {
+	if (ver_format>FORMAT_VERSION ||  ver_major>VERSION_MAJOR) {
 
 
 		f->close();
 		f->close();
 		return "";
 		return "";
@@ -1000,8 +1065,10 @@ ResourceInteractiveLoaderBinary::~ResourceInteractiveLoaderBinary() {
 }
 }
 
 
 
 
-Ref<ResourceInteractiveLoader> ResourceFormatLoaderBinary::load_interactive(const String &p_path) {
+Ref<ResourceInteractiveLoader> ResourceFormatLoaderBinary::load_interactive(const String &p_path, Error *r_error) {
 
 
+	if (r_error)
+		*r_error=ERR_FILE_CANT_OPEN;
 
 
 	Error err;
 	Error err;
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
@@ -1114,7 +1181,7 @@ Error ResourceFormatLoaderBinary::load_import_metadata(const String &p_path, Ref
 }
 }
 
 
 
 
-void ResourceFormatLoaderBinary::get_dependencies(const String& p_path,List<String> *p_dependencies) {
+void ResourceFormatLoaderBinary::get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types) {
 
 
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
 	ERR_FAIL_COND(!f);
 	ERR_FAIL_COND(!f);
@@ -1123,7 +1190,217 @@ void ResourceFormatLoaderBinary::get_dependencies(const String& p_path,List<Stri
 	ria->local_path=Globals::get_singleton()->localize_path(p_path);
 	ria->local_path=Globals::get_singleton()->localize_path(p_path);
 	ria->res_path=ria->local_path;
 	ria->res_path=ria->local_path;
 //	ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
 //	ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
-	ria->get_dependencies(f,p_dependencies);
+	ria->get_dependencies(f,p_dependencies,p_add_types);
+}
+
+Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path,const Map<String,String>& p_map) {
+
+
+//	Error error=OK;
+
+
+	FileAccess *f=FileAccess::open(p_path,FileAccess::READ);
+	ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
+
+	FileAccess* fw=NULL;//=FileAccess::open(p_path+".depren");
+
+	String local_path=p_path.get_base_dir();
+
+	uint8_t header[4];
+	f->get_buffer(header,4);
+	if (header[0]=='R' && header[1]=='S' && header[2]=='C' && header[3]=='C') {
+		//compressed
+		FileAccessCompressed *fac = memnew( FileAccessCompressed );
+		fac->open_after_magic(f);
+		f=fac;
+
+		FileAccessCompressed *facw = memnew( FileAccessCompressed );
+		facw->configure("RSCC");
+		Error err = facw->_open(p_path+".depren",FileAccess::WRITE);
+		if (err) {
+			memdelete(fac);
+			memdelete(facw);
+			ERR_FAIL_COND_V(err,ERR_FILE_CORRUPT);
+		}
+
+		fw=facw;
+
+
+	} else if (header[0]!='R' || header[1]!='S' || header[2]!='R' || header[3]!='C') {
+		//not normal
+
+		//error=ERR_FILE_UNRECOGNIZED;
+		memdelete(f);
+		ERR_EXPLAIN("Unrecognized binary resource file: "+local_path);
+		ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
+	} else {
+		fw = FileAccess::open(p_path+".depren",FileAccess::WRITE);
+		if (!fw) {
+			memdelete(f);
+		}
+		ERR_FAIL_COND_V(!fw,ERR_CANT_CREATE);
+	}
+
+	bool big_endian = f->get_32();
+#ifdef BIG_ENDIAN_ENABLED
+	endian_swap = !big_endian;
+#else
+	bool endian_swap = big_endian;
+#endif
+
+	bool use_real64 = f->get_32();
+
+	f->set_endian_swap(big_endian!=0); //read big endian if saved as big endian
+	fw->store_32(endian_swap);
+	fw->set_endian_swap(big_endian!=0);
+	fw->store_32(use_real64); //use real64
+
+	uint32_t ver_major=f->get_32();
+	uint32_t ver_minor=f->get_32();
+	uint32_t ver_format=f->get_32();
+
+	if (ver_format<FORMAT_VERSION_CAN_RENAME_DEPS) {
+
+		memdelete(f);
+		memdelete(fw);
+		DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+		da->remove(p_path+".depren");
+		memdelete(da);
+		//fuck it, use the old approach;
+
+		WARN_PRINT(("This file is old, so it can't refactor dependencies, opening and resaving: "+p_path).utf8().get_data());
+
+		Error err;
+		f = FileAccess::open(p_path,FileAccess::READ,&err);
+		if (err!=OK) {
+			ERR_FAIL_COND_V(err!=OK,ERR_FILE_CANT_OPEN);
+		}
+
+		Ref<ResourceInteractiveLoaderBinary> ria = memnew( ResourceInteractiveLoaderBinary );
+		ria->local_path=Globals::get_singleton()->localize_path(p_path);
+		ria->res_path=ria->local_path;
+		ria->remaps=p_map;
+	//	ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
+		ria->open(f);
+
+		err = ria->poll();
+
+		while(err==OK) {
+			err=ria->poll();
+		}
+
+		ERR_FAIL_COND_V(err!=ERR_FILE_EOF,ERR_FILE_CORRUPT);
+		RES res = ria->get_resource();
+		ERR_FAIL_COND_V(!res.is_valid(),ERR_FILE_CORRUPT);
+
+		return ResourceFormatSaverBinary::singleton->save(p_path,res);
+	}
+
+	if (ver_format>FORMAT_VERSION ||  ver_major>VERSION_MAJOR) {
+
+		memdelete(f);
+		memdelete(fw);
+		ERR_EXPLAIN("File Format '"+itos(FORMAT_VERSION)+"."+itos(ver_major)+"."+itos(ver_minor)+"' is too new! Please upgrade to a a new engine version: "+local_path);
+		ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
+
+	}
+
+	fw->store_32( VERSION_MAJOR ); //current version
+	fw->store_32( VERSION_MINOR );
+	fw->store_32( FORMAT_VERSION );
+
+	save_ustring(fw,get_ustring(f)); //type
+
+
+	size_t md_ofs = f->get_pos();
+	size_t importmd_ofs = f->get_64();
+	fw->store_64(0); //metadata offset
+
+	for(int i=0;i<14;i++) {
+		fw->store_32(0);
+		f->get_32();
+	}
+
+	//string table
+	uint32_t string_table_size=f->get_32();
+
+	fw->store_32(string_table_size);
+
+	for(uint32_t i=0;i<string_table_size;i++) {
+
+		String s = get_ustring(f);
+		save_ustring(fw,s);
+	}
+
+	//external resources
+	uint32_t ext_resources_size=f->get_32();
+	fw->store_32(ext_resources_size);
+	for(uint32_t i=0;i<ext_resources_size;i++) {
+
+		String type = get_ustring(f);
+		String path = get_ustring(f);
+
+		bool relative=false;
+		if (!path.begins_with("res://")) {
+			path=local_path.plus_file(path).simplify_path();
+			relative=true;
+		}
+
+
+		if (p_map.has(path)) {
+			String np=p_map[path];
+			path=np;
+		}
+
+		if (relative) {
+			//restore relative
+			path=local_path.path_to_file(path);
+		}
+
+		save_ustring(fw,type);
+		save_ustring(fw,path);
+	}
+
+	int64_t size_diff = (int64_t)fw->get_pos() - (int64_t)f->get_pos();
+
+	//internal resources
+	uint32_t int_resources_size=f->get_32();
+	fw->store_32(int_resources_size);
+
+	for(uint32_t i=0;i<int_resources_size;i++) {
+
+
+		String path=get_ustring(f);
+		uint64_t offset=f->get_64();
+		save_ustring(fw,path);
+		fw->store_64(offset+size_diff);
+	}
+
+	//rest of file
+	uint8_t b = f->get_8();
+	while(!f->eof_reached()) {
+		fw->store_8(b);
+		b = f->get_8();
+	}
+
+	bool all_ok = fw->get_error()==OK;
+
+	fw->seek(md_ofs);
+	fw->store_64(importmd_ofs+size_diff);
+
+
+	memdelete(f);
+	memdelete(fw);
+
+	if (!all_ok) {
+		return ERR_CANT_CREATE;
+	}
+
+	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	da->remove(p_path);
+	da->rename(p_path+".depren",p_path);
+	memdelete(da);
+	return OK;
 }
 }
 
 
 
 
@@ -1433,10 +1710,8 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant& p_property,
 			}
 			}
 
 
 			if (res->get_path().length() && res->get_path().find("::")==-1) {
 			if (res->get_path().length() && res->get_path().find("::")==-1) {
-				f->store_32(OBJECT_EXTERNAL_RESOURCE);
-				save_unicode_string(res->get_save_type());
-				String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path();
-				save_unicode_string(path);
+				f->store_32(OBJECT_EXTERNAL_RESOURCE_INDEX);
+				f->store_32(external_resources[res]);
 			} else {
 			} else {
 
 
 				if (!resource_set.has(res)) {
 				if (!resource_set.has(res)) {
@@ -1594,11 +1869,12 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant& p_variant
 
 
 			RES res = p_variant.operator RefPtr();
 			RES res = p_variant.operator RefPtr();
 
 
-			if (res.is_null())
+			if (res.is_null() || external_resources.has(res))
 				return;
 				return;
 
 
 			if (!p_main && (!bundle_resources ) && res->get_path().length() && res->get_path().find("::") == -1 ) {
 			if (!p_main && (!bundle_resources ) && res->get_path().length() && res->get_path().find("::") == -1 ) {
-				external_resources.insert(res);
+				int idx = external_resources.size();
+				external_resources[res]=idx;
 				return;
 				return;
 			}
 			}
 
 
@@ -1842,10 +2118,18 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
 
 
 	// save external resource table
 	// save external resource table
 	f->store_32(external_resources.size()); //amount of external resources
 	f->store_32(external_resources.size()); //amount of external resources
-	for(Set<RES>::Element *E=external_resources.front();E;E=E->next()) {
+	Vector<RES> save_order;
+	save_order.resize(external_resources.size());
+
+	for(Map<RES,int>::Element *E=external_resources.front();E;E=E->next()) {
+		save_order[E->get()]=E->key();
+	}
 
 
-		save_unicode_string(E->get()->get_save_type());
-		String path = E->get()->get_path();
+	for(int i=0;i<save_order.size();i++) {
+
+		save_unicode_string(save_order[i]->get_save_type());
+		String path = save_order[i]->get_path();
+		path=relative_paths?local_path.path_to_file(path):path;
 		save_unicode_string(path);
 		save_unicode_string(path);
 	}
 	}
 	// save internal resource table
 	// save internal resource table
@@ -1995,3 +2279,9 @@ void ResourceFormatSaverBinary::get_recognized_extensions(const RES& p_resource,
 
 
 }
 }
 
 
+ResourceFormatSaverBinary* ResourceFormatSaverBinary::singleton=NULL;
+
+ResourceFormatSaverBinary::ResourceFormatSaverBinary() {
+
+	singleton=this;
+}

+ 9 - 5
core/io/resource_format_binary.h

@@ -71,6 +71,7 @@ class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader {
 	String get_unicode_string();
 	String get_unicode_string();
 	void _advance_padding(uint32_t p_len);
 	void _advance_padding(uint32_t p_len);
 
 
+	Map<String,String> remaps;
 	Error error;
 	Error error;
 
 
 	int stage;
 	int stage;
@@ -88,9 +89,10 @@ public:
 	virtual int get_stage() const;
 	virtual int get_stage() const;
 	virtual int get_stage_count() const;
 	virtual int get_stage_count() const;
 
 
+	void set_remaps(const Map<String,String>& p_remaps) { remaps=p_remaps; }
 	void open(FileAccess *p_f);
 	void open(FileAccess *p_f);
 	String recognize(FileAccess *p_f);
 	String recognize(FileAccess *p_f);
-	void get_dependencies(FileAccess *p_f,List<String> *p_dependencies);
+	void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
 
 
 
 
 	ResourceInteractiveLoaderBinary();
 	ResourceInteractiveLoaderBinary();
@@ -101,13 +103,14 @@ public:
 class ResourceFormatLoaderBinary : public ResourceFormatLoader {
 class ResourceFormatLoaderBinary : public ResourceFormatLoader {
 public:
 public:
 
 
-	virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path);
+	virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,Error *r_error=NULL);
 	virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const;
 	virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const;
 	virtual void get_recognized_extensions(List<String> *p_extensions) const;
 	virtual void get_recognized_extensions(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;
-	virtual void get_dependencies(const String& p_path,List<String> *p_dependencies);
+	virtual void get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types=false);
 	virtual Error load_import_metadata(const String &p_path, Ref<ResourceImportMetadata>& r_var) const;
 	virtual Error load_import_metadata(const String &p_path, Ref<ResourceImportMetadata>& r_var) const;
+	virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map);
 
 
 
 
 
 
@@ -134,7 +137,7 @@ class ResourceFormatSaverBinaryInstance  {
 	Vector<StringName> strings;
 	Vector<StringName> strings;
 
 
 
 
-	Set<RES> external_resources;
+	Map<RES,int> external_resources;
 	List<RES> saved_resources;
 	List<RES> saved_resources;
 
 
 
 
@@ -174,11 +177,12 @@ class ResourceFormatSaverBinary : public ResourceFormatSaver  {
 
 
 public:
 public:
 
 
+	static ResourceFormatSaverBinary* singleton;
 	virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0);
 	virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0);
 	virtual bool recognize(const RES& p_resource) const;
 	virtual bool recognize(const RES& p_resource) const;
 	virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const;
 	virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const;
 
 
-
+	ResourceFormatSaverBinary();
 };
 };
 
 
 
 

+ 269 - 53
core/io/resource_format_xml.cpp

@@ -29,10 +29,10 @@
 #include "resource_format_xml.h"
 #include "resource_format_xml.h"
 #include "globals.h"
 #include "globals.h"
 #include "version.h"
 #include "version.h"
+#include "os/dir_access.h"
 
 
 
 
-
-ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool *r_exit,bool p_printerr) {
+ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool *r_exit, bool p_printerr, List<String> *r_order) {
 
 
 
 
 	while(get_char()!='<' && !f->eof_reached()) {}
 	while(get_char()!='<' && !f->eof_reached()) {}
@@ -107,7 +107,11 @@ ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool
 				if (r_value.size()) {
 				if (r_value.size()) {
 
 
 					r_value.push_back(0);
 					r_value.push_back(0);
-					tag.args[name].parse_utf8(r_value.get_data());
+					String str;
+					str.parse_utf8(r_value.get_data());
+					tag.args[name]=str;
+					if (r_order)
+						r_order->push_back(name);
 				}
 				}
 				break;
 				break;
 
 
@@ -119,7 +123,11 @@ ResourceInteractiveLoaderXML::Tag* ResourceInteractiveLoaderXML::parse_tag(bool
 				} else if (reading_value && r_value.size()) {
 				} else if (reading_value && r_value.size()) {
 
 
 					r_value.push_back(0);
 					r_value.push_back(0);
-					tag.args[name].parse_utf8(r_value.get_data());
+					String str;
+					str.parse_utf8(r_value.get_data());
+					tag.args[name]=str;
+					if (r_order)
+						r_order->push_back(name);
 					name="";
 					name="";
 					r_value.clear();
 					r_value.clear();
 					reading_value=false;
 					reading_value=false;
@@ -463,6 +471,10 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name)
 
 
 			}
 			}
 
 
+			if (remaps.has(path)) {
+				path=remaps[path];
+			}
+
 			//take advantage of the resource loader cache. The resource is cached on it, even if
 			//take advantage of the resource loader cache. The resource is cached on it, even if
 			RES res=ResourceLoader::load(path,hint);
 			RES res=ResourceLoader::load(path,hint);
 
 
@@ -473,10 +485,31 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name)
 			}
 			}
 
 
 			r_v=res.get_ref_ptr();
 			r_v=res.get_ref_ptr();
+		} else if (tag->args.has("external")) {
+
+			int index = tag->args["external"].to_int();
+			if (ext_resources.has(index)) {
+				String path=ext_resources[index].path;
+				String type=ext_resources[index].type;
+
+				//take advantage of the resource loader cache. The resource is cached on it, even if
+				RES res=ResourceLoader::load(path,type);
+
+				if (res.is_null()) {
+
+					WARN_PRINT(String("Couldn't load externalresource: "+path).ascii().get_data());
+				}
+
+				r_v=res.get_ref_ptr();
+			} else {
+				WARN_PRINT(String("Invalid external resource index: "+itos(index)).ascii().get_data());
+
+			}
 		}
 		}
 
 
 
 
 
 
+
 		Error err=goto_end_of_tag();
 		Error err=goto_end_of_tag();
 		if (err) {
 		if (err) {
 			ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Error closing <resource> tag.");
 			ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": Error closing <resource> tag.");
@@ -1364,32 +1397,6 @@ Error ResourceInteractiveLoaderXML::poll() {
 	if (error!=OK)
 	if (error!=OK)
 		return error;
 		return error;
 
 
-	if (ext_resources.size()) {
-
-		error=ERR_FILE_CORRUPT;
-		String path=ext_resources.front()->get();
-
-		RES res = ResourceLoader::load(path);
-
-		if (res.is_null()) {
-
-			if (ResourceLoader::get_abort_on_missing_resources()) {
-				ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": editor exported nonexistent resource at: "+path);
-				ERR_FAIL_V(error);
-			} else {
-				ResourceLoader::notify_load_error("Resource Not Found: "+path);
-			}
-		} else {
-
-			resource_cache.push_back(res);
-		}
-
-		error=OK;
-		ext_resources.pop_front();
-		resource_current++;
-		return error;
-	}
-
 	bool exit;
 	bool exit;
 	Tag *tag = parse_tag(&exit);
 	Tag *tag = parse_tag(&exit);
 
 
@@ -1413,12 +1420,13 @@ Error ResourceInteractiveLoaderXML::poll() {
 		ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> missing 'path' field.");
 		ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> missing 'path' field.");
 		ERR_FAIL_COND_V(!tag->args.has("path"),ERR_FILE_CORRUPT);
 		ERR_FAIL_COND_V(!tag->args.has("path"),ERR_FILE_CORRUPT);
 
 
-		String type;
+		String type="Resource";
 		if (tag->args.has("type"))
 		if (tag->args.has("type"))
 			type=tag->args["type"];
 			type=tag->args["type"];
 
 
 		String path = tag->args["path"];
 		String path = tag->args["path"];
 
 
+
 		ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> can't use a local path, this is a bug?.");
 		ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> can't use a local path, this is a bug?.");
 		ERR_FAIL_COND_V(path.begins_with("local://"),ERR_FILE_CORRUPT);
 		ERR_FAIL_COND_V(path.begins_with("local://"),ERR_FILE_CORRUPT);
 
 
@@ -1427,6 +1435,9 @@ Error ResourceInteractiveLoaderXML::poll() {
 			path=Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
 			path=Globals::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
 		}
 		}
 
 
+		if (remaps.has(path)) {
+			path=remaps[path];
+		}
 
 
 		RES res = ResourceLoader::load(path,type);
 		RES res = ResourceLoader::load(path,type);
 
 
@@ -1436,13 +1447,21 @@ Error ResourceInteractiveLoaderXML::poll() {
 				ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> referenced nonexistent resource at: "+path);
 				ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <ext_resource> referenced nonexistent resource at: "+path);
 				ERR_FAIL_V(error);
 				ERR_FAIL_V(error);
 			} else {
 			} else {
-				ResourceLoader::notify_load_error("Resource Not Found: "+path);
+				ResourceLoader::notify_dependency_error(local_path,path,type);
 			}
 			}
 		} else {
 		} else {
 
 
 			resource_cache.push_back(res);
 			resource_cache.push_back(res);
 		}
 		}
 
 
+		if (tag->args.has("index")) {
+			ExtResource er;
+			er.path=path;
+			er.type=type;
+			ext_resources[tag->args["index"].to_int()]=er;
+		}
+
+
 		Error err = close_tag("ext_resource");
 		Error err = close_tag("ext_resource");
 		if (err)
 		if (err)
 			return error;
 			return error;
@@ -1566,7 +1585,7 @@ int ResourceInteractiveLoaderXML::get_stage() const {
 }
 }
 int ResourceInteractiveLoaderXML::get_stage_count() const {
 int ResourceInteractiveLoaderXML::get_stage_count() const {
 
 
-	return resources_total+ext_resources.size();
+	return resources_total;//+ext_resources;
 }
 }
 
 
 ResourceInteractiveLoaderXML::~ResourceInteractiveLoaderXML() {
 ResourceInteractiveLoaderXML::~ResourceInteractiveLoaderXML() {
@@ -1574,7 +1593,7 @@ ResourceInteractiveLoaderXML::~ResourceInteractiveLoaderXML() {
 	memdelete(f);
 	memdelete(f);
 }
 }
 
 
-void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List<String> *p_dependencies) {
+void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List<String> *p_dependencies,bool p_add_types) {
 
 
 
 
 	open(f);
 	open(f);
@@ -1617,6 +1636,10 @@ void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List<String> *
 			path = ResourceLoader::guess_full_filename(path,type);
 			path = ResourceLoader::guess_full_filename(path,type);
 		}
 		}
 
 
+		if (p_add_types && tag->args.has("type")) {
+			path+="::"+tag->args["type"];
+		}
+
 		p_dependencies->push_back(path);
 		p_dependencies->push_back(path);
 
 
 		Error err = close_tag("ext_resource");
 		Error err = close_tag("ext_resource");
@@ -1628,6 +1651,167 @@ void ResourceInteractiveLoaderXML::get_dependencies(FileAccess *f,List<String> *
 
 
 }
 }
 
 
+Error ResourceInteractiveLoaderXML::rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map) {
+
+	open(p_f);
+	ERR_FAIL_COND_V(error!=OK,error);
+
+	//FileAccess
+
+	bool old_format=false;
+
+	FileAccess *fw = NULL;
+
+	String base_path=local_path.get_base_dir();
+
+	while(true) {
+		bool exit;
+		List<String> order;
+
+		Tag *tag = parse_tag(&exit,true,&order);
+
+		bool done=false;
+
+		if (!tag) {
+			if (fw) {
+				memdelete(fw);
+			}
+			error=ERR_FILE_CORRUPT;
+			ERR_FAIL_COND_V(!exit,error);
+			error=ERR_FILE_EOF;
+
+			return error;
+		}
+
+		if (tag->name=="ext_resource") {
+
+			if (!tag->args.has("index") || !tag->args.has("path") || !tag->args.has("type")) {
+				old_format=true;
+				break;
+			}
+
+			if (!fw) {
+
+				fw=FileAccess::open(p_path+".depren",FileAccess::WRITE);
+				fw->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); //no escape
+				fw->store_line("<resource_file type=\""+resource_type+"\" subresource_count=\""+itos(resources_total)+"\" version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\" version_name=\""+VERSION_FULL_NAME+"\">");
+
+			}
+
+			String path = tag->args["path"];
+			String index = tag->args["index"];
+			String type = tag->args["type"];
+
+
+			bool relative=false;
+			if (!path.begins_with("res://")) {
+				path=base_path.plus_file(path).simplify_path();
+				relative=true;
+			}
+
+
+			if (p_map.has(path)) {
+				String np=p_map[path];
+				path=np;
+			}
+
+			if (relative) {
+				//restore relative
+				path=base_path.path_to_file(path);
+			}
+
+			tag->args["path"]=path;
+			tag->args["index"]=index;
+			tag->args["type"]=type;
+
+		} else {
+
+			done=true;
+		}
+
+		String tagt="\t<";
+		if (exit)
+			tagt+="/";
+		tagt+=tag->name;
+
+		for(List<String>::Element *E=order.front();E;E=E->next()) {
+			tagt+=" "+E->get()+"=\""+tag->args[E->get()]+"\"";
+		}
+		tagt+=">";
+		fw->store_line(tagt);
+		if (done)
+			break;
+		close_tag("ext_resource");
+		fw->store_line("\t</ext_resource>");
+
+	}
+
+
+	if (old_format) {
+		if (fw)
+			memdelete(fw);
+
+		DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+		da->remove(p_path+".depren");
+		memdelete(da);
+		//fuck it, use the old approach;
+
+		WARN_PRINT(("This file is old, so it can't refactor dependencies, opening and resaving: "+p_path).utf8().get_data());
+
+		Error err;
+		FileAccess *f2 = FileAccess::open(p_path,FileAccess::READ,&err);
+		if (err!=OK) {
+			ERR_FAIL_COND_V(err!=OK,ERR_FILE_CANT_OPEN);
+		}
+
+		Ref<ResourceInteractiveLoaderXML> ria = memnew( ResourceInteractiveLoaderXML );
+		ria->local_path=Globals::get_singleton()->localize_path(p_path);
+		ria->res_path=ria->local_path;
+		ria->remaps=p_map;
+	//	ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
+		ria->open(f2);
+
+		err = ria->poll();
+
+		while(err==OK) {
+			err=ria->poll();
+		}
+
+		ERR_FAIL_COND_V(err!=ERR_FILE_EOF,ERR_FILE_CORRUPT);
+		RES res = ria->get_resource();
+		ERR_FAIL_COND_V(!res.is_valid(),ERR_FILE_CORRUPT);
+
+		return ResourceFormatSaverXML::singleton->save(p_path,res);
+	}
+
+	if (!fw) {
+
+		return OK; //nothing to rename, do nothing
+	}
+
+	uint8_t c=f->get_8();
+	while(!f->eof_reached()) {
+		fw->store_8(c);
+		c=f->get_8();
+	}
+
+	bool all_ok = fw->get_error()==OK;
+
+	memdelete(fw);
+
+	if (!all_ok) {
+		return ERR_CANT_CREATE;
+	}
+
+	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	da->remove(p_path);
+	da->rename(p_path+".depren",p_path);
+	memdelete(da);
+
+	return OK;
+
+}
+
 
 
 void ResourceInteractiveLoaderXML::open(FileAccess *p_f) {
 void ResourceInteractiveLoaderXML::open(FileAccess *p_f) {
 
 
@@ -1686,6 +1870,7 @@ void ResourceInteractiveLoaderXML::open(FileAccess *p_f) {
 
 
 	}
 	}
 
 
+	/*
 	String preload_depts = "deps/"+local_path.md5_text();
 	String preload_depts = "deps/"+local_path.md5_text();
 	if (Globals::get_singleton()->has(preload_depts)) {
 	if (Globals::get_singleton()->has(preload_depts)) {
 		ext_resources.clear();
 		ext_resources.clear();
@@ -1697,7 +1882,7 @@ void ResourceInteractiveLoaderXML::open(FileAccess *p_f) {
 		}
 		}
 		print_line(local_path+" - EXTERNAL RESOURCES: "+itos(ext_resources.size()));
 		print_line(local_path+" - EXTERNAL RESOURCES: "+itos(ext_resources.size()));
 	}
 	}
-
+*/
 
 
 }
 }
 
 
@@ -1730,7 +1915,10 @@ String ResourceInteractiveLoaderXML::recognize(FileAccess *p_f) {
 
 
 /////////////////////
 /////////////////////
 
 
-Ref<ResourceInteractiveLoader> ResourceFormatLoaderXML::load_interactive(const String &p_path) {
+Ref<ResourceInteractiveLoader> ResourceFormatLoaderXML::load_interactive(const String &p_path, Error *r_error) {
+
+	if (r_error)
+		*r_error=ERR_CANT_OPEN;
 
 
 	Error err;
 	Error err;
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
@@ -1816,7 +2004,7 @@ String ResourceFormatLoaderXML::get_resource_type(const String &p_path) const{
 }
 }
 
 
 
 
-void ResourceFormatLoaderXML::get_dependencies(const String& p_path,List<String> *p_dependencies) {
+void ResourceFormatLoaderXML::get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types) {
 
 
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
 	if (!f) {
 	if (!f) {
@@ -1828,11 +2016,27 @@ void ResourceFormatLoaderXML::get_dependencies(const String& p_path,List<String>
 	ria->local_path=Globals::get_singleton()->localize_path(p_path);
 	ria->local_path=Globals::get_singleton()->localize_path(p_path);
 	ria->res_path=ria->local_path;
 	ria->res_path=ria->local_path;
 //	ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
 //	ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
-	ria->get_dependencies(f,p_dependencies);
+	ria->get_dependencies(f,p_dependencies,p_add_types);
+
 
 
+}
+
+Error ResourceFormatLoaderXML::rename_dependencies(const String &p_path,const Map<String,String>& p_map) {
+
+	FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
+	if (!f) {
 
 
+		ERR_FAIL_V(ERR_CANT_OPEN);
+	}
+
+	Ref<ResourceInteractiveLoaderXML> ria = memnew( ResourceInteractiveLoaderXML );
+	ria->local_path=Globals::get_singleton()->localize_path(p_path);
+	ria->res_path=ria->local_path;
+//	ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
+	return ria->rename_dependencies(f,p_path,p_map);
 }
 }
 
 
+
 /****************************************************************************************/
 /****************************************************************************************/
 /****************************************************************************************/
 /****************************************************************************************/
 /****************************************************************************************/
 /****************************************************************************************/
@@ -2024,20 +2228,26 @@ void ResourceFormatSaverXMLInstance::write_property(const String& p_name,const V
 				return; // don't save it
 				return; // don't save it
 			}
 			}
 
 
-			params="resource_type=\""+res->get_save_type()+"\"";
+			if (external_resources.has(res)) {
 
 
-			if (res->get_path().length() && res->get_path().find("::")==-1) {
-				//external resource
-				String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path();
-				escape(path);
-				params+=" path=\""+path+"\"";
+				params="external=\""+itos(external_resources[res])+"\"";
 			} else {
 			} else {
+				params="resource_type=\""+res->get_save_type()+"\"";
 
 
-				//internal resource
-				ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
-				ERR_FAIL_COND(!resource_set.has(res));
 
 
-				params+=" path=\"local://"+itos(res->get_subindex())+"\"";
+				if (res->get_path().length() && res->get_path().find("::")==-1) {
+					//external resource
+					String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path();
+					escape(path);
+					params+=" path=\""+path+"\"";
+				} else {
+
+					//internal resource
+					ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
+					ERR_FAIL_COND(!resource_set.has(res));
+
+					params+=" path=\"local://"+itos(res->get_subindex())+"\"";
+				}
 			}
 			}
 
 
 		} break;
 		} break;
@@ -2441,11 +2651,12 @@ void ResourceFormatSaverXMLInstance::_find_resources(const Variant& p_variant,bo
 
 
 			RES res = p_variant.operator RefPtr();
 			RES res = p_variant.operator RefPtr();
 
 
-			if (res.is_null())
+			if (res.is_null() || external_resources.has(res))
 				return;
 				return;
 
 
 			if (!p_main && (!bundle_resources ) && res->get_path().length() && res->get_path().find("::") == -1 ) {
 			if (!p_main && (!bundle_resources ) && res->get_path().length() && res->get_path().find("::") == -1 ) {
-				external_resources.push_back(res);
+				int index = external_resources.size();
+				external_resources[res]=index;
 				return;
 				return;
 			}
 			}
 
 
@@ -2533,12 +2744,12 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res
 	enter_tag("resource_file","type=\""+p_resource->get_type()+"\" subresource_count=\""+itos(saved_resources.size()+external_resources.size())+"\" version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\" version_name=\""+VERSION_FULL_NAME+"\"");
 	enter_tag("resource_file","type=\""+p_resource->get_type()+"\" subresource_count=\""+itos(saved_resources.size()+external_resources.size())+"\" version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\" version_name=\""+VERSION_FULL_NAME+"\"");
 	write_string("\n",false);
 	write_string("\n",false);
 
 
-	for(List<RES>::Element *E=external_resources.front();E;E=E->next()) {
+	for(Map<RES,int>::Element *E=external_resources.front();E;E=E->next()) {
 
 
 		write_tabs();
 		write_tabs();
-		String p = E->get()->get_path();
+		String p = E->key()->get_path();
 
 
-		enter_tag("ext_resource","path=\""+p+"\" type=\""+E->get()->get_save_type()+"\""); //bundled
+		enter_tag("ext_resource","path=\""+p+"\" type=\""+E->key()->get_save_type()+"\" index=\""+itos(E->get())+"\""); //bundled
 		exit_tag("ext_resource"); //bundled
 		exit_tag("ext_resource"); //bundled
 		write_string("\n",false);
 		write_string("\n",false);
 	}
 	}
@@ -2667,3 +2878,8 @@ void ResourceFormatSaverXML::get_recognized_extensions(const RES& p_resource,Lis
 	}
 	}
 
 
 }
 }
+
+ResourceFormatSaverXML* ResourceFormatSaverXML::singleton=NULL;
+ResourceFormatSaverXML::ResourceFormatSaverXML() {
+	singleton=this;
+}

+ 18 - 7
core/io/resource_format_xml.h

@@ -46,13 +46,21 @@ class ResourceInteractiveLoaderXML : public ResourceInteractiveLoader {
 
 
 		String name;
 		String name;
 		HashMap<String,String> args;
 		HashMap<String,String> args;
+
 	};
 	};
 
 
 	_FORCE_INLINE_ Error _parse_array_element(Vector<char> &buff,bool p_number_only,FileAccess *f,bool *end);
 	_FORCE_INLINE_ Error _parse_array_element(Vector<char> &buff,bool p_number_only,FileAccess *f,bool *end);
 
 
 
 
+	struct ExtResource {
+		String path;
+		String type;
+	};
+
 
 
-	List<StringName> ext_resources;
+	Map<String,String> remaps;
+
+	Map<int,ExtResource> ext_resources;
 
 
 	int resources_total;
 	int resources_total;
 	int resource_current;
 	int resource_current;
@@ -66,7 +74,7 @@ friend class ResourceFormatLoaderXML;
 	List<Tag> tag_stack;
 	List<Tag> tag_stack;
 
 
 	List<RES> resource_cache;
 	List<RES> resource_cache;
-	Tag* parse_tag(bool* r_exit=NULL,bool p_printerr=true);
+	Tag* parse_tag(bool* r_exit=NULL,bool p_printerr=true,List<String> *r_order=NULL);
 	Error close_tag(const String& p_name);
 	Error close_tag(const String& p_name);
 	_FORCE_INLINE_ void unquote(String& p_str);
 	_FORCE_INLINE_ void unquote(String& p_str);
 	Error goto_end_of_tag();
 	Error goto_end_of_tag();
@@ -87,7 +95,8 @@ public:
 
 
 	void open(FileAccess *p_f);
 	void open(FileAccess *p_f);
 	String recognize(FileAccess *p_f);
 	String recognize(FileAccess *p_f);
-	void get_dependencies(FileAccess *p_f,List<String> *p_dependencies);
+	void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
+	Error rename_dependencies(FileAccess *p_f, const String &p_path,const Map<String,String>& p_map);
 
 
 
 
 	~ResourceInteractiveLoaderXML();
 	~ResourceInteractiveLoaderXML();
@@ -97,12 +106,13 @@ public:
 class ResourceFormatLoaderXML : public ResourceFormatLoader {
 class ResourceFormatLoaderXML : public ResourceFormatLoader {
 public:
 public:
 
 
-	virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path);
+	virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,Error *r_error=NULL);
 	virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const;
 	virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const;
 	virtual void get_recognized_extensions(List<String> *p_extensions) const;
 	virtual void get_recognized_extensions(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;
-	virtual void get_dependencies(const String& p_path,List<String> *p_dependencies);
+	virtual void get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types=false);
+	virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map);
 
 
 
 
 };
 };
@@ -125,7 +135,7 @@ class ResourceFormatSaverXMLInstance  {
 	int depth;
 	int depth;
 	Set<RES> resource_set;
 	Set<RES> resource_set;
 	List<RES> saved_resources;
 	List<RES> saved_resources;
-	List<RES> external_resources;
+	Map<RES,int> external_resources;
 
 
 	void enter_tag(const char* p_tag,const String& p_args=String());
 	void enter_tag(const char* p_tag,const String& p_args=String());
 	void exit_tag(const char* p_tag);
 	void exit_tag(const char* p_tag);
@@ -148,11 +158,12 @@ public:
 
 
 class ResourceFormatSaverXML : public ResourceFormatSaver {
 class ResourceFormatSaverXML : public ResourceFormatSaver {
 public:
 public:
+	static ResourceFormatSaverXML* singleton;
 	virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0);
 	virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0);
 	virtual bool recognize(const RES& p_resource) const;
 	virtual bool recognize(const RES& p_resource) const;
 	virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const;
 	virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const;
 
 
-
+	ResourceFormatSaverXML();
 };
 };
 
 
 
 

+ 54 - 11
core/io/resource_loader.cpp

@@ -103,10 +103,10 @@ public:
 
 
 
 
 
 
-Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const String &p_path) {
+Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const String &p_path, Error *r_error) {
 
 
 	//either this
 	//either this
-	Ref<Resource> res = load(p_path);
+	Ref<Resource> res = load(p_path,p_path,r_error);
 	if (res.is_null())
 	if (res.is_null())
 		return Ref<ResourceInteractiveLoader>();
 		return Ref<ResourceInteractiveLoader>();
 
 
@@ -115,12 +115,13 @@ Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const Stri
 	return ril;
 	return ril;
 }
 }
 
 
-RES ResourceFormatLoader::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoader::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
 
 
 	String path=p_path;
 	String path=p_path;
 
 
 	//or this must be implemented
 	//or this must be implemented
-	Ref<ResourceInteractiveLoader> ril = load_interactive(p_path);
+	Ref<ResourceInteractiveLoader> ril = load_interactive(p_path,r_error);
 	if (!ril.is_valid())
 	if (!ril.is_valid())
 		return RES();
 		return RES();
 	ril->set_local_path(p_original_path);
 	ril->set_local_path(p_original_path);
@@ -130,9 +131,14 @@ RES ResourceFormatLoader::load(const String &p_path,const String& p_original_pat
 		Error err = ril->poll();
 		Error err = ril->poll();
 
 
 		if (err==ERR_FILE_EOF) {
 		if (err==ERR_FILE_EOF) {
+			if (r_error)
+				*r_error=OK;
 			return ril->get_resource();
 			return ril->get_resource();
 		}
 		}
 
 
+		if (r_error)
+			*r_error=err;
+
 		ERR_FAIL_COND_V(err!=OK,RES());
 		ERR_FAIL_COND_V(err!=OK,RES());
 	}
 	}
 
 
@@ -140,7 +146,7 @@ RES ResourceFormatLoader::load(const String &p_path,const String& p_original_pat
 
 
 }
 }
 
 
-void ResourceFormatLoader::get_dependencies(const String& p_path,List<String> *p_dependencies) {
+void ResourceFormatLoader::get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types) {
 
 
 	//do nothing by default
 	//do nothing by default
 }
 }
@@ -149,7 +155,10 @@ void ResourceFormatLoader::get_dependencies(const String& p_path,List<String> *p
 ///////////////////////////////////
 ///////////////////////////////////
 
 
 
 
-RES ResourceLoader::load(const String &p_path,const String& p_type_hint,bool p_no_cache) {
+RES ResourceLoader::load(const String &p_path, const String& p_type_hint, bool p_no_cache, Error *r_error) {
+
+	if (r_error)
+		*r_error=ERR_CANT_OPEN;
 
 
 	String local_path;
 	String local_path;
 	if (p_path.is_rel_path())
 	if (p_path.is_rel_path())
@@ -183,7 +192,7 @@ RES ResourceLoader::load(const String &p_path,const String& p_type_hint,bool p_n
 		if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
 		if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
 			continue;
 			continue;
 		found=true;
 		found=true;
-		RES res = loader[i]->load(remapped_path,local_path);
+		RES res = loader[i]->load(remapped_path,local_path,r_error);
 		if (res.is_null())
 		if (res.is_null())
 			continue;
 			continue;
 		if (!p_no_cache)
 		if (!p_no_cache)
@@ -289,9 +298,11 @@ String ResourceLoader::find_complete_path(const String& p_path,const String& p_t
 	return local_path;
 	return local_path;
 }
 }
 
 
-Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_path,const String& p_type_hint,bool p_no_cache) {
+Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_path,const String& p_type_hint,bool p_no_cache,Error *r_error) {
 
 
 
 
+	if (r_error)
+		*r_error=ERR_CANT_OPEN;
 
 
 	String local_path;
 	String local_path;
 	if (p_path.is_rel_path())
 	if (p_path.is_rel_path())
@@ -327,7 +338,7 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_
 		if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
 		if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
 			continue;
 			continue;
 		found=true;
 		found=true;
-		Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(remapped_path);
+		Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(remapped_path,r_error);
 		if (ril.is_null())
 		if (ril.is_null())
 			continue;
 			continue;
 		if (!p_no_cache)
 		if (!p_no_cache)
@@ -352,7 +363,32 @@ void ResourceLoader::add_resource_format_loader(ResourceFormatLoader *p_format_l
 	loader[loader_count++]=p_format_loader;
 	loader[loader_count++]=p_format_loader;
 }
 }
 
 
-void ResourceLoader::get_dependencies(const String& p_path,List<String> *p_dependencies) {
+void ResourceLoader::get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types) {
+
+
+	String local_path;
+	if (p_path.is_rel_path())
+		local_path="res://"+p_path;
+	else
+		local_path = Globals::get_singleton()->localize_path(p_path);
+
+	String remapped_path = PathRemap::get_singleton()->get_remap(local_path);
+
+	String extension=remapped_path.extension();
+
+	for (int i=0;i<loader_count;i++) {
+
+		if (!loader[i]->recognize(extension))
+			continue;
+		//if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
+		//	continue;
+
+		loader[i]->get_dependencies(remapped_path,p_dependencies,p_add_types);
+
+	}
+}
+
+Error ResourceLoader::rename_dependencies(const String &p_path,const Map<String,String>& p_map) {
 
 
 
 
 	String local_path;
 	String local_path;
@@ -372,11 +408,15 @@ void ResourceLoader::get_dependencies(const String& p_path,List<String> *p_depen
 		//if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
 		//if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
 		//	continue;
 		//	continue;
 
 
-		loader[i]->get_dependencies(remapped_path,p_dependencies);
+		return loader[i]->rename_dependencies(p_path,p_map);
 
 
 	}
 	}
+
+	return OK; // ??
+
 }
 }
 
 
+
 String ResourceLoader::guess_full_filename(const String &p_path,const String& p_type) {
 String ResourceLoader::guess_full_filename(const String &p_path,const String& p_type) {
 
 
 	String local_path;
 	String local_path;
@@ -414,6 +454,9 @@ String ResourceLoader::get_resource_type(const String &p_path) {
 ResourceLoadErrorNotify ResourceLoader::err_notify=NULL;
 ResourceLoadErrorNotify ResourceLoader::err_notify=NULL;
 void *ResourceLoader::err_notify_ud=NULL;
 void *ResourceLoader::err_notify_ud=NULL;
 
 
+DependencyErrorNotify ResourceLoader::dep_err_notify=NULL;
+void *ResourceLoader::dep_err_notify_ud=NULL;
+
 bool ResourceLoader::abort_on_missing_resource=true;
 bool ResourceLoader::abort_on_missing_resource=true;
 bool ResourceLoader::timestamp_on_load=false;
 bool ResourceLoader::timestamp_on_load=false;
 
 

+ 16 - 6
core/io/resource_loader.h

@@ -57,21 +57,23 @@ public:
 class ResourceFormatLoader {
 class ResourceFormatLoader {
 public:
 public:
 
 
-	virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path);
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,Error *r_error=NULL);
+	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(List<String> *p_extensions) const=0;
 	virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const;
 	virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const;
 	bool recognize(const String& p_extension) const;
 	bool recognize(const String& p_extension) const;
 	virtual bool handles_type(const String& p_type) const=0;
 	virtual bool handles_type(const String& p_type) const=0;
 	virtual String get_resource_type(const String &p_path) 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);
+	virtual void get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types=false);
 	virtual Error load_import_metadata(const String &p_path, Ref<ResourceImportMetadata>& r_var) const { return ERR_UNAVAILABLE; }
 	virtual Error load_import_metadata(const String &p_path, Ref<ResourceImportMetadata>& r_var) const { return ERR_UNAVAILABLE; }
+	virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map) { return OK; }
 
 
 	virtual ~ResourceFormatLoader() {}
 	virtual ~ResourceFormatLoader() {}
 };
 };
 
 
 
 
 typedef void (*ResourceLoadErrorNotify)(void *p_ud,const String& p_text);
 typedef void (*ResourceLoadErrorNotify)(void *p_ud,const String& p_text);
+typedef void (*DependencyErrorNotify)(void *p_ud,const String& p_loading,const String& p_which,const String& p_type);
 
 
 
 
 class ResourceLoader {	
 class ResourceLoader {	
@@ -86,6 +88,8 @@ class ResourceLoader {
 
 
 	static void* err_notify_ud;
 	static void* err_notify_ud;
 	static ResourceLoadErrorNotify err_notify;
 	static ResourceLoadErrorNotify err_notify;
+	static void* dep_err_notify_ud;
+	static DependencyErrorNotify dep_err_notify;
 	static bool abort_on_missing_resource;
 	static bool abort_on_missing_resource;
 
 
 	static String find_complete_path(const String& p_path,const String& p_type);
 	static String find_complete_path(const String& p_path,const String& p_type);
@@ -93,14 +97,15 @@ public:
 
 
 
 
 	
 	
-	static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,const String& p_type_hint="",bool p_no_cache=false);
-	static RES load(const String &p_path,const String& p_type_hint="",bool p_no_cache=false);
+	static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,const String& p_type_hint="",bool p_no_cache=false,Error *r_error=NULL);
+	static RES load(const String &p_path,const String& p_type_hint="",bool p_no_cache=false,Error *r_error=NULL);
 	static Ref<ResourceImportMetadata> load_import_metadata(const String &p_path);
 	static Ref<ResourceImportMetadata> load_import_metadata(const String &p_path);
 
 
 	static void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions);
 	static void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions);
 	static void add_resource_format_loader(ResourceFormatLoader *p_format_loader);
 	static void add_resource_format_loader(ResourceFormatLoader *p_format_loader);
 	static String get_resource_type(const String &p_path);
 	static String get_resource_type(const String &p_path);
-	static void get_dependencies(const String& p_path,List<String> *p_dependencies);
+	static void get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types=false);
+	static Error rename_dependencies(const String &p_path,const Map<String,String>& p_map);
 
 
 	static String guess_full_filename(const String &p_path,const String& p_type);
 	static String guess_full_filename(const String &p_path,const String& p_type);
 
 
@@ -108,6 +113,11 @@ public:
 
 
 	static void notify_load_error(const String& p_err) { if (err_notify) err_notify(err_notify_ud,p_err); }
 	static void notify_load_error(const String& p_err) { if (err_notify) err_notify(err_notify_ud,p_err); }
 	static void set_error_notify_func(void* p_ud,ResourceLoadErrorNotify p_err_notify) { err_notify=p_err_notify; err_notify_ud=p_ud;}
 	static void set_error_notify_func(void* p_ud,ResourceLoadErrorNotify p_err_notify) { err_notify=p_err_notify; err_notify_ud=p_ud;}
+
+	static void notify_dependency_error(const String& p_path,const String& p_dependency,const String& p_type) { if (dep_err_notify) dep_err_notify(dep_err_notify_ud,p_path,p_dependency,p_type); }
+	static void set_dependency_error_notify_func(void* p_ud,DependencyErrorNotify p_err_notify) { dep_err_notify=p_err_notify; dep_err_notify_ud=p_ud;}
+
+
 	static void set_abort_on_missing_resources(bool p_abort) { abort_on_missing_resource=p_abort; }
 	static void set_abort_on_missing_resources(bool p_abort) { abort_on_missing_resource=p_abort; }
 	static bool get_abort_on_missing_resources() { return abort_on_missing_resource; }
 	static bool get_abort_on_missing_resources() { return abort_on_missing_resource; }
 };
 };

+ 1 - 1
core/io/resource_saver.h

@@ -46,7 +46,7 @@ public:
 	virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0)=0;
 	virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0)=0;
 	virtual bool recognize(const RES& p_resource) const=0;
 	virtual bool recognize(const RES& p_resource) const=0;
 	virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const=0;
 	virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const=0;
-		
+
 	virtual ~ResourceFormatSaver() {}
 	virtual ~ResourceFormatSaver() {}
 };
 };
 
 

+ 8 - 1
core/io/translation_loader_po.cpp

@@ -30,7 +30,10 @@
 #include "os/file_access.h"
 #include "os/file_access.h"
 #include "translation.h"
 #include "translation.h"
 
 
-RES TranslationLoaderPO::load(const String &p_path,const String& p_original_path) {
+RES TranslationLoaderPO::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+	if (r_error)
+		*r_error=ERR_CANT_OPEN;
 
 
 	FileAccess *f=FileAccess::open(p_path,FileAccess::READ);
 	FileAccess *f=FileAccess::open(p_path,FileAccess::READ);
 	ERR_FAIL_COND_V(!f,RES());
 	ERR_FAIL_COND_V(!f,RES());
@@ -49,6 +52,8 @@ RES TranslationLoaderPO::load(const String &p_path,const String& p_original_path
 	String msg_id;
 	String msg_id;
 	String msg_str;
 	String msg_str;
 	String config;
 	String config;
+	if (r_error)
+		*r_error=ERR_FILE_CORRUPT;
 
 
 	Ref<Translation> translation = Ref<Translation>( memnew( Translation ));
 	Ref<Translation> translation = Ref<Translation>( memnew( Translation ));
 	int line = 1;
 	int line = 1;
@@ -174,6 +179,8 @@ RES TranslationLoaderPO::load(const String &p_path,const String& p_original_path
 		}
 		}
 	}
 	}
 
 
+	if (r_error)
+		*r_error=OK;
 
 
 	return translation;
 	return translation;
 
 

+ 1 - 1
core/io/translation_loader_po.h

@@ -34,7 +34,7 @@
 class TranslationLoaderPO : public ResourceFormatLoader {
 class TranslationLoaderPO : public ResourceFormatLoader {
 public:
 public:
 
 
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 12 - 1
drivers/chibi/event_stream_chibi.cpp

@@ -779,8 +779,10 @@ EventStreamChibi::EventStreamChibi() {
 
 
 
 
 
 
-RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderChibi::load(const String &p_path, const String& p_original_path, Error *r_error) {
 
 
+	if (r_error)
+		*r_error=ERR_FILE_CANT_OPEN;
 	String el = p_path.extension().to_lower();
 	String el = p_path.extension().to_lower();
 
 
 	CPFileAccessWrapperImpl f;
 	CPFileAccessWrapperImpl f;
@@ -791,6 +793,8 @@ RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_origina
 		CPLoader_IT loader(&f);
 		CPLoader_IT loader(&f);
 		CPLoader::Error err = loader.load_song(p_path.utf8().get_data(),&esc->song,false);
 		CPLoader::Error err = loader.load_song(p_path.utf8().get_data(),&esc->song,false);
 		ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES());
 		ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES());
+		if (r_error)
+			*r_error=OK;
 
 
 		return esc;
 		return esc;
 
 
@@ -800,6 +804,8 @@ RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_origina
 		CPLoader_XM loader(&f);
 		CPLoader_XM loader(&f);
 		CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false);
 		CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false);
 		ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES());
 		ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES());
+		if (r_error)
+			*r_error=OK;
 		return esc;
 		return esc;
 
 
 	} else if (el=="s3m") {
 	} else if (el=="s3m") {
@@ -808,6 +814,9 @@ RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_origina
 		CPLoader_S3M loader(&f);
 		CPLoader_S3M loader(&f);
 		CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false);
 		CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false);
 		ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES());
 		ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES());
+		if (r_error)
+			*r_error=OK;
+
 		return esc;
 		return esc;
 
 
 	} else if (el=="mod") {
 	} else if (el=="mod") {
@@ -816,6 +825,8 @@ RES ResourceFormatLoaderChibi::load(const String &p_path,const String& p_origina
 		CPLoader_MOD loader(&f);
 		CPLoader_MOD loader(&f);
 		CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false);
 		CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false);
 		ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES());
 		ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES());
+		if (r_error)
+			*r_error=OK;
 		return esc;
 		return esc;
 	}
 	}
 
 

+ 1 - 1
drivers/chibi/event_stream_chibi.h

@@ -301,7 +301,7 @@ public:
 class ResourceFormatLoaderChibi : public ResourceFormatLoader {
 class ResourceFormatLoaderChibi : public ResourceFormatLoader {
 
 
 public:
 public:
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 9 - 1
drivers/dds/texture_loader_dds.cpp

@@ -64,8 +64,10 @@ static const DDSFormatInfo dds_format_info[DDS_MAX]={
 };
 };
 
 
 
 
-RES ResourceFormatDDS::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatDDS::load(const String &p_path, const String& p_original_path, Error *r_error) {
 
 
+	if (r_error)
+		*r_error=ERR_CANT_OPEN;
 
 
 	Error err;
 	Error err;
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
@@ -73,6 +75,8 @@ RES ResourceFormatDDS::load(const String &p_path,const String& p_original_path)
 		return RES();
 		return RES();
 
 
 	FileAccessRef fref(f);
 	FileAccessRef fref(f);
+	if (r_error)
+		*r_error=ERR_FILE_CORRUPT;
 
 
 	ERR_EXPLAIN("Unable to open DDS texture file: "+p_path);
 	ERR_EXPLAIN("Unable to open DDS texture file: "+p_path);
 	ERR_FAIL_COND_V(err!=OK,RES());
 	ERR_FAIL_COND_V(err!=OK,RES());
@@ -427,6 +431,10 @@ RES ResourceFormatDDS::load(const String &p_path,const String& p_original_path)
 	Ref<ImageTexture> texture = memnew( ImageTexture );
 	Ref<ImageTexture> texture = memnew( ImageTexture );
 	texture->create_from_image(img);
 	texture->create_from_image(img);
 
 
+	if (r_error)
+		*r_error=OK;
+
+
 	return texture;
 	return texture;
 
 
 }
 }

+ 1 - 1
drivers/dds/texture_loader_dds.h

@@ -7,7 +7,7 @@
 class ResourceFormatDDS : public ResourceFormatLoader{
 class ResourceFormatDDS : public ResourceFormatLoader{
 public:
 public:
 
 
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 3 - 2
drivers/mpc/audio_stream_mpc.cpp

@@ -366,8 +366,9 @@ AudioStreamMPC::~AudioStreamMPC() {
 
 
 
 
 
 
-RES ResourceFormatLoaderAudioStreamMPC::load(const String &p_path,const String& p_original_path) {
-
+RES ResourceFormatLoaderAudioStreamMPC::load(const String &p_path, const String& p_original_path, Error *r_error) {
+	if (r_error)
+		*r_error=OK; //streamed so it will always work..
 	AudioStreamMPC *mpc_stream = memnew(AudioStreamMPC);
 	AudioStreamMPC *mpc_stream = memnew(AudioStreamMPC);
 	mpc_stream->set_file(p_path);
 	mpc_stream->set_file(p_path);
 	return Ref<AudioStreamMPC>(mpc_stream);
 	return Ref<AudioStreamMPC>(mpc_stream);

+ 1 - 1
drivers/mpc/audio_stream_mpc.h

@@ -88,7 +88,7 @@ public:
 
 
 class ResourceFormatLoaderAudioStreamMPC : public ResourceFormatLoader {
 class ResourceFormatLoaderAudioStreamMPC : public ResourceFormatLoader {
 public:
 public:
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 8 - 1
drivers/pvr/texture_loader_pvr.cpp

@@ -22,8 +22,10 @@ enum PVRFLags {
 
 
 
 
 
 
-RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path,Error *r_error) {
 
 
+	if (r_error)
+		*r_error=ERR_CANT_OPEN;
 
 
 	Error err;
 	Error err;
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
@@ -34,6 +36,8 @@ RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path)
 
 
 	ERR_FAIL_COND_V(err,RES());
 	ERR_FAIL_COND_V(err,RES());
 
 
+	if (r_error)
+		*r_error=ERR_FILE_CORRUPT;
 
 
 	uint32_t hsize = f->get_32();
 	uint32_t hsize = f->get_32();
 
 
@@ -135,6 +139,9 @@ RES ResourceFormatPVR::load(const String &p_path,const String& p_original_path)
 	Ref<ImageTexture> texture = memnew( ImageTexture );
 	Ref<ImageTexture> texture = memnew( ImageTexture );
 	texture->create_from_image(image,tex_flags);
 	texture->create_from_image(image,tex_flags);
 
 
+	if (r_error)
+		*r_error=OK;
+
 	return texture;
 	return texture;
 
 
 }
 }

+ 1 - 1
drivers/pvr/texture_loader_pvr.h

@@ -9,7 +9,7 @@
 class ResourceFormatPVR : public ResourceFormatLoader{
 class ResourceFormatPVR : public ResourceFormatLoader{
 public:
 public:
 
 
-	virtual RES load(const String &p_path,const String& p_original_path);
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 4 - 1
drivers/speex/audio_stream_speex.cpp

@@ -530,7 +530,10 @@ AudioStreamSpeex::~AudioStreamSpeex() {
 	unload();
 	unload();
 }
 }
 
 
-RES ResourceFormatLoaderAudioStreamSpeex::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderAudioStreamSpeex::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+	if (r_error)
+		*r_error=OK;
 
 
 	AudioStreamSpeex *stream = memnew(AudioStreamSpeex);
 	AudioStreamSpeex *stream = memnew(AudioStreamSpeex);
 	stream->set_file(p_path);
 	stream->set_file(p_path);

+ 1 - 1
drivers/speex/audio_stream_speex.h

@@ -91,7 +91,7 @@ public:
 
 
 class ResourceFormatLoaderAudioStreamSpeex : public ResourceFormatLoader {
 class ResourceFormatLoaderAudioStreamSpeex : public ResourceFormatLoader {
 public:
 public:
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 1 - 1
drivers/theora/video_stream_theora.h

@@ -102,7 +102,7 @@ public:
 
 
 class ResourceFormatLoaderVideoStreamTheora : public ResourceFormatLoader {
 class ResourceFormatLoaderVideoStreamTheora : public ResourceFormatLoader {
 public:
 public:
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 3 - 1
drivers/theoraplayer/video_stream_theoraplayer.cpp

@@ -525,7 +525,9 @@ VideoStreamTheoraplayer::VideoStreamTheoraplayer() {
 };
 };
 
 
 
 
-RES ResourceFormatLoaderVideoStreamTheoraplayer::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderVideoStreamTheoraplayer::load(const String &p_path, const String& p_original_path, Error *r_error) {
+	if (r_error)
+		*r_error=OK;
 
 
 	VideoStreamTheoraplayer *stream = memnew(VideoStreamTheoraplayer);
 	VideoStreamTheoraplayer *stream = memnew(VideoStreamTheoraplayer);
 	stream->set_file(p_path);
 	stream->set_file(p_path);

+ 1 - 1
drivers/theoraplayer/video_stream_theoraplayer.h

@@ -54,7 +54,7 @@ public:
 
 
 class ResourceFormatLoaderVideoStreamTheoraplayer : public ResourceFormatLoader {
 class ResourceFormatLoaderVideoStreamTheoraplayer : public ResourceFormatLoader {
 public:
 public:
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 3 - 1
drivers/vorbis/audio_stream_ogg_vorbis.cpp

@@ -385,7 +385,9 @@ AudioStreamOGGVorbis::~AudioStreamOGGVorbis() {
 
 
 
 
 
 
-RES ResourceFormatLoaderAudioStreamOGGVorbis::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderAudioStreamOGGVorbis::load(const String &p_path, const String& p_original_path, Error *r_error) {
+	if (r_error)
+		*r_error=OK;
 
 
 	AudioStreamOGGVorbis *ogg_stream = memnew(AudioStreamOGGVorbis);
 	AudioStreamOGGVorbis *ogg_stream = memnew(AudioStreamOGGVorbis);
 	ogg_stream->set_file(p_path);
 	ogg_stream->set_file(p_path);

+ 1 - 1
drivers/vorbis/audio_stream_ogg_vorbis.h

@@ -111,7 +111,7 @@ public:
 
 
 class ResourceFormatLoaderAudioStreamOGGVorbis : public ResourceFormatLoader {
 class ResourceFormatLoaderAudioStreamOGGVorbis : public ResourceFormatLoader {
 public:
 public:
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 6 - 1
modules/gdscript/gd_script.cpp

@@ -2710,7 +2710,10 @@ GDScriptLanguage::~GDScriptLanguage() {
 
 
 /*************** RESOURCE ***************/
 /*************** RESOURCE ***************/
 
 
-RES ResourceFormatLoaderGDScript::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderGDScript::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+	if (r_error)
+		*r_error=ERR_FILE_CANT_OPEN;
 
 
 	GDScript *script = memnew( GDScript );
 	GDScript *script = memnew( GDScript );
 
 
@@ -2742,6 +2745,8 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path,const String& p_orig
 
 
 		script->reload();
 		script->reload();
 	}
 	}
+	if (r_error)
+		*r_error=OK;
 
 
 	return scriptres;
 	return scriptres;
 }
 }

+ 1 - 1
modules/gdscript/gd_script.h

@@ -557,7 +557,7 @@ public:
 class ResourceFormatLoaderGDScript : public ResourceFormatLoader {
 class ResourceFormatLoaderGDScript : public ResourceFormatLoader {
 public:
 public:
 
 
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 3 - 1
platform/x11/detect.py

@@ -126,7 +126,9 @@ def configure(env):
 	env.ParseConfig('pkg-config x11 --cflags --libs')
 	env.ParseConfig('pkg-config x11 --cflags --libs')
 	env.ParseConfig('pkg-config xinerama --cflags --libs')
 	env.ParseConfig('pkg-config xinerama --cflags --libs')
 	env.ParseConfig('pkg-config xcursor --cflags --libs')
 	env.ParseConfig('pkg-config xcursor --cflags --libs')
-	env.ParseConfig('pkg-config openssl --cflags --libs')
+
+	if (env["openssl"]=="yes"):
+		env.ParseConfig('pkg-config openssl --cflags --libs')
 
 
 
 
 	env.ParseConfig('pkg-config freetype2 --cflags --libs')
 	env.ParseConfig('pkg-config freetype2 --cflags --libs')

+ 1 - 1
scene/gui/dialogs.cpp

@@ -274,7 +274,7 @@ Button* AcceptDialog::add_button(const String& p_text,bool p_right,const String&
 	}
 	}
 
 
 	if (p_action!="") {
 	if (p_action!="") {
-		button->connect("pressed",this,"_custom_action",make_binds(p_action));
+		button->connect("pressed",this,"_custom_action",varray(p_action));
 	}
 	}
 
 
 	return button;
 	return button;

+ 25 - 12
scene/gui/item_list.cpp

@@ -187,6 +187,7 @@ void ItemList::select(int p_idx,bool p_single){
 		}
 		}
 
 
 		current=p_idx;
 		current=p_idx;
+		ensure_selected_visible=false;
 	} else {
 	} else {
 
 
 		if (items[p_idx].selectable) {
 		if (items[p_idx].selectable) {
@@ -195,6 +196,7 @@ void ItemList::select(int p_idx,bool p_single){
 	}
 	}
 	update();
 	update();
 
 
+
 }
 }
 void ItemList::unselect(int p_idx){
 void ItemList::unselect(int p_idx){
 
 
@@ -246,12 +248,14 @@ void ItemList::remove_item(int p_idx){
 	update();
 	update();
 	shape_changed=true;
 	shape_changed=true;
 
 
+
 }
 }
 
 
 void ItemList::clear(){
 void ItemList::clear(){
 
 
 	items.clear();
 	items.clear();
 	current=-1;
 	current=-1;
+	ensure_selected_visible=false;
 	update();
 	update();
 
 
 }
 }
@@ -602,18 +606,8 @@ void ItemList::_input_event(const InputEvent& p_event) {
 
 
 void ItemList::ensure_current_is_visible() {
 void ItemList::ensure_current_is_visible() {
 
 
-	if (current>=0 && current <=items.size()) {
-
-		Rect2 r = items[current].rect_cache;
-		int from = scroll_bar->get_val();
-		int to = from + scroll_bar->get_page();
-
-		if (r.pos.y < from) {
-			scroll_bar->set_val(r.pos.y);
-		} else if (r.pos.y+r.size.y > to) {
-			scroll_bar->set_val(r.pos.y+r.size.y - (to-from));
-		}
-	}
+	ensure_selected_visible=true;
+	update();
 }
 }
 
 
 void ItemList::_notification(int p_what) {
 void ItemList::_notification(int p_what) {
@@ -928,6 +922,24 @@ void ItemList::_notification(int p_what) {
 			draw_line(Vector2(bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),Vector2(size.width-bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),guide_color);
 			draw_line(Vector2(bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),Vector2(size.width-bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),guide_color);
 		}
 		}
 
 
+
+		if (ensure_selected_visible && current>=0 && current <=items.size()) {
+
+			Rect2 r = items[current].rect_cache;
+			int from = scroll_bar->get_val();
+			int to = from + scroll_bar->get_page();
+
+			if (r.pos.y < from) {
+				scroll_bar->set_val(r.pos.y);
+			} else if (r.pos.y+r.size.y > to) {
+				scroll_bar->set_val(r.pos.y+r.size.y - (to-from));
+			}
+
+
+		}
+
+		ensure_selected_visible=false;
+
 	}
 	}
 }
 }
 
 
@@ -1095,6 +1107,7 @@ ItemList::ItemList() {
 	set_focus_mode(FOCUS_ALL);
 	set_focus_mode(FOCUS_ALL);
 	current_columns=1;
 	current_columns=1;
 	search_time_msec=0;
 	search_time_msec=0;
+	ensure_selected_visible=false;
 
 
 }
 }
 
 

+ 2 - 0
scene/gui/item_list.h

@@ -41,6 +41,8 @@ private:
 
 
 	bool shape_changed;
 	bool shape_changed;
 
 
+	bool ensure_selected_visible;
+
 	Vector<Item> items;
 	Vector<Item> items;
 	Vector<int> separators;
 	Vector<int> separators;
 
 

+ 132 - 0
scene/gui/patch_9_frame.cpp

@@ -0,0 +1,132 @@
+#include "patch_9_frame.h"
+
+#include "servers/visual_server.h"
+
+void Patch9Frame::_notification(int p_what) {
+
+	if (p_what==NOTIFICATION_DRAW) {
+
+		if (texture.is_null())
+			return;
+
+
+		Size2 s=get_size();
+		RID ci = get_canvas_item();
+		VS::get_singleton()->canvas_item_add_style_box(ci,Rect2(Point2(),s),texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center,modulate);
+//		draw_texture_rect(texture,Rect2(Point2(),s),false,modulate);
+
+/*
+		Vector<Point2> points;
+		points.resize(4);
+		points[0]=Point2(0,0);
+		points[1]=Point2(s.x,0);
+		points[2]=Point2(s.x,s.y);
+		points[3]=Point2(0,s.y);
+		Vector<Point2> uvs;
+		uvs.resize(4);
+		uvs[0]=Point2(0,0);
+		uvs[1]=Point2(1,0);
+		uvs[2]=Point2(1,1);
+		uvs[3]=Point2(0,1);
+
+		VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid());
+*/
+	}
+}
+
+Size2 Patch9Frame::get_minimum_size() const {
+
+	return Size2(margin[MARGIN_LEFT]+margin[MARGIN_RIGHT],margin[MARGIN_TOP]+margin[MARGIN_BOTTOM]);
+}
+void Patch9Frame::_bind_methods() {
+
+
+	ObjectTypeDB::bind_method(_MD("set_texture","texture"), & Patch9Frame::set_texture );
+	ObjectTypeDB::bind_method(_MD("get_texture"), & Patch9Frame::get_texture );
+	ObjectTypeDB::bind_method(_MD("set_modulate","modulate"), & Patch9Frame::set_modulate );
+	ObjectTypeDB::bind_method(_MD("get_modulate"), & Patch9Frame::get_modulate );
+	ObjectTypeDB::bind_method(_MD("set_patch_margin","margin","value"), & Patch9Frame::set_patch_margin );
+	ObjectTypeDB::bind_method(_MD("get_patch_margin","margin"), & Patch9Frame::get_patch_margin );
+	ObjectTypeDB::bind_method(_MD("set_draw_center","draw_center"), & Patch9Frame::set_draw_center );
+	ObjectTypeDB::bind_method(_MD("get_draw_center"), & Patch9Frame::get_draw_center );
+
+	ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") );
+	ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate") );
+	ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "draw_center"), _SCS("set_draw_center"),_SCS("get_draw_center") );
+	ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/left",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_LEFT );
+	ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/top",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_TOP );
+	ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/right",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_RIGHT );
+	ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/bottom",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_BOTTOM );
+
+}
+
+
+void Patch9Frame::set_texture(const Ref<Texture>& p_tex) {
+
+	texture=p_tex;
+	update();
+	//if (texture.is_valid())
+	//	texture->set_flags(texture->get_flags()&(~Texture::FLAG_REPEAT)); //remove repeat from texture, it looks bad in sprites
+	minimum_size_changed();
+}
+
+Ref<Texture> Patch9Frame::get_texture() const {
+
+	return texture;
+}
+
+void Patch9Frame::set_modulate(const Color& p_tex) {
+
+	modulate=p_tex;
+	update();
+}
+
+Color Patch9Frame::get_modulate() const{
+
+	return modulate;
+}
+
+
+void Patch9Frame::set_patch_margin(Margin p_margin,int p_size) {
+
+	ERR_FAIL_INDEX(p_margin,4);
+	margin[p_margin]=p_size;
+	update();
+	minimum_size_changed();
+}
+
+int Patch9Frame::get_patch_margin(Margin p_margin) const{
+
+	ERR_FAIL_INDEX_V(p_margin,4,0);
+	return margin[p_margin];
+}
+
+void Patch9Frame::set_draw_center(bool p_draw) {
+
+	draw_center=p_draw;
+	update();
+}
+
+bool Patch9Frame::get_draw_center() const{
+
+	return draw_center;
+}
+
+Patch9Frame::Patch9Frame() {
+
+
+	margin[MARGIN_LEFT]=0;
+	margin[MARGIN_RIGHT]=0;
+	margin[MARGIN_BOTTOM]=0;
+	margin[MARGIN_TOP]=0;
+	modulate=Color(1,1,1,1);
+	set_ignore_mouse(true);
+	draw_center=true;
+}
+
+
+Patch9Frame::~Patch9Frame()
+{
+}
+
+

+ 40 - 0
scene/gui/patch_9_frame.h

@@ -0,0 +1,40 @@
+#ifndef PATCH_9_FRAME_H
+#define PATCH_9_FRAME_H
+
+#include "scene/gui/control.h"
+/**
+	@author Juan Linietsky <[email protected]>
+*/
+class Patch9Frame : public Control {
+
+	OBJ_TYPE(Patch9Frame,Control);
+
+	bool draw_center;
+	int margin[4];
+	Color modulate;
+	Ref<Texture> texture;
+protected:
+
+	void _notification(int p_what);
+	virtual Size2 get_minimum_size() const;
+	static void _bind_methods();
+
+public:
+
+	void set_texture(const Ref<Texture>& p_tex);
+	Ref<Texture> get_texture() const;
+
+	void set_modulate(const Color& p_tex);
+	Color get_modulate() const;
+
+	void set_patch_margin(Margin p_margin,int p_size);
+	int get_patch_margin(Margin p_margin) const;
+
+	void set_draw_center(bool p_enable);
+	bool get_draw_center() const;
+
+	Patch9Frame();
+	~Patch9Frame();
+
+};
+#endif // PATCH_9_FRAME_H

+ 5 - 0
scene/gui/tree.cpp

@@ -2360,6 +2360,11 @@ void Tree::_notification(int p_what) {
 		}
 		}
 	}
 	}
 
 
+	if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+		drag_touching=false;
+	}
+
 	if (p_what==NOTIFICATION_ENTER_TREE) {
 	if (p_what==NOTIFICATION_ENTER_TREE) {
 
 
 		update_cache();;
 		update_cache();;

+ 11 - 2
scene/io/resource_format_image.cpp

@@ -31,9 +31,11 @@
 #include "io/image_loader.h"
 #include "io/image_loader.h"
 #include "globals.h"
 #include "globals.h"
 #include "os/os.h"
 #include "os/os.h"
-RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_original_path) {
-	
+RES ResourceFormatLoaderImage::load(const String &p_path, const String& p_original_path, Error *r_error) {
 	
 	
+	if (r_error)
+		*r_error=ERR_CANT_OPEN;
+
 	if (p_path.extension()=="cube") {
 	if (p_path.extension()=="cube") {
 		// open as cubemap txture
 		// open as cubemap txture
 
 
@@ -83,6 +85,8 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina
 		memdelete(f);
 		memdelete(f);
 
 
 		cubemap->set_name(p_path.get_file());
 		cubemap->set_name(p_path.get_file());
+		if (r_error)
+			*r_error=OK;
 
 
 		return cubemap;
 		return cubemap;
 	
 	
@@ -112,6 +116,8 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina
 
 
 		ERR_EXPLAIN("Failed loading image: "+p_path);
 		ERR_EXPLAIN("Failed loading image: "+p_path);
 		ERR_FAIL_COND_V(err, RES());		
 		ERR_FAIL_COND_V(err, RES());		
+		if (r_error)
+			*r_error=ERR_FILE_CORRUPT;
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
@@ -199,6 +205,9 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina
 			print_line("  -make texture: "+rtos(total));
 			print_line("  -make texture: "+rtos(total));
 		}
 		}
 
 
+		if (r_error)
+			*r_error=OK;
+
 		return RES( texture );
 		return RES( texture );
 	}
 	}
 	
 	

+ 1 - 1
scene/io/resource_format_image.h

@@ -40,7 +40,7 @@ class ResourceFormatLoaderImage : public ResourceFormatLoader {
 	int max_texture_size;
 	int max_texture_size;
 public:
 public:
 
 
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 9 - 1
scene/io/resource_format_wav.cpp

@@ -31,13 +31,18 @@
 #include "scene/resources/sample.h"
 #include "scene/resources/sample.h"
 
 
 
 
-RES ResourceFormatLoaderWAV::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderWAV::load(const String &p_path, const String& p_original_path, Error *r_error) {
+	if (r_error)
+		*r_error=ERR_FILE_CANT_OPEN;
 
 
 	Error err;
 	Error err;
 	FileAccess *file=FileAccess::open(p_path, FileAccess::READ,&err);
 	FileAccess *file=FileAccess::open(p_path, FileAccess::READ,&err);
 
 
 	ERR_FAIL_COND_V( err!=OK, RES() );
 	ERR_FAIL_COND_V( err!=OK, RES() );
 
 
+	if (r_error)
+		*r_error=ERR_FILE_CORRUPT;
+
 	/* CHECK RIFF */
 	/* CHECK RIFF */
 	char riff[5];
 	char riff[5];
 	riff[4]=0;
 	riff[4]=0;
@@ -244,6 +249,9 @@ RES ResourceFormatLoaderWAV::load(const String &p_path,const String& p_original_
 	file->close();
 	file->close();
 	memdelete(file);
 	memdelete(file);
 
 
+	if (r_error)
+		*r_error=OK;
+
 	return sample;
 	return sample;
 
 
 }
 }

+ 1 - 1
scene/io/resource_format_wav.h

@@ -33,7 +33,7 @@
 
 
 class ResourceFormatLoaderWAV : public ResourceFormatLoader {
 class ResourceFormatLoaderWAV : public ResourceFormatLoader {
 public:
 public:
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 2 - 0
scene/register_scene_types.cpp

@@ -52,6 +52,7 @@
 #include "scene/gui/option_button.h"
 #include "scene/gui/option_button.h"
 #include "scene/gui/color_picker.h"
 #include "scene/gui/color_picker.h"
 #include "scene/gui/texture_frame.h"
 #include "scene/gui/texture_frame.h"
+#include "scene/gui/patch_9_frame.h"
 #include "scene/gui/menu_button.h"
 #include "scene/gui/menu_button.h"
 #include "scene/gui/check_box.h"
 #include "scene/gui/check_box.h"
 #include "scene/gui/check_button.h"
 #include "scene/gui/check_button.h"
@@ -302,6 +303,7 @@ void register_scene_types() {
 	OS::get_singleton()->yield(); //may take time to init
 	OS::get_singleton()->yield(); //may take time to init
 
 
 	ObjectTypeDB::register_type<TextureFrame>();
 	ObjectTypeDB::register_type<TextureFrame>();
+	ObjectTypeDB::register_type<Patch9Frame>();
 	ObjectTypeDB::register_type<TabContainer>();
 	ObjectTypeDB::register_type<TabContainer>();
 	ObjectTypeDB::register_type<Tabs>();
 	ObjectTypeDB::register_type<Tabs>();
 	ObjectTypeDB::register_virtual_type<Separator>();
 	ObjectTypeDB::register_virtual_type<Separator>();

+ 6 - 1
scene/resources/bit_mask.cpp

@@ -205,7 +205,10 @@ BitMap::BitMap() {
 //////////////////////////////////////
 //////////////////////////////////////
 
 
 
 
-RES ResourceFormatLoaderBitMap::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderBitMap::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+	if (r_error)
+		*r_error=ERR_FILE_CANT_OPEN;
 
 
 	BitMap* ptr = memnew(BitMap);
 	BitMap* ptr = memnew(BitMap);
 	Ref<BitMap> bitmap( ptr );
 	Ref<BitMap> bitmap( ptr );
@@ -219,6 +222,8 @@ RES ResourceFormatLoaderBitMap::load(const String &p_path,const String& p_origin
 	ERR_FAIL_COND_V(err, RES());
 	ERR_FAIL_COND_V(err, RES());
 
 
 	bitmap->create_from_image_alpha(image);
 	bitmap->create_from_image_alpha(image);
+	if (r_error)
+		*r_error=OK;
 
 
 	return bitmap;
 	return bitmap;
 
 

+ 1 - 1
scene/resources/bit_mask.h

@@ -66,7 +66,7 @@ class ResourceFormatLoaderBitMap : public ResourceFormatLoader {
 
 
 public:
 public:
 
 
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 8 - 1
scene/resources/shader.cpp

@@ -219,7 +219,10 @@ Shader::~Shader() {
 
 
 
 
 
 
-RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderShader::load(const String &p_path, const String& p_original_path, Error *r_error) {
+
+	if (r_error)
+		*r_error=ERR_FILE_CANT_OPEN;
 
 
 	String fragment_code;
 	String fragment_code;
 	String vertex_code;
 	String vertex_code;
@@ -235,6 +238,8 @@ RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_origin
 	ERR_FAIL_COND_V(err,RES());
 	ERR_FAIL_COND_V(err,RES());
 	String base_path = p_path.get_base_dir();
 	String base_path = p_path.get_base_dir();
 
 
+	if (r_error)
+		*r_error=ERR_FILE_CORRUPT;
 
 
 	Ref<Shader> shader;//( memnew( Shader ) );
 	Ref<Shader> shader;//( memnew( Shader ) );
 
 
@@ -435,6 +440,8 @@ RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_origin
 
 
 	f->close();
 	f->close();
 	memdelete(f);
 	memdelete(f);
+	if (r_error)
+		*r_error=OK;
 
 
 	return shader;
 	return shader;
 }
 }

+ 1 - 1
scene/resources/shader.h

@@ -126,7 +126,7 @@ public:
 
 
 class ResourceFormatLoaderShader : public ResourceFormatLoader {
 class ResourceFormatLoaderShader : public ResourceFormatLoader {
 public:
 public:
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 8 - 1
scene/resources/theme.cpp

@@ -601,7 +601,9 @@ Theme::~Theme()
 
 
 
 
 
 
-RES ResourceFormatLoaderTheme::load(const String &p_path,const String& p_original_path) {
+RES ResourceFormatLoaderTheme::load(const String &p_path, const String& p_original_path, Error *r_error) {
+	if (r_error)
+		*r_error=ERR_CANT_OPEN;
 
 
 	Error err;
 	Error err;
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
 	FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err);
@@ -611,6 +613,8 @@ RES ResourceFormatLoaderTheme::load(const String &p_path,const String& p_origina
 	String base_path = p_path.get_base_dir();
 	String base_path = p_path.get_base_dir();
 	Ref<Theme> theme( memnew( Theme ) );
 	Ref<Theme> theme( memnew( Theme ) );
 	Map<StringName,Variant> library;
 	Map<StringName,Variant> library;
+	if (r_error)
+		*r_error=ERR_FILE_CORRUPT;
 
 
 	bool reading_library=false;
 	bool reading_library=false;
 	int line=0;
 	int line=0;
@@ -1003,6 +1007,9 @@ RES ResourceFormatLoaderTheme::load(const String &p_path,const String& p_origina
 	f->close();
 	f->close();
 	memdelete(f);
 	memdelete(f);
 
 
+	if (r_error)
+		*r_error=OK;
+
 	return theme;
 	return theme;
 }
 }
 
 

+ 1 - 1
scene/resources/theme.h

@@ -124,7 +124,7 @@ public:
 
 
 class ResourceFormatLoaderTheme : public ResourceFormatLoader {
 class ResourceFormatLoaderTheme : public ResourceFormatLoader {
 public:
 public:
-	virtual RES load(const String &p_path,const String& p_original_path="");
+	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(List<String> *p_extensions) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual bool handles_type(const String& p_type) const;
 	virtual String get_resource_type(const String &p_path) const;
 	virtual String get_resource_type(const String &p_path) const;

+ 512 - 0
tools/editor/dependency_editor.cpp

@@ -0,0 +1,512 @@
+#include "dependency_editor.h"
+#include "os/file_access.h"
+#include "scene/gui/margin_container.h"
+#include "io/resource_loader.h"
+#include "editor_node.h"
+
+void DependencyEditor::_notification(int p_what){
+
+
+}
+
+void DependencyEditor::_searched(const String& p_path) {
+
+	Map<String,String> dep_rename;
+	dep_rename[replacing]=p_path;
+
+
+	ResourceLoader::rename_dependencies(editing,dep_rename);
+
+	_update_list();
+	_update_file();
+}
+
+void DependencyEditor::_load_pressed(Object* p_item,int p_cell,int p_button){
+
+	TreeItem *ti=p_item->cast_to<TreeItem>();
+	String fname = ti->get_text(0);
+	replacing = ti->get_text(1);
+
+	search->set_title("Search Replacement For: "+replacing.get_file());
+
+	search->clear_filters();
+	List<String> ext;
+	ResourceLoader::get_recognized_extensions_for_type(ti->get_metadata(0),&ext);
+	for (List<String>::Element *E=ext.front();E;E=E->next()) {
+		search->add_filter("*"+E->get());
+	}
+	search->popup_centered_ratio();
+
+}
+
+void DependencyEditor::_fix_and_find(EditorFileSystemDirectory *efsd, Map<String,Map<String,String> >& candidates){
+
+	for(int i=0;i<efsd->get_subdir_count();i++) {
+		_fix_and_find(efsd->get_subdir(i),candidates);
+	}
+
+	for(int i=0;i<efsd->get_file_count();i++) {
+
+		String file = efsd->get_file(i);
+		if (!candidates.has(file))
+			continue;
+
+		String path = efsd->get_file_path(i);
+		Map<String,String> &ss = candidates[file];
+
+
+		for(Map<String,String>::Element *E=candidates[file].front();E;E=E->next()) {
+
+			if (E->get()==String()) {
+				E->get()=path;
+				continue;
+			}
+
+			//must match the best, using subdirs
+			String existing=E->get().replace_first("res://","");
+			String current=path.replace_first("res://","");
+			String lost=E->key().replace_first("res://","");
+
+			Vector<String> existingv=existing.split("/");
+			existingv.invert();
+			Vector<String> currentv=current.split("/");
+			currentv.invert();
+			Vector<String> lostv=lost.split("/");
+			lostv.invert();
+
+			int existing_score=0;
+			int current_score=0;
+
+			for(int j=0;j<lostv.size();j++) {
+
+				if (j<existingv.size() && lostv[j]==existingv[j]) {
+					existing_score++;
+				}
+				if (j<currentv.size() && lostv[j]==currentv[j]) {
+					current_score++;
+				}
+			}
+
+			if (current_score > existing_score) {
+
+				//if it was the same, could track distance to new path but..
+
+				E->get()=path; //replace by more accurate
+			}
+
+		}
+
+	}
+
+}
+
+
+void DependencyEditor::_fix_all(){
+
+	if (!EditorFileSystem::get_singleton()->get_filesystem())
+		return;
+
+	Map<String,Map<String,String> > candidates;
+
+	for (List<String>::Element *E=missing.front();E;E=E->next()) {
+
+		String base = E->get().get_file();
+		if (!candidates.has(base)) {
+			candidates[base]=Map<String,String>();
+		}
+
+		candidates[base][E->get()]="";
+	}
+
+	_fix_and_find(EditorFileSystem::get_singleton()->get_filesystem(),candidates);
+
+	Map<String,String> remaps;
+
+	for (Map<String,Map<String,String> >::Element *E=candidates.front();E;E=E->next()) {
+
+		for (Map<String,String>::Element *F=E->get().front();F;F=F->next()) {
+
+			if (F->get()!=String()) {
+				remaps[F->key()]=F->get();
+			}
+		}
+
+	}
+
+	if (remaps.size()) {
+
+		ResourceLoader::rename_dependencies(editing,remaps);
+
+		_update_list();
+		_update_file();
+	}
+}
+
+void DependencyEditor::_update_file() {
+
+	EditorFileSystem::get_singleton()->update_file(editing);
+
+}
+
+void DependencyEditor::_update_list() {
+
+	List<String> deps;
+	ResourceLoader::get_dependencies(editing,&deps,true);
+
+	tree->clear();
+	missing.clear();
+
+	TreeItem *root = tree->create_item();
+
+	Ref<Texture> folder = get_icon("folder","FileDialog");
+
+	bool broken=false;
+
+	for(List<String>::Element *E=deps.front();E;E=E->next()) {
+
+		TreeItem *item = tree->create_item(root);
+
+		String n = E->get();
+		String path;
+		String type;
+
+		if (n.find("::")!=-1) {
+			path = n.get_slice("::",0);
+			type = n.get_slice("::",1);
+		} else {
+			path=n;
+			type="Resource";
+		}
+		String name = path.get_file();
+
+		Ref<Texture> icon;
+		if (has_icon(type,"EditorIcons")) {
+			icon=get_icon(type,"EditorIcons");
+		} else {
+			icon=get_icon("Object","EditorIcons");
+		}
+		item->set_text(0,name);
+		item->set_icon(0,icon);
+		item->set_metadata(0,type);
+		item->set_text(1,path);
+
+		if (!FileAccess::exists(path)) {
+			item->set_custom_color(1,Color(1,0.4,0.3));
+			missing.push_back(path);
+			broken=true;
+		}
+
+		item->add_button(1,folder,0);
+	}
+
+	fixdeps->set_disabled(!broken);
+
+}
+
+
+
+void DependencyEditor::edit(const String& p_path) {
+
+
+	editing=p_path;
+	set_title("Dependencies For: "+p_path.get_file());
+
+	_update_list();
+	popup_centered_ratio();
+
+	if (EditorNode::get_singleton()->is_scene_open(p_path)) {
+		EditorNode::get_singleton()->show_warning("Scene '"+p_path.get_file()+"' is currently being edited.\nChanges will not take effect unless reloaded.");
+	} else if (ResourceCache::has(p_path)) {
+		EditorNode::get_singleton()->show_warning("Resource '"+p_path.get_file()+"' is in use.\nChanges will take effect when reloaded.");
+	}
+}
+
+
+void DependencyEditor::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("_searched"),&DependencyEditor::_searched);
+	ObjectTypeDB::bind_method(_MD("_load_pressed"),&DependencyEditor::_load_pressed);
+	ObjectTypeDB::bind_method(_MD("_fix_all"),&DependencyEditor::_fix_all);
+
+}
+
+DependencyEditor::DependencyEditor() {
+
+	VBoxContainer *vb = memnew( VBoxContainer );
+	vb->set_name("Dependencies");
+	add_child(vb);
+	set_child_rect(vb);
+
+	tree = memnew( Tree );
+	tree->set_columns(2);
+	tree->set_column_titles_visible(true);
+	tree->set_column_title(0,"Resource");
+	tree->set_column_title(1,"Path");
+	tree->set_hide_root(true);
+	tree->connect("button_pressed",this,"_load_pressed");
+
+	HBoxContainer *hbc = memnew( HBoxContainer );
+	Label *label = memnew( Label("Dependencies:"));
+	hbc->add_child(label);
+	hbc->add_spacer();
+	fixdeps = memnew( Button("Fix Broken"));
+	hbc->add_child(fixdeps);
+	fixdeps->connect("pressed",this,"_fix_all");
+
+	vb->add_child(hbc);
+
+	MarginContainer *mc = memnew( MarginContainer );
+	mc->set_v_size_flags(SIZE_EXPAND_FILL);
+
+	mc->add_child(tree);
+	vb->add_child(mc);
+
+	set_title("Dependency Editor");
+	search = memnew( EditorFileDialog );
+	search->connect("file_selected",this,"_searched");
+	search->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+	search->set_title("Search Replacement Resource:");
+	add_child(search);
+
+}
+
+/////////////////////////////////////
+
+
+
+void DependencyEditorOwners::_fill_owners(EditorFileSystemDirectory *efsd) {
+
+	if (!efsd)
+		return;
+
+	for(int i=0;i<efsd->get_subdir_count();i++) {
+		_fill_owners(efsd->get_subdir(i));
+	}
+
+	for(int i=0;i<efsd->get_file_count();i++) {
+
+		Vector<String> deps = efsd->get_file_deps(i);
+		//print_line(":::"+efsd->get_file_path(i));
+		bool found=false;
+		for(int j=0;j<deps.size();j++) {
+			//print_line("\t"+deps[j]+" vs "+editing);
+			if (deps[j]==editing) {
+				//print_line("found");
+				found=true;
+				break;
+			}
+		}
+		if (!found)
+			continue;
+
+		Ref<Texture> icon;
+		String type=efsd->get_file_type(i);
+		if (!has_icon(type,"EditorIcons")) {
+			icon=get_icon("Object","EditorIcons");
+		} else {
+			icon=get_icon(type,"EditorIcons");
+		}
+
+		owners->add_item(efsd->get_file_path(i),icon);
+	}
+
+}
+
+void DependencyEditorOwners::show(const String& p_path) {
+
+	editing=p_path;
+	owners->clear();
+	_fill_owners(EditorFileSystem::get_singleton()->get_filesystem());
+	popup_centered_ratio();
+
+	set_title("Owners Of: "+p_path.get_file());
+
+}
+
+DependencyEditorOwners::DependencyEditorOwners() {
+
+
+	owners = memnew( ItemList );
+	add_child(owners);
+	set_child_rect(owners);
+
+
+}
+
+///////////////////////
+
+
+void DependencyRemoveDialog::_fill_owners(EditorFileSystemDirectory *efsd) {
+
+	if (!efsd)
+		return;
+
+	for(int i=0;i<efsd->get_subdir_count();i++) {
+		_fill_owners(efsd->get_subdir(i));
+	}
+
+	for(int i=0;i<efsd->get_file_count();i++) {
+
+		Vector<String> deps = efsd->get_file_deps(i);
+		//print_line(":::"+efsd->get_file_path(i));
+		Set<String> met;
+		for(int j=0;j<deps.size();j++) {
+			if (files.has(deps[j])) {
+				met.insert(deps[j]);
+			}
+		}
+		if (!met.size())
+			continue;
+
+		exist=true;
+
+		Ref<Texture> icon;
+		String type=efsd->get_file_type(i);
+		if (!has_icon(type,"EditorIcons")) {
+			icon=get_icon("Object","EditorIcons");
+		} else {
+			icon=get_icon(type,"EditorIcons");
+		}
+
+
+		for(Set<String>::Element *E=met.front();E;E=E->next()) {
+
+			String which = E->get();
+			if (!files[which]) {
+				TreeItem *ti=owners->create_item(owners->get_root());
+				ti->set_text(0,which.get_file());
+				files[which]=ti;
+
+			}
+			TreeItem *ti=owners->create_item(files[which]);
+			ti->set_text(0,efsd->get_file_path(i));
+			ti->set_icon(0,icon);
+		}
+
+	}
+
+}
+
+void DependencyRemoveDialog::show(const Vector<String> &to_erase) {
+
+	exist=false;
+	owners->clear();
+	files.clear();
+	TreeItem *root=owners->create_item();
+	for(int i=0;i<to_erase.size();i++) {
+		files[to_erase[i]]=NULL;
+	}
+
+	_fill_owners(EditorFileSystem::get_singleton()->get_filesystem());
+
+	if (exist) {
+		owners->show();
+		text->set_text("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)");
+		popup_centered_minsize(Size2(500,220));
+	} else {
+		owners->hide();
+		text->set_text("Remove selected files from the project? (no undo)");
+		popup_centered_minsize(Size2(400,100));
+	}
+
+}
+
+void DependencyRemoveDialog::ok_pressed() {
+
+
+	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	for (Map<String,TreeItem*>::Element *E=files.front();E;E=E->next()) {
+
+		da->remove(E->key());
+		EditorFileSystem::get_singleton()->update_file(E->key());
+	}
+	memdelete(da);
+
+}
+
+DependencyRemoveDialog::DependencyRemoveDialog() {
+
+	VBoxContainer *vb = memnew( VBoxContainer );
+	add_child(vb);
+	set_child_rect(vb);
+
+	text = memnew( Label );
+	vb->add_child(text);
+
+	owners = memnew( Tree );
+	owners->set_hide_root(true);
+	vb->add_child(owners);
+	owners->set_v_size_flags(SIZE_EXPAND_FILL);
+	get_ok()->set_text("Remove");
+}
+
+
+//////////////
+
+
+void DependencyErrorDialog::show(const String& p_for_file,const Vector<String> &report) {
+
+
+	for_file=p_for_file;
+	set_title("Error loading: "+p_for_file.get_file());
+	files->clear();
+
+	TreeItem *root = files->create_item(NULL);
+	for(int i=0;i<report.size();i++) {
+
+		String dep;
+		String type="Object";
+		dep=report[i].get_slice("::",0);
+		if (report[i].get_slice_count("::")>0)
+			type=report[i].get_slice("::",1);
+
+		Ref<Texture> icon;
+		if (!has_icon(type,"EditorIcons")) {
+			icon=get_icon("Object","EditorIcons");
+		} else {
+			icon=get_icon(type,"EditorIcons");
+		}
+
+		TreeItem *ti=files->create_item(root);
+		ti->set_text(0,dep);
+		ti->set_icon(0,icon);
+
+	}
+
+	popup_centered_minsize(Size2(500,220));
+
+}
+
+void DependencyErrorDialog::ok_pressed() {
+
+	EditorNode::get_singleton()->load_scene(for_file,true);
+}
+
+void DependencyErrorDialog::custom_action(const String&) {
+
+	EditorNode::get_singleton()->fix_dependencies(for_file);
+}
+
+DependencyErrorDialog::DependencyErrorDialog() {
+
+	VBoxContainer *vb = memnew( VBoxContainer );
+	add_child(vb);
+	set_child_rect(vb);
+
+
+	files = memnew( Tree );
+	files->set_hide_root(true);
+	vb->add_margin_child("Scene failed to load due to missing dependencies:",files,true);
+	files->set_v_size_flags(SIZE_EXPAND_FILL);
+	get_ok()->set_text("Open Anyway");
+
+	text = memnew( Label );
+	vb->add_child(text);
+	text->set_text("Which action should be taken?");
+
+
+	fdep=add_button("Fix Dependencies",true,"fixdeps");
+
+	set_title("Errors loading!");
+
+}

+ 94 - 0
tools/editor/dependency_editor.h

@@ -0,0 +1,94 @@
+#ifndef DEPENDENCY_EDITOR_H
+#define DEPENDENCY_EDITOR_H
+
+#include "scene/gui/dialogs.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/tab_container.h"
+#include "editor_file_dialog.h"
+
+class EditorFileSystemDirectory;
+
+class DependencyEditor : public AcceptDialog {
+	OBJ_TYPE(DependencyEditor,AcceptDialog);
+
+
+	Tree *tree;
+	Button *fixdeps;
+
+	EditorFileDialog *search;
+
+	String replacing;
+	String editing;
+	List<String> missing;
+
+
+	void _fix_and_find(EditorFileSystemDirectory *efsd, Map<String,Map<String,String> >& candidates);
+
+	void _searched(const String& p_path);
+	void _load_pressed(Object* p_item,int p_cell,int p_button);
+	void _fix_all();
+	void _update_list();
+
+	void _update_file();
+
+protected:
+
+	static void _bind_methods();
+	void _notification(int p_what);
+public:
+
+
+	void edit(const String& p_path);
+	DependencyEditor();
+};
+
+class DependencyEditorOwners : public AcceptDialog {
+	OBJ_TYPE(DependencyEditorOwners,AcceptDialog);
+
+	ItemList *owners;
+	String editing;
+	void _fill_owners(EditorFileSystemDirectory *efsd);
+
+public:
+
+	void show(const String& p_path);
+	DependencyEditorOwners();
+};
+
+class DependencyRemoveDialog : public ConfirmationDialog {
+	OBJ_TYPE(DependencyRemoveDialog,ConfirmationDialog);
+
+
+	Label *text;
+	Tree *owners;
+	bool exist;
+	Map<String,TreeItem*> files;
+	void _fill_owners(EditorFileSystemDirectory *efsd);
+
+	void ok_pressed();
+
+public:
+
+	void show(const Vector<String> &to_erase);
+	DependencyRemoveDialog();
+};
+
+
+class DependencyErrorDialog : public ConfirmationDialog {
+	OBJ_TYPE(DependencyErrorDialog,ConfirmationDialog);
+
+
+	String for_file;
+	Button *fdep;
+	Label *text;
+	Tree *files;
+	void ok_pressed();
+	void custom_action(const String&);
+
+public:
+
+	void show(const String& p_for,const Vector<String> &report);
+	DependencyErrorDialog();
+};
+
+#endif // DEPENDENCY_EDITOR_H

+ 3 - 2
tools/editor/editor_file_dialog.cpp

@@ -190,7 +190,7 @@ void EditorFileDialog::_thumbnail_done(const String& p_path,const Ref<Texture>&
 void EditorFileDialog::_request_single_thumbnail(const String& p_path) {
 void EditorFileDialog::_request_single_thumbnail(const String& p_path) {
 
 
 	EditorResourcePreview::get_singleton()->queue_resource_preview(p_path,this,"_thumbnail_done",p_path);
 	EditorResourcePreview::get_singleton()->queue_resource_preview(p_path,this,"_thumbnail_done",p_path);
-	print_line("want file "+p_path);
+	//print_line("want file "+p_path);
 	set_process(true);
 	set_process(true);
 	preview_waiting=true;
 	preview_waiting=true;
 	preview_wheel_timeout=0;
 	preview_wheel_timeout=0;
@@ -359,7 +359,7 @@ void EditorFileDialog::_item_dc_selected(int p_item) {
 
 
 	if (d["dir"]) {
 	if (d["dir"]) {
 
 
-		print_line("change dir: "+String(d["name"]));
+		//print_line("change dir: "+String(d["name"]));
 		dir_access->change_dir(d["name"]);
 		dir_access->change_dir(d["name"]);
 		if (mode==MODE_OPEN_FILE || mode==MODE_OPEN_FILES || mode==MODE_OPEN_DIR)
 		if (mode==MODE_OPEN_FILE || mode==MODE_OPEN_FILES || mode==MODE_OPEN_DIR)
 			file->set_text("");
 			file->set_text("");
@@ -536,6 +536,7 @@ void EditorFileDialog::update_file_list() {
 
 
 			if (get_icon_func) {
 			if (get_icon_func) {
 
 
+				
 				Ref<Texture> icon = get_icon_func(base_dir.plus_file(files.front()->get()));
 				Ref<Texture> icon = get_icon_func(base_dir.plus_file(files.front()->get()));
 				//ti->set_icon(0,icon);
 				//ti->set_icon(0,icon);
 				if (display_mode==DISPLAY_THUMBNAILS) {
 				if (display_mode==DISPLAY_THUMBNAILS) {

+ 41 - 3
tools/editor/editor_file_system.cpp

@@ -94,6 +94,12 @@ bool EditorFileSystemDirectory::get_file_meta(int p_idx) const {
 	return files[p_idx].meta.enabled;
 	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;
+
+}
 Vector<String> EditorFileSystemDirectory::get_missing_sources(int p_idx) const {
 Vector<String> EditorFileSystemDirectory::get_missing_sources(int p_idx) const {
 
 
 	ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>());
 	ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>());
@@ -118,7 +124,7 @@ bool EditorFileSystemDirectory::is_missing_sources(int p_idx) const {
 	return false;
 	return false;
 }
 }
 
 
-String EditorFileSystemDirectory::get_file_type(int p_idx) const {
+StringName EditorFileSystemDirectory::get_file_type(int p_idx) const {
 
 
 	ERR_FAIL_INDEX_V(p_idx,files.size(),"");
 	ERR_FAIL_INDEX_V(p_idx,files.size(),"");
 	return files[p_idx].type;
 	return files[p_idx].type;
@@ -198,6 +204,13 @@ EditorFileSystemDirectory::ImportMeta EditorFileSystem::_get_meta(const String&
 		}
 		}
 		m.import_editor=imd->get_editor();
 		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;
 	return m;
 }
 }
 
 
@@ -358,7 +371,7 @@ void EditorFileSystem::_scan_scenes() {
 
 
 	String project=Globals::get_singleton()->get_resource_path();
 	String project=Globals::get_singleton()->get_resource_path();
 
 
-	String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("file_cache");
+	String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache");
 	FileAccess *f =FileAccess::open(fscache,FileAccess::READ);
 	FileAccess *f =FileAccess::open(fscache,FileAccess::READ);
 
 
 	if (f) {
 	if (f) {
@@ -397,7 +410,7 @@ void EditorFileSystem::_scan_scenes() {
 
 
 			} else {
 			} else {
 				Vector<String> split = l.split("::");
 				Vector<String> split = l.split("::");
-				ERR_CONTINUE( split.size() != 4);
+				ERR_CONTINUE( split.size() != 5);
 				String name = split[0];
 				String name = split[0];
 				String file;
 				String file;
 
 
@@ -429,6 +442,15 @@ void EditorFileSystem::_scan_scenes() {
 					}
 					}
 
 
 				}
 				}
+				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);
+					}
+				}
+
 				file_cache[name]=fc;
 				file_cache[name]=fc;
 
 
 				ERR_CONTINUE(!dc);
 				ERR_CONTINUE(!dc);
@@ -530,6 +552,7 @@ void EditorFileSystem::scan() {
 		thread = Thread::create(_thread_func,this,s);
 		thread = Thread::create(_thread_func,this,s);
 		//tree->hide();
 		//tree->hide();
 		//progress->show();
 		//progress->show();
+
 	}
 	}
 
 
 
 
@@ -798,6 +821,14 @@ void EditorFileSystem::_save_type_cache_fs(DirItem *p_dir,FileAccess *p_file) {
 
 
 			}
 			}
 		}
 		}
+		s+="::";
+		for(int j=0;j<p_dir->files[i]->meta.deps.size();j++) {
+
+			if (j>0)
+				s+="<>";
+			s+=p_dir->files[i]->meta.deps[j];
+		}
+
 		p_file->store_line(s);
 		p_file->store_line(s);
 	}
 	}
 
 
@@ -1037,6 +1068,13 @@ void EditorFileSystem::update_file(const String& p_file) {
 		return;
 		return;
     }
     }
 
 
+    if (!FileAccess::exists(p_file)) {
+	    //was removed
+	    fs->files.remove(cpos);
+	    call_deferred("emit_signal","filesystem_changed"); //update later
+	    return;
+
+    }
 
 
     String type = ResourceLoader::get_resource_type(p_file);
     String type = ResourceLoader::get_resource_type(p_file);
 
 

+ 6 - 3
tools/editor/editor_file_system.h

@@ -59,13 +59,14 @@ class EditorFileSystemDirectory : public Object {
 
 
 		Vector<Source> sources;
 		Vector<Source> sources;
 		String import_editor;
 		String import_editor;
+		Vector<String> deps;
 		bool enabled;
 		bool enabled;
 
 
 	};
 	};
 
 
 	struct FileInfo {
 	struct FileInfo {
 		String file;
 		String file;
-		String type;
+		StringName type;
 		uint64_t modified_time;
 		uint64_t modified_time;
 
 
 		ImportMeta meta;
 		ImportMeta meta;
@@ -87,10 +88,11 @@ public:
 	int get_file_count() const;
 	int get_file_count() const;
 	String get_file(int p_idx) const;
 	String get_file(int p_idx) const;
 	String get_file_path(int p_idx) const;
 	String get_file_path(int p_idx) const;
-	String get_file_type(int p_idx) const;
+	StringName get_file_type(int p_idx) const;
 	bool get_file_meta(int p_idx) const;
 	bool get_file_meta(int p_idx) const;
 	bool is_missing_sources(int p_idx) const;
 	bool is_missing_sources(int p_idx) const;
 	Vector<String> get_missing_sources(int p_idx) const;
 	Vector<String> get_missing_sources(int p_idx) const;
+	Vector<String> get_file_deps(int p_idx) const;
 
 
 	EditorFileSystemDirectory *get_parent();
 	EditorFileSystemDirectory *get_parent();
 
 
@@ -120,7 +122,7 @@ class EditorFileSystem : public Node {
 		String path;
 		String path;
 		String name;
 		String name;
 		Vector<DirItem*> dirs;
 		Vector<DirItem*> dirs;
-		Vector<SceneItem*> files;
+		Vector<SceneItem*> files;		
 		~DirItem();
 		~DirItem();
 	};
 	};
 
 
@@ -149,6 +151,7 @@ class EditorFileSystem : public Node {
 		String type;
 		String type;
 		uint64_t modification_time;
 		uint64_t modification_time;
 		EditorFileSystemDirectory::ImportMeta meta;
 		EditorFileSystemDirectory::ImportMeta meta;
+		Vector<String> deps;
 	};
 	};
 
 
 	struct DirCache {
 	struct DirCache {

+ 64 - 3
tools/editor/editor_node.cpp

@@ -1803,6 +1803,13 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 			quick_open->popup("Script");
 			quick_open->popup("Script");
 			quick_open->set_title("Quick Open Script..");
 			quick_open->set_title("Quick Open Script..");
 
 
+		} break;
+		case FILE_QUICK_OPEN_FILE: {
+
+
+			quick_open->popup("Resource",false,true);
+			quick_open->set_title("Quick Search File..");
+
 		} break;
 		} break;
 		case FILE_RUN_SCRIPT: {
 		case FILE_RUN_SCRIPT: {
 
 
@@ -3050,7 +3057,21 @@ void EditorNode::set_current_scene(int p_idx) {
 
 
 }
 }
 
 
-Error EditorNode::load_scene(const String& p_scene) {
+bool EditorNode::is_scene_open(const String& p_path) {
+
+	for(int i=0;i<editor_data.get_edited_scene_count();i++) {
+		if (editor_data.get_scene_path(i)==p_path)
+			return true;
+	}
+
+	return false;
+}
+
+void EditorNode::fix_dependencies(const String& p_for_file) {
+	dependency_fixer->edit(p_for_file);
+}
+
+Error EditorNode::load_scene(const String& p_scene, bool p_ignore_broken_deps) {
 
 
 	if (!is_inside_tree()) {
 	if (!is_inside_tree()) {
 		defer_load_scene = p_scene;
 		defer_load_scene = p_scene;
@@ -3096,6 +3117,8 @@ Error EditorNode::load_scene(const String& p_scene) {
 
 
 	//_cleanup_scene(); // i'm sorry but this MUST happen to avoid modified resources to not be reloaded.
 	//_cleanup_scene(); // i'm sorry but this MUST happen to avoid modified resources to not be reloaded.
 
 
+	dependency_errors.clear();
+
 	Ref<PackedScene> sdata = ResourceLoader::load(lpath,"",true);
 	Ref<PackedScene> sdata = ResourceLoader::load(lpath,"",true);
 	if (!sdata.is_valid()) {
 	if (!sdata.is_valid()) {
 
 
@@ -3113,6 +3136,35 @@ Error EditorNode::load_scene(const String& p_scene) {
 		return ERR_FILE_NOT_FOUND;
 		return ERR_FILE_NOT_FOUND;
 	}
 	}
 
 
+	if (!p_ignore_broken_deps && dependency_errors.has(lpath)) {
+
+		current_option=-1;
+		Vector<String> errors;
+		for(Set<String>::Element *E=dependency_errors[lpath].front();E;E=E->next()) {
+
+			errors.push_back(E->get());
+		}
+		dependency_error->show(lpath,errors);
+		opening_prev=false;
+
+		if (prev!=-1) {
+			set_current_scene(prev);
+			editor_data.remove_scene(idx);
+		}
+		return ERR_FILE_MISSING_DEPENDENCIES;
+	}
+
+	dependency_errors.erase(lpath); //at least not self path
+
+	for (Map<String,Set<String> >::Element *E=dependency_errors.front();E;E=E->next()) {
+
+		String txt="Scene '"+E->key()+"' has broken dependencies:\n";
+		for(Set<String>::Element *F=E->get().front();F;F=F->next()) {
+			txt+="\t"+F->get()+"\n";
+		}
+		add_io_error(txt);
+	}
+
 	sdata->set_path(lpath,true); //take over path
 	sdata->set_path(lpath,true); //take over path
 
 
 	Node*new_scene=sdata->instance(true);
 	Node*new_scene=sdata->instance(true);
@@ -3408,9 +3460,12 @@ void EditorNode::hide_animation_player_editors() {
 
 
 void EditorNode::_quick_opened(const String& p_resource) {
 void EditorNode::_quick_opened(const String& p_resource) {
 
 
-	print_line("quick_opened");
-	if (quick_open->get_base_type()=="PackedScene") {
+	if (current_option==FILE_QUICK_OPEN_FILE) {
+		scenes_dock->open(p_resource);
+		return;
+	}
 
 
+	if (quick_open->get_base_type()=="PackedScene") {
 		open_request(p_resource);
 		open_request(p_resource);
 	} else {
 	} else {
 		load_resource(p_resource);
 		load_resource(p_resource);
@@ -4120,6 +4175,7 @@ EditorNode::EditorNode() {
 	ResourceLoader::set_abort_on_missing_resources(false);
 	ResourceLoader::set_abort_on_missing_resources(false);
 	FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files"));
 	FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("file_dialog/show_hidden_files"));
 	ResourceLoader::set_error_notify_func(this,_load_error_notify);
 	ResourceLoader::set_error_notify_func(this,_load_error_notify);
+	ResourceLoader::set_dependency_error_notify_func(this,_dependency_error_report);
 
 
 	ResourceLoader::set_timestamp_on_load(true);
 	ResourceLoader::set_timestamp_on_load(true);
 	ResourceSaver::set_timestamp_on_save(true);
 	ResourceSaver::set_timestamp_on_save(true);
@@ -4493,6 +4549,7 @@ EditorNode::EditorNode() {
 	p->add_separator();
 	p->add_separator();
 	p->add_item("Quick Open Scene..",FILE_QUICK_OPEN_SCENE,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_O);
 	p->add_item("Quick Open Scene..",FILE_QUICK_OPEN_SCENE,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_O);
 	p->add_item("Quick Open Script..",FILE_QUICK_OPEN_SCRIPT,KEY_MASK_ALT+KEY_MASK_CMD+KEY_O);
 	p->add_item("Quick Open Script..",FILE_QUICK_OPEN_SCRIPT,KEY_MASK_ALT+KEY_MASK_CMD+KEY_O);
+	p->add_item("Quick Search File..",FILE_QUICK_OPEN_FILE,KEY_MASK_ALT+KEY_MASK_CMD+KEY_P);
 	p->add_separator();
 	p->add_separator();
 
 
 	PopupMenu *pm_export = memnew(PopupMenu );
 	PopupMenu *pm_export = memnew(PopupMenu );
@@ -4929,7 +4986,11 @@ EditorNode::EditorNode() {
 
 
 
 
 
 
+	dependency_error = memnew( DependencyErrorDialog );
+	gui_base->add_child(dependency_error);
 
 
+	dependency_fixer = memnew( DependencyEditor );
+	gui_base->add_child( dependency_fixer );
 	
 	
 	settings_config_dialog = memnew( EditorSettingsDialog );
 	settings_config_dialog = memnew( EditorSettingsDialog );
 	gui_base->add_child(settings_config_dialog);
 	gui_base->add_child(settings_config_dialog);

+ 18 - 1
tools/editor/editor_node.h

@@ -123,6 +123,7 @@ class EditorNode : public Node {
 		FILE_OPEN_OLD_SCENE,
 		FILE_OPEN_OLD_SCENE,
 		FILE_QUICK_OPEN_SCENE,
 		FILE_QUICK_OPEN_SCENE,
 		FILE_QUICK_OPEN_SCRIPT,
 		FILE_QUICK_OPEN_SCRIPT,
+		FILE_QUICK_OPEN_FILE,
 		FILE_RUN_SCRIPT,
 		FILE_RUN_SCRIPT,
 		FILE_OPEN_PREV,
 		FILE_OPEN_PREV,
 		FILE_CLOSE,
 		FILE_CLOSE,
@@ -312,6 +313,9 @@ class EditorNode : public Node {
 	ProgressDialog *progress_dialog;
 	ProgressDialog *progress_dialog;
 	BackgroundProgress *progress_hb;
 	BackgroundProgress *progress_hb;
 
 
+	DependencyErrorDialog *dependency_error;
+	DependencyEditor *dependency_fixer;
+
 	TabContainer *dock_slot[DOCK_SLOT_MAX];
 	TabContainer *dock_slot[DOCK_SLOT_MAX];
 	Rect2 dock_select_rect[DOCK_SLOT_MAX];
 	Rect2 dock_select_rect[DOCK_SLOT_MAX];
 	int dock_select_rect_over;
 	int dock_select_rect_over;
@@ -451,6 +455,16 @@ class EditorNode : public Node {
 	void _save_scene_with_preview(String p_file);
 	void _save_scene_with_preview(String p_file);
 
 
 
 
+	Map<String,Set<String> > dependency_errors;
+
+	static void _dependency_error_report(void *ud,const String& p_path,const String& p_dep,const String& p_type) {
+		EditorNode*en=(EditorNode*)ud;
+		if (!en->dependency_errors.has(p_path))
+			en->dependency_errors[p_path]=Set<String>();
+		en->dependency_errors[p_path].insert(p_dep+"::"+p_type);
+
+	}
+
 	struct ExportDefer {
 	struct ExportDefer {
 		String platform;
 		String platform;
 		String path;
 		String path;
@@ -534,10 +548,13 @@ public:
 	Viewport *get_scene_root() { return scene_root; } //root of the scene being edited
 	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);
 	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(); }
 	void clear_scene() { _cleanup_scene(); }
-	Error load_scene(const String& p_scene);
+	Error load_scene(const String& p_scene,bool p_ignore_broken_deps=false);
 	Error load_resource(const String& p_scene);
 	Error load_resource(const String& p_scene);
 
 
+	bool is_scene_open(const String& p_path);
+
 	void set_current_version(uint64_t p_version);
 	void set_current_version(uint64_t p_version);
 	void set_current_scene(int p_idx);
 	void set_current_scene(int p_idx);
 
 

二进制
tools/editor/icons/icon_anchor.png


二进制
tools/editor/icons/icon_control_align_bottom_center.png


二进制
tools/editor/icons/icon_control_align_bottom_left.png


二进制
tools/editor/icons/icon_control_align_bottom_right.png


二进制
tools/editor/icons/icon_control_align_bottom_wide.png


二进制
tools/editor/icons/icon_control_align_center.png


二进制
tools/editor/icons/icon_control_align_center_left.png


二进制
tools/editor/icons/icon_control_align_center_right.png


二进制
tools/editor/icons/icon_control_align_left_center.png


二进制
tools/editor/icons/icon_control_align_left_wide.png


二进制
tools/editor/icons/icon_control_align_right_center.png


二进制
tools/editor/icons/icon_control_align_right_wide.png


二进制
tools/editor/icons/icon_control_align_top_center.png


二进制
tools/editor/icons/icon_control_align_top_left.png


二进制
tools/editor/icons/icon_control_align_top_right.png


二进制
tools/editor/icons/icon_control_align_top_wide.png


二进制
tools/editor/icons/icon_control_align_wide.png


二进制
tools/editor/icons/icon_control_hcenter_wide.png


二进制
tools/editor/icons/icon_control_vcenter_wide.png


二进制
tools/editor/icons/icon_file_list.png


二进制
tools/editor/icons/icon_filesystem.png


二进制
tools/editor/icons/icon_non_favorite.png


二进制
tools/editor/icons/icon_patch_9_frame.png


+ 120 - 0
tools/editor/plugins/canvas_item_editor_plugin.cpp

@@ -1910,12 +1910,20 @@ void CanvasItemEditor::_notification(int p_what) {
 
 
 		List<Node*> &selection = editor_selection->get_selected_node_list();
 		List<Node*> &selection = editor_selection->get_selected_node_list();
 
 
+		bool all_control=true;
+		bool has_control=false;
+
 		for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 		for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
 
 
 			CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
 			CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
 			if (!canvas_item || !canvas_item->is_visible())
 			if (!canvas_item || !canvas_item->is_visible())
 				continue;
 				continue;
 
 
+			if (canvas_item->cast_to<Control>())
+				has_control=true;
+			else
+				all_control=false;
+
 			CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
 			CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
 			if (!se)
 			if (!se)
 				continue;
 				continue;
@@ -1932,6 +1940,13 @@ void CanvasItemEditor::_notification(int p_what) {
 
 
 		}
 		}
 
 
+		bool show_anchor = all_control && has_control;
+		if (show_anchor != !anchor_menu->is_hidden()) {
+			if (show_anchor)
+				anchor_menu->show();
+			else
+				anchor_menu->hide();
+		}
 
 
 		for(Map<ObjectID,BoneList>::Element *E=bone_list.front();E;E=E->next()) {
 		for(Map<ObjectID,BoneList>::Element *E=bone_list.front();E;E=E->next()) {
 
 
@@ -1974,6 +1989,32 @@ void CanvasItemEditor::_notification(int p_what) {
 		ungroup_button->set_icon(get_icon("Ungroup","EditorIcons"));
 		ungroup_button->set_icon(get_icon("Ungroup","EditorIcons"));
 		key_insert_button->set_icon(get_icon("Key","EditorIcons"));
 		key_insert_button->set_icon(get_icon("Key","EditorIcons"));
 
 
+
+		//anchor_menu->add_icon_override("Align Top Left");
+		anchor_menu->set_icon(get_icon("Anchor","EditorIcons"));
+		PopupMenu *p=anchor_menu->get_popup();
+
+		p->add_icon_item(get_icon("ControlAlignTopLeft","EditorIcons"),"Top Left",ANCHOR_ALIGN_TOP_LEFT);
+		p->add_icon_item(get_icon("ControlAlignTopRight","EditorIcons"),"Top Right",ANCHOR_ALIGN_TOP_RIGHT);
+		p->add_icon_item(get_icon("ControlAlignBottomRight","EditorIcons"),"Bottom Right",ANCHOR_ALIGN_BOTTOM_RIGHT);
+		p->add_icon_item(get_icon("ControlAlignBottomLeft","EditorIcons"),"Bottom Left",ANCHOR_ALIGN_BOTTOM_LEFT);
+		p->add_separator();
+		p->add_icon_item(get_icon("ControlAlignLeftCenter","EditorIcons"),"Center Left",ANCHOR_ALIGN_CENTER_LEFT);
+		p->add_icon_item(get_icon("ControlAlignTopCenter","EditorIcons"),"Center Top",ANCHOR_ALIGN_CENTER_TOP);
+		p->add_icon_item(get_icon("ControlAlignRightCenter","EditorIcons"),"Center Right",ANCHOR_ALIGN_CENTER_RIGHT);
+		p->add_icon_item(get_icon("ControlAlignBottomCenter","EditorIcons"),"Center Bottom",ANCHOR_ALIGN_CENTER_BOTTOM);
+		p->add_icon_item(get_icon("ControlAlignCenter","EditorIcons"),"Center",ANCHOR_ALIGN_CENTER);
+		p->add_separator();
+		p->add_icon_item(get_icon("ControlAlignLeftWide","EditorIcons"),"Left Wide",ANCHOR_ALIGN_LEFT_WIDE);
+		p->add_icon_item(get_icon("ControlAlignTopWide","EditorIcons"),"Top Wide",ANCHOR_ALIGN_TOP_WIDE);
+		p->add_icon_item(get_icon("ControlAlignRightWide","EditorIcons"),"Right Wide",ANCHOR_ALIGN_RIGHT_WIDE);
+		p->add_icon_item(get_icon("ControlAlignBottomWide","EditorIcons"),"Bottom Wide",ANCHOR_ALIGN_BOTTOM_WIDE);
+		p->add_icon_item(get_icon("ControlVcenterWide","EditorIcons"),"VCenter Wide ",ANCHOR_ALIGN_VCENTER_WIDE);
+		p->add_icon_item(get_icon("ControlHcenterWide","EditorIcons"),"HCenter Wide ",ANCHOR_ALIGN_HCENTER_WIDE);
+		p->add_separator();
+		p->add_icon_item(get_icon("ControlAlignWide","EditorIcons"),"Full Rect",ANCHOR_ALIGN_WIDE);
+
+
 	}
 	}
 
 
 	if (p_what==NOTIFICATION_READY) {
 	if (p_what==NOTIFICATION_READY) {
@@ -2179,6 +2220,27 @@ void CanvasItemEditor::_update_scroll(float) {
 
 
 }
 }
 
 
+void CanvasItemEditor::_set_anchor(Control::AnchorType p_left,Control::AnchorType p_top,Control::AnchorType p_right,Control::AnchorType p_bottom) {
+	List<Node*> &selection = editor_selection->get_selected_node_list();
+
+	undo_redo->create_action("Change Anchors");
+	for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+		Control *c = E->get()->cast_to<Control>();
+
+		undo_redo->add_do_method(c,"set_anchor",MARGIN_LEFT,p_left);
+		undo_redo->add_do_method(c,"set_anchor",MARGIN_TOP,p_top);
+		undo_redo->add_do_method(c,"set_anchor",MARGIN_RIGHT,p_right);
+		undo_redo->add_do_method(c,"set_anchor",MARGIN_BOTTOM,p_bottom);
+		undo_redo->add_undo_method(c,"set_anchor",MARGIN_LEFT,c->get_anchor(MARGIN_LEFT));
+		undo_redo->add_undo_method(c,"set_anchor",MARGIN_TOP,c->get_anchor(MARGIN_TOP));
+		undo_redo->add_undo_method(c,"set_anchor",MARGIN_RIGHT,c->get_anchor(MARGIN_RIGHT));
+		undo_redo->add_undo_method(c,"set_anchor",MARGIN_BOTTOM,c->get_anchor(MARGIN_BOTTOM));
+	}
+
+	undo_redo->commit_action();
+
+}
 
 
 void CanvasItemEditor::_popup_callback(int p_op) {
 void CanvasItemEditor::_popup_callback(int p_op) {
 
 
@@ -2381,6 +2443,56 @@ void CanvasItemEditor::_popup_callback(int p_op) {
 		case SPACE_VERTICAL: {
 		case SPACE_VERTICAL: {
 			//space_selected_items< proj_vector2_y, compare_items_y >();
 			//space_selected_items< proj_vector2_y, compare_items_y >();
 		} break;
 		} break;
+		case ANCHOR_ALIGN_TOP_LEFT: {
+			_set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN);
+		} break;
+		case ANCHOR_ALIGN_TOP_RIGHT: {
+			_set_anchor(ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN);
+		} break;
+		case ANCHOR_ALIGN_BOTTOM_LEFT: {
+			_set_anchor(ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END);
+		} break;
+		case ANCHOR_ALIGN_BOTTOM_RIGHT: {
+			_set_anchor(ANCHOR_END,ANCHOR_END,ANCHOR_END,ANCHOR_END);
+		} break;
+		case ANCHOR_ALIGN_CENTER_LEFT: {
+			_set_anchor(ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER);
+		} break;
+		case ANCHOR_ALIGN_CENTER_RIGHT: {
+
+			_set_anchor(ANCHOR_END,ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER);
+		} break;
+		case ANCHOR_ALIGN_CENTER_TOP: {
+			_set_anchor(ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_BEGIN);
+		} break;
+		case ANCHOR_ALIGN_CENTER_BOTTOM: {
+			_set_anchor(ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER,ANCHOR_END);
+		} break;
+		case ANCHOR_ALIGN_CENTER: {
+			_set_anchor(ANCHOR_CENTER,ANCHOR_CENTER,ANCHOR_CENTER,ANCHOR_CENTER);
+		} break;
+		case ANCHOR_ALIGN_TOP_WIDE: {
+			_set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN);
+		} break;
+		case ANCHOR_ALIGN_LEFT_WIDE: {
+			_set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END);
+		} break;
+		case ANCHOR_ALIGN_RIGHT_WIDE: {
+			_set_anchor(ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END);
+		} break;
+		case ANCHOR_ALIGN_BOTTOM_WIDE: {
+			_set_anchor(ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END,ANCHOR_END);
+		} break;
+		case ANCHOR_ALIGN_VCENTER_WIDE: {
+			_set_anchor(ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_END);
+		} break;
+		case ANCHOR_ALIGN_HCENTER_WIDE: {
+			_set_anchor(ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER);
+		} break;
+		case ANCHOR_ALIGN_WIDE: {
+			_set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END);
+		} break;
+
 		case ANIM_INSERT_KEY:
 		case ANIM_INSERT_KEY:
 		case ANIM_INSERT_KEY_EXISTING: {
 		case ANIM_INSERT_KEY_EXISTING: {
 
 
@@ -2999,6 +3111,14 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
 	p->add_item("Center Selection", VIEW_CENTER_TO_SELECTION, KEY_F);
 	p->add_item("Center Selection", VIEW_CENTER_TO_SELECTION, KEY_F);
 	p->add_item("Frame Selection", VIEW_FRAME_TO_SELECTION, KEY_MASK_CMD|KEY_F);
 	p->add_item("Frame Selection", VIEW_FRAME_TO_SELECTION, KEY_MASK_CMD|KEY_F);
 
 
+	anchor_menu = memnew( MenuButton );
+	anchor_menu->set_text("Anchor");
+	hb->add_child(anchor_menu);
+	anchor_menu->get_popup()->connect("item_pressed", this,"_popup_callback");
+	anchor_menu->hide();
+
+	//p = anchor_menu->get_popup();
+
 
 
 
 
 	animation_hb = memnew( HBoxContainer );
 	animation_hb = memnew( HBoxContainer );

+ 20 - 0
tools/editor/plugins/canvas_item_editor_plugin.h

@@ -90,6 +90,23 @@ class CanvasItemEditor : public VBoxContainer {
 		UNGROUP_SELECTED,
 		UNGROUP_SELECTED,
 		ALIGN_HORIZONTAL,
 		ALIGN_HORIZONTAL,
 		ALIGN_VERTICAL,
 		ALIGN_VERTICAL,
+		ANCHOR_ALIGN_TOP_LEFT,
+		ANCHOR_ALIGN_TOP_RIGHT,
+		ANCHOR_ALIGN_BOTTOM_LEFT,
+		ANCHOR_ALIGN_BOTTOM_RIGHT,
+		ANCHOR_ALIGN_CENTER_LEFT,
+		ANCHOR_ALIGN_CENTER_RIGHT,
+		ANCHOR_ALIGN_CENTER_TOP,
+		ANCHOR_ALIGN_CENTER_BOTTOM,
+		ANCHOR_ALIGN_CENTER,
+		ANCHOR_ALIGN_TOP_WIDE,
+		ANCHOR_ALIGN_LEFT_WIDE,
+		ANCHOR_ALIGN_RIGHT_WIDE,
+		ANCHOR_ALIGN_BOTTOM_WIDE,
+		ANCHOR_ALIGN_VCENTER_WIDE,
+		ANCHOR_ALIGN_HCENTER_WIDE,
+		ANCHOR_ALIGN_WIDE,
+
 		SPACE_HORIZONTAL,
 		SPACE_HORIZONTAL,
 		SPACE_VERTICAL,
 		SPACE_VERTICAL,
 		EXPAND_TO_PARENT,
 		EXPAND_TO_PARENT,
@@ -225,6 +242,7 @@ class CanvasItemEditor : public VBoxContainer {
 	MenuButton *view_menu;
 	MenuButton *view_menu;
 	HBoxContainer *animation_hb;
 	HBoxContainer *animation_hb;
 	MenuButton *animation_menu;
 	MenuButton *animation_menu;
+	MenuButton *anchor_menu;
 
 
 	Button *key_loc_button;
 	Button *key_loc_button;
 	Button *key_rot_button;
 	Button *key_rot_button;
@@ -305,6 +323,8 @@ class CanvasItemEditor : public VBoxContainer {
 	void _viewport_input_event(const InputEvent& p_event);
 	void _viewport_input_event(const InputEvent& p_event);
 	void _viewport_draw();
 	void _viewport_draw();
 
 
+	void _set_anchor(Control::AnchorType p_left,Control::AnchorType p_top,Control::AnchorType p_right,Control::AnchorType p_bottom);
+
 	HSplitContainer *palette_split;
 	HSplitContainer *palette_split;
 	VSplitContainer *bottom_split;
 	VSplitContainer *bottom_split;
 
 

+ 3 - 1
tools/editor/project_export.cpp

@@ -80,7 +80,7 @@ bool ProjectExportDialog::_create_tree(TreeItem *p_parent,EditorFileSystemDirect
 		String path = p_dir->get_file_path(i);
 		String path = p_dir->get_file_path(i);
 		fitem->set_tooltip(0,path);
 		fitem->set_tooltip(0,path);
 		fitem->set_metadata(0,path);
 		fitem->set_metadata(0,path);
-		Ref<Texture> icon = get_icon( (has_icon(p_dir->get_file_type(i),"EditorIcons")?p_dir->get_file_type(i):String("Object")),"EditorIcons");
+		Ref<Texture> icon = get_icon( (has_icon(p_dir->get_file_type(i),ei)?p_dir->get_file_type(i):ot),ei);
 		fitem->set_icon(0,icon);
 		fitem->set_icon(0,icon);
 
 
 		fitem->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
 		fitem->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
@@ -1372,6 +1372,8 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
 	button_export = add_button("Export..",!OS::get_singleton()->get_swap_ok_cancel(),"export_pck");
 	button_export = add_button("Export..",!OS::get_singleton()->get_swap_ok_cancel(),"export_pck");
 	updating_script=false;
 	updating_script=false;
 
 
+	ei="EditorIcons";
+	ot="Object";
 
 
 }
 }
 
 

+ 3 - 0
tools/editor/project_export.h

@@ -78,6 +78,9 @@ private:
 	HBoxContainer *plat_errors;
 	HBoxContainer *plat_errors;
 	Label *platform_error_string;
 	Label *platform_error_string;
 
 
+	StringName ei;
+	StringName ot;
+
 	Tree * tree;
 	Tree * tree;
 
 
 	EditorFileDialog *pck_export;
 	EditorFileDialog *pck_export;

+ 36 - 6
tools/editor/quick_open.cpp

@@ -30,8 +30,9 @@
 #include "os/keyboard.h"
 #include "os/keyboard.h"
 
 
 
 
-void EditorQuickOpen::popup(const String& p_base, bool p_dontclear) {
+void EditorQuickOpen::popup(const StringName &p_base, bool p_dontclear, bool p_add_dirs) {
 
 
+	add_directories=p_add_dirs;
 	popup_centered_ratio(0.6);
 	popup_centered_ratio(0.6);
 	if (p_dontclear)
 	if (p_dontclear)
 		search_box->select_all();
 		search_box->select_all();
@@ -66,27 +67,53 @@ void EditorQuickOpen::_sbox_input(const InputEvent& p_ie) {
 
 
 void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd) {
 void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd) {
 
 
-	for(int i=0;i<efsd->get_subdir_count();i++) {
+	if (!add_directories) {
+		for(int i=0;i<efsd->get_subdir_count();i++) {
 
 
-		_parse_fs(efsd->get_subdir(i));
+			_parse_fs(efsd->get_subdir(i));
+		}
 	}
 	}
 
 
+	TreeItem *root = search_options->get_root();
+
+	if (add_directories) {
+		String path = efsd->get_path();
+		if (!path.ends_with("/"))
+			path+="/";
+		if (path!="res://") {
+			path=path.substr(6,path.length());
+			if (path.findn(search_box->get_text())!=-1) {
+				TreeItem *ti = search_options->create_item(root);
+				ti->set_text(0,path);
+				Ref<Texture> icon = get_icon("folder","FileDialog");
+				ti->set_icon(0,icon);
+			}
+		}
+	}
 	for(int i=0;i<efsd->get_file_count();i++) {
 	for(int i=0;i<efsd->get_file_count();i++) {
 
 
 		String file = efsd->get_file_path(i);
 		String file = efsd->get_file_path(i);
 		file=file.substr(6,file.length());
 		file=file.substr(6,file.length());
 		if (ObjectTypeDB::is_type(efsd->get_file_type(i),base_type) && (search_box->get_text()=="" || file.findn(search_box->get_text())!=-1)) {
 		if (ObjectTypeDB::is_type(efsd->get_file_type(i),base_type) && (search_box->get_text()=="" || file.findn(search_box->get_text())!=-1)) {
 
 
-			TreeItem *root = search_options->get_root();
 			TreeItem *ti = search_options->create_item(root);
 			TreeItem *ti = search_options->create_item(root);
 			ti->set_text(0,file);
 			ti->set_text(0,file);
-			Ref<Texture> icon = get_icon( (has_icon(efsd->get_file_type(i),"EditorIcons")?efsd->get_file_type(i):String("Object")),"EditorIcons");
+			Ref<Texture> icon = get_icon( (has_icon(efsd->get_file_type(i),ei)?efsd->get_file_type(i):ot),ei);
 			ti->set_icon(0,icon);
 			ti->set_icon(0,icon);
 			if (root->get_children()==ti)
 			if (root->get_children()==ti)
 				ti->select(0);
 				ti->select(0);
 
 
 		}
 		}
 	}
 	}
+
+
+	if (add_directories) {
+		for(int i=0;i<efsd->get_subdir_count();i++) {
+
+			_parse_fs(efsd->get_subdir(i));
+		}
+	}
+
 }
 }
 
 
 void EditorQuickOpen::_update_search() {
 void EditorQuickOpen::_update_search() {
@@ -118,7 +145,7 @@ void EditorQuickOpen::_notification(int p_what) {
 }
 }
 
 
 
 
-String EditorQuickOpen::get_base_type() const {
+StringName EditorQuickOpen::get_base_type() const {
 
 
 	return base_type;
 	return base_type;
 }
 }
@@ -152,4 +179,7 @@ EditorQuickOpen::EditorQuickOpen() {
 	set_hide_on_ok(false);
 	set_hide_on_ok(false);
 	search_options->connect("item_activated",this,"_confirmed");
 	search_options->connect("item_activated",this,"_confirmed");
 	search_options->set_hide_root(true);
 	search_options->set_hide_root(true);
+	ei="EditorIcons";
+	ot="Object";
+	add_directories=false;
 }
 }

+ 7 - 3
tools/editor/quick_open.h

@@ -38,7 +38,11 @@ class EditorQuickOpen : public ConfirmationDialog {
 
 
 	LineEdit *search_box;
 	LineEdit *search_box;
 	Tree *search_options;
 	Tree *search_options;
-	String base_type;
+	StringName base_type;
+	StringName ei;
+	StringName ot;
+	bool add_directories;
+
 
 
 	void _update_search();
 	void _update_search();
 
 
@@ -55,9 +59,9 @@ protected:
 	static void _bind_methods();
 	static void _bind_methods();
 public:
 public:
 
 
-	String get_base_type() const;
+	StringName get_base_type() const;
 
 
-	void popup(const String& p_base,bool p_dontclear=false);
+	void popup(const StringName& p_base,bool p_dontclear=false,bool p_add_dirs=false);
 	EditorQuickOpen();
 	EditorQuickOpen();
 };
 };
 
 

文件差异内容过多而无法显示
+ 869 - 62
tools/editor/scenes_dock.cpp


+ 84 - 46
tools/editor/scenes_dock.h

@@ -36,40 +36,112 @@
 #include "scene/gui/tool_button.h"
 #include "scene/gui/tool_button.h"
 #include "scene/gui/option_button.h"
 #include "scene/gui/option_button.h"
 #include "scene/gui/box_container.h"
 #include "scene/gui/box_container.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/item_list.h"
+#include "scene/gui/progress_bar.h"
+
 #include "os/dir_access.h"
 #include "os/dir_access.h"
 #include "os/thread.h"
 #include "os/thread.h"
 
 
 #include "editor_file_system.h"
 #include "editor_file_system.h"
-
+#include "editor_dir_dialog.h"
+#include "dependency_editor.h"
 
 
 class EditorNode;
 class EditorNode;
 
 
-class ScenesDockFilter;
+
 class ScenesDock : public VBoxContainer {
 class ScenesDock : public VBoxContainer {
 	OBJ_TYPE( ScenesDock, VBoxContainer );
 	OBJ_TYPE( ScenesDock, VBoxContainer );
 
 
+	enum FileMenu {
+		FILE_DEPENDENCIES,
+		FILE_OWNERS,
+		FILE_MOVE,
+		FILE_REMOVE,
+		FILE_REIMPORT,
+		FILE_INFO
+	};
+
+
+	VBoxContainer *scanning_vb;
+	ProgressBar *scanning_progress;
+
 	EditorNode *editor;
 	EditorNode *editor;
 	Set<String> favorites;
 	Set<String> favorites;
 
 
 	Button *button_reload;
 	Button *button_reload;
 	Button *button_instance;
 	Button *button_instance;
 	Button *button_favorite;
 	Button *button_favorite;
+	Button *button_fav_up;
+	Button *button_fav_down;
 	Button *button_open;
 	Button *button_open;
-	Timer *timer;
+	Button *button_back;
+	Button *display_mode;
+	Button *button_hist_next;
+	Button *button_hist_prev;
+	LineEdit *current_path;
+	HBoxContainer *path_hb;
+
+	MenuButton *file_options;
+
+
+	DependencyEditor *deps_editor;
+	DependencyEditorOwners *owners_editor;
+	DependencyRemoveDialog *remove_dialog;
+
+	EditorDirDialog *move_dialog;
+	EditorFileDialog *rename_dialog;
 
 
-	ScenesDockFilter *tree_filter;
+	Vector<String> move_dirs;
+	Vector<String> move_files;
+
+
+	Vector<String> history;
+	int history_pos;
+
+	String path;
+
+	bool initialized;
 
 
 	bool updating_tree;
 	bool updating_tree;
-	Tree * tree;
+	Tree * tree; //directories
+	ItemList *files;
+
+	bool tree_mode;
+
+	void _go_to_tree();
+	void _go_to_dir(const String& p_dir);
+	void _select_file(int p_idx);
+
 	bool _create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir);
 	bool _create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir);
+	void _thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata);
+	void _find_inside_move_files(EditorFileSystemDirectory *efsd,Vector<String>& files);
+	void _find_remaps(EditorFileSystemDirectory *efsd,Map<String,String> &renames,List<String>& to_remaps);
+
+	void _rename_operation(const String& p_to_path);
+	void _move_operation(const String& p_to_path);
+
+
+	void _file_option(int p_option);
+	void _update_files(bool p_keep_selection);
+	void _change_file_display();
 
 
+	void _fs_changed();
+	void _fw_history();
+	void _bw_history();
+	void _push_to_history();
+
+	void _fav_up_pressed();
+	void _fav_down_pressed();
+	void _dir_selected();
 	void _update_tree();
 	void _update_tree();
 	void _rescan();
 	void _rescan();
-	void _favorites_toggled(bool);
-	void _favorite_toggled();
+	void _set_scannig_mode();
+
+	void _favorites_pressed();	
 	void _instance_pressed();
 	void _instance_pressed();
 	void _open_pressed();
 	void _open_pressed();
-	void _save_favorites();
+
 
 
 protected:
 protected:
 	void _notification(int p_what);
 	void _notification(int p_what);
@@ -77,48 +149,14 @@ protected:
 public:
 public:
 
 
 	String get_selected_path() const;
 	String get_selected_path() const;
+	void open(const String& p_path);
+
+	void fix_dependencies(const String& p_for_file);
+
 
 
 	ScenesDock(EditorNode *p_editor);
 	ScenesDock(EditorNode *p_editor);
 	~ScenesDock();
 	~ScenesDock();
 };
 };
 
 
-class ScenesDockFilter : public HBoxContainer {
-
-	OBJ_TYPE( ScenesDockFilter, HBoxContainer );
-
-private:
-	friend class ScenesDock;
-
-	enum Command {
-		CMD_CLEAR_FILTER,
-	};
-
-	Tree *tree;
-	OptionButton *filter_option;
-	LineEdit *search_box;
-	ToolButton *clear_search_button;
-
-	enum FilterOption {
-		FILTER_PATH, // NAME or Folder
-		FILTER_NAME,
-		FILTER_FOLDER,
-	};
-	FilterOption _current_filter;
-	//Vector<String> filters;
-
-	void _command(int p_command);
-	void _search_text_changed(const String& p_newtext);
-	void _setup_filters();
-	void _file_filter_selected(int p_idx);
-
-protected:
-	void _notification(int p_what);
-	static void _bind_methods();
-
-public:
-	String get_search_term();
-	FilterOption get_file_filter();
-	ScenesDockFilter();
-};
 
 
 #endif // SCENES_DOCK_H
 #endif // SCENES_DOCK_H

+ 4 - 3
version.py

@@ -1,7 +1,8 @@
 short_name="godot"
 short_name="godot"
 name="Godot Engine"
 name="Godot Engine"
-major=1
-minor=1
-status="stable"
+major=2
+minor=0
+status="alpha"
+
 
 
 
 

部分文件因为文件数量过多而无法显示