Procházet zdrojové kódy

work in progress, resource previews

Juan Linietsky před 10 roky
rodič
revize
d5348eebdc

+ 7 - 3
core/image.cpp

@@ -1746,6 +1746,10 @@ Error Image::_decompress_bc() {
 	return OK;
 }
 
+bool Image::is_compressed() const {
+	return format>=FORMAT_BC1;
+}
+
 
 Image Image::decompressed() const {
 
@@ -1998,7 +2002,7 @@ void Image::blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2&
 }
 
 
-Image (*Image::_png_mem_loader_func)(const uint8_t*)=NULL;
+Image (*Image::_png_mem_loader_func)(const uint8_t*,int)=NULL;
 void (*Image::_image_compress_bc_func)(Image *)=NULL;
 void (*Image::_image_compress_pvrtc2_func)(Image *)=NULL;
 void (*Image::_image_compress_pvrtc4_func)(Image *)=NULL;
@@ -2167,7 +2171,7 @@ void Image::fix_alpha_edges() {
 
 }
 
-Image::Image(const uint8_t* p_png) {
+Image::Image(const uint8_t* p_png,int p_len) {
 
 	width=0;
 	height=0;
@@ -2175,7 +2179,7 @@ Image::Image(const uint8_t* p_png) {
 	format=FORMAT_GRAYSCALE;
 
 	if (_png_mem_loader_func) {
-		*this = _png_mem_loader_func(p_png);
+		*this = _png_mem_loader_func(p_png,p_len);
 	}
 }
 

+ 3 - 2
core/image.h

@@ -94,7 +94,7 @@ public:
 		/* INTERPOLATE GAUSS */
 	};
 
-	static Image (*_png_mem_loader_func)(const uint8_t* p_png);
+	static Image (*_png_mem_loader_func)(const uint8_t* p_png,int p_size);
 	static void (*_image_compress_bc_func)(Image *);
 	static void (*_image_compress_pvrtc2_func)(Image *);
 	static void (*_image_compress_pvrtc4_func)(Image *);
@@ -335,6 +335,7 @@ public:
 	Image compressed(int p_mode); /* from the Image::CompressMode enum */
 	Error decompress();
 	Image decompressed() const;
+	bool is_compressed() const;
 
 	void fix_alpha_edges();
 	void premultiply_alpha();
@@ -349,7 +350,7 @@ public:
 	Image get_rect(const Rect2& p_area) const;
 
 	static void set_compress_bc_func(void (*p_compress_func)(Image *));
-	Image(const uint8_t* p_mem_png);
+	Image(const uint8_t* p_mem_png, int p_len=-1);
 	Image(const char **p_xpm);
 	~Image();
 

+ 8 - 0
core/io/file_access_memory.cpp

@@ -74,6 +74,14 @@ bool FileAccessMemory::file_exists(const String& p_name) {
 }
 
 
+Error FileAccessMemory::open_custom(const uint8_t* p_data, int p_len) {
+
+	data=(uint8_t*)p_data;
+	length=p_len;
+	pos=0;
+	return OK;
+}
+
 Error FileAccessMemory::_open(const String& p_path, int p_mode_flags) {
 
 	ERR_FAIL_COND_V(!files, ERR_FILE_NOT_FOUND);

+ 1 - 0
core/io/file_access_memory.h

@@ -44,6 +44,7 @@ public:
 	static void register_file(String p_name, Vector<uint8_t> p_data);
 	static void cleanup();
 
+	virtual Error open_custom(const uint8_t* p_data, int p_len); ///< open a file
 	virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
 	virtual void close(); ///< close a file
 	virtual bool is_open() const; ///< true when file is open

+ 1 - 1
core/object.cpp

@@ -1351,7 +1351,7 @@ Error Object::connect(const StringName& p_signal, Object *p_to_object, const Str
 	if (!s) {
 		bool signal_is_valid = ObjectTypeDB::has_signal(get_type_name(),p_signal);
 		if (!signal_is_valid) {
-			ERR_EXPLAIN("Attempt to connect to nonexistent signal: "+p_signal);
+			ERR_EXPLAIN("Attempt to connect nonexistent signal '"+p_signal+"' to method '"+p_to_method+"'");
 			ERR_FAIL_COND_V(!signal_is_valid,ERR_INVALID_PARAMETER);
 		}
 		signal_map[p_signal]=Signal();

+ 18 - 4
drivers/png/image_loader_png.cpp

@@ -31,6 +31,8 @@
 #include "print_string.h"
 #include "os/os.h"
 
+
+
 void ImageLoaderPNG::_read_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length) {
 
 	FileAccess *f = (FileAccess*)png_get_io_ptr(png_ptr);
@@ -253,6 +255,7 @@ void ImageLoaderPNG::get_recognized_extensions(List<String> *p_extensions) const
 struct PNGReadStatus {
 
 	int offset;
+	int size;
 	const unsigned char *image;
 };
 
@@ -261,17 +264,26 @@ static void user_read_data(png_structp png_ptr,png_bytep data, png_size_t p_leng
 	PNGReadStatus *rstatus;
 	rstatus=(PNGReadStatus*)png_get_io_ptr(png_ptr);
 
-	memcpy(data,&rstatus->image[rstatus->offset],p_length);
-	rstatus->offset+=p_length;
+	int to_read=p_length;
+	if (rstatus->size>=0) {
+		to_read = MIN( p_length, rstatus->size - rstatus->offset);
+	}
+	memcpy(data,&rstatus->image[rstatus->offset],to_read);
+	rstatus->offset+=to_read;
+
+	if (to_read<p_length) {
+		memset(&data[to_read],0,p_length-to_read);
+	}
 }
 
 
-static Image _load_mem_png(const uint8_t* p_png) {
+static Image _load_mem_png(const uint8_t* p_png,int p_size) {
 
 
 	PNGReadStatus prs;
 	prs.image=p_png;
 	prs.offset=0;
+	prs.size=p_size;
 
 	Image img;
 	Error err = ImageLoaderPNG::_load_image(&prs,user_read_data,&img);
@@ -283,9 +295,10 @@ static Image _load_mem_png(const uint8_t* p_png) {
 
 static Image _lossless_unpack_png(const DVector<uint8_t>& p_data) {
 
+	int len = p_data.size();
 	DVector<uint8_t>::Read r = p_data.read();
 	ERR_FAIL_COND_V(r[0]!='P' || r[1]!='N' || r[2]!='G' || r[3]!=' ',Image());
-	return _load_mem_png(&r[4]);
+	return _load_mem_png(&r[4],len-4);
 
 }
 
@@ -424,6 +437,7 @@ static DVector<uint8_t> _lossless_pack_png(const Image& p_image) {
 
 ImageLoaderPNG::ImageLoaderPNG() {
 
+
 	Image::_png_mem_loader_func=_load_mem_png;
 	Image::lossless_unpacker=_lossless_unpack_png;
 	Image::lossless_packer=_lossless_pack_png;

+ 3 - 0
drivers/png/image_loader_png.h

@@ -40,7 +40,10 @@ class ImageLoaderPNG : public ImageFormatLoader {
 	static void _read_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length);
 
 
+
 public:
+
+
 	static Error _load_image(void *rf_up,png_rw_ptr p_func,Image *p_image);
 	virtual Error load_image(Image *p_image,FileAccess *f);
 	virtual void get_recognized_extensions(List<String> *p_extensions) const;	

+ 0 - 1
scene/resources/default_theme/default_theme.cpp

@@ -692,7 +692,6 @@ void make_default_theme() {
 	// FileDialog
 	
 	t->set_icon("folder","FileDialog",make_icon(icon_folder_png));
-
 	t->set_color("files_disabled","FileDialog",Color(0,0,0,0.7));
 
 

+ 874 - 0
tools/editor/editor_file_dialog.cpp

@@ -0,0 +1,874 @@
+#include "editor_file_dialog.h"
+#include "scene/gui/label.h"
+#include "scene/gui/center_container.h"
+#include "print_string.h"
+#include "os/keyboard.h"
+#include "editor_resource_preview.h"
+
+
+EditorFileDialog::GetIconFunc EditorFileDialog::get_icon_func=NULL;
+EditorFileDialog::GetIconFunc EditorFileDialog::get_large_icon_func=NULL;
+
+EditorFileDialog::RegisterFunc EditorFileDialog::register_func=NULL;
+EditorFileDialog::RegisterFunc EditorFileDialog::unregister_func=NULL;
+
+
+VBoxContainer *EditorFileDialog::get_vbox() {
+	return vbox;
+
+}
+
+void EditorFileDialog::_notification(int p_what) {
+	if (p_what==NOTIFICATION_PROCESS) {
+
+		if (preview_waiting) {
+			preview_wheel_timeout-=get_process_delta_time();
+			if (preview_wheel_timeout<=0) {
+				preview_wheel_index++;
+				if (preview_wheel_index>=8)
+					preview_wheel_index=0;
+				Ref<Texture> frame = get_icon("WaitPreview"+itos(preview_wheel_index+1),"EditorIcons");
+				preview->set_texture(frame);
+				preview_wheel_timeout=0.1;
+			}
+		}
+	}
+
+	if (p_what==NOTIFICATION_DRAW) {
+
+		//RID ci = get_canvas_item();
+		//get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
+	}
+}
+
+void EditorFileDialog::set_enable_multiple_selection(bool p_enable) {
+
+	tree->set_select_mode(p_enable?Tree::SELECT_MULTI : Tree::SELECT_SINGLE);
+};
+
+Vector<String> EditorFileDialog::get_selected_files() const {
+
+	Vector<String> list;
+
+	TreeItem* item = tree->get_root();
+	while ( (item = tree->get_next_selected(item)) ) {
+
+		list.push_back(dir_access->get_current_dir().plus_file(item->get_text(0)));
+	};
+
+	return list;
+};
+
+void EditorFileDialog::update_dir() {
+
+	dir->set_text(dir_access->get_current_dir());
+}
+
+void EditorFileDialog::_dir_entered(String p_dir) {
+
+
+	dir_access->change_dir(p_dir);
+	file->set_text("");
+	invalidate();
+	update_dir();
+}
+
+void EditorFileDialog::_file_entered(const String& p_file) {
+
+	_action_pressed();
+}
+
+void EditorFileDialog::_save_confirm_pressed() {
+	String f=dir_access->get_current_dir().plus_file(file->get_text());
+	emit_signal("file_selected",f);
+	hide();
+}
+
+void EditorFileDialog::_post_popup() {
+
+	ConfirmationDialog::_post_popup();
+	if (invalidated) {
+		update_file_list();
+		invalidated=false;
+	}
+	if (mode==MODE_SAVE_FILE)
+		file->grab_focus();
+	else
+		tree->grab_focus();
+
+	if (is_visible() && get_current_file()!="")
+		_request_single_thumbnail(get_current_dir().plus_file(get_current_file()));
+
+}
+
+void EditorFileDialog::_thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) {
+
+	set_process(false);
+	preview_waiting=false;
+
+	if (p_preview.is_valid() && get_current_path()==p_path) {
+
+		preview->set_texture(p_preview);
+		preview_vb->show();
+
+	} else {
+		preview_vb->hide();
+		preview->set_texture(Ref<Texture>());
+
+	}
+
+}
+
+void EditorFileDialog::_request_single_thumbnail(const String& p_path) {
+
+	EditorResourcePreview::get_singleton()->queue_resource_preview(p_path,this,"_thumbnail_done",p_path);
+	print_line("want file "+p_path);
+	set_process(true);
+	preview_waiting=true;
+	preview_wheel_timeout=0;
+
+}
+
+void EditorFileDialog::_action_pressed() {
+
+	if (mode==MODE_OPEN_FILES) {
+
+		TreeItem *ti=tree->get_next_selected(NULL);
+		String fbase=dir_access->get_current_dir();
+
+		DVector<String> files;
+		while(ti) {
+
+			files.push_back( fbase.plus_file(ti->get_text(0)) );
+			ti=tree->get_next_selected(ti);
+		}
+
+		if (files.size()) {
+			emit_signal("files_selected",files);
+			hide();
+		}
+
+		return;
+	}
+
+	String f=dir_access->get_current_dir().plus_file(file->get_text());
+
+	if (mode==MODE_OPEN_FILE && dir_access->file_exists(f)) {
+		emit_signal("file_selected",f);
+		hide();
+	}
+
+	if (mode==MODE_OPEN_DIR) {
+
+
+		String path=dir_access->get_current_dir();
+		/*if (tree->get_selected()) {
+			Dictionary d = tree->get_selected()->get_metadata(0);
+			if (d["dir"]) {
+				path=path+"/"+String(d["name"]);
+			}
+		}*/
+		path=path.replace("\\","/");
+		emit_signal("dir_selected",path);
+		hide();
+	}
+
+	if (mode==MODE_SAVE_FILE) {
+
+		bool valid=false;
+
+		if (filter->get_selected()==filter->get_item_count()-1) {
+			valid=true; //match none
+		} else if (filters.size()>1 && filter->get_selected()==0) {
+			// match all filters
+			for (int i=0;i<filters.size();i++) {
+
+				String flt=filters[i].get_slice(";",0);
+				for (int j=0;j<flt.get_slice_count(",");j++) {
+
+					String str = flt.get_slice(",",j).strip_edges();
+					if (f.match(str)) {
+						valid=true;
+						break;
+					}
+				}
+				if (valid)
+					break;
+			}
+		} else {
+			int idx=filter->get_selected();
+			if (filters.size()>1)
+				idx--;
+			if (idx>=0 && idx<filters.size()) {
+
+				String flt=filters[idx].get_slice(";",0);
+				int filterSliceCount=flt.get_slice_count(",");
+				for (int j=0;j<filterSliceCount;j++) {
+
+					String str = (flt.get_slice(",",j).strip_edges());
+					if (f.match(str)) {
+						valid=true;
+						break;
+					}
+				}
+
+				if (!valid && filterSliceCount>0) {
+					String str = (flt.get_slice(",",0).strip_edges());
+					f+=str.substr(1, str.length()-1);
+					_request_single_thumbnail(get_current_dir().plus_file(f.get_file()));
+					file->set_text(f.get_file());
+					valid=true;
+				}
+			} else {
+				valid=true;
+			}
+		}
+
+
+		if (!valid) {
+
+			exterr->popup_centered_minsize(Size2(250,80));
+			return;
+
+		}
+
+		if (dir_access->file_exists(f)) {
+			confirm_save->set_text("File Exists, Overwrite?");
+			confirm_save->popup_centered(Size2(200,80));
+		} else {
+
+
+			emit_signal("file_selected",f);
+			hide();
+		}
+	}
+}
+
+void EditorFileDialog::_cancel_pressed() {
+
+	file->set_text("");
+	invalidate();
+	hide();
+}
+
+void EditorFileDialog::_tree_selected() {
+
+	TreeItem *ti=tree->get_selected();
+	if (!ti)
+		return;
+	Dictionary d=ti->get_metadata(0);
+
+	if (!d["dir"]) {
+
+		file->set_text(d["name"]);
+		_request_single_thumbnail(get_current_dir().plus_file(get_current_file()));
+	}
+}
+
+void EditorFileDialog::_tree_dc_selected() {
+
+
+	TreeItem *ti=tree->get_selected();
+	if (!ti)
+		return;
+
+	Dictionary d=ti->get_metadata(0);
+
+	if (d["dir"]) {
+
+		dir_access->change_dir(d["name"]);
+		if (mode==MODE_OPEN_FILE || mode==MODE_OPEN_FILES || mode==MODE_OPEN_DIR)
+			file->set_text("");
+		call_deferred("_update_file_list");
+		call_deferred("_update_dir");
+	} else {
+
+		_action_pressed();
+	}
+}
+
+void EditorFileDialog::update_file_list() {
+
+	tree->clear();
+	dir_access->list_dir_begin();
+
+	TreeItem *root = tree->create_item();
+	Ref<Texture> folder = get_icon("folder","FileDialog");
+	List<String> files;
+	List<String> dirs;
+
+	bool isdir;
+	bool ishidden;
+	bool show_hidden = show_hidden_files;
+	String item;
+
+	while ((item=dir_access->get_next(&isdir))!="") {
+
+		ishidden = dir_access->current_is_hidden();
+
+		if (show_hidden || !ishidden) {
+			if (!isdir)
+				files.push_back(item);
+			else
+				dirs.push_back(item);
+		}
+	}
+
+	dirs.sort_custom<NoCaseComparator>();
+	files.sort_custom<NoCaseComparator>();
+
+	while(!dirs.empty()) {
+
+		if (dirs.front()->get()!=".") {
+			TreeItem *ti=tree->create_item(root);
+			ti->set_text(0,dirs.front()->get()+"/");
+			ti->set_icon(0,folder);
+			Dictionary d;
+			d["name"]=dirs.front()->get();
+			d["dir"]=true;
+			ti->set_metadata(0,d);
+		}
+		dirs.pop_front();
+
+	}
+
+	dirs.clear();
+
+	List<String> patterns;
+	// build filter
+	if (filter->get_selected()==filter->get_item_count()-1) {
+
+		// match all
+	} else if (filters.size()>1 && filter->get_selected()==0) {
+		// match all filters
+		for (int i=0;i<filters.size();i++) {
+
+			String f=filters[i].get_slice(";",0);
+			for (int j=0;j<f.get_slice_count(",");j++) {
+
+				patterns.push_back(f.get_slice(",",j).strip_edges());
+			}
+		}
+	} else {
+		int idx=filter->get_selected();
+		if (filters.size()>1)
+			idx--;
+
+		if (idx>=0 && idx<filters.size()) {
+
+			String f=filters[idx].get_slice(";",0);
+			for (int j=0;j<f.get_slice_count(",");j++) {
+
+				patterns.push_back(f.get_slice(",",j).strip_edges());
+			}
+		}
+	}
+
+
+	String base_dir = dir_access->get_current_dir();
+
+
+	while(!files.empty()) {
+
+		bool match=patterns.empty();
+
+		for(List<String>::Element *E=patterns.front();E;E=E->next()) {
+
+			if (files.front()->get().matchn(E->get())) {
+
+				match=true;
+				break;
+			}
+		}
+
+		if (match) {
+			TreeItem *ti=tree->create_item(root);
+			ti->set_text(0,files.front()->get());
+
+			if (get_icon_func) {
+
+				Ref<Texture> icon = get_icon_func(base_dir.plus_file(files.front()->get()));
+				ti->set_icon(0,icon);
+			}
+
+			if (mode==MODE_OPEN_DIR) {
+				ti->set_custom_color(0,get_color("files_disabled"));
+				ti->set_selectable(0,false);
+			}
+			Dictionary d;
+			d["name"]=files.front()->get();
+			d["dir"]=false;
+			ti->set_metadata(0,d);
+
+			if (file->get_text()==files.front()->get())
+				ti->select(0);
+		}
+
+		files.pop_front();
+	}
+
+	if (tree->get_root() && tree->get_root()->get_children())
+		tree->get_root()->get_children()->select(0);
+
+	files.clear();
+
+}
+
+void EditorFileDialog::_filter_selected(int) {
+
+	update_file_list();
+}
+
+void EditorFileDialog::update_filters() {
+
+	filter->clear();
+
+	if (filters.size()>1) {
+		String all_filters;
+
+		const int max_filters=5;
+
+		for(int i=0;i<MIN( max_filters, filters.size()) ;i++) {
+			String flt=filters[i].get_slice(";",0);
+			if (i>0)
+				all_filters+=",";
+			all_filters+=flt;
+		}
+
+		if (max_filters<filters.size())
+			all_filters+=", ...";
+
+		filter->add_item("All Recognized ( "+all_filters+" )");
+	}
+	for(int i=0;i<filters.size();i++) {
+
+		String flt=filters[i].get_slice(";",0).strip_edges();
+		String desc=filters[i].get_slice(";",1).strip_edges();
+		if (desc.length())
+			filter->add_item(desc+" ( "+flt+" )");
+		else
+			filter->add_item("( "+flt+" )");
+	}
+
+	filter->add_item("All Files (*)");
+
+}
+
+void EditorFileDialog::clear_filters() {
+
+	filters.clear();
+	update_filters();
+	invalidate();
+}
+void EditorFileDialog::add_filter(const String& p_filter) {
+
+	filters.push_back(p_filter);
+	update_filters();
+	invalidate();
+
+}
+
+String EditorFileDialog::get_current_dir() const {
+
+	return dir->get_text();
+}
+String EditorFileDialog::get_current_file() const {
+
+	return file->get_text();
+}
+String EditorFileDialog::get_current_path() const {
+
+	return dir->get_text().plus_file(file->get_text());
+}
+void EditorFileDialog::set_current_dir(const String& p_dir) {
+
+	dir_access->change_dir(p_dir);
+	update_dir();
+	invalidate();
+
+}
+void EditorFileDialog::set_current_file(const String& p_file) {
+
+	file->set_text(p_file);
+	update_dir();
+	invalidate();
+	int lp = p_file.find_last(".");
+	if (lp!=-1) {
+		file->select(0,lp);
+		file->grab_focus();
+	}
+
+	if (is_visible())
+		_request_single_thumbnail(get_current_dir().plus_file(get_current_file()));
+
+
+}
+void EditorFileDialog::set_current_path(const String& p_path) {
+
+	if (!p_path.size())
+		return;
+	int pos=MAX( p_path.find_last("/"), p_path.find_last("\\") );
+	if (pos==-1) {
+
+		set_current_file(p_path);
+	} else {
+
+		String dir=p_path.substr(0,pos);
+		String file=p_path.substr(pos+1,p_path.length());
+		set_current_dir(dir);
+		set_current_file(file);
+	}
+}
+
+
+void EditorFileDialog::set_mode(Mode p_mode) {
+
+	mode=p_mode;
+	switch(mode) {
+
+		case MODE_OPEN_FILE: get_ok()->set_text("Open"); set_title("Open a File"); makedir->hide(); break;
+		case MODE_OPEN_FILES: get_ok()->set_text("Open"); set_title("Open File(s)"); makedir->hide(); break;
+		case MODE_SAVE_FILE: get_ok()->set_text("Save"); set_title("Save a File"); makedir->show(); break;
+		case MODE_OPEN_DIR: get_ok()->set_text("Open"); set_title("Open a Directory"); makedir->show(); break;
+	}
+
+	if (mode==MODE_OPEN_FILES) {
+		tree->set_select_mode(Tree::SELECT_MULTI);
+	} else {
+		tree->set_select_mode(Tree::SELECT_SINGLE);
+
+	}
+}
+
+EditorFileDialog::Mode EditorFileDialog::get_mode() const {
+
+	return mode;
+}
+
+void EditorFileDialog::set_access(Access p_access) {
+
+	ERR_FAIL_INDEX(p_access,3);
+	if (access==p_access)
+		return;
+	memdelete( dir_access );
+	switch(p_access) {
+		case ACCESS_FILESYSTEM: {
+
+			dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+		} break;
+		case ACCESS_RESOURCES: {
+
+			dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+		} break;
+		case ACCESS_USERDATA: {
+
+			dir_access = DirAccess::create(DirAccess::ACCESS_USERDATA);
+		} break;
+	}
+	access=p_access;
+	_update_drives();
+	invalidate();
+	update_filters();
+	update_dir();
+}
+
+void EditorFileDialog::invalidate() {
+
+	if (is_visible()) {
+		update_file_list();
+		invalidated=false;
+	} else {
+		invalidated=true;
+	}
+
+}
+
+EditorFileDialog::Access EditorFileDialog::get_access() const{
+
+	return access;
+}
+
+void EditorFileDialog::_make_dir_confirm() {
+
+
+	Error err = dir_access->make_dir( makedirname->get_text() );
+	if (err==OK) {
+		dir_access->change_dir(makedirname->get_text());
+		invalidate();
+		update_filters();
+		update_dir();
+	} else {
+		mkdirerr->popup_centered_minsize(Size2(250,50));
+	}
+}
+
+
+void EditorFileDialog::_make_dir() {
+
+	makedialog->popup_centered_minsize(Size2(250,80));
+	makedirname->grab_focus();
+
+}
+
+void EditorFileDialog::_select_drive(int p_idx) {
+
+	String d = drives->get_item_text(p_idx);
+	dir_access->change_dir(d);
+	file->set_text("");
+	invalidate();
+	update_dir();
+
+}
+
+void EditorFileDialog::_update_drives() {
+
+
+	int dc = dir_access->get_drive_count();
+	if (dc==0 || access!=ACCESS_FILESYSTEM) {
+		drives->hide();
+	} else {
+		drives->clear();
+		drives->show();
+
+		for(int i=0;i<dir_access->get_drive_count();i++) {
+			String d = dir_access->get_drive(i);
+			drives->add_item(dir_access->get_drive(i));
+		}
+
+		drives->select(dir_access->get_current_drive());
+
+	}
+}
+
+bool EditorFileDialog::default_show_hidden_files=true;
+
+
+void EditorFileDialog::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("_tree_selected"),&EditorFileDialog::_tree_selected);
+	ObjectTypeDB::bind_method(_MD("_tree_db_selected"),&EditorFileDialog::_tree_dc_selected);
+	ObjectTypeDB::bind_method(_MD("_dir_entered"),&EditorFileDialog::_dir_entered);
+	ObjectTypeDB::bind_method(_MD("_file_entered"),&EditorFileDialog::_file_entered);
+	ObjectTypeDB::bind_method(_MD("_action_pressed"),&EditorFileDialog::_action_pressed);
+	ObjectTypeDB::bind_method(_MD("_cancel_pressed"),&EditorFileDialog::_cancel_pressed);
+	ObjectTypeDB::bind_method(_MD("_filter_selected"),&EditorFileDialog::_filter_selected);
+	ObjectTypeDB::bind_method(_MD("_save_confirm_pressed"),&EditorFileDialog::_save_confirm_pressed);
+
+	ObjectTypeDB::bind_method(_MD("clear_filters"),&EditorFileDialog::clear_filters);
+	ObjectTypeDB::bind_method(_MD("add_filter","filter"),&EditorFileDialog::add_filter);
+	ObjectTypeDB::bind_method(_MD("get_current_dir"),&EditorFileDialog::get_current_dir);
+	ObjectTypeDB::bind_method(_MD("get_current_file"),&EditorFileDialog::get_current_file);
+	ObjectTypeDB::bind_method(_MD("get_current_path"),&EditorFileDialog::get_current_path);
+	ObjectTypeDB::bind_method(_MD("set_current_dir","dir"),&EditorFileDialog::set_current_dir);
+	ObjectTypeDB::bind_method(_MD("set_current_file","file"),&EditorFileDialog::set_current_file);
+	ObjectTypeDB::bind_method(_MD("set_current_path","path"),&EditorFileDialog::set_current_path);
+	ObjectTypeDB::bind_method(_MD("set_mode","mode"),&EditorFileDialog::set_mode);
+	ObjectTypeDB::bind_method(_MD("get_mode"),&EditorFileDialog::get_mode);
+	ObjectTypeDB::bind_method(_MD("get_vbox:VBoxContainer"),&EditorFileDialog::get_vbox);
+	ObjectTypeDB::bind_method(_MD("set_access","access"),&EditorFileDialog::set_access);
+	ObjectTypeDB::bind_method(_MD("get_access"),&EditorFileDialog::get_access);
+	ObjectTypeDB::bind_method(_MD("set_show_hidden_files"),&EditorFileDialog::set_show_hidden_files);
+	ObjectTypeDB::bind_method(_MD("is_showing_hidden_files"),&EditorFileDialog::is_showing_hidden_files);
+	ObjectTypeDB::bind_method(_MD("_select_drive"),&EditorFileDialog::_select_drive);
+	ObjectTypeDB::bind_method(_MD("_make_dir"),&EditorFileDialog::_make_dir);
+	ObjectTypeDB::bind_method(_MD("_make_dir_confirm"),&EditorFileDialog::_make_dir_confirm);
+	ObjectTypeDB::bind_method(_MD("_update_file_list"),&EditorFileDialog::update_file_list);
+	ObjectTypeDB::bind_method(_MD("_update_dir"),&EditorFileDialog::update_dir);
+	ObjectTypeDB::bind_method(_MD("_thumbnail_done"),&EditorFileDialog::_thumbnail_done);
+
+	ObjectTypeDB::bind_method(_MD("invalidate"),&EditorFileDialog::invalidate);
+
+	ADD_SIGNAL(MethodInfo("file_selected",PropertyInfo( Variant::STRING,"path")));
+	ADD_SIGNAL(MethodInfo("files_selected",PropertyInfo( Variant::STRING_ARRAY,"paths")));
+	ADD_SIGNAL(MethodInfo("dir_selected",PropertyInfo( Variant::STRING,"dir")));
+
+	BIND_CONSTANT( MODE_OPEN_FILE );
+	BIND_CONSTANT( MODE_OPEN_FILES );
+	BIND_CONSTANT( MODE_OPEN_DIR );
+	BIND_CONSTANT( MODE_SAVE_FILE );
+
+	BIND_CONSTANT( ACCESS_RESOURCES );
+	BIND_CONSTANT( ACCESS_USERDATA );
+	BIND_CONSTANT( ACCESS_FILESYSTEM );
+
+}
+
+
+void EditorFileDialog::set_show_hidden_files(bool p_show) {
+	show_hidden_files=p_show;
+	invalidate();
+}
+
+bool EditorFileDialog::is_showing_hidden_files() const {
+	return show_hidden_files;
+}
+
+void EditorFileDialog::set_default_show_hidden_files(bool p_show) {
+	default_show_hidden_files=p_show;
+}
+
+EditorFileDialog::EditorFileDialog() {
+
+	show_hidden_files=true;
+
+	VBoxContainer *vbc = memnew( VBoxContainer );
+	add_child(vbc);
+	set_child_rect(vbc);
+
+	mode=MODE_SAVE_FILE;
+	set_title("Save a File");
+
+	dir = memnew(LineEdit);
+	HBoxContainer *pathhb = memnew( HBoxContainer );
+	pathhb->add_child(dir);
+	dir->set_h_size_flags(SIZE_EXPAND_FILL);
+
+	drives = memnew( OptionButton );
+	pathhb->add_child(drives);
+	drives->connect("item_selected",this,"_select_drive");
+
+	makedir = memnew( Button );
+	makedir->set_text("Create Folder");
+	makedir->connect("pressed",this,"_make_dir");
+	pathhb->add_child(makedir);
+
+	vbc->add_margin_child("Path:",pathhb);
+
+	list_hb = memnew( HBoxContainer );
+	vbc->add_margin_child("Directories & Files:",list_hb,true);
+
+	tree = memnew(Tree);
+	tree->set_hide_root(true);
+	tree->set_h_size_flags(SIZE_EXPAND_FILL);
+	list_hb->add_child(tree);
+
+	HBoxContainer* filter_hb = memnew( HBoxContainer );
+	vbc->add_child(filter_hb);
+
+	VBoxContainer *filter_vb = memnew( VBoxContainer );
+	filter_hb->add_child(filter_vb);
+	filter_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+
+	preview_vb = memnew( VBoxContainer );
+	filter_hb->add_child(preview_vb);
+	CenterContainer *prev_cc = memnew( CenterContainer );
+	preview_vb->add_margin_child("Preview:",prev_cc);
+	preview = memnew( TextureFrame );
+	prev_cc->add_child(preview);
+	preview_vb->hide();
+
+
+	file = memnew(LineEdit);
+	//add_child(file);
+	filter_vb->add_margin_child("File:",file);
+
+
+	filter = memnew( OptionButton );
+	//add_child(filter);
+	filter_vb->add_margin_child("Filter:",filter);
+	filter->set_clip_text(true);//too many extensions overflow it
+
+	dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+	access=ACCESS_RESOURCES;
+	_update_drives();
+
+
+	connect("confirmed", this,"_action_pressed");
+	//cancel->connect("pressed", this,"_cancel_pressed");
+	tree->connect("cell_selected", this,"_tree_selected",varray(),CONNECT_DEFERRED);
+	tree->connect("item_activated", this,"_tree_db_selected",varray());
+	dir->connect("text_entered", this,"_dir_entered");
+	file->connect("text_entered", this,"_file_entered");
+	filter->connect("item_selected", this,"_filter_selected");
+
+
+	confirm_save = memnew( ConfirmationDialog );
+	confirm_save->set_as_toplevel(true);
+	add_child(confirm_save);
+
+
+	confirm_save->connect("confirmed", this,"_save_confirm_pressed");
+
+	makedialog = memnew( ConfirmationDialog );
+	makedialog->set_title("Create Folder");
+	VBoxContainer *makevb= memnew( VBoxContainer );
+	makedialog->add_child(makevb);
+	makedialog->set_child_rect(makevb);
+	makedirname = memnew( LineEdit );
+	makevb->add_margin_child("Name:",makedirname);
+	add_child(makedialog);
+	makedialog->register_text_enter(makedirname);
+	makedialog->connect("confirmed",this,"_make_dir_confirm");
+	mkdirerr = memnew( AcceptDialog );
+	mkdirerr->set_text("Could not create folder.");
+	add_child(mkdirerr);
+
+	exterr = memnew( AcceptDialog );
+	exterr->set_text("Must use a valid extension.");
+	add_child(exterr);
+
+
+	//update_file_list();
+	update_filters();
+	update_dir();
+
+	set_hide_on_ok(false);
+	vbox=vbc;
+
+
+	invalidated=true;
+	if (register_func)
+		register_func(this);
+
+	preview_wheel_timeout=0;
+	preview_wheel_index=0;
+	preview_waiting=false;
+
+}
+
+
+EditorFileDialog::~EditorFileDialog() {
+
+	if (unregister_func)
+		unregister_func(this);
+	memdelete(dir_access);
+}
+
+
+void EditorLineEditFileChooser::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("_browse"),&EditorLineEditFileChooser::_browse);
+	ObjectTypeDB::bind_method(_MD("_chosen"),&EditorLineEditFileChooser::_chosen);
+	ObjectTypeDB::bind_method(_MD("get_button:Button"),&EditorLineEditFileChooser::get_button);
+	ObjectTypeDB::bind_method(_MD("get_line_edit:LineEdit"),&EditorLineEditFileChooser::get_line_edit);
+	ObjectTypeDB::bind_method(_MD("get_file_dialog:EditorFileDialog"),&EditorLineEditFileChooser::get_file_dialog);
+
+}
+
+void EditorLineEditFileChooser::_chosen(const String& p_text){
+
+	line_edit->set_text(p_text);
+	line_edit->emit_signal("text_entered",p_text);
+}
+
+void EditorLineEditFileChooser::_browse() {
+
+	dialog->popup_centered_ratio();
+}
+
+EditorLineEditFileChooser::EditorLineEditFileChooser() {
+
+	line_edit = memnew( LineEdit );
+	add_child(line_edit);
+	line_edit->set_h_size_flags(SIZE_EXPAND_FILL);
+	button = memnew( Button );
+	button->set_text(" .. ");
+	add_child(button);
+	button->connect("pressed",this,"_browse");
+	dialog = memnew( EditorFileDialog);
+	add_child(dialog);
+	dialog->connect("file_selected",this,"_chosen");
+	dialog->connect("dir_selected",this,"_chosen");
+	dialog->connect("files_selected",this,"_chosen");
+
+}

+ 198 - 0
tools/editor/editor_file_dialog.h

@@ -0,0 +1,198 @@
+/*************************************************************************/
+/*  file_dialog.h                                                        */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                    http://www.godotengine.org                         */
+/*************************************************************************/
+/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur.                 */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+
+#ifndef EDITORFILEDIALOG_H
+#define EDITORFILEDIALOG_H
+
+#include "scene/gui/dialogs.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/dialogs.h"
+#include "os/dir_access.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/texture_frame.h"
+
+/**
+	@author Juan Linietsky <[email protected]>
+*/
+class EditorFileDialog : public ConfirmationDialog {
+
+	OBJ_TYPE( EditorFileDialog, ConfirmationDialog );
+
+public:
+
+	enum Access {
+		ACCESS_RESOURCES,
+		ACCESS_USERDATA,
+		ACCESS_FILESYSTEM
+	};
+
+
+	enum Mode {
+		MODE_OPEN_FILE,
+		MODE_OPEN_FILES,
+		MODE_OPEN_DIR,
+		MODE_SAVE_FILE,
+	};
+
+	typedef Ref<Texture> (*GetIconFunc)(const String&);
+	typedef void (*RegisterFunc)(EditorFileDialog*);
+
+	static GetIconFunc get_icon_func;
+	static GetIconFunc get_large_icon_func;
+	static RegisterFunc register_func;
+	static RegisterFunc unregister_func;
+
+private:
+
+	ConfirmationDialog *makedialog;
+	LineEdit *makedirname;
+
+	Button *makedir;
+	Access access;
+	//Button *action;
+	VBoxContainer *vbox;
+	Mode mode;
+	LineEdit *dir;
+	OptionButton *drives;
+	Tree *tree;
+	TextureFrame *preview;
+	VBoxContainer *preview_vb;
+	HBoxContainer *list_hb;
+	LineEdit *file;
+	AcceptDialog *mkdirerr;
+	AcceptDialog *exterr;
+	OptionButton *filter;
+	DirAccess *dir_access;
+	ConfirmationDialog *confirm_save;
+
+	Vector<String> filters;
+
+	bool preview_waiting;
+	int preview_wheel_index;
+	float preview_wheel_timeout;
+	static bool default_show_hidden_files;
+	bool show_hidden_files;
+
+	bool invalidated;
+
+	void update_dir();
+	void update_file_list();
+	void update_filters();
+
+	void _tree_selected();
+
+	void _select_drive(int p_idx);
+	void _tree_dc_selected();
+	void _dir_entered(String p_dir);
+	void _file_entered(const String& p_file);
+	void _action_pressed();
+	void _save_confirm_pressed();
+	void _cancel_pressed();
+	void _filter_selected(int);
+	void _make_dir();
+	void _make_dir_confirm();
+
+	void _update_drives();
+
+	virtual void _post_popup();
+
+
+	//callback funtion is callback(String p_path,Ref<Texture> preview,Variant udata) preview null if could not load
+
+	void _thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata);
+	void _request_single_thumbnail(const String& p_path);
+
+protected:
+
+	void _notification(int p_what);
+	static void _bind_methods();
+	//bind helpers
+public:
+
+	void clear_filters();
+	void add_filter(const String& p_filter);
+
+	void set_enable_multiple_selection(bool p_enable);
+	Vector<String> get_selected_files() const;
+
+	String get_current_dir() const;
+	String get_current_file() const;
+	String get_current_path() const;
+	void set_current_dir(const String& p_dir);
+	void set_current_file(const String& p_file);
+	void set_current_path(const String& p_path);
+
+	void set_mode(Mode p_mode);
+	Mode get_mode() const;
+
+	VBoxContainer *get_vbox();
+	LineEdit *get_line_edit() { return file; }
+
+	void set_access(Access p_access);
+	Access get_access() const;
+
+	void set_show_hidden_files(bool p_show);
+	bool is_showing_hidden_files() const;
+
+	static void set_default_show_hidden_files(bool p_show);
+
+	void invalidate();
+
+	EditorFileDialog();
+	~EditorFileDialog();
+
+};
+
+class EditorLineEditFileChooser : public HBoxContainer {
+
+	OBJ_TYPE( EditorLineEditFileChooser, HBoxContainer );
+	Button *button;
+	LineEdit *line_edit;
+	EditorFileDialog *dialog;
+
+	void _chosen(const String& p_text);
+	void _browse();
+protected:
+	static void _bind_methods();
+public:
+
+	Button *get_button() { return button; }
+	LineEdit *get_line_edit() { return line_edit; }
+	EditorFileDialog *get_file_dialog() { return dialog; }
+
+	EditorLineEditFileChooser();
+};
+
+VARIANT_ENUM_CAST( EditorFileDialog::Mode );
+VARIANT_ENUM_CAST( EditorFileDialog::Access );
+
+#endif // EDITORFILEDIALOG_H

+ 142 - 11
tools/editor/editor_node.cpp

@@ -99,6 +99,7 @@
 #include "tools/editor/io_plugins/editor_translation_import_plugin.h"
 #include "tools/editor/io_plugins/editor_mesh_import_plugin.h"
 
+#include "plugins/editor_preview_plugins.h"
 
 
 EditorNode *EditorNode::singleton=NULL;
@@ -320,6 +321,11 @@ void EditorNode::_fs_changed() {
 
 		E->get()->invalidate();
 	}
+
+	for(Set<EditorFileDialog*>::Element *E=editor_file_dialogs.front();E;E=E->next()) {
+
+		E->get()->invalidate();
+	}
 }
 
 void EditorNode::_sources_changed(bool p_exist) {
@@ -386,7 +392,7 @@ void EditorNode::edit_node(Node *p_node) {
 void EditorNode::open_resource(const String& p_type) {
 
 
-	file->set_mode(FileDialog::MODE_OPEN_FILE);
+	file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
 
 	List<String> extensions;
 	ResourceLoader::get_recognized_extensions_for_type(p_type,&extensions);
@@ -718,6 +724,96 @@ void EditorNode::_save_edited_subresources(Node* scene,Map<RES,bool>& processed,
 
 }
 
+void EditorNode::_find_node_types(Node* p_node, int&count_2d, int&count_3d) {
+
+	if (p_node->is_type("Viewport") || (p_node!=get_edited_scene() && p_node->get_owner()!=get_edited_scene()))
+		return;
+
+	if (p_node->is_type("CanvasItem"))
+		count_2d++;
+	else if (p_node->is_type("Spatial"))
+		count_3d++;
+
+	for(int i=0;i<p_node->get_child_count();i++)
+		_find_node_types(p_node->get_child(i),count_2d,count_3d);
+
+}
+
+
+void EditorNode::_save_scene_with_preview(String p_file) {
+
+	int c2d=0;
+	int c3d=0;
+
+	EditorProgress save("save","Saving Scene",4);
+	save.step("Analyzing",0);
+	_find_node_types(get_edited_scene(),c2d,c3d);
+
+	RID viewport;
+	bool is2d;
+	if (c3d<c2d) {
+		viewport=scene_root->get_viewport();
+		is2d=true;
+	} else {
+		viewport=SpatialEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_viewport();
+		is2d=false;
+
+	}
+	save.step("Creating Thumbnail",1);
+	//current view?
+	int screen =-1;
+	for(int i=0;i<editor_table.size();i++) {
+		if (editor_plugin_screen==editor_table[i]) {
+			screen=i;
+			break;
+		}
+	}
+
+	_editor_select(is2d?0:1);
+
+	VS::get_singleton()->viewport_queue_screen_capture(viewport);
+	save.step("Creating Thumbnail",2);
+	save.step("Creating Thumbnail",3);
+	Image img = VS::get_singleton()->viewport_get_screen_capture(viewport);
+	int preview_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");;
+	int width,height;
+	if (img.get_width() > preview_size && img.get_width() >= img.get_height()) {
+
+		width=preview_size;
+		height = img.get_height() * preview_size / img.get_width();
+	} else if (img.get_height() > preview_size &&  img.get_height() >= img.get_width()) {
+
+		height=preview_size;
+		width = img.get_width() * preview_size / img.get_height();
+	}  else {
+
+		width=img.get_width();
+		height=img.get_height();
+	}
+
+	img.convert(Image::FORMAT_RGB);
+	img.resize(width,height);
+
+	String pfile = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/last_scene_preview.png");
+	img.save_png(pfile);
+	Vector<uint8_t> imgdata = FileAccess::get_file_as_array(pfile);
+
+	print_line("img data is "+itos(imgdata.size()));
+
+	if (scene_import_metadata.is_null())
+		scene_import_metadata = Ref<ResourceImportMetadata>( memnew( ResourceImportMetadata ) );
+	scene_import_metadata->set_option("thumbnail",imgdata);
+
+	//tamanio tel thumbnail
+	if (screen!=-1) {
+		_editor_select(screen);
+	}
+	save.step("Saving Scene",4);
+	_save_scene(p_file);
+
+}
+
+
 void EditorNode::_save_scene(String p_file) {
 
 	Node *scene = edited_scene;
@@ -1016,7 +1112,9 @@ void EditorNode::_dialog_action(String p_file) {
 
 			if (file->get_mode()==FileDialog::MODE_SAVE_FILE) {
 
-				_save_scene(p_file);
+				//_save_scene(p_file);
+				_save_scene_with_preview(p_file);
+
 			}
 
 		} break;
@@ -1024,7 +1122,8 @@ void EditorNode::_dialog_action(String p_file) {
 		case FILE_SAVE_AND_RUN: {
 			if (file->get_mode()==FileDialog::MODE_SAVE_FILE) {
 
-				_save_scene(p_file);
+				//_save_scene(p_file);
+				_save_scene_with_preview(p_file);
 				_run(false);
 			}
 		} break;
@@ -1177,7 +1276,8 @@ void EditorNode::_dialog_action(String p_file) {
 			
 			if (file->get_mode()==FileDialog::MODE_SAVE_FILE) {
 
-				_save_scene(p_file);
+				//_save_scene(p_file);
+				_save_scene_with_preview(p_file);
 			}
 			
 		} break;
@@ -1505,7 +1605,8 @@ void EditorNode::_run(bool p_current,const String& p_custom) {
 					return;
 				}
 
-				_save_scene(scene->get_filename());
+				//_save_scene(scene->get_filename());
+				_save_scene_with_preview(scene->get_filename());
 			}
 		}
 
@@ -1608,7 +1709,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 			
 			
 			//print_tree();
-			file->set_mode(FileDialog::MODE_OPEN_FILE);
+			file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
 			//not for now?
 			List<String> extensions;
 			ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
@@ -1659,7 +1760,8 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 			Node *scene = edited_scene;
 			if (scene && scene->get_filename()!="") {
 
-				_save_scene(scene->get_filename());
+				//_save_scene(scene->get_filename());
+				_save_scene_with_preview(scene->get_filename());
 				return;
 			};
 			// fallthrough to save_as
@@ -1678,7 +1780,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 				break;				
 			}
 			
-			file->set_mode(FileDialog::MODE_SAVE_FILE);
+			file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
 			bool relpaths = (scene->has_meta("__editor_relpaths__") && scene->get_meta("__editor_relpaths__").operator bool());
 
 
@@ -1761,7 +1863,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 
 			bool relpaths = (scene->has_meta("__editor_relpaths__") && scene->get_meta("__editor_relpaths__").operator bool());
 
-			file->set_mode(FileDialog::MODE_SAVE_FILE);
+			file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
 
 			file->set_current_path(cpath);
 			file->set_title("Save Translatable Strings");
@@ -1810,7 +1912,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 				break;
 			}
 
-			file->set_mode(FileDialog::MODE_SAVE_FILE);
+			file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
 
 			List<String> extensions;
 			Ref<PackedScene> sd = memnew( PackedScene );
@@ -3132,6 +3234,7 @@ void EditorNode::register_editor_types() {
 	ObjectTypeDB::register_type<EditorImportPlugin>();
 	ObjectTypeDB::register_type<EditorScenePostImport>();
 	ObjectTypeDB::register_type<EditorScript>();
+	ObjectTypeDB::register_type<EditorFileDialog>();
 
 
 	//ObjectTypeDB::register_type<EditorImporter>();
@@ -3282,6 +3385,16 @@ void EditorNode::_file_dialog_unregister(FileDialog *p_dialog){
 	singleton->file_dialogs.erase(p_dialog);
 }
 
+void EditorNode::_editor_file_dialog_register(EditorFileDialog *p_dialog) {
+
+	singleton->editor_file_dialogs.insert(p_dialog);
+}
+
+void EditorNode::_editor_file_dialog_unregister(EditorFileDialog *p_dialog){
+
+	singleton->editor_file_dialogs.erase(p_dialog);
+}
+
 Vector<EditorNodeInitCallback> EditorNode::_init_callbacks;
 
 Error EditorNode::export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after) {
@@ -3334,6 +3447,11 @@ EditorNode::EditorNode() {
 	FileDialog::register_func=_file_dialog_register;
 	FileDialog::unregister_func=_file_dialog_unregister;
 
+	EditorFileDialog::get_icon_func=_file_dialog_get_icon;
+	EditorFileDialog::register_func=_editor_file_dialog_register;
+	EditorFileDialog::unregister_func=_editor_file_dialog_unregister;
+
+
 	editor_import_export = memnew( EditorImportExport );
 	add_child(editor_import_export);
 
@@ -3358,6 +3476,9 @@ EditorNode::EditorNode() {
 	editor_register_icons(theme);
 	editor_register_fonts(theme);
 
+	//theme->set_icon("folder","EditorFileDialog",Theme::get_default()->get_icon("folder","EditorFileDialog"));
+	//theme->set_color("files_disabled","EditorFileDialog",Color(0,0,0,0.7));
+
 	String global_font = EditorSettings::get_singleton()->get("global/font");
 	if (global_font!="") {
 		Ref<Font> fnt = ResourceLoader::load(global_font);
@@ -3376,6 +3497,8 @@ EditorNode::EditorNode() {
 	theme->set_stylebox("EditorFocus","EditorStyles",focus_sbt);
 
 
+	resource_preview = memnew( EditorResourcePreview );
+	add_child(resource_preview);
 	progress_dialog = memnew( ProgressDialog );
 	gui_base->add_child(progress_dialog);
 
@@ -3473,6 +3596,7 @@ EditorNode::EditorNode() {
 	animation_panel=pc;
 	animation_panel->hide();
 
+
 	HBoxContainer *animation_hb = memnew( HBoxContainer);
 	animation_vb->add_child(animation_hb);
 
@@ -4031,7 +4155,7 @@ EditorNode::EditorNode() {
 	file_templates->add_filter("*.tpz ; Template Package");
 
 
-	file = memnew( FileDialog );
+	file = memnew( EditorFileDialog );
 	gui_base->add_child(file);
 	file->set_current_dir("res://");
 
@@ -4161,6 +4285,13 @@ EditorNode::EditorNode() {
 	for(int i=0;i<EditorPlugins::get_plugin_count();i++)
 		add_editor_plugin( EditorPlugins::create(i,this) );
 
+
+	resource_preview->add_preview_generator( Ref<EditorTexturePreviewPlugin>( memnew(EditorTexturePreviewPlugin )));
+	resource_preview->add_preview_generator( Ref<EditorPackedScenePreviewPlugin>( memnew(EditorPackedScenePreviewPlugin )));
+	resource_preview->add_preview_generator( Ref<EditorMaterialPreviewPlugin>( memnew(EditorMaterialPreviewPlugin )));
+	resource_preview->add_preview_generator( Ref<EditorScriptPreviewPlugin>( memnew(EditorScriptPreviewPlugin )));
+	resource_preview->add_preview_generator( Ref<EditorSamplePreviewPlugin>( memnew(EditorSamplePreviewPlugin )));
+
 	circle_step_msec=OS::get_singleton()->get_ticks_msec();
 	circle_step_frame=OS::get_singleton()->get_frames_drawn();;
 	circle_step=0;

+ 10 - 2
tools/editor/editor_node.h

@@ -78,7 +78,7 @@
 #include "tools/editor/editor_plugin.h"
 
 #include "fileserver/editor_file_server.h"
-
+#include "editor_resource_preview.h"
 
 
 
@@ -238,7 +238,7 @@ class EditorNode : public Node {
 	EditorSettingsDialog *settings_config_dialog;
 	RunSettingsDialog *run_settings_dialog;
 	ProjectSettings *project_settings;
-	FileDialog *file;
+	EditorFileDialog *file;
 	FileDialog *file_templates;
 	FileDialog *file_export;
 	FileDialog *file_export_lib;
@@ -304,6 +304,7 @@ class EditorNode : public Node {
 	EditorSelection *editor_selection;
 	ProjectExport *project_export;
 	ProjectExportDialog *project_export_settings;
+	EditorResourcePreview *resource_preview;
 
 	EditorFileServer *file_server;
 
@@ -381,11 +382,15 @@ class EditorNode : public Node {
 	String import_reload_fn;
 
 	Set<FileDialog*> file_dialogs;
+	Set<EditorFileDialog*> editor_file_dialogs;
+
 	Map<String,Ref<Texture> > icon_type_cache;
 
 	static Ref<Texture> _file_dialog_get_icon(const String& p_path);
 	static void _file_dialog_register(FileDialog *p_dialog);
 	static void _file_dialog_unregister(FileDialog *p_dialog);
+	static void _editor_file_dialog_register(EditorFileDialog *p_dialog);
+	static void _editor_file_dialog_unregister(EditorFileDialog *p_dialog);
 
 
 	void _cleanup_scene();
@@ -394,6 +399,9 @@ class EditorNode : public Node {
 	bool _find_and_save_edited_subresources(Object *obj,Map<RES,bool>& processed,int32_t flags);
 	void _save_edited_subresources(Node* scene,Map<RES,bool>& processed,int32_t flags);
 
+	void _find_node_types(Node* p_node, int&count_2d, int&count_3d);
+	void _save_scene_with_preview(String p_file);
+
 
 	struct ExportDefer {
 		String platform;

+ 260 - 0
tools/editor/editor_resource_preview.cpp

@@ -0,0 +1,260 @@
+#include "editor_resource_preview.h"
+#include "editor_settings.h"
+#include "os/file_access.h"
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+#include "globals.h"
+
+
+Ref<Texture> EditorResourcePreviewGenerator::generate_from_path(const String& p_path) {
+
+	RES res = ResourceLoader::load(p_path);
+	if (!res.is_valid())
+		return res;
+	return generate(res);
+}
+
+EditorResourcePreviewGenerator::EditorResourcePreviewGenerator() {
+
+
+}
+
+
+EditorResourcePreview* EditorResourcePreview::singleton=NULL;
+
+
+void EditorResourcePreview::_thread_func(void *ud) {
+
+	EditorResourcePreview *erp=(EditorResourcePreview*)ud;
+	erp->_thread();
+
+}
+
+
+void EditorResourcePreview::_preview_ready(const String& p_str,const Ref<Texture>& p_texture,ObjectID id,const StringName& p_func,const Variant& p_ud) {
+
+	print_line("preview is ready");
+	preview_mutex->lock();
+
+	Item item;
+	item.order=order++;
+	item.preview=p_texture;
+	cache[p_str]=item;
+
+	Object *recv = ObjectDB::get_instance(id);
+	if (recv) {
+		recv->call_deferred(p_func,p_str,p_texture,p_ud);
+	}
+
+	preview_mutex->unlock();
+}
+
+Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem& p_item,const String& cache_base) {
+
+	String type = ResourceLoader::get_resource_type(p_item.path);
+	print_line("resource type is: "+type);
+
+	if (type=="")
+		return Ref<Texture>(); //could not guess type
+
+	Ref<Texture> generated;
+
+	for(int i=0;i<preview_generators.size();i++) {
+		if (!preview_generators[i]->handles(type))
+			continue;
+		generated = preview_generators[i]->generate_from_path(p_item.path);
+
+		break;
+	}
+
+	if (generated.is_valid()) {
+		print_line("was generated");
+		int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
+		//wow it generated a preview... save cache
+		ResourceSaver::save(cache_base+".png",generated);
+		FileAccess *f=FileAccess::open(cache_base+".txt",FileAccess::WRITE);
+		f->store_line(itos(thumbnail_size));
+		f->store_line(itos(FileAccess::get_modified_time(p_item.path)));
+		f->store_line(FileAccess::get_md5(p_item.path));
+		memdelete(f);
+	} else {
+		print_line("was not generated");
+
+	}
+
+	return generated;
+}
+
+void EditorResourcePreview::_thread() {
+
+	print_line("begin thread");
+	while(!exit) {
+
+		print_line("wait for semaphore");
+		preview_sem->wait();
+		preview_mutex->lock();
+
+		print_line("blue team go");
+
+		if (queue.size()) {
+
+			print_line("pop from queue");
+
+			QueueItem item = queue.front()->get();
+			queue.pop_front();
+			preview_mutex->unlock();
+
+			Ref<Texture> texture;
+
+
+			uint64_t modtime = FileAccess::get_modified_time(item.path);
+			int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
+
+			if (cache.has(item.path)) {
+				//already has it because someone loaded it, just let it know it's ready
+				call_deferred("_preview_ready",item.path,cache[item.path].preview,item.id,item.function,item.userdata);
+
+			} else {
+
+
+				String temp_path=EditorSettings::get_singleton()->get_settings_path().plus_file("tmp");
+				String cache_base = Globals::get_singleton()->globalize_path(item.path).md5_text();
+				cache_base = temp_path.plus_file("resthumb-"+cache_base);
+
+				//does not have it, try to load a cached thumbnail
+
+				String file = cache_base+".txt";
+				print_line("cachetxt at "+file);
+				FileAccess *f=FileAccess::open(file,FileAccess::READ);
+				if (!f) {
+
+					print_line("generate because not cached");
+
+					//generate
+					texture=_generate_preview(item,cache_base);
+				} else {
+
+					int tsize = f->get_line().to_int64();
+					uint64_t last_modtime = f->get_line().to_int64();
+
+					bool cache_valid = true;
+
+					if (tsize!=thumbnail_size) {
+						cache_valid=false;
+						memdelete(f);
+					} else if (last_modtime!=modtime) {
+
+						String last_md5 = f->get_line();
+						String md5 = FileAccess::get_md5(item.path);
+						memdelete(f);
+
+						if (last_md5!=md5) {
+
+							cache_valid=false;
+						} else {
+							//update modified time
+
+							f=FileAccess::open(file,FileAccess::WRITE);
+							f->store_line(itos(modtime));
+							f->store_line(md5);
+							memdelete(f);
+						}
+					} else {
+						memdelete(f);
+					}
+
+					if (cache_valid) {
+
+						texture = ResourceLoader::load(cache_base+".png","ImageTexture",true);
+						if (!texture.is_valid()) {
+							//well fuck
+							cache_valid=false;
+						}
+					}
+
+					if (!cache_valid) {
+
+						texture=_generate_preview(item,cache_base);
+					}
+
+				}
+
+				print_line("notify of preview ready");
+				call_deferred("_preview_ready",item.path,texture,item.id,item.function,item.userdata);
+
+			}
+
+		} else {
+			preview_mutex->unlock();
+		}
+
+	}
+}
+
+
+
+
+void EditorResourcePreview::queue_resource_preview(const String& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata) {
+
+	ERR_FAIL_NULL(p_receiver);
+	preview_mutex->lock();
+	if (cache.has(p_path)) {
+		cache[p_path].order=order++;
+		p_receiver->call_deferred(p_receiver_func,p_path,cache[p_path].preview,p_userdata);
+		preview_mutex->unlock();
+		return;
+
+	}
+
+	print_line("send to thread");
+	QueueItem item;
+	item.function=p_receiver_func;
+	item.id=p_receiver->get_instance_ID();
+	item.path=p_path;
+	item.userdata=p_userdata;
+
+	queue.push_back(item);
+	preview_mutex->unlock();
+	preview_sem->post();
+
+}
+
+void EditorResourcePreview::add_preview_generator(const Ref<EditorResourcePreviewGenerator>& p_generator) {
+
+	preview_generators.push_back(p_generator);
+}
+
+EditorResourcePreview* EditorResourcePreview::get_singleton() {
+
+	return singleton;
+}
+
+void EditorResourcePreview::_bind_methods() {
+
+	ObjectTypeDB::bind_method("_preview_ready",&EditorResourcePreview::_preview_ready);
+}
+
+EditorResourcePreview::EditorResourcePreview() {
+	singleton=this;
+	preview_mutex = Mutex::create();
+	preview_sem  = Semaphore::create();
+	order=0;
+	exit=false;
+
+	thread = Thread::create(_thread_func,this);
+}
+
+
+EditorResourcePreview::~EditorResourcePreview()
+{
+
+	exit=true;
+	preview_sem->post();
+	Thread::wait_to_finish(thread);
+	memdelete(thread);
+	memdelete(preview_mutex);
+	memdelete(preview_sem);
+
+
+}
+

+ 95 - 0
tools/editor/editor_resource_preview.h

@@ -0,0 +1,95 @@
+#ifndef EDITORRESOURCEPREVIEW_H
+#define EDITORRESOURCEPREVIEW_H
+
+#include "scene/main/node.h"
+#include "os/semaphore.h"
+#include "os/thread.h"
+#include "scene/resources/texture.h"
+
+/* make previews for:
+*packdscene
+-wav
+*image
+-mesh
+-font
+*script
+*material
+-shader
+-shader graph?
+-navigation mesh
+-collision?
+-occluder polygon
+-navigation polygon
+-tileset
+-curve and curve2D
+*/
+
+
+class EditorResourcePreviewGenerator : public Reference {
+
+	OBJ_TYPE(EditorResourcePreviewGenerator,Reference );
+
+public:
+
+	virtual bool handles(const String& p_type) const=0;
+	virtual Ref<Texture> generate(const RES& p_from)=0;
+	virtual Ref<Texture> generate_from_path(const String& p_path);
+
+	EditorResourcePreviewGenerator();
+};
+
+
+class EditorResourcePreview : public Node {
+
+	OBJ_TYPE(EditorResourcePreview,Node);
+
+
+	static EditorResourcePreview* singleton;
+
+	struct QueueItem {
+		String path;
+		ObjectID id;
+		StringName function;
+		Variant userdata;
+	};
+
+	List<QueueItem> queue;
+
+	Mutex *preview_mutex;
+	Semaphore *preview_sem;
+	Thread *thread;
+	bool exit;
+
+	struct Item {
+		Ref<Texture> preview;
+		int order;
+	};
+
+	int order;
+
+	Map<String,Item> cache;
+
+	void _preview_ready(const String& p_str,const Ref<Texture>& p_texture, ObjectID id, const StringName &p_func, const Variant &p_ud);
+	Ref<Texture> _generate_preview(const QueueItem& p_item, const String &cache_base);
+
+	static void _thread_func(void *ud);
+	void _thread();
+
+	Vector<Ref<EditorResourcePreviewGenerator> > preview_generators;
+protected:
+
+	static void _bind_methods();
+public:
+
+	static EditorResourcePreview* get_singleton();
+
+	//callback funtion is callback(String p_path,Ref<Texture> preview,Variant udata) preview null if could not load
+	void queue_resource_preview(const String& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata);
+
+	void add_preview_generator(const Ref<EditorResourcePreviewGenerator>& p_generator);
+
+	EditorResourcePreview();
+	~EditorResourcePreview();
+};
+
+#endif // EDITORRESOURCEPREVIEW_H

+ 2 - 0
tools/editor/editor_settings.cpp

@@ -448,6 +448,8 @@ void EditorSettings::_load_defaults() {
 	set("text_editor/create_signal_callbacks",true);
 
 	set("file_dialog/show_hidden_files", false);
+	set("file_dialog/thumbnail_size", 64);
+	hints["file_dialog/thumbnail_size"]=PropertyInfo(Variant::INT,"file_dialog/thumbnail_size",PROPERTY_HINT_RANGE,"32,128,16");
 
 	set("animation/autorename_animation_tracks",true);
 	set("animation/confirm_insert_track",true);

binární
tools/editor/icons/icon_wait_no_preview.png


binární
tools/editor/icons/icon_wait_preview_1.png


binární
tools/editor/icons/icon_wait_preview_2.png


binární
tools/editor/icons/icon_wait_preview_3.png


binární
tools/editor/icons/icon_wait_preview_4.png


binární
tools/editor/icons/icon_wait_preview_5.png


binární
tools/editor/icons/icon_wait_preview_6.png


binární
tools/editor/icons/icon_wait_preview_7.png


binární
tools/editor/icons/icon_wait_preview_8.png


+ 664 - 0
tools/editor/plugins/editor_preview_plugins.cpp

@@ -0,0 +1,664 @@
+#include "editor_preview_plugins.h"
+#include "io/resource_loader.h"
+#include "tools/editor/editor_settings.h"
+#include "io/file_access_memory.h"
+#include "os/os.h"
+#include "scene/resources/material.h"
+#include "scene/resources/sample.h"
+
+bool EditorTexturePreviewPlugin::handles(const String& p_type) const {
+
+	return ObjectTypeDB::is_type(p_type,"ImageTexture");
+}
+
+Ref<Texture> EditorTexturePreviewPlugin::generate(const RES& p_from) {
+
+	Ref<ImageTexture> tex =p_from;
+	Image img = tex->get_data();
+	if (img.empty())
+		return Ref<Texture>();
+
+	img.clear_mipmaps();
+
+	int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
+	if (img.is_compressed()) {
+		if (img.decompress()!=OK)
+			return Ref<Texture>();
+	} else if (img.get_format()!=Image::FORMAT_RGB && img.get_format()!=Image::FORMAT_RGB) {
+		img.convert(Image::FORMAT_RGBA);
+	}
+
+	int width,height;
+	if (img.get_width() > thumbnail_size && img.get_width() >= img.get_height()) {
+
+		width=thumbnail_size;
+		height = img.get_height() * thumbnail_size / img.get_width();
+	} else if (img.get_height() > thumbnail_size &&  img.get_height() >= img.get_width()) {
+
+		height=thumbnail_size;
+		width = img.get_width() * thumbnail_size / img.get_height();
+	}  else {
+
+		width=img.get_width();
+		height=img.get_height();
+	}
+
+	img.resize(width,height);
+
+	Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
+
+	ptex->create_from_image(img,0);
+	return ptex;
+
+}
+
+EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() {
+
+
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+
+Ref<Texture> EditorPackedScenePreviewPlugin::_gen_from_imd(Ref<ResourceImportMetadata> p_imd) {
+
+	if (p_imd.is_null())
+		return Ref<Texture>();
+
+	if (!p_imd->has_option("thumbnail"))
+		return Ref<Texture>();
+
+	Variant tn = p_imd->get_option("thumbnail");
+	print_line(Variant::get_type_name(tn.get_type()));
+	DVector<uint8_t> thumbnail = tn;
+
+	int len = thumbnail.size();
+	if (len==0)
+		return Ref<Texture>();
+
+
+	DVector<uint8_t>::Read r = thumbnail.read();
+
+	Image img(r.ptr(),len);
+	if (img.empty())
+		return Ref<Texture>();
+
+	Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
+	ptex->create_from_image(img,0);
+	return ptex;
+
+}
+
+bool EditorPackedScenePreviewPlugin::handles(const String& p_type) const {
+
+	return ObjectTypeDB::is_type(p_type,"PackedScene");
+}
+Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES& p_from) {
+
+	Ref<ResourceImportMetadata> imd = p_from->get_import_metadata();
+	return _gen_from_imd(imd);
+}
+
+Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String& p_path) {
+
+	Ref<ResourceImportMetadata> imd = ResourceLoader::load_import_metadata(p_path);
+	return _gen_from_imd(imd);
+}
+
+EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() {
+
+}
+
+//////////////////////////////////////////////////////////////////
+
+bool EditorMaterialPreviewPlugin::handles(const String& p_type) const {
+
+	return ObjectTypeDB::is_type(p_type,"Material"); //any material
+}
+
+Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES& p_from) {
+
+	Ref<Material> material = p_from;
+	ERR_FAIL_COND_V(material.is_null(),Ref<Texture>());
+
+	VS::get_singleton()->mesh_surface_set_material(sphere,0,material->get_rid());
+
+	VS::get_singleton()->viewport_queue_screen_capture(viewport);
+	VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture
+//	print_line("queue capture!");
+	Image img;
+
+	int timeout=1000;
+	while(timeout) {
+		//print_line("try capture?");
+		OS::get_singleton()->delay_usec(10);
+		img = VS::get_singleton()->viewport_get_screen_capture(viewport);
+		if (!img.empty())
+			break;
+		timeout--;
+	}
+
+	//print_line("captured!");
+	VS::get_singleton()->mesh_surface_set_material(sphere,0,RID());
+
+	int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
+	img.resize(thumbnail_size,thumbnail_size);
+
+	Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
+	ptex->create_from_image(img,0);
+	return ptex;
+}
+
+EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
+
+	scenario = VS::get_singleton()->scenario_create();
+
+	viewport = VS::get_singleton()->viewport_create();
+	VS::get_singleton()->viewport_set_as_render_target(viewport,true);
+	VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_DISABLED);
+	VS::get_singleton()->viewport_set_scenario(viewport,scenario);
+	VS::ViewportRect vr;
+	vr.x=0;
+	vr.y=0;
+	vr.width=128;
+	vr.height=128;
+	VS::get_singleton()->viewport_set_rect(viewport,vr);
+
+	camera = VS::get_singleton()->camera_create();
+	VS::get_singleton()->viewport_attach_camera(viewport,camera);
+	VS::get_singleton()->camera_set_transform(camera,Transform(Matrix3(),Vector3(0,0,3)));
+	VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
+
+	light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+	light_instance = VS::get_singleton()->instance_create2(light,scenario);
+	VS::get_singleton()->instance_set_transform(light_instance,Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0)));
+
+	light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+	VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_DIFFUSE,Color(0.7,0.7,0.7));
+	VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_SPECULAR,Color(0.0,0.0,0.0));
+	light_instance2 = VS::get_singleton()->instance_create2(light2,scenario);
+
+	VS::get_singleton()->instance_set_transform(light_instance2,Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1)));
+
+	sphere = VS::get_singleton()->mesh_create();
+	sphere_instance = VS::get_singleton()->instance_create2(sphere,scenario);
+
+	int lats=32;
+	int lons=32;
+	float radius=1.0;
+
+	DVector<Vector3> vertices;
+	DVector<Vector3> normals;
+	DVector<Vector2> uvs;
+	DVector<float> tangents;
+	Matrix3 tt = Matrix3(Vector3(0,1,0),Math_PI*0.5);
+
+	for(int i = 1; i <= lats; i++) {
+		double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats);
+		double z0  = Math::sin(lat0);
+		double zr0 =  Math::cos(lat0);
+
+		double lat1 = Math_PI * (-0.5 + (double) i / lats);
+		double z1 = Math::sin(lat1);
+		double zr1 = Math::cos(lat1);
+
+		for(int j = lons; j >= 1; j--) {
+
+			double lng0 = 2 * Math_PI * (double) (j - 1) / lons;
+			double x0 = Math::cos(lng0);
+			double y0 = Math::sin(lng0);
+
+			double lng1 = 2 * Math_PI * (double) (j) / lons;
+			double x1 = Math::cos(lng1);
+			double y1 = Math::sin(lng1);
+
+
+			Vector3 v[4]={
+				Vector3(x1 * zr0, z0, y1 *zr0),
+				Vector3(x1 * zr1, z1, y1 *zr1),
+				Vector3(x0 * zr1, z1, y0 *zr1),
+				Vector3(x0 * zr0, z0, y0 *zr0)
+			};
+
+#define ADD_POINT(m_idx) \
+	normals.push_back(v[m_idx]);\
+	vertices.push_back(v[m_idx]*radius);\
+	{ Vector2 uv(Math::atan2(v[m_idx].x,v[m_idx].z),Math::atan2(-v[m_idx].y,v[m_idx].z));\
+	  uv/=Math_PI;\
+	  uv*=4.0;\
+	  uv=uv*0.5+Vector2(0.5,0.5);\
+	  uvs.push_back(uv);\
+	 }\
+	 { Vector3 t = tt.xform(v[m_idx]);\
+	   tangents.push_back(t.x);\
+	   tangents.push_back(t.y);\
+	   tangents.push_back(t.z);\
+	   tangents.push_back(1.0);\
+	  }
+
+
+
+			ADD_POINT(0);
+			ADD_POINT(1);
+			ADD_POINT(2);
+
+			ADD_POINT(2);
+			ADD_POINT(3);
+			ADD_POINT(0);
+		}
+	}
+
+	Array arr;
+	arr.resize(VS::ARRAY_MAX);
+	arr[VS::ARRAY_VERTEX]=vertices;
+	arr[VS::ARRAY_NORMAL]=normals;
+	arr[VS::ARRAY_TANGENT]=tangents;
+	arr[VS::ARRAY_TEX_UV]=uvs;
+	VS::get_singleton()->mesh_add_surface(sphere,VS::PRIMITIVE_TRIANGLES,arr);
+
+}
+
+EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() {
+
+	VS::get_singleton()->free(sphere);
+	VS::get_singleton()->free(sphere_instance);
+	VS::get_singleton()->free(viewport);
+	VS::get_singleton()->free(light);
+	VS::get_singleton()->free(light_instance);
+	VS::get_singleton()->free(light2);
+	VS::get_singleton()->free(light_instance2);
+	VS::get_singleton()->free(camera);
+	VS::get_singleton()->free(scenario);
+
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+static bool _is_text_char(CharType c) {
+
+	return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_';
+}
+
+bool EditorScriptPreviewPlugin::handles(const String& p_type) const {
+
+	return ObjectTypeDB::is_type(p_type,"Script");
+}
+
+Ref<Texture> EditorScriptPreviewPlugin::generate(const RES& p_from) {
+
+
+	Ref<Script> scr = p_from;
+	if (scr.is_null())
+		return Ref<Texture>();
+
+	String code = scr->get_source_code().strip_edges();
+	if (code=="")
+		return Ref<Texture>();
+
+	List<String> kwors;
+	scr->get_language()->get_reserved_words(&kwors);
+
+	Set<String> keywords;
+
+	for(List<String>::Element *E=kwors.front();E;E=E->next()) {
+
+		keywords.insert(E->get());
+
+	}
+
+
+	int line = 0;
+	int col=0;
+	int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
+	Image img(thumbnail_size,thumbnail_size,0,Image::FORMAT_RGBA);
+
+
+
+	Color bg_color = EditorSettings::get_singleton()->get("text_editor/background_color");
+	bg_color.a=1.0;
+	Color keyword_color = EditorSettings::get_singleton()->get("text_editor/keyword_color");
+	Color text_color = EditorSettings::get_singleton()->get("text_editor/text_color");
+	Color symbol_color = EditorSettings::get_singleton()->get("text_editor/symbol_color");
+	Color comment_color = EditorSettings::get_singleton()->get("text_editor/comment_color");
+
+
+	for(int i=0;i<thumbnail_size;i++) {
+		for(int j=0;j<thumbnail_size;j++) {
+			img.put_pixel(i,j,bg_color);
+		}
+
+	}
+
+	bool prev_is_text=false;
+	bool in_keyword=false;
+	for(int i=0;i<code.length();i++) {
+
+		CharType c = code[i];
+		if (c>32) {
+			if (col<thumbnail_size) {
+				Color color = text_color;
+
+				if (c!='_' && ((c>='!' && c<='/') || (c>=':' && c<='@') || (c>='[' && c<='`') || (c>='{' && c<='~') || c=='\t')) {
+					//make symbol a little visible
+					color=symbol_color;
+					in_keyword=false;
+				} else if (!prev_is_text && _is_text_char(c)) {
+					int pos = i;
+
+					while(_is_text_char(code[pos])) {
+						pos++;
+					}
+					///print_line("from "+itos(i)+" to "+itos(pos));
+					String word = code.substr(i,pos-i);
+					//print_line("found word: "+word);
+					if (keywords.has(word))
+						in_keyword=true;
+
+				} else if (!_is_text_char(c)) {
+					in_keyword=false;
+				}
+
+				if (in_keyword)
+					color=keyword_color;
+
+				Color ul=color;
+				ul.a*=0.5;
+				img.put_pixel(col,line*2,bg_color.blend(ul));
+				img.put_pixel(col,line*2+1,color);
+
+				prev_is_text=_is_text_char(c);
+			}
+		} else {
+
+			prev_is_text=false;
+			in_keyword=false;
+
+			if (c=='\n') {
+				col=0;
+				line++;
+				if (line>=thumbnail_size/2)
+					break;
+			} else if (c=='\t') {
+				col+=3;
+			}
+		}
+		col++;
+	}
+
+	Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture));
+
+	ptex->create_from_image(img,0);
+	return ptex;
+
+}
+
+EditorScriptPreviewPlugin::EditorScriptPreviewPlugin() {
+
+
+}
+///////////////////////////////////////////////////////////////////
+
+bool EditorSamplePreviewPlugin::handles(const String& p_type) const {
+
+	return ObjectTypeDB::is_type(p_type,"Sample");
+}
+
+Ref<Texture> EditorSamplePreviewPlugin::generate(const RES& p_from) {
+
+	Ref<Sample> smp =p_from;
+	ERR_FAIL_COND_V(smp.is_null(),Ref<Texture>());
+
+
+	int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
+
+	DVector<uint8_t> img;
+	int w = thumbnail_size;
+	int h = thumbnail_size;
+	img.resize(w*h*3);
+
+	DVector<uint8_t>::Write imgdata = img.write();
+	uint8_t * imgw = imgdata.ptr();
+	DVector<uint8_t> data = smp->get_data();
+	DVector<uint8_t>::Read sampledata = data.read();
+	const uint8_t *sdata=sampledata.ptr();
+
+	bool stereo = smp->is_stereo();
+	bool _16=smp->get_format()==Sample::FORMAT_PCM16;
+	int len = smp->get_length();
+
+	if (len<1)
+		return Ref<Texture>();
+
+	if (smp->get_format()==Sample::FORMAT_IMA_ADPCM) {
+
+		struct IMA_ADPCM_State {
+
+			int16_t step_index;
+			int32_t predictor;
+			/* values at loop point */
+			int16_t loop_step_index;
+			int32_t loop_predictor;
+			int32_t last_nibble;
+			int32_t loop_pos;
+			int32_t window_ofs;
+			const uint8_t *ptr;
+		} ima_adpcm;
+
+		ima_adpcm.step_index=0;
+		ima_adpcm.predictor=0;
+		ima_adpcm.loop_step_index=0;
+		ima_adpcm.loop_predictor=0;
+		ima_adpcm.last_nibble=-1;
+		ima_adpcm.loop_pos=0x7FFFFFFF;
+		ima_adpcm.window_ofs=0;
+		ima_adpcm.ptr=NULL;
+
+
+		for(int i=0;i<w;i++) {
+
+			float max[2]={-1e10,-1e10};
+			float min[2]={1e10,1e10};
+			int from = i*len/w;
+			int to = (i+1)*len/w;
+			if (to>=len)
+				to=len-1;
+
+			for(int j=from;j<to;j++) {
+
+				while(j>ima_adpcm.last_nibble) {
+
+					static const int16_t _ima_adpcm_step_table[89] = {
+						7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+						19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+						50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+						130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+						337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+						876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+						2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+						5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+						15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+					};
+
+					static const int8_t _ima_adpcm_index_table[16] = {
+						-1, -1, -1, -1, 2, 4, 6, 8,
+						-1, -1, -1, -1, 2, 4, 6, 8
+					};
+
+					int16_t nibble,signed_nibble,diff,step;
+
+					ima_adpcm.last_nibble++;
+					const uint8_t *src_ptr=sdata;
+
+					nibble = (ima_adpcm.last_nibble&1)?
+							(src_ptr[ima_adpcm.last_nibble>>1]>>4):(src_ptr[ima_adpcm.last_nibble>>1]&0xF);
+					step=_ima_adpcm_step_table[ima_adpcm.step_index];
+
+					ima_adpcm.step_index += _ima_adpcm_index_table[nibble];
+					if (ima_adpcm.step_index<0)
+						ima_adpcm.step_index=0;
+					if (ima_adpcm.step_index>88)
+						ima_adpcm.step_index=88;
+
+					/*
+					signed_nibble = (nibble&7) * ((nibble&8)?-1:1);
+					diff = (2 * signed_nibble + 1) * step / 4; */
+
+					diff = step >> 3 ;
+					if (nibble & 1)
+						diff += step >> 2 ;
+					if (nibble & 2)
+						diff += step >> 1 ;
+					if (nibble & 4)
+						diff += step ;
+					if (nibble & 8)
+						diff = -diff ;
+
+					ima_adpcm.predictor+=diff;
+					if (ima_adpcm.predictor<-0x8000)
+						ima_adpcm.predictor=-0x8000;
+					else if (ima_adpcm.predictor>0x7FFF)
+						ima_adpcm.predictor=0x7FFF;
+
+
+					/* store loop if there */
+					if (ima_adpcm.last_nibble==ima_adpcm.loop_pos) {
+
+						ima_adpcm.loop_step_index = ima_adpcm.step_index;
+						ima_adpcm.loop_predictor = ima_adpcm.predictor;
+					}
+
+				}
+
+				float v=ima_adpcm.predictor/32767.0;
+				if (v>max[0])
+					max[0]=v;
+				if (v<min[0])
+					min[0]=v;
+			}
+			max[0]*=0.8;
+			min[0]*=0.8;
+
+			for(int j=0;j<h;j++) {
+				float v = (j/(float)h) * 2.0 - 1.0;
+				uint8_t* imgofs = &imgw[(j*w+i)*3];
+				if (v>min[0] && v<max[0]) {
+					imgofs[0]=255;
+					imgofs[1]=150;
+					imgofs[2]=80;
+				} else {
+					imgofs[0]=0;
+					imgofs[1]=0;
+					imgofs[2]=0;
+				}
+			}
+		}
+	} else {
+		for(int i=0;i<w;i++) {
+			// i trust gcc will optimize this loop
+			float max[2]={-1e10,-1e10};
+			float min[2]={1e10,1e10};
+			int c=stereo?2:1;
+			int from = i*len/w;
+			int to = (i+1)*len/w;
+			if (to>=len)
+				to=len-1;
+
+			if (_16) {
+				const int16_t*src =(const int16_t*)sdata;
+
+				for(int j=0;j<c;j++) {
+
+					for(int k=from;k<=to;k++) {
+
+						float v = src[k*c+j]/32768.0;
+						if (v>max[j])
+							max[j]=v;
+						if (v<min[j])
+							min[j]=v;
+					}
+
+				}
+			} else {
+
+				const int8_t*src =(const int8_t*)sdata;
+
+				for(int j=0;j<c;j++) {
+
+					for(int k=from;k<=to;k++) {
+
+						float v = src[k*c+j]/128.0;
+						if (v>max[j])
+							max[j]=v;
+						if (v<min[j])
+							min[j]=v;
+					}
+
+				}
+			}
+
+			max[0]*=0.8;
+			max[1]*=0.8;
+			min[0]*=0.8;
+			min[1]*=0.8;
+
+			if (!stereo) {
+				for(int j=0;j<h;j++) {
+					float v = (j/(float)h) * 2.0 - 1.0;
+					uint8_t* imgofs = &imgw[(j*w+i)*3];
+					if (v>min[0] && v<max[0]) {
+						imgofs[0]=255;
+						imgofs[1]=150;
+						imgofs[2]=80;
+					} else {
+						imgofs[0]=0;
+						imgofs[1]=0;
+						imgofs[2]=0;
+					}
+				}
+			} else {
+
+				for(int j=0;j<h;j++) {
+
+					int half,ofs;
+					float v;
+					if (j<(h/2)) {
+						half=0;
+						ofs=0;
+						v = (j/(float)(h/2)) * 2.0 - 1.0;
+					} else {
+						half=1;
+						ofs=h/2;
+						v = ((j-(h/2))/(float)(h/2)) * 2.0 - 1.0;
+					}
+
+					uint8_t* imgofs = &imgw[(j*w+i)*3];
+					if (v>min[half] && v<max[half]) {
+						imgofs[0]=255;
+						imgofs[1]=150;
+						imgofs[2]=80;
+					} else {
+						imgofs[0]=0;
+						imgofs[1]=0;
+						imgofs[2]=0;
+					}
+				}
+
+			}
+
+		}
+	}
+
+	imgdata = DVector<uint8_t>::Write();
+
+	Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture));
+	ptex->create_from_image(Image(w,h,0,Image::FORMAT_RGB,img),0);
+	return ptex;
+
+}
+
+EditorSamplePreviewPlugin::EditorSamplePreviewPlugin() {
+
+
+}
+
+///////////////////////////////////////////////////////////////////////////

+ 69 - 0
tools/editor/plugins/editor_preview_plugins.h

@@ -0,0 +1,69 @@
+#ifndef EDITORPREVIEWPLUGINS_H
+#define EDITORPREVIEWPLUGINS_H
+
+#include "tools/editor/editor_resource_preview.h"
+
+class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator {
+public:
+
+	virtual bool handles(const String& p_type) const;
+	virtual Ref<Texture> generate(const RES& p_from);
+
+	EditorTexturePreviewPlugin();
+};
+
+
+class EditorPackedScenePreviewPlugin : public EditorResourcePreviewGenerator {
+
+	Ref<Texture> _gen_from_imd(Ref<ResourceImportMetadata> p_imd);
+public:
+
+	virtual bool handles(const String& p_type) const;
+	virtual Ref<Texture> generate(const RES& p_from);
+	virtual Ref<Texture> generate_from_path(const String& p_path);
+
+	EditorPackedScenePreviewPlugin();
+};
+
+class EditorMaterialPreviewPlugin : public EditorResourcePreviewGenerator {
+
+	RID scenario;
+	RID sphere;
+	RID sphere_instance;
+	RID viewport;
+	RID light;
+	RID light_instance;
+	RID light2;
+	RID light_instance2;
+	RID camera;
+public:
+
+	virtual bool handles(const String& p_type) const;
+	virtual Ref<Texture> generate(const RES& p_from);
+
+	EditorMaterialPreviewPlugin();
+	~EditorMaterialPreviewPlugin();
+};
+
+class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator {
+public:
+
+	virtual bool handles(const String& p_type) const;
+	virtual Ref<Texture> generate(const RES& p_from);
+
+	EditorScriptPreviewPlugin();
+};
+
+
+class EditorSamplePreviewPlugin : public EditorResourcePreviewGenerator {
+public:
+
+	virtual bool handles(const String& p_type) const;
+	virtual Ref<Texture> generate(const RES& p_from);
+
+	EditorSamplePreviewPlugin();
+};
+
+
+
+#endif // EDITORPREVIEWPLUGINS_H

+ 119 - 0
tools/editor/plugins/sample_editor_plugin.cpp

@@ -98,6 +98,125 @@ void SampleEditor::generate_preview_texture(const Ref<Sample>& p_sample,Ref<Imag
 	if (p_sample->get_format()==Sample::FORMAT_IMA_ADPCM) {
 
 
+		struct IMA_ADPCM_State {
+
+			int16_t step_index;
+			int32_t predictor;
+			/* values at loop point */
+			int16_t loop_step_index;
+			int32_t loop_predictor;
+			int32_t last_nibble;
+			int32_t loop_pos;
+			int32_t window_ofs;
+			const uint8_t *ptr;
+		} ima_adpcm;
+
+		ima_adpcm.step_index=0;
+		ima_adpcm.predictor=0;
+		ima_adpcm.loop_step_index=0;
+		ima_adpcm.loop_predictor=0;
+		ima_adpcm.last_nibble=-1;
+		ima_adpcm.loop_pos=0x7FFFFFFF;
+		ima_adpcm.window_ofs=0;
+		ima_adpcm.ptr=NULL;
+
+
+		for(int i=0;i<w;i++) {
+
+			float max[2]={-1e10,-1e10};
+			float min[2]={1e10,1e10};
+			int from = i*len/w;
+			int to = (i+1)*len/w;
+			if (to>=len)
+				to=len-1;
+
+			for(int j=from;j<to;j++) {
+
+				while(j>ima_adpcm.last_nibble) {
+
+					static const int16_t _ima_adpcm_step_table[89] = {
+						7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+						19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+						50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+						130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+						337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+						876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+						2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+						5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+						15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+					};
+
+					static const int8_t _ima_adpcm_index_table[16] = {
+						-1, -1, -1, -1, 2, 4, 6, 8,
+						-1, -1, -1, -1, 2, 4, 6, 8
+					};
+
+					int16_t nibble,signed_nibble,diff,step;
+
+					ima_adpcm.last_nibble++;
+					const uint8_t *src_ptr=sdata;
+
+					nibble = (ima_adpcm.last_nibble&1)?
+							(src_ptr[ima_adpcm.last_nibble>>1]>>4):(src_ptr[ima_adpcm.last_nibble>>1]&0xF);
+					step=_ima_adpcm_step_table[ima_adpcm.step_index];
+
+					ima_adpcm.step_index += _ima_adpcm_index_table[nibble];
+					if (ima_adpcm.step_index<0)
+						ima_adpcm.step_index=0;
+					if (ima_adpcm.step_index>88)
+						ima_adpcm.step_index=88;
+
+					/*
+					signed_nibble = (nibble&7) * ((nibble&8)?-1:1);
+					diff = (2 * signed_nibble + 1) * step / 4; */
+
+					diff = step >> 3 ;
+					if (nibble & 1)
+						diff += step >> 2 ;
+					if (nibble & 2)
+						diff += step >> 1 ;
+					if (nibble & 4)
+						diff += step ;
+					if (nibble & 8)
+						diff = -diff ;
+
+					ima_adpcm.predictor+=diff;
+					if (ima_adpcm.predictor<-0x8000)
+						ima_adpcm.predictor=-0x8000;
+					else if (ima_adpcm.predictor>0x7FFF)
+						ima_adpcm.predictor=0x7FFF;
+
+
+					/* store loop if there */
+					if (ima_adpcm.last_nibble==ima_adpcm.loop_pos) {
+
+						ima_adpcm.loop_step_index = ima_adpcm.step_index;
+						ima_adpcm.loop_predictor = ima_adpcm.predictor;
+					}
+
+				}
+
+				float v=ima_adpcm.predictor/32767.0;
+				if (v>max[0])
+					max[0]=v;
+				if (v<min[0])
+					min[0]=v;
+			}
+
+			for(int j=0;j<h;j++) {
+				float v = (j/(float)h) * 2.0 - 1.0;
+				uint8_t* imgofs = &imgw[(j*w+i)*3];
+				if (v>min[0] && v<max[0]) {
+					imgofs[0]=255;
+					imgofs[1]=150;
+					imgofs[2]=80;
+				} else {
+					imgofs[0]=0;
+					imgofs[1]=0;
+					imgofs[2]=0;
+				}
+			}
+		}
 	} else {
 		for(int i=0;i<w;i++) {
 			// i trust gcc will optimize this loop

+ 7 - 1
tools/editor/plugins/spatial_editor_plugin.h

@@ -239,7 +239,7 @@ public:
 	void set_state(const Dictionary& p_state);
 	Dictionary get_state() const;
 	void reset();
-
+	Viewport *get_viewport_node() { return viewport; }
 
 
 	SpatialEditorViewport(SpatialEditor *p_spatial_editor,EditorNode *p_editor,int p_index);
@@ -422,6 +422,7 @@ private:
 	HBoxContainer *hbc_menu;
 
 
+
 //
 //
 	void _generate_selection_box();
@@ -514,6 +515,11 @@ public:
 
 	void set_can_preview(Camera* p_preview);
 
+	SpatialEditorViewport *get_editor_viewport(int p_idx) {
+		ERR_FAIL_INDEX_V(p_idx,4,NULL);
+		return viewports[p_idx];
+	}
+
 	Camera *get_camera() { return NULL; }
 	void edit(Spatial *p_spatial);
 	void clear();

+ 2 - 2
tools/editor/resources_dock.cpp

@@ -152,7 +152,7 @@ void ResourcesDock::save_resource_as(const Ref<Resource>& p_resource) {
 
 	List<String> extensions;
 	ResourceSaver::get_recognized_extensions(res,&extensions);
-	file->set_mode(FileDialog::MODE_SAVE_FILE);
+	file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
 
 	if (p_resource->get_path()!="" && p_resource->get_path().find("::")==-1) {
 
@@ -396,7 +396,7 @@ ResourcesDock::ResourcesDock(EditorNode *p_editor) {
 	accept = memnew (AcceptDialog);
 	add_child(accept);
 
-	file = memnew( FileDialog );
+	file = memnew( EditorFileDialog );
 	add_child(file);
 	file->connect("file_selected",this,"_file_action");
 

+ 2 - 1
tools/editor/resources_dock.h

@@ -38,6 +38,7 @@
 #include "scene/gui/menu_button.h"
 #include "scene/gui/file_dialog.h"
 #include "create_dialog.h"
+#include "editor_file_dialog.h"
 
 
 class EditorNode;
@@ -68,7 +69,7 @@ class ResourcesDock : public VBoxContainer {
 	CreateDialog *create_dialog;
 
 	AcceptDialog *accept;
-	FileDialog *file;
+	EditorFileDialog *file;
 	Tree *resources;
 	bool block_add;
 	int current_action;