소스 검색

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

James McLean 10 년 전
부모
커밋
8edf4a56f1
37개의 변경된 파일1260개의 추가작업 그리고 276개의 파일을 삭제
  1. 43 7
      core/io/resource_format_binary.cpp
  2. 1 1
      core/io/resource_format_binary.h
  3. 39 7
      core/io/resource_format_xml.cpp
  4. 1 1
      core/io/resource_format_xml.h
  5. 58 0
      core/object.cpp
  6. 7 0
      core/object.h
  7. 12 0
      core/resource.cpp
  8. 4 0
      core/resource.h
  9. 3 2
      core/undo_redo.cpp
  10. BIN
      demos/2d/space_shooter/level_tiles.scn
  11. 1 1
      modules/gdscript/gd_editor.cpp
  12. 58 2
      scene/gui/item_list.cpp
  13. 9 0
      scene/gui/item_list.h
  14. 43 5
      scene/gui/tabs.cpp
  15. 16 0
      scene/gui/tabs.h
  16. 2 0
      scene/gui/tree.h
  17. 10 0
      scene/main/node.cpp
  18. 2 0
      scene/main/node.h
  19. BIN
      scene/resources/default_theme/selection.png
  20. BIN
      scene/resources/default_theme/selection_oof.png
  21. 2 2
      scene/resources/default_theme/theme_data.h
  22. 173 0
      tools/editor/editor_data.cpp
  23. 44 0
      tools/editor/editor_data.h
  24. 408 79
      tools/editor/editor_node.cpp
  25. 26 7
      tools/editor/editor_node.h
  26. 7 0
      tools/editor/editor_plugin.cpp
  27. 3 1
      tools/editor/editor_plugin.h
  28. 1 1
      tools/editor/editor_run_script.cpp
  29. 2 0
      tools/editor/editor_settings.cpp
  30. BIN
      tools/editor/icons/icon_panel_top.png
  31. 1 1
      tools/editor/io_plugins/editor_mesh_import_plugin.cpp
  32. 1 1
      tools/editor/plugins/multimesh_editor_plugin.cpp
  33. 240 141
      tools/editor/plugins/script_editor_plugin.cpp
  34. 37 15
      tools/editor/plugins/script_editor_plugin.h
  35. 1 1
      tools/editor/property_editor.cpp
  36. 1 0
      tools/editor/scene_tree_dock.h
  37. 4 1
      tools/editor/scene_tree_editor.h

+ 43 - 7
core/io/resource_format_binary.cpp

@@ -663,14 +663,18 @@ Error ResourceInteractiveLoaderBinary::poll(){
 
 	//maybe it is loaded already
 	String path;
+	int subindex=0;
 
 
 
 	if (!main) {
 
 		path=internal_resources[s].path;
-		if (path.begins_with("local://"))
-			path=path.replace("local://",res_path+"::");
+		if (path.begins_with("local://")) {
+			path=path.replace_first("local://","");
+			subindex = path.to_int();
+			path=res_path+"::"+path;
+		}
 
 
 
@@ -709,6 +713,7 @@ Error ResourceInteractiveLoaderBinary::poll(){
 	RES res = RES( r );
 
 	r->set_path(path);
+	r->set_subindex(subindex);
 
 	int pc = f->get_32();
 
@@ -1434,14 +1439,14 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant& p_property,
 				save_unicode_string(path);
 			} else {
 
-				if (!resource_map.has(res)) {
+				if (!resource_set.has(res)) {
 					f->store_32(OBJECT_EMPTY);
 					ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
 					ERR_FAIL();
 				}
 
 				f->store_32(OBJECT_INTERNAL_RESOURCE);
-				f->store_32(resource_map[res]);
+				f->store_32(res->get_subindex());
 				//internal resource
 			}
 
@@ -1598,7 +1603,7 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant& p_variant
 			}
 
 
-			if (resource_map.has(res))
+			if (resource_set.has(res))
 				return;
 
 			List<PropertyInfo> property_list;
@@ -1613,7 +1618,7 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant& p_variant
 				}
 			}
 
-			resource_map[ res ] = saved_resources.size();
+			resource_set.insert(res);
 			saved_resources.push_back(res);
 
 		} break;
@@ -1846,11 +1851,42 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_
 	// save internal resource table
 	f->store_32(saved_resources.size()); //amount of internal resources
 	Vector<uint64_t> ofs_pos;
+	Set<int> used_indices;
+
+	for(List<RES>::Element *E=saved_resources.front();E;E=E->next()) {
+
+		RES r = E->get();
+		if (r->get_path()=="" || r->get_path().find("::")!=-1) {
+
+			if (r->get_subindex()!=0) {
+				if (used_indices.has(r->get_subindex())) {
+					r->set_subindex(0); //repeated
+				} else {
+					used_indices.insert(r->get_subindex());
+				}
+			}
+		}
+
+	}
+
+
 	for(List<RES>::Element *E=saved_resources.front();E;E=E->next()) {
 
+
 		RES r = E->get();
 		if (r->get_path()=="" || r->get_path().find("::")!=-1) {
-			save_unicode_string("local://"+itos(ofs_pos.size()));
+			if (r->get_subindex()==0) {
+				int new_subindex=1;
+				if (used_indices.size()) {
+					new_subindex=used_indices.back()->get()+1;
+				}
+
+				r->set_subindex(new_subindex);
+				used_indices.insert(new_subindex);
+
+			}
+
+			save_unicode_string("local://"+itos(r->get_subindex()));
 			if (takeover_paths) {
 				r->set_path(p_path+"::"+itos(ofs_pos.size()),true);
 			}

+ 1 - 1
core/io/resource_format_binary.h

@@ -129,7 +129,7 @@ class ResourceFormatSaverBinaryInstance  {
 	int bin_meta_idx;
 	FileAccess *f;
 	String magic;
-	Map<RES,int> resource_map;
+	Set<RES> resource_set;
 	Map<StringName,int> string_map;
 	Vector<StringName> strings;
 

+ 39 - 7
core/io/resource_format_xml.cpp

@@ -1466,6 +1466,7 @@ Error ResourceInteractiveLoaderXML::poll() {
 
 	String type;
 	String path;
+	int subres=0;
 
 	if (!main) {
 		//loading resource
@@ -1476,11 +1477,15 @@ Error ResourceInteractiveLoaderXML::poll() {
 		ERR_EXPLAIN(local_path+":"+itos(get_current_line())+": <resource> missing 'type' field.");
 		ERR_FAIL_COND_V(!tag->args.has("type"),ERR_FILE_CORRUPT);
 		path=tag->args["path"];
+
 		error=OK;
 
 		if (path.begins_with("local://")) {
 			//built-in resource (but really external)
-			path=path.replace("local://",local_path+"::");
+
+			path=path.replace("local://","");
+			subres=path.to_int();
+			path=local_path+"::"+path;
 		}
 
 
@@ -1519,6 +1524,7 @@ Error ResourceInteractiveLoaderXML::poll() {
 	res = RES( r );
 	if (path!="")
 		r->set_path(path);
+	r->set_subindex(subres);
 
 	//load properties
 
@@ -2029,9 +2035,9 @@ void ResourceFormatSaverXMLInstance::write_property(const String& p_name,const V
 
 				//internal resource
 				ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
-				ERR_FAIL_COND(!resource_map.has(res));
+				ERR_FAIL_COND(!resource_set.has(res));
 
-				params+=" path=\"local://"+itos(resource_map[res])+"\"";
+				params+=" path=\"local://"+itos(res->get_subindex())+"\"";
 			}
 
 		} break;
@@ -2443,7 +2449,7 @@ void ResourceFormatSaverXMLInstance::_find_resources(const Variant& p_variant,bo
 				return;
 			}
 
-			if (resource_map.has(res))
+			if (resource_set.has(res))
 				return;
 
 			List<PropertyInfo> property_list;
@@ -2466,7 +2472,7 @@ void ResourceFormatSaverXMLInstance::_find_resources(const Variant& p_variant,bo
 				I=I->next();
 			}
 
-			resource_map[ res ] = resource_map.size(); //saved after, so the childs it needs are available when loaded
+			resource_set.insert( res ); //saved after, so the childs it needs are available when loaded
 			saved_resources.push_back(res);
 
 		} break;
@@ -2537,12 +2543,27 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res
 		write_string("\n",false);
 	}
 
+	Set<int> used_indices;
+
+	for(List<RES>::Element *E=saved_resources.front();E;E=E->next()) {
+
+		RES res = E->get();
+		if (E->next() && (res->get_path()=="" || res->get_path().find("::") != -1 )) {
 
+			if (res->get_subindex()!=0) {
+				if (used_indices.has(res->get_subindex())) {
+					res->set_subindex(0); //repeated
+				} else {
+					used_indices.insert(res->get_subindex());
+				}
+			}
+		}
+	}
 
 	for(List<RES>::Element *E=saved_resources.front();E;E=E->next()) {
 
 		RES res = E->get();
-		ERR_CONTINUE(!resource_map.has(res));
+		ERR_CONTINUE(!resource_set.has(res));
 		bool main = (E->next()==NULL);
 
 		write_tabs();
@@ -2552,7 +2573,18 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res
 		else if (res->get_path().length() && res->get_path().find("::") == -1 )
 			enter_tag("resource","type=\""+res->get_type()+"\" path=\""+res->get_path()+"\""); //bundled
 		else {
-			int idx = resource_map[res];
+
+			if (res->get_subindex()==0) {
+				int new_subindex=1;
+				if (used_indices.size()) {
+					new_subindex=used_indices.back()->get()+1;
+				}
+
+				res->set_subindex(new_subindex);
+				used_indices.insert(new_subindex);
+			}
+
+			int idx = res->get_subindex();
 			enter_tag("resource","type=\""+res->get_type()+"\" path=\"local://"+itos(idx)+"\"");
 			if (takeover_paths) {
 				res->set_path(p_path+"::"+itos(idx),true);

+ 1 - 1
core/io/resource_format_xml.h

@@ -123,7 +123,7 @@ class ResourceFormatSaverXMLInstance  {
 	bool skip_editor;
 	FileAccess *f;
 	int depth;
-	Map<RES,int> resource_map;
+	Set<RES> resource_set;
 	List<RES> saved_resources;
 	List<RES> external_resources;
 

+ 58 - 0
core/object.cpp

@@ -34,6 +34,7 @@
 #include "core_string_names.h"
 #include "translation.h"
 #include "os/os.h"
+#include "resource.h"
 
 #ifdef DEBUG_ENABLED
 
@@ -1464,6 +1465,63 @@ StringName Object::tr(const StringName& p_message) const {
 
 }
 
+
+void Object::_clear_internal_resource_paths(const Variant &p_var) {
+
+	switch(p_var.get_type()) {
+
+		case Variant::OBJECT: {
+
+			RES r = p_var;
+			if (!r.is_valid())
+				return;
+
+			if (!r->get_path().begins_with("res://") || r->get_path().find("::")==-1)
+				return; //not an internal resource
+
+			Object *object=p_var;
+			if (!object)
+				return;
+
+			r->set_path("");
+			r->clear_internal_resource_paths();
+		} break;
+		case Variant::ARRAY: {
+
+			Array a=p_var;
+			for(int i=0;i<a.size();i++) {
+				_clear_internal_resource_paths(a[i]);
+			}
+
+		} break;
+		case Variant::DICTIONARY: {
+
+			Dictionary d=p_var;
+			List<Variant> keys;
+			d.get_key_list(&keys);
+
+			for (List<Variant>::Element *E=keys.front();E;E=E->next()) {
+
+				_clear_internal_resource_paths(E->get());
+				_clear_internal_resource_paths(d[E->get()]);
+			}
+		} break;
+	}
+
+}
+
+void Object::clear_internal_resource_paths() {
+
+	List<PropertyInfo> pinfo;
+
+	get_property_list(&pinfo);
+
+	for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+
+		_clear_internal_resource_paths(get(E->get().name));
+	}
+}
+
 void Object::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("get_type"),&Object::get_type);

+ 7 - 0
core/object.h

@@ -451,6 +451,8 @@ protected:
 	Array _get_property_list_bind() const;
 	Array _get_method_list_bind() const;
 
+	void _clear_internal_resource_paths(const Variant &p_var);
+
 public: //should be protected, but bug in clang++
 	static void initialize_type();
 	_FORCE_INLINE_ static void register_custom_data_to_otdb() {};
@@ -599,6 +601,9 @@ public:
 
 	_FORCE_INLINE_ void set_message_translation(bool p_enable) { _can_translate=p_enable; }
 	_FORCE_INLINE_ bool can_translate_messages() const { return _can_translate; }
+
+	void clear_internal_resource_paths();
+
 	Object();	
 	virtual ~Object();
 
@@ -651,6 +656,8 @@ public:
 
 #endif
 
+
+
 };
 
 //needed by macros

+ 12 - 0
core/resource.cpp

@@ -195,6 +195,17 @@ String Resource::get_path() const {
 	return path_cache;
 }
 
+void Resource::set_subindex(int p_sub_index) {
+
+	subindex=p_sub_index;
+}
+
+int Resource::get_subindex() const{
+
+	return subindex;
+}
+
+
 void Resource::set_name(const String& p_name) {
 
 	name=p_name;
@@ -326,6 +337,7 @@ Resource::Resource() {
 	last_modified_time=0;
 #endif
 
+	subindex=0;
 }
 
 

+ 4 - 0
core/resource.h

@@ -99,6 +99,7 @@ friend class ResourceCache;
 	
 	String name;
 	String path_cache;
+	int subindex;
 
 	virtual bool _use_builtin_script() const { return true; }
 
@@ -132,6 +133,9 @@ public:
 	void set_path(const String& p_path,bool p_take_over=false);
 	String get_path() const;
 
+	void set_subindex(int p_sub_index);
+	int get_subindex() const;
+
 	Ref<Resource> duplicate(bool p_subresources=false);
 
 	void set_import_metadata(const Ref<ResourceImportMetadata>& p_metadata);

+ 3 - 2
core/undo_redo.cpp

@@ -282,6 +282,7 @@ void UndoRedo::undo() {
 		return; //nothing to redo
 	_process_operation_list(actions[current_action].undo_ops.front());
 	current_action--;
+	version--;
 }
 
 void UndoRedo::clear_history() {
@@ -292,7 +293,7 @@ void UndoRedo::clear_history() {
 	while(actions.size())
 		_pop_history_tail();
 
-	version++;
+	//version++;
 }
 
 String UndoRedo::get_current_action_name() const {
@@ -326,7 +327,7 @@ void UndoRedo::set_commit_notify_callback(CommitNotifyCallback p_callback,void*
 
 UndoRedo::UndoRedo() {
 
-	version=0;
+	version=1;
 	action_level=0;
 	current_action=-1;
 	max_steps=-1;

BIN
demos/2d/space_shooter/level_tiles.scn


+ 1 - 1
modules/gdscript/gd_editor.cpp

@@ -1195,7 +1195,7 @@ static void _find_identifiers(GDCompletionContext& context,int p_line,bool p_onl
 	}
 
 	static const char*_type_names[Variant::VARIANT_MAX]={
-		"null","bool","int","float","String","Vector2","Rect2","Vector3","Matrix32","Plane","Quat","AABB","Matrix3","Trasnform",
+		"null","bool","int","float","String","Vector2","Rect2","Vector3","Matrix32","Plane","Quat","AABB","Matrix3","Transform",
 		"Color","Image","NodePath","RID","Object","InputEvent","Dictionary","Array","RawArray","IntArray","FloatArray","StringArray",
 		"Vector2Array","Vector3Array","ColorArray"};
 

+ 58 - 2
scene/gui/item_list.cpp

@@ -11,6 +11,7 @@ void ItemList::add_item(const String& p_item,const Ref<Texture>& p_texture,bool
 	item.selectable=p_selectable;
 	item.selected=false;
 	item.disabled=false;
+	item.custom_bg=Color(0,0,0,0);
 	items.push_back(item);
 
 	update();
@@ -26,6 +27,7 @@ void ItemList::add_icon_item(const Ref<Texture>& p_item,bool p_selectable){
 	item.selectable=p_selectable;
 	item.selected=false;
 	item.disabled=false;
+	item.custom_bg=Color(0,0,0,0);
 	items.push_back(item);
 
 	update();
@@ -85,6 +87,23 @@ Ref<Texture> ItemList::get_item_icon(int p_idx) const{
 
 }
 
+void ItemList::set_item_custom_bg_color(int p_idx,const Color& p_custom_bg_color) {
+
+	ERR_FAIL_INDEX(p_idx,items.size());
+
+	items[p_idx].custom_bg=p_custom_bg_color;
+
+}
+
+Color ItemList::get_item_custom_bg_color(int p_idx) const {
+
+	ERR_FAIL_INDEX_V(p_idx,items.size(),Color());
+
+	return items[p_idx].custom_bg;
+
+}
+
+
 
 void ItemList::set_item_tag_icon(int p_idx,const Ref<Texture>& p_tag_icon){
 
@@ -635,6 +654,7 @@ void ItemList::_notification(int p_what) {
 		Ref<Font> font = get_font("font");
 		Color guide_color = get_color("guide_color");
 		Color font_color = get_color("font_color");
+		Color font_color_selected = get_color("font_color_selected");
 		int font_height = font->get_height();
 		Vector<int> line_size_cache;
 		Vector<int> line_limit_cache;
@@ -781,6 +801,11 @@ void ItemList::_notification(int p_what) {
 			if (current_columns==1) {
 				rcache.size.width = width-rcache.pos.x;
 			}
+			if (items[i].custom_bg.a>0.001) {
+				Rect2 r=rcache;
+				r.pos+=base_ofs;
+				draw_rect(r,items[i].custom_bg);
+			}
 			if (items[i].selected) {
 				Rect2 r=rcache;
 				r.pos+=base_ofs;
@@ -864,7 +889,7 @@ void ItemList::_notification(int p_what) {
 							if (line>=max_text_lines)
 								break;
 						}
-						ofs+=font->draw_char(get_canvas_item(),text_ofs+Vector2(ofs+(max_len-line_size_cache[line])/2,line*(font_height+line_separation)).floor(),items[i].text[j],items[i].text[j+1],font_color);
+						ofs+=font->draw_char(get_canvas_item(),text_ofs+Vector2(ofs+(max_len-line_size_cache[line])/2,line*(font_height+line_separation)).floor(),items[i].text[j],items[i].text[j+1],items[i].selected?font_color_selected:font_color);
 					}
 
 					//special multiline mode
@@ -884,7 +909,7 @@ void ItemList::_notification(int p_what) {
 					text_ofs+=base_ofs;
 					text_ofs+=items[i].rect_cache.pos;
 
-					draw_string(font,text_ofs,items[i].text,font_color,max_len+1);
+					draw_string(font,text_ofs,items[i].text,items[i].selected?font_color_selected:font_color,max_len+1);
 				}
 
 
@@ -954,6 +979,30 @@ String ItemList::get_tooltip(const Point2& p_pos) const {
 
 }
 
+void ItemList::sort_items_by_text() {
+	items.sort();
+	update();
+	if (select_mode==SELECT_SINGLE) {
+		for(int i=0;i<items.size();i++) {
+			if (items[i].selected) {
+				select(i);
+				return;
+			}
+		}
+	}
+}
+
+int ItemList::find_metadata(const Variant& p_metadata) const {
+
+	for(int i=0;i<items.size();i++) {
+		if (items[i].metadata==p_metadata) {
+			return i;
+		}
+	}
+
+	return -1;
+
+}
 
 void ItemList::_bind_methods(){
 
@@ -972,6 +1021,12 @@ void ItemList::_bind_methods(){
 	ObjectTypeDB::bind_method(_MD("set_item_disabled","idx","disabled"),&ItemList::set_item_disabled);
 	ObjectTypeDB::bind_method(_MD("is_item_disabled","idx"),&ItemList::is_item_disabled);
 
+	ObjectTypeDB::bind_method(_MD("set_item_metadata","idx","metadata"),&ItemList::set_item_metadata);
+	ObjectTypeDB::bind_method(_MD("get_item_metadata","idx"),&ItemList::get_item_metadata);
+
+	ObjectTypeDB::bind_method(_MD("set_item_custom_bg_color","idx","custom_bg_color"),&ItemList::set_item_custom_bg_color);
+	ObjectTypeDB::bind_method(_MD("get_item_custom_bg_color","idx"),&ItemList::get_item_custom_bg_color);
+
 	ObjectTypeDB::bind_method(_MD("set_item_tooltip","idx","tooltip"),&ItemList::set_item_tooltip);
 	ObjectTypeDB::bind_method(_MD("get_item_tooltip","idx"),&ItemList::get_item_tooltip);
 
@@ -983,6 +1038,7 @@ void ItemList::_bind_methods(){
 	ObjectTypeDB::bind_method(_MD("remove_item","idx"),&ItemList::remove_item);
 
 	ObjectTypeDB::bind_method(_MD("clear"),&ItemList::clear);
+	ObjectTypeDB::bind_method(_MD("sort_items_by_text"),&ItemList::clear);
 
 	ObjectTypeDB::bind_method(_MD("set_fixed_column_width","width"),&ItemList::set_fixed_column_width);
 	ObjectTypeDB::bind_method(_MD("get_fixed_column_width"),&ItemList::get_fixed_column_width);

+ 9 - 0
scene/gui/item_list.h

@@ -29,8 +29,12 @@ private:
 		bool disabled;
 		Variant metadata;
 		String tooltip;
+		Color custom_bg;
+
 
 		Rect2 rect_cache;
+
+		bool operator<(const Item& p_another) const { return text<p_another.text; }
 	};
 
 	int current;
@@ -85,6 +89,9 @@ public:
 	void set_item_tooltip(int p_idx,const String& p_tooltip);
 	String get_item_tooltip(int p_idx) const;
 
+	void set_item_custom_bg_color(int p_idx,const Color& p_custom_bg_color);
+	Color get_item_custom_bg_color(int p_idx) const;
+
 	void select(int p_idx,bool p_single=true);
 	void unselect(int p_idx);
 	bool is_selected(int p_idx) const;
@@ -118,6 +125,8 @@ public:
 
 	void ensure_current_is_visible();
 
+	void sort_items_by_text();
+	int find_metadata(const Variant& p_metadata) const;
 
 	virtual String get_tooltip(const Point2& p_pos) const;
 

+ 43 - 5
scene/gui/tabs.cpp

@@ -77,8 +77,8 @@ void Tabs::_input_event(const InputEvent& p_event) {
 		for(int i=0;i<tabs.size();i++) {
 
 			int ofs=tabs[i].ofs_cache;
-
-			if (pos.x < ofs) {
+			int size = tabs[i].ofs_cache;
+			if (pos.x >=tabs[i].ofs_cache && pos.x<tabs[i].ofs_cache+tabs[i].size_cache) {
 
 				found=i;
 				break;
@@ -89,6 +89,7 @@ void Tabs::_input_event(const InputEvent& p_event) {
 		if (found!=-1) {
 
 			set_current_tab(found);
+			emit_signal("tab_changed",found);
 		}
 	}
 
@@ -117,8 +118,22 @@ void Tabs::_notification(int p_what) {
 
 			int w=0;
 
+			int mw = get_minimum_size().width;
+
+			if (tab_align==ALIGN_CENTER) {
+				w=(get_size().width-mw)/2;
+			} else if (tab_align==ALIGN_RIGHT) {
+				w=get_size().width-mw;
+
+			}
+
+			if (w<0) {
+				w=0;
+			}
+
 			for(int i=0;i<tabs.size();i++) {
 
+				tabs[i].ofs_cache=w;
 
 				String s = tabs[i].text;
 				int lsize=0;
@@ -171,7 +186,7 @@ void Tabs::_notification(int p_what) {
 
 				w+=slen+sb->get_margin(MARGIN_RIGHT);
 
-				tabs[i].ofs_cache=w;
+				tabs[i].size_cache=w-tabs[i].ofs_cache;
 
 			}
 
@@ -195,7 +210,7 @@ void Tabs::set_current_tab(int p_current) {
 	current=p_current;	
 
 	_change_notify("current_tab");
-	emit_signal("tab_changed",current);
+	//emit_signal("tab_changed",current);
 	update();
 }
 
@@ -249,6 +264,12 @@ void Tabs::add_tab(const String& p_str,const Ref<Texture>& p_icon) {
 
 }
 
+void Tabs::clear_tabs() {
+	tabs.clear();
+	current=0;
+	update();
+}
+
 void Tabs::remove_tab(int p_idx) {
 
 	ERR_FAIL_INDEX(p_idx,tabs.size());
@@ -263,8 +284,19 @@ void Tabs::remove_tab(int p_idx) {
 	if (current>=tabs.size())
 		current=tabs.size()-1;
 
-	emit_signal("tab_changed",current);
+	//emit_signal("tab_changed",current);
+
+}
+
+void Tabs::set_tab_align(TabAlign p_align) {
+
+	tab_align=p_align;
+	update();
+}
+
+Tabs::TabAlign Tabs::get_tab_align() const {
 
+	return tab_align;
 }
 
 
@@ -280,15 +312,21 @@ void Tabs::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("get_tab_icon:Texture","tab_idx"),&Tabs::get_tab_icon);
 	ObjectTypeDB::bind_method(_MD("remove_tab","tab_idx"),&Tabs::remove_tab);
 	ObjectTypeDB::bind_method(_MD("add_tab","title","icon:Texture"),&Tabs::add_tab);
+	ObjectTypeDB::bind_method(_MD("set_tab_align","align"),&Tabs::set_tab_align);
+	ObjectTypeDB::bind_method(_MD("get_tab_align"),&Tabs::get_tab_align);
 
 	ADD_SIGNAL(MethodInfo("tab_changed",PropertyInfo(Variant::INT,"tab")));
 
 	ADD_PROPERTY( PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE,"-1,4096,1",PROPERTY_USAGE_EDITOR), _SCS("set_current_tab"), _SCS("get_current_tab") );
 
+	BIND_CONSTANT( ALIGN_LEFT );
+	BIND_CONSTANT( ALIGN_CENTER );
+	BIND_CONSTANT( ALIGN_RIGHT );
 }
 
 Tabs::Tabs() {
 
 	current=0;
+	tab_align=ALIGN_CENTER;
 
 }

+ 16 - 0
scene/gui/tabs.h

@@ -34,6 +34,14 @@
 class Tabs : public Control {
 
 	OBJ_TYPE( Tabs, Control );
+public:
+
+	enum TabAlign {
+
+		ALIGN_LEFT,
+		ALIGN_CENTER,
+		ALIGN_RIGHT
+	};
 private:
 
 
@@ -42,12 +50,14 @@ private:
 		String text;
 		Ref<Texture> icon;
 		int ofs_cache;
+		int size_cache;
 	};
 
 	Vector<Tab> tabs;
 	int current;
 	Control *_get_tab(int idx) const;
 	int _get_top_margin() const;
+	TabAlign tab_align;
 
 protected:
 
@@ -65,16 +75,22 @@ public:
 	void set_tab_icon(int p_tab,const Ref<Texture>& p_icon);
 	Ref<Texture> get_tab_icon(int p_tab) const;
 
+	void set_tab_align(TabAlign p_align);
+	TabAlign get_tab_align() const;
+
 	int get_tab_count() const;
 	void set_current_tab(int p_current);
 	int get_current_tab() const;
 
 	void remove_tab(int p_idx);
 
+	void clear_tabs();
+
 	Size2 get_minimum_size() const;
 
 	Tabs();
 };
 
+VARIANT_ENUM_CAST(Tabs::TabAlign);
 
 #endif // TABS_H

+ 2 - 0
scene/gui/tree.h

@@ -454,6 +454,8 @@ public:
 	void set_cursor_can_exit_tree(bool p_enable);
 	bool can_cursor_exit_tree() const;
 
+	VScrollBar *get_vscroll_bar() { return v_scroll; }
+
 	Tree();
 	~Tree();	
 

+ 10 - 0
scene/main/node.cpp

@@ -1816,6 +1816,16 @@ void Node::get_argument_options(const StringName& p_function,int p_idx,List<Stri
 	Object::get_argument_options(p_function,p_idx,r_options);
 }
 
+
+void Node::clear_internal_tree_resource_paths() {
+
+	clear_internal_resource_paths();
+	for(int i=0;i<data.children.size();i++) {
+		data.children[i]->clear_internal_tree_resource_paths();
+	}
+
+}
+
 void Node::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("set_name","name"),&Node::set_name);

+ 2 - 0
scene/main/node.h

@@ -290,6 +290,8 @@ public:
 
 	void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
 
+	void clear_internal_tree_resource_paths();
+
 	_FORCE_INLINE_ Viewport *get_viewport() const { return data.viewport; }
 
 	/* CANVAS */

BIN
scene/resources/default_theme/selection.png


BIN
scene/resources/default_theme/selection_oof.png


+ 2 - 2
scene/resources/default_theme/theme_data.h

@@ -340,12 +340,12 @@ static const unsigned char scroll_grabber_hl_png[]={
 
 
 static const unsigned char selection_png[]={
-0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x11,0x12,0x2a,0x16,0x85,0x48,0x8b,0x13,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xba,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0x93,0x31,0xa,0xc2,0x50,0x10,0x44,0xdf,0x97,0xbf,0x8a,0x3f,0x45,0xd0,0x52,0xbb,0xfc,0x63,0x88,0x88,0xa7,0xd0,0x23,0x9a,0x63,0x84,0x90,0x63,0x24,0x9d,0x9d,0x60,0x95,0x2f,0xb2,0x21,0x5a,0x18,0xb4,0x52,0x3,0x69,0x2c,0x9c,0x6e,0x8b,0x99,0xd9,0x59,0x76,0xc,0x30,0x6,0xa6,0xc0,0x4,0x18,0xd1,0xf,0x2d,0x70,0x5,0x2e,0xb6,0x23,0x2f,0x81,0x19,0x20,0x3d,0x5,0x14,0x38,0x3,0x47,0xdb,0x39,0xcf,0xd7,0xab,0xcd,0xc2,0x27,0xfe,0x20,0x22,0xe6,0x23,0x53,0xf5,0x56,0x56,0xe5,0x3e,0x2f,0x32,0x3,0x9c,0x6c,0xb7,0xb6,0xf5,0x89,0x4f,0x43,0x8,0xd4,0x21,0x7c,0xb4,0x8e,0x9c,0x33,0x3e,0xf1,0x69,0x5e,0x64,0x5b,0x60,0xf4,0xcc,0x2c,0x22,0x5f,0xc9,0x0,0x75,0x8,0x88,0xbc,0x92,0xf6,0x3d,0xda,0x5b,0xfc,0x5,0x7e,0x4a,0x40,0x55,0x89,0x9c,0xfb,0x4a,0x88,0x9c,0x43,0x55,0x9f,0xb3,0xe5,0x51,0x8c,0xa6,0xac,0xca,0x9d,0x4f,0xfc,0x21,0x8e,0xe3,0x5e,0xaf,0xc,0x34,0x40,0x6b,0x80,0x98,0x1,0x65,0x32,0xc,0xac,0xf3,0x1d,0x55,0xc6,0x3e,0x2,0xe2,0x2e,0xc9,0xc8,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x15,0x0,0x15,0x0,0x17,0xc8,0x7d,0x47,0xd1,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdf,0x6,0x14,0x14,0x31,0x1a,0x5f,0x97,0xc4,0x56,0x0,0x0,0x0,0x1d,0x69,0x54,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x0,0x0,0x0,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x64,0x2e,0x65,0x7,0x0,0x0,0x0,0xa3,0x49,0x44,0x41,0x54,0x38,0xcb,0xed,0x93,0xbd,0xa,0xc2,0x40,0x10,0x84,0xbf,0xbb,0x6c,0x72,0x8,0x1,0x51,0x4b,0xdf,0x23,0xc9,0xfb,0x57,0x12,0x9f,0x43,0xb0,0x10,0x2c,0x14,0xe4,0x92,0xcb,0xc5,0x66,0x3,0x36,0x26,0x7,0x69,0x2c,0x9c,0x6e,0x60,0x67,0xf6,0x87,0x1d,0x3,0x14,0xc0,0x6,0x70,0x80,0x25,0xd,0x11,0xf0,0xc0,0x4b,0x54,0x7c,0x4,0x76,0x40,0x9e,0x68,0xd0,0x3,0x77,0xe0,0x22,0xda,0x79,0x3f,0xf4,0x63,0x4b,0xa0,0x56,0x3e,0x7,0x8f,0x70,0xce,0x72,0x53,0x1,0x37,0xd1,0xb1,0x85,0x40,0xc3,0xc8,0xc3,0x47,0xae,0x73,0x6a,0x67,0x29,0x9,0x34,0xaa,0xb3,0x9f,0x3b,0x17,0x3e,0xf2,0x5c,0x9a,0x5d,0x6b,0x8a,0x89,0xa7,0x1e,0xed,0x2b,0xfe,0x6,0xbf,0x66,0xd0,0x39,0x4b,0xb9,0x24,0xd0,0x9a,0x6e,0xe2,0xa2,0xc1,0x8,0x8,0x2d,0x81,0xda,0x65,0x1c,0x12,0x5e,0xf9,0x4,0x54,0x40,0x34,0xc0,0x76,0x4d,0x98,0xcc,0xda,0x38,0xbf,0x1,0xae,0x5a,0x2a,0xba,0xb8,0xa1,0xb8,0x4f,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
 };
 
 
 static const unsigned char selection_oof_png[]={
-0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x4c,0x0,0x4a,0x0,0x4e,0x88,0x29,0x6a,0xb6,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x10,0x15,0x32,0x22,0x9b,0x14,0x96,0x1f,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0xba,0x49,0x44,0x41,0x54,0x38,0x8d,0xed,0xd3,0xb1,0x4e,0xc3,0x40,0x10,0x84,0xe1,0xef,0xc2,0x4a,0x9c,0x90,0xb,0x6a,0x9f,0xe0,0x9,0x2,0xbc,0x58,0xc2,0xcb,0xc0,0x8b,0x85,0xa4,0xa6,0x41,0x4e,0x4d,0x41,0x71,0x91,0xe,0x99,0x2,0xd7,0x76,0xa4,0x34,0x14,0x6c,0xb9,0xda,0xf9,0x47,0x2b,0xcd,0x24,0xdc,0xe0,0x16,0x1d,0xae,0x90,0xcc,0xcf,0x88,0x6f,0x7c,0xe1,0x33,0x26,0xf1,0x23,0xee,0x90,0xcf,0x4,0x54,0x7c,0xe0,0x2d,0x26,0xe7,0xfb,0x87,0xf5,0xd3,0xba,0xf4,0x65,0x13,0x11,0xb3,0x80,0xd6,0xda,0x38,0x1c,0x87,0xd7,0xfd,0x61,0x97,0xf0,0x1e,0x8,0x5c,0x97,0xbe,0x6c,0x6b,0xad,0x6a,0xad,0xb3,0xf6,0x39,0xe7,0x54,0xfa,0xb2,0xdd,0x1f,0x76,0xcf,0x88,0xd5,0xb4,0x4f,0x11,0xb1,0x28,0x86,0x5a,0xab,0x88,0x60,0x7a,0x75,0x35,0x7f,0xbe,0x3c,0xff,0x80,0xbf,0x4,0x18,0x5b,0x6b,0x72,0xce,0x8b,0x82,0x9c,0xb3,0xd6,0x1a,0xbf,0x91,0x16,0x68,0x38,0xd,0xc7,0xe1,0xa5,0xf4,0x65,0xd3,0x75,0xdd,0x59,0x51,0xc6,0x9,0x2d,0xa1,0x77,0x41,0x99,0x92,0xb,0xeb,0xfc,0x3,0xd0,0xc5,0x44,0x36,0x1d,0x79,0x84,0xde,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x15,0x0,0x15,0x0,0x17,0xc8,0x7d,0x47,0xd1,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdf,0x6,0x14,0x14,0x32,0x15,0xe4,0x5,0x8a,0x4,0x0,0x0,0x0,0x1d,0x69,0x54,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x0,0x0,0x0,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x64,0x2e,0x65,0x7,0x0,0x0,0x0,0xa5,0x49,0x44,0x41,0x54,0x38,0xcb,0xed,0xd3,0x41,0x6a,0x2,0x51,0x10,0x4,0xd0,0xf7,0xe7,0xff,0xc1,0x30,0x4,0xe2,0x5a,0x18,0x4f,0x10,0x2,0x9e,0x29,0xe7,0xca,0x99,0x4,0xc9,0xda,0xcd,0x5c,0x20,0x8b,0x20,0x8a,0xfe,0x8c,0x9b,0x76,0xeb,0x8,0xb3,0xc9,0xc2,0x82,0xde,0x34,0x55,0xd5,0x34,0x54,0x25,0x74,0x58,0xe2,0x15,0x19,0xc9,0x7d,0x8c,0xa8,0xf8,0xc5,0x4f,0x9,0xf1,0x7,0x7a,0xbc,0x3c,0x68,0x70,0xc4,0x80,0x5d,0x89,0xcb,0x6b,0xef,0xcd,0x57,0xdd,0xd6,0x1e,0xed,0x84,0xc1,0x39,0x6f,0xf2,0xe0,0xfb,0xef,0x13,0xfb,0x82,0x82,0x45,0x88,0xf,0x31,0xf7,0xd0,0xd5,0x6d,0xed,0x73,0x9b,0x16,0x28,0x4d,0x2c,0x53,0x5c,0x9e,0x12,0xb,0x4e,0x7b,0x7b,0xb5,0x31,0x13,0x4f,0x83,0xff,0x64,0x30,0xe2,0x1c,0xbd,0x98,0x42,0x17,0xdc,0x51,0xa4,0xf0,0x82,0x53,0xde,0xe4,0x21,0xd2,0xf8,0xf6,0x50,0x94,0x39,0xe1,0x92,0xb0,0x9a,0x53,0xa6,0x34,0xb7,0xce,0x57,0x8f,0xdf,0x31,0x5b,0x17,0xde,0x59,0x7e,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
 };
 
 

+ 173 - 0
tools/editor/editor_data.cpp

@@ -424,9 +424,182 @@ void EditorData::remove_custom_type(const String& p_type){
 
 }
 
+int EditorData::add_edited_scene(int p_at_pos) {
+
+	if (p_at_pos<0)
+		p_at_pos=edited_scene.size();
+	EditedScene es;
+	es.root=NULL;
+	es.history_current=-1;
+	es.version=0;
+
+	if (p_at_pos==edited_scene.size())
+		edited_scene.push_back(es);
+	else
+		edited_scene.insert(p_at_pos,es);
+
+	if (current_edited_scene<0)
+		current_edited_scene=0;
+	return p_at_pos;
+}
+
+void EditorData::move_edited_scene_index(int p_idx,int p_to_idx){
+
+	ERR_FAIL_INDEX(p_idx,edited_scene.size());
+	ERR_FAIL_INDEX(p_to_idx,edited_scene.size());
+	SWAP(edited_scene[p_idx],edited_scene[p_to_idx]);
+}
+void EditorData::remove_scene(int p_idx){
+	ERR_FAIL_INDEX(p_idx,edited_scene.size());
+	if (edited_scene[p_idx].root)
+		memdelete(edited_scene[p_idx].root);
+
+	if (current_edited_scene>p_idx)
+		current_edited_scene--;
+	else if (current_edited_scene==p_idx && current_edited_scene>0) {
+		current_edited_scene--;
+	}
+
+	edited_scene.remove(p_idx);
+
+}
+int EditorData::get_edited_scene() const {
+
+	return current_edited_scene;
+}
+void EditorData::set_edited_scene(int p_idx){
+
+	ERR_FAIL_INDEX(p_idx,edited_scene.size());
+	current_edited_scene=p_idx;
+	//swap
+}
+Node* EditorData::get_edited_scene_root(){
+
+	ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),NULL);
+
+	return edited_scene[current_edited_scene].root;
+}
+void EditorData::set_edited_scene_root(Node* p_root) {
+
+	ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
+	edited_scene[current_edited_scene].root=p_root;
+}
+
+int EditorData::get_edited_scene_count() const {
+
+	return edited_scene.size();
+}
+
+void EditorData::set_edited_scene_version(uint64_t version) {
+	ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
+	edited_scene[current_edited_scene].version=version;
+
+}
+
+uint64_t EditorData::get_edited_scene_version() const{
+
+	ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),0);
+	return edited_scene[current_edited_scene].version;
+
+}
+uint64_t EditorData::get_scene_version(int p_idx) const{
+	ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),false);
+	return edited_scene[p_idx].version;
+}
+
+String EditorData::get_scene_title(int p_idx) const {
+	ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),String());
+	if (!edited_scene[p_idx].root)
+		return "[empty]";
+	if (edited_scene[p_idx].root->get_filename()=="")
+		return "[unsaved]";
+	return edited_scene[p_idx].root->get_filename().get_file();
+}
+
+
+String EditorData::get_scene_path(int p_idx) const {
+
+	ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),String());
+
+	if (!edited_scene[p_idx].root)
+		return "";
+	return edited_scene[p_idx].root->get_filename();
+
+}
+
+void EditorData::save_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history, const Dictionary& p_custom) {
+
+	ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
+
+	EditedScene &es=edited_scene[current_edited_scene];
+	es.selection = p_selection->get_selected_node_list();
+	es.history_current=p_history->current;
+	es.history_stored=p_history->history;
+	es.editor_states=get_editor_states();
+	es.custom_state=p_custom;
+
+}
+
+Dictionary EditorData::restore_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history) {
+	ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),Dictionary());
+
+	EditedScene &es=edited_scene[current_edited_scene];
+
+	p_history->current=es.history_current;
+	p_history->history=es.history_stored;
+
+
+	p_selection->clear();
+	for(List<Node*>::Element *E=es.selection.front();E;E=E->next()) {
+		p_selection->add_node(E->get());
+	}
+	set_editor_states(es.editor_states);
+
+	return es.custom_state;
+}
+
+
+void EditorData::set_edited_scene_import_metadata(Ref<ResourceImportMetadata> p_mdata) {
+
+	ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
+	edited_scene[current_edited_scene].medatata=p_mdata;
+
+}
+
+Ref<ResourceImportMetadata> EditorData::get_edited_scene_import_metadata() const{
+
+	ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),Ref<ResourceImportMetadata>());
+	return edited_scene[current_edited_scene].medatata;
+}
+
+void EditorData::clear_edited_scenes() {
+
+	for(int i=0;i<edited_scene.size();i++) {
+		if (edited_scene[i].root) {
+			memdelete( edited_scene[i].root );
+		}
+	}
+	edited_scene.clear();
+}
+
+
+
+void EditorData::set_plugin_window_layout(Ref<ConfigFile> p_layout) {
+	for(int i=0;i<editor_plugins.size();i++) {
+		editor_plugins[i]->set_window_layout(p_layout);
+	}
+}
+
+void EditorData::get_plugin_window_layout(Ref<ConfigFile> p_layout) {
+	for(int i=0;i<editor_plugins.size();i++) {
+		editor_plugins[i]->get_window_layout(p_layout);
+	}
+}
 
 EditorData::EditorData() {
 
+	current_edited_scene=-1;
+
 //	load_imported_scenes_from_globals();
 }
 

+ 44 - 0
tools/editor/editor_data.h

@@ -55,6 +55,7 @@ class EditorHistory {
 		Vector<Obj> path;
 		int level;
 	};
+friend class EditorData;
 
 	Vector<History> history;
 	int current;
@@ -91,6 +92,8 @@ public:
 	EditorHistory();
 };
 
+class EditorSelection;
+
 class EditorData {
 
 public:
@@ -117,6 +120,21 @@ private:
 
 	void _cleanup_history();
 
+	struct EditedScene {
+		Node* root;
+		Dictionary editor_states;
+		Ref<ResourceImportMetadata> medatata;
+		List<Node*> selection;
+		Vector<EditorHistory::History> history_stored;
+		int history_current;
+		Dictionary custom_state;
+		uint64_t version;
+
+
+	};
+
+	Vector<EditedScene> edited_scene;
+	int current_edited_scene;
 
 public:
 
@@ -146,6 +164,32 @@ public:
 	void remove_custom_type(const String& p_type);
 	const Map<String,Vector<CustomType> >& get_custom_types() const { return custom_types; }
 
+
+	int add_edited_scene(int p_at_pos);
+	void move_edited_scene_index(int p_idx,int p_to_idx);
+	void remove_scene(int p_idx);
+	void set_edited_scene(int p_idx);
+	void set_edited_scene_root(Node* p_root);
+	void set_edited_scene_import_metadata(Ref<ResourceImportMetadata> p_mdata);
+	Ref<ResourceImportMetadata> get_edited_scene_import_metadata() const;
+	int get_edited_scene() const;
+	Node* get_edited_scene_root();
+	int get_edited_scene_count() const;
+	String get_scene_title(int p_idx) const;
+	String get_scene_path(int p_idx) const;
+	void set_edited_scene_version(uint64_t version);
+	uint64_t get_edited_scene_version() const;
+	uint64_t get_scene_version(int p_idx) const;
+	void clear_edited_scenes();
+
+
+	void set_plugin_window_layout(Ref<ConfigFile> p_layout);
+	void get_plugin_window_layout(Ref<ConfigFile> p_layout);
+
+	void save_edited_scene_state(EditorSelection *p_selection,EditorHistory *p_history,const Dictionary& p_custom);
+	Dictionary restore_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history);
+
+
 	EditorData();
 };
 

+ 408 - 79
tools/editor/editor_node.cpp

@@ -105,11 +105,24 @@
 
 EditorNode *EditorNode::singleton=NULL;
 
+void EditorNode::_update_scene_tabs() {
+
+	scene_tabs->clear_tabs();
+	for(int i=0;i<editor_data.get_edited_scene_count();i++) {
+		int current = editor_data.get_edited_scene();
+		bool unsaved = (i==current)?saved_version!=editor_data.get_undo_redo().get_version():editor_data.get_scene_version(i)!=0;
+		scene_tabs->add_tab(editor_data.get_scene_title(i)+(unsaved?"(*)":""));
+	}
+
+	scene_tabs->set_current_tab(editor_data.get_edited_scene());
+
+}
+
 void EditorNode::_update_title() {
 
 	String appname = Globals::get_singleton()->get("application/name");
 	String title = appname.empty()?String(VERSION_FULL_NAME):String(_MKSTR(VERSION_NAME) + String(" - ") + appname);
-	String edited = edited_scene?edited_scene->get_filename():String();
+	String edited = editor_data.get_edited_scene_root()?editor_data.get_edited_scene_root()->get_filename():String();
 	if (!edited.empty())
 		title+=" - " + String(edited.get_file());
 	if (unsaved_cache)
@@ -174,6 +187,11 @@ void EditorNode::_notification(int p_what) {
 			_update_title();
 		}
 
+		if (last_checked_version!=editor_data.get_undo_redo().get_version()) {
+			_update_scene_tabs();
+			last_checked_version=editor_data.get_undo_redo().get_version();
+		}
+
 		//get_root_node()->set_rect(viewport->get_global_rect());
 
 		//update the circle
@@ -231,6 +249,13 @@ void EditorNode::_notification(int p_what) {
 
 		//import_monitor->scan_changes();
 	}
+
+	if (p_what==NOTIFICATION_EXIT_TREE) {
+
+
+		editor_data.clear_edited_scenes();
+
+	}
 	if (p_what==NOTIFICATION_READY) {
 
 		VisualServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport(),true);
@@ -468,7 +493,7 @@ void EditorNode::_dialog_display_file_error(String p_file,Error p_error) {
 
 void EditorNode::_get_scene_metadata() {
 
-	Node *scene = edited_scene;
+	Node *scene = editor_data.get_edited_scene_root();
 
 	if (!scene)
 		return;
@@ -495,7 +520,7 @@ void EditorNode::_get_scene_metadata() {
 
 void EditorNode::_set_scene_metadata() {
 
-	Node *scene = edited_scene;
+	Node *scene = editor_data.get_edited_scene_root();
 
 	if (!scene)
 		return;
@@ -718,7 +743,7 @@ void EditorNode::_save_edited_subresources(Node* scene,Map<RES,bool>& processed,
 	for(int i=0;i<scene->get_child_count();i++) {
 
 		Node *n = scene->get_child(i);
-		if (n->get_owner()!=edited_scene)
+		if (n->get_owner()!=editor_data.get_edited_scene_root())
 			continue;
 		_save_edited_subresources(n,processed,flags);
 	}
@@ -727,7 +752,7 @@ 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()))
+	if (p_node->is_type("Viewport") || (p_node!=editor_data.get_edited_scene_root() && p_node->get_owner()!=editor_data.get_edited_scene_root()))
 		return;
 
 	if (p_node->is_type("CanvasItem"))
@@ -748,7 +773,7 @@ void EditorNode::_save_scene_with_preview(String p_file) {
 
 	EditorProgress save("save","Saving Scene",4);
 	save.step("Analyzing",0);
-	_find_node_types(get_edited_scene(),c2d,c3d);
+	_find_node_types(editor_data.get_edited_scene_root(),c2d,c3d);
 
 	RID viewport;
 	bool is2d;
@@ -799,11 +824,11 @@ void EditorNode::_save_scene_with_preview(String p_file) {
 	img.save_png(pfile);
 	Vector<uint8_t> imgdata = FileAccess::get_file_as_array(pfile);
 
-	print_line("img data is "+itos(imgdata.size()));
+	//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);
+	if (editor_data.get_edited_scene_import_metadata().is_null())
+		editor_data.set_edited_scene_import_metadata(Ref<ResourceImportMetadata>( memnew( ResourceImportMetadata ) ) );
+	editor_data.get_edited_scene_import_metadata()->set_option("thumbnail",imgdata);
 
 	//tamanio tel thumbnail
 	if (screen!=-1) {
@@ -817,7 +842,7 @@ void EditorNode::_save_scene_with_preview(String p_file) {
 
 void EditorNode::_save_scene(String p_file) {
 
-	Node *scene = edited_scene;
+	Node *scene = editor_data.get_edited_scene_root();
 
 	if (!scene) {
 
@@ -851,7 +876,7 @@ void EditorNode::_save_scene(String p_file) {
 		return;
 	}
 
-	sdata->set_import_metadata(scene_import_metadata);
+	sdata->set_import_metadata(editor_data.get_edited_scene_import_metadata());
 	int flg=0;
 	if (EditorSettings::get_singleton()->get("on_save/compress_binary_resources"))
 		flg|=ResourceSaver::FLAG_COMPRESS;
@@ -867,7 +892,7 @@ void EditorNode::_save_scene(String p_file) {
 	if (err==OK) {
 		scene->set_filename( Globals::get_singleton()->localize_path(p_file) );
 		//EditorFileSystem::get_singleton()->update_file(p_file,sdata->get_type());
-		saved_version=editor_data.get_undo_redo().get_version();
+		set_current_version(editor_data.get_undo_redo().get_version());
 		_update_title();
 	} else {
 
@@ -1055,7 +1080,7 @@ void EditorNode::_dialog_action(String p_file) {
 			Node *base = selection.front()->get();
 
 			Map<Node*,Node*> reown;
-			reown[get_edited_scene()]=base;
+			reown[editor_data.get_edited_scene_root()]=base;
 			Node *copy = base->duplicate_and_reown(reown);
 			if (copy) {
 
@@ -1150,7 +1175,7 @@ void EditorNode::_dialog_action(String p_file) {
 				ml = Ref<MeshLibrary>( memnew( MeshLibrary ));
 			}
 
-			MeshLibraryEditor::update_library_file(edited_scene,ml,true);
+			MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(),ml,true);
 
 			Error err = ResourceSaver::save(p_file,ml);
 			if (err) {
@@ -1184,7 +1209,7 @@ void EditorNode::_dialog_action(String p_file) {
 				ml = Ref<TileSet>( memnew( TileSet ));
 			}
 
-			TileSetEditor::update_library_file(edited_scene,ml,true);
+			TileSetEditor::update_library_file(editor_data.get_edited_scene_root(),ml,true);
 
 			Error err = ResourceSaver::save(p_file,ml);
 			if (err) {
@@ -1325,15 +1350,15 @@ void EditorNode::_property_editor_back() {
 
 void EditorNode::_imported(Node *p_node) {
 
-	Node *scene = edited_scene;
-	set_edited_scene(p_node);
-
+	Node *scene = editor_data.get_edited_scene_root();
+//	add_edited_scene(p_node);
+/*
 	if (scene) {
 		String path = scene->get_filename();
 		p_node->set_filename(path);
 		memdelete(scene);
 	}
-
+*/
 
 
 }
@@ -1408,17 +1433,22 @@ void EditorNode::_edit_current() {
 		if (main_plugin!=editor_plugin_screen) {
 
 			// update screen main_plugin
-			if (editor_plugin_screen)
-				editor_plugin_screen->make_visible(false);
-			editor_plugin_screen=main_plugin;
-			editor_plugin_screen->edit(current_obj);
-			editor_plugin_screen->make_visible(true);
 
+			if (!changing_scene) {
 
-			for(int i=0;i<editor_table.size();i++) {
-				if (editor_table[i]==main_plugin) {
-					main_editor_tabs->set_current_tab(i);
-					break;
+				if (editor_plugin_screen)
+					editor_plugin_screen->make_visible(false);
+				editor_plugin_screen=main_plugin;
+				editor_plugin_screen->edit(current_obj);
+
+				editor_plugin_screen->make_visible(true);
+
+
+				for(int i=0;i<editor_table.size();i++) {
+					if (editor_table[i]==main_plugin) {
+						main_editor_tabs->set_current_tab(i);
+						break;
+					}
 				}
 			}
 
@@ -1527,10 +1557,10 @@ void EditorNode::_run(bool p_current,const String& p_custom) {
 
 
 
-	if (p_current || (edited_scene && p_custom==edited_scene->get_filename())) {
+	if (p_current || (editor_data.get_edited_scene_root() && p_custom==editor_data.get_edited_scene_root()->get_filename())) {
 
 
-		Node *scene = edited_scene;
+		Node *scene = editor_data.get_edited_scene_root();
 
 		if (!scene) {
 
@@ -1592,7 +1622,7 @@ void EditorNode::_run(bool p_current,const String& p_custom) {
 
 		if (unsaved_cache) {
 
-			Node *scene = edited_scene;
+			Node *scene = editor_data.get_edited_scene_root();
 
 			if (scene) { //only autosave if there is a scene obviously
 
@@ -1644,8 +1674,8 @@ void EditorNode::_run(bool p_current,const String& p_custom) {
 
 void EditorNode::_cleanup_scene() {
 
-
-	Node *scene = edited_scene;
+#if 0
+	Node *scene = editor_data.get_edited_scene_root();
 	editor_selection->clear();
 	editor_data.clear_editor_states();
 	editor_history.clear();
@@ -1654,7 +1684,7 @@ void EditorNode::_cleanup_scene() {
 	property_editor->edit(NULL);
 	resources_dock->cleanup();
 	scene_import_metadata.unref();
-	set_edited_scene(NULL);
+	//set_edited_scene(NULL);
 	if (scene) {
 		if (scene->get_filename()!="") {
 			previous_scenes.push_back(scene->get_filename());
@@ -1680,7 +1710,7 @@ void EditorNode::_cleanup_scene() {
 	}
 	
 	_update_title();
-
+#endif
 }
 
 void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
@@ -1693,16 +1723,20 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 	switch( p_option ) {
 		case FILE_NEW_SCENE: {
 
+			/*
 			if (!p_confirmed) {
 				confirmation->get_ok()->set_text("Yes");
 				//confirmation->get_cancel()->show();
 				confirmation->set_text("Start a New Scene? (Current will be lost)");
 				confirmation->popup_centered_minsize();
 				break;
-			}
+			}*/
+
 
+			int idx = editor_data.add_edited_scene(-1);
+			_scene_tab_changed(idx);
 
-			_cleanup_scene();
+			//_cleanup_scene();
 
 			
 		} break;
@@ -1722,7 +1756,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 			
 
 			//file->set_current_path(current_path);
-			Node *scene = edited_scene;
+			Node *scene = editor_data.get_edited_scene_root();
 			if (scene) {
 				file->set_current_path(scene->get_filename());
 			};
@@ -1754,11 +1788,26 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 			opening_prev=true;
 			open_request(previous_scenes.back()->get());
 
+		} break;
+		case FILE_CLOSE: {
+
+			if (!p_confirmed) {
+				confirmation->get_ok()->set_text("Yes");
+				//confirmation->get_cancel()->show();
+				confirmation->set_text("Close scene? (Unsaved changes will be lost)");
+				confirmation->popup_centered_minsize();
+				break;
+			}
+
+			_remove_edited_scene();
+
+
+
 		} break;
 		case FILE_SAVE_SCENE: {
 
 
-			Node *scene = edited_scene;
+			Node *scene = editor_data.get_edited_scene_root();
 			if (scene && scene->get_filename()!="") {
 
 				//_save_scene(scene->get_filename());
@@ -1769,7 +1818,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 		};
 		case FILE_SAVE_AS_SCENE: {
 			
-			Node *scene = edited_scene;
+			Node *scene = editor_data.get_edited_scene_root();
 			
 			if (!scene) {
 				
@@ -1831,7 +1880,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 
 		case FILE_DUMP_STRINGS: {
 
-			Node *scene = edited_scene;
+			Node *scene = editor_data.get_edited_scene_root();
 
 			if (!scene) {
 
@@ -1875,7 +1924,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 
 		case FILE_SAVE_SUBSCENE: {
 
-			Node *scene = edited_scene;
+			Node *scene = editor_data.get_edited_scene_root();
 
 			if (!scene) {
 
@@ -1902,7 +1951,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 
 			Node *tocopy = selection.front()->get();
 
-			if (tocopy!=edited_scene && tocopy->get_filename()!="") {
+			if (tocopy!=editor_data.get_edited_scene_root() && tocopy->get_filename()!="") {
 
 
 				current_option=-1;
@@ -1936,7 +1985,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 			file->set_title("Save Sub-Scene As..");
 		} break;
 		case FILE_SAVE_OPTIMIZED: {
-			Node *scene = edited_scene;
+			Node *scene = editor_data.get_edited_scene_root();
 #if 0
 			if (!scene) {
 
@@ -1998,7 +2047,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 
 		case FILE_EXPORT_MESH_LIBRARY: {
 
-			if (!edited_scene) {
+			if (!editor_data.get_edited_scene_root()) {
 
 				current_option=-1;
 				//confirmation->get_cancel()->hide();
@@ -2043,7 +2092,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 
 			//import_subscene->popup_centered_ratio();
 
-			if (!edited_scene) {
+			if (!editor_data.get_edited_scene_root()) {
 
 				current_option=-1;
 				//accept->get_cancel()->hide();
@@ -2569,30 +2618,54 @@ void EditorNode::remove_editor_import_plugin(const Ref<EditorImportPlugin>& p_ed
 	_rebuild_import_menu();
 }
 
+void EditorNode::_remove_edited_scene() {
+	int new_index = editor_data.get_edited_scene();
+	int old_index=new_index;
+
+	if (new_index>0) {
+		new_index=new_index-1;
+	} else if (editor_data.get_edited_scene_count()>1) {
+		new_index=1;
+	} else {
+		editor_data.add_edited_scene(-1);
+		new_index=1;
+	}
+
+	_scene_tab_changed(new_index);
+	editor_data.remove_scene(old_index);
+	editor_data.get_undo_redo().clear_history();
+	_update_title();
+	_update_scene_tabs();
 
+	if (editor_data.get_edited_scene_count()==1) {
+		//make new scene appear saved
+		set_current_version(editor_data.get_undo_redo().get_version());
+		unsaved_cache=false;
+	}
+}
 void EditorNode::set_edited_scene(Node *p_scene) {
 
-	if (edited_scene) {
-		if (edited_scene->get_parent()==scene_root)
-			scene_root->remove_child(edited_scene);
+	if (get_editor_data().get_edited_scene_root()) {
+		if (get_editor_data().get_edited_scene_root()->get_parent()==scene_root)
+			scene_root->remove_child(get_editor_data().get_edited_scene_root());
 		animation_editor->set_root(NULL);
 	}	
-	edited_scene=p_scene;
-	if (edited_scene && edited_scene->cast_to<Popup>())
-		edited_scene->cast_to<Popup>()->show(); //show popups
-	scene_tree_dock->set_edited_scene(edited_scene);
+	get_editor_data().set_edited_scene_root(p_scene);
+	
+	if (p_scene && p_scene->cast_to<Popup>())
+		p_scene->cast_to<Popup>()->show(); //show popups
+	scene_tree_dock->set_edited_scene(p_scene);
 	if (get_tree())
-		get_tree()->set_edited_scene_root(edited_scene);
+		get_tree()->set_edited_scene_root(p_scene);
 
-	if (edited_scene) {
+	if (p_scene) {
 		if (p_scene->get_parent()!=scene_root)
 			scene_root->add_child(p_scene);
 		animation_editor->set_root(p_scene);
 	}
-
-
 }
 
+
 void EditorNode::_fetch_translatable_strings(const Object *p_object,Set<StringName>& strings) {
 
 
@@ -2818,6 +2891,115 @@ Error EditorNode::save_optimized_copy(const String& p_scene,const String& p_pres
 	return OK;
 }
 
+
+Dictionary EditorNode::_get_main_scene_state() {
+
+	Dictionary state;
+	state["main_tab"]=main_editor_tabs->get_current_tab();
+	state["scene_tree_offset"]=scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->get_val();
+	state["property_edit_offset"]=get_property_editor()->get_scene_tree()->get_vscroll_bar()->get_val();
+	state["saved_version"]=saved_version;
+	//print_line(" getting main tab: "+itos(state["main_tab"]));
+	return state;
+}
+
+void EditorNode::_set_main_scene_state(Dictionary p_state) {
+
+	//print_line("set current 7 ");
+
+	if (p_state.has("main_tab")) {
+		int idx = p_state["main_tab"];
+		int current=-1;
+		for(int i=0;i<editor_table.size();i++) {
+			if (editor_plugin_screen==editor_table[i]) {
+				current=i;
+				break;
+			}
+		}
+
+		if (idx<2 && current<2) {
+			//only set tab for 2D and 3D
+			_editor_select(p_state["main_tab"]);
+			//print_line(" setting main tab: "+itos(p_state["main_tab"]));
+		}
+	}
+
+	if (p_state.has("scene_tree_offset"))
+		scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->set_val(p_state["scene_tree_offset"]);
+	if (p_state.has("property_edit_offset"))
+		get_property_editor()->get_scene_tree()->get_vscroll_bar()->set_val(p_state["property_edit_offset"]);
+
+	//print_line("set current 8 ");
+
+
+}
+
+void EditorNode::set_current_version(uint64_t p_version) {
+
+	saved_version=p_version;
+	editor_data.set_edited_scene_version(p_version);
+}
+
+bool EditorNode::is_changing_scene() const {
+	return changing_scene;
+}
+void EditorNode::set_current_scene(int p_idx) {
+
+	changing_scene=true;
+	editor_data.save_edited_scene_state(editor_selection,&editor_history,_get_main_scene_state());
+
+	if (get_editor_data().get_edited_scene_root()) {
+		if (get_editor_data().get_edited_scene_root()->get_parent()==scene_root)
+			scene_root->remove_child(get_editor_data().get_edited_scene_root());
+		animation_editor->set_root(NULL);
+	}
+
+	//print_line("set current 2 ");
+
+	editor_selection->clear();
+	editor_data.set_edited_scene(p_idx);
+
+	Node* new_scene = editor_data.get_edited_scene_root();
+
+	if (new_scene && new_scene->cast_to<Popup>())
+		new_scene->cast_to<Popup>()->show(); //show popups
+
+	//print_line("set current 3 ");
+
+	scene_tree_dock->set_edited_scene(new_scene);
+	if (get_tree())
+		get_tree()->set_edited_scene_root(new_scene);
+
+	if (new_scene) {
+		if (new_scene->get_parent()!=scene_root)
+			scene_root->add_child(new_scene);
+		animation_editor->set_root(new_scene);
+	}
+	//print_line("set current 4 ");
+
+
+	Dictionary state = editor_data.restore_edited_scene_state(editor_selection,&editor_history);
+	_edit_current();
+
+	/*if (!unsaved) {
+		saved_version=editor_data.get_undo_redo().get_version();
+		if (p_backwards)
+			saved_version--;
+		else
+			saved_version++;
+		print_line("was saved, updating version");
+	} else {
+		saved_version=state["saved_version"];
+	}*/
+	//_set_main_scene_state(state);
+
+	call_deferred("_set_main_scene_state",state); //do after everything else is done setting up
+	//print_line("set current 6 ");
+	changing_scene=false;
+
+
+}
+
 Error EditorNode::load_scene(const String& p_scene) {
 
 	if (!is_inside_tree()) {
@@ -2826,6 +3008,14 @@ Error EditorNode::load_scene(const String& p_scene) {
 	}
 
 
+	for(int i=0;i<editor_data.get_edited_scene_count();i++) {
+
+		if (editor_data.get_scene_path(i)==p_scene) {
+			_scene_tab_changed(i);
+			return OK;
+		}
+	}
+
 
 	load_errors->clear();
 	String lpath = Globals::get_singleton()->localize_path(p_scene);
@@ -2841,7 +3031,20 @@ Error EditorNode::load_scene(const String& p_scene) {
 		return ERR_FILE_NOT_FOUND;
 	}
 
-	_cleanup_scene(); // i'm sorry but this MUST happen to avoid modified resources to not be reloaded.
+	int prev = editor_data.get_edited_scene();
+	int idx = editor_data.add_edited_scene(-1);
+	//print_line("load scene callback");
+	//set_current_scene(idx);
+
+	if (!editor_data.get_edited_scene_root() && editor_data.get_edited_scene_count()==2) {
+		_remove_edited_scene();
+	} else {
+		_scene_tab_changed(idx);
+	}
+
+
+
+	//_cleanup_scene(); // i'm sorry but this MUST happen to avoid modified resources to not be reloaded.
 
 	Ref<PackedScene> sdata = ResourceLoader::load(lpath);
 	if (!sdata.is_valid()) {
@@ -2852,6 +3055,11 @@ Error EditorNode::load_scene(const String& p_scene) {
 		accept->set_text("Error loading scene.");
 		accept->popup_centered_minsize();
 		opening_prev=false;
+
+		if (prev!=-1) {
+			set_current_scene(prev);
+			editor_data.remove_scene(idx);
+		}
 		return ERR_FILE_NOT_FOUND;
 	}
 
@@ -2859,15 +3067,23 @@ Error EditorNode::load_scene(const String& p_scene) {
 
 	if (!new_scene) {
 
+		sdata.unref();
 		current_option=-1;
 		//accept->get_cancel()->hide();
 		accept->get_ok()->set_text("Ugh");
 		accept->set_text("Error loading scene.");
 		accept->popup_centered_minsize();
 		opening_prev=false;
+		if (prev!=-1) {
+			set_current_scene(prev);
+			editor_data.remove_scene(idx);
+		}
 		return ERR_FILE_NOT_FOUND;
 	}
 
+	//guess not needed in the end?
+	//new_scene->clear_internal_tree_resource_paths(); //make sure no internal tree paths to internal resources exist
+
 	/*
 	Node *old_scene = edited_scene;
 	_hide_top_editors();
@@ -2880,16 +3096,23 @@ Error EditorNode::load_scene(const String& p_scene) {
 		memdelete(old_scene);
 	}
 */
+
 	set_edited_scene(new_scene);
 	_get_scene_metadata();
+	/*
+	editor_data.set_edited_scene_root(new_scene);
+
 	scene_tree_dock->set_selected(new_scene, true);
 	property_editor->edit(new_scene);
-	scene_import_metadata = sdata->get_import_metadata();
+	editor_data.set_edited_scene_root(new_scene);
+*/
+	editor_data.set_edited_scene_import_metadata( sdata->get_import_metadata() );
 
-	editor_data.get_undo_redo().clear_history();
+
+//	editor_data.get_undo_redo().clear_history();
 	saved_version=editor_data.get_undo_redo().get_version();
 	_update_title();
-
+	_update_scene_tabs();
 	_add_to_recent_scenes(lpath);
 
 	if (new_scene->has_meta("__editor_plugin_screen__")) {
@@ -2919,8 +3142,9 @@ Error EditorNode::load_scene(const String& p_scene) {
 
 void EditorNode::open_request(const String& p_path) {
 
-	external_file=p_path;
-	_menu_option_confirm(FILE_EXTERNAL_OPEN_SCENE,false);
+	load_scene(p_path); // as it will be opened in separate tab
+	//external_file=p_path;
+	//_menu_option_confirm(FILE_EXTERNAL_OPEN_SCENE,false);
 }
 
 
@@ -3058,15 +3282,16 @@ void EditorNode::_open_recent_scene(int p_idx) {
 
 	String path = "res://"+rc[p_idx];
 
-	if (unsaved_cache) {
+
+	/*if (unsaved_cache) {
 		_recent_scene=rc[p_idx];
 		open_recent_confirmation->set_text("Discard current scene and open:\n'"+rc[p_idx]+"'");
 		open_recent_confirmation->get_label()->set_align(Label::ALIGN_CENTER);
 		open_recent_confirmation->popup_centered(Size2(400,100));
 		return;
-	}
+	}*/
 
-	load_scene(rc[p_idx]);
+	load_scene(path);
 
 
 }
@@ -3110,12 +3335,6 @@ void EditorNode::_save_optimized() {
 #endif
 }
 
-void EditorNode::_open_recent_scene_confirm() {
-
-	load_scene(_recent_scene);
-
-}
-
 void EditorNode::_update_recent_scenes() {
 
 	String base="_"+Globals::get_singleton()->get_resource_path().replace("\\","::").replace("/","::");
@@ -3325,7 +3544,7 @@ void EditorNode::_bind_methods() {
 	//ObjectTypeDB::bind_method("_import",&EditorNode::_import);
 //	ObjectTypeDB::bind_method("_import_conflicts_solved",&EditorNode::_import_conflicts_solved);
 	ObjectTypeDB::bind_method("_open_recent_scene",&EditorNode::_open_recent_scene);
-	ObjectTypeDB::bind_method("_open_recent_scene_confirm",&EditorNode::_open_recent_scene_confirm);
+//	ObjectTypeDB::bind_method("_open_recent_scene_confirm",&EditorNode::_open_recent_scene_confirm);
 
 	ObjectTypeDB::bind_method("_save_optimized",&EditorNode::_save_optimized);
 	ObjectTypeDB::bind_method(_MD("animation_panel_make_visible","enable"),&EditorNode::animation_panel_make_visible);
@@ -3343,6 +3562,11 @@ void EditorNode::_bind_methods() {
 	ObjectTypeDB::bind_method("_dock_move_left",&EditorNode::_dock_move_left);
 	ObjectTypeDB::bind_method("_dock_move_right",&EditorNode::_dock_move_right);
 
+	ObjectTypeDB::bind_method("set_current_scene",&EditorNode::set_current_scene);
+	ObjectTypeDB::bind_method("set_current_version",&EditorNode::set_current_version);
+	ObjectTypeDB::bind_method("_scene_tab_changed",&EditorNode::_scene_tab_changed);
+	ObjectTypeDB::bind_method("_set_main_scene_state",&EditorNode::_set_main_scene_state);
+	ObjectTypeDB::bind_method("_update_scene_tabs",&EditorNode::_update_scene_tabs);
 
 
 
@@ -3655,10 +3879,29 @@ void EditorNode::_save_docks() {
 	}
 
 
+	HSplitContainer *h_splits[4]={
+		left_l_hsplit,
+		left_r_hsplit,
+		main_hsplit,
+		right_hsplit,
+	};
+
+	for(int i=0;i<4;i++) {
+
+		config->set_value("docks","dock_hsplit_"+itos(i+1),h_splits[i]->get_split_offset());
+	}
+
+	editor_data.get_plugin_window_layout(config);
+
 	config->save(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg"));
 
 }
 
+void EditorNode::save_layout() {
+
+	dock_drag_timer->start();
+}
+
 void EditorNode::_dock_split_dragged(int ofs) {
 
 	dock_drag_timer->start();
@@ -3732,6 +3975,20 @@ void EditorNode::_load_docks() {
 		splits[i]->set_split_offset(ofs);
 	}
 
+	HSplitContainer *h_splits[4]={
+		left_l_hsplit,
+		left_r_hsplit,
+		main_hsplit,
+		right_hsplit,
+	};
+
+	for(int i=0;i<4;i++) {
+		if (!config->has_section_key("docks","dock_hsplit_"+itos(i+1)))
+			continue;
+		int ofs = config->get_value("docks","dock_hsplit_"+itos(i+1));
+		h_splits[i]->set_split_offset(ofs);
+	}
+
 	for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
 		bool in_use = dock_slot[i*2+0]->get_tab_count() || dock_slot[i*2+1]->get_tab_count();
 		if (in_use)
@@ -3747,6 +4004,38 @@ void EditorNode::_load_docks() {
 		}
 	}
 
+	editor_data.set_plugin_window_layout(config);
+
+}
+
+
+void EditorNode::_scene_tab_changed(int p_tab) {
+
+
+	//print_line("set current 1 ");
+	bool unsaved = (saved_version!=editor_data.get_undo_redo().get_version());
+	//print_line("version: "+itos(editor_data.get_undo_redo().get_version())+", saved "+itos(saved_version));
+
+	if (p_tab==editor_data.get_edited_scene())
+		return; //pointless
+
+	uint64_t next_scene_version = editor_data.get_scene_version(p_tab);
+
+
+
+	//print_line("scene tab changed???");
+	editor_data.get_undo_redo().create_action("Switch Scene Tab");
+	editor_data.get_undo_redo().add_do_method(this,"set_current_version",unsaved?saved_version:0);
+	editor_data.get_undo_redo().add_do_method(this,"set_current_scene",p_tab);
+	editor_data.get_undo_redo().add_do_method(scene_tabs,"set_current_tab",p_tab);
+	editor_data.get_undo_redo().add_do_method(this,"set_current_version",next_scene_version==0?editor_data.get_undo_redo().get_version()+1:next_scene_version);
+
+	editor_data.get_undo_redo().add_undo_method(this,"set_current_version",next_scene_version);
+	editor_data.get_undo_redo().add_undo_method(this,"set_current_scene",editor_data.get_edited_scene());
+	editor_data.get_undo_redo().add_undo_method(scene_tabs,"set_current_tab",editor_data.get_edited_scene());
+	editor_data.get_undo_redo().add_undo_method(this,"set_current_version",saved_version);
+	editor_data.get_undo_redo().commit_action();
+
 }
 
 EditorNode::EditorNode() {
@@ -3754,6 +4043,8 @@ EditorNode::EditorNode() {
 	EditorHelp::generate_doc(); //before any editor classes are crated
 
 	singleton=this;
+	last_checked_version=0;
+	changing_scene=false;
 
 	FileAccess::set_backup_save(true);
 
@@ -3841,14 +4132,38 @@ EditorNode::EditorNode() {
 	gui_base->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END );
 	gui_base->set_anchor( MARGIN_BOTTOM, Control::ANCHOR_END );
 	gui_base->set_end( Point2(0,0) );
-	
+
 	main_vbox = memnew( VBoxContainer );
 	gui_base->add_child(main_vbox);
 	main_vbox->set_area_as_parent_rect(8);
 
+	PanelContainer *top_dark_panel = memnew( PanelContainer );
+	Ref<StyleBoxTexture> top_dark_sb;
+	top_dark_sb.instance();;
+	top_dark_sb->set_texture(theme->get_icon("PanelTop","EditorIcons"));
+	for(int i=0;i<4;i++) {
+		top_dark_sb->set_margin_size(Margin(i),3);
+		top_dark_sb->set_default_margin(Margin(i),0);
+	}
+	top_dark_sb->set_expand_margin_size(MARGIN_LEFT,20);
+	top_dark_sb->set_expand_margin_size(MARGIN_RIGHT,20);
+
+	top_dark_panel->add_style_override("panel",top_dark_sb);
+	VBoxContainer *top_dark_vb = memnew( VBoxContainer );
+	main_vbox->add_child(top_dark_panel);
+	top_dark_panel->add_child(top_dark_vb);
+
+
+
+
 	menu_hb = memnew( HBoxContainer );
-	main_vbox->add_child(menu_hb);
+	top_dark_vb->add_child(menu_hb);
 
+	scene_tabs=memnew( Tabs );
+	scene_tabs->add_tab("unsaved");
+	scene_tabs->set_tab_align(Tabs::ALIGN_CENTER);
+	scene_tabs->connect("tab_changed",this,"_scene_tab_changed");
+	top_dark_vb->add_child(scene_tabs);
 	//left
 	left_l_hsplit = memnew( HSplitContainer );
 	main_vbox->add_child(left_l_hsplit);
@@ -3912,6 +4227,12 @@ EditorNode::EditorNode() {
 	right_l_vsplit->connect("dragged",this,"_dock_split_dragged");
 	right_r_vsplit->connect("dragged",this,"_dock_split_dragged");
 
+	left_l_hsplit->connect("dragged",this,"_dock_split_dragged");
+	left_r_hsplit->connect("dragged",this,"_dock_split_dragged");
+	main_hsplit->connect("dragged",this,"_dock_split_dragged");
+	right_hsplit->connect("dragged",this,"_dock_split_dragged");
+
+
 
 	dock_select_popoup = memnew( PopupPanel );
 	gui_base->add_child(dock_select_popoup);
@@ -4101,7 +4422,9 @@ EditorNode::EditorNode() {
 	p->add_item("Save Scene",FILE_SAVE_SCENE,KEY_MASK_CMD+KEY_S);
 	p->add_item("Save Scene As..",FILE_SAVE_AS_SCENE,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_S);
 	p->add_separator();
-	p->add_item("Goto Prev. Scene",FILE_OPEN_PREV,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_P);
+	p->add_item("Close Scene",FILE_CLOSE,KEY_MASK_SHIFT+KEY_MASK_CTRL+KEY_W);
+	p->add_separator();
+	p->add_item("Close Goto Prev. Scene",FILE_OPEN_PREV,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_P);
 	p->add_submenu_item("Open Recent","RecentScenes",FILE_OPEN_RECENT);
 	p->add_separator();
 	p->add_item("Quick Open Scene..",FILE_QUICK_OPEN_SCENE,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_O);
@@ -4791,8 +5114,8 @@ EditorNode::EditorNode() {
 	}
 
 
-	edited_scene=NULL;
-	saved_version=0;
+	//edited_scene=NULL;
+	saved_version=1;
 	unsaved_cache=true;
 	_last_instanced_scene=NULL;
 
@@ -4854,7 +5177,13 @@ EditorNode::EditorNode() {
 	for(int i=0;i<_init_callbacks.size();i++)
 		_init_callbacks[i]();
 
+	editor_data.add_edited_scene(-1);
+	editor_data.set_edited_scene(0);
+	_update_scene_tabs();
+
 	_load_docks();
+
+
 }
 
 

+ 26 - 7
tools/editor/editor_node.h

@@ -125,6 +125,7 @@ class EditorNode : public Node {
 		FILE_QUICK_OPEN_SCRIPT,
 		FILE_RUN_SCRIPT,
 		FILE_OPEN_PREV,
+		FILE_CLOSE,
 		FILE_QUIT,
 		FILE_EXTERNAL_OPEN_SCENE,
 		EDIT_UNDO,
@@ -183,16 +184,16 @@ class EditorNode : public Node {
 	};
 
 
-	Node *edited_scene; //scene being edited
+	//Node *edited_scene; //scene being edited
 	Viewport *scene_root; //root of the scene being edited
 
-	Ref<ResourceImportMetadata> scene_import_metadata;
+	//Ref<ResourceImportMetadata> scene_import_metadata;
 
 	Control* scene_root_parent;
 	Control *gui_base;
 	VBoxContainer *main_vbox;
 
-
+	//split
 
 	HSplitContainer *left_l_hsplit;
 	VSplitContainer *left_l_vsplit;
@@ -205,6 +206,9 @@ class EditorNode : public Node {
 
 	VSplitContainer *center_split;
 
+	//main tabs
+
+	Tabs *scene_tabs;
 
 
 	int old_split_ofs;
@@ -324,8 +328,10 @@ class EditorNode : public Node {
 	bool reference_resource_mem;
 	bool save_external_resources_mem;
 	uint64_t saved_version;
+	uint64_t last_checked_version;
 	bool unsaved_cache;
 	String open_navigate;
+	bool changing_scene;
 
 	uint32_t circle_step_msec;
 	uint64_t circle_step_frame;
@@ -375,6 +381,7 @@ class EditorNode : public Node {
 	void _set_scene_metadata();
 	void _get_scene_metadata();
 	void _update_title();
+	void _update_scene_tabs();
 	void _close_messages();
 	void _show_messages();
 	void _vp_resized();
@@ -402,7 +409,7 @@ class EditorNode : public Node {
 	void _add_to_recent_scenes(const String& p_scene);
 	void _update_recent_scenes();
 	void _open_recent_scene(int p_idx);
-	void _open_recent_scene_confirm();
+	//void _open_recent_scene_confirm();
 	String _recent_scene;
 
 	bool convert_old;
@@ -431,7 +438,7 @@ class EditorNode : public Node {
 
 
 	void _cleanup_scene();
-
+	void _remove_edited_scene();
 	bool _find_and_save_resource(RES p_res,Map<RES,bool>& processed,int32_t flags);
 	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);
@@ -461,6 +468,10 @@ class EditorNode : public Node {
 	void _dock_pre_popup(int p_which);
 	void _dock_split_dragged(int ofs);
 	void _dock_popup_exit();
+	void _scene_tab_changed(int p_tab);
+
+	Dictionary _get_main_scene_state();
+	void _set_main_scene_state(Dictionary p_state);
 
 	void _save_docks();
 	void _load_docks();
@@ -498,7 +509,7 @@ public:
 
 	void open_request(const String& p_path);
 
-	void set_edited_scene(Node *p_scene);
+	bool is_changing_scene() const;
 
 
 	static EditorLog *get_log() { return singleton->log; }
@@ -511,7 +522,9 @@ public:
 	void hide_animation_player_editors();
 	void animation_panel_make_visible(bool p_visible);
 
-	Node *get_edited_scene() { return edited_scene; }
+	void set_edited_scene(Node *p_scene);
+
+	Node *get_edited_scene() { return editor_data.get_edited_scene_root(); }
 
 	Viewport *get_scene_root() { return scene_root; } //root of the scene being edited
 	Error save_optimized_copy(const String& p_scene,const String& p_preset);
@@ -520,6 +533,9 @@ public:
 	Error load_scene(const String& p_scene);
 	Error load_resource(const String& p_scene);
 
+	void set_current_version(uint64_t p_version);
+	void set_current_scene(int p_idx);
+
 	static EditorData& get_editor_data() { return singleton->editor_data; }
 
 	static VSplitContainer *get_top_split() { return singleton->top_split; }
@@ -566,6 +582,9 @@ public:
 	bool is_scene_in_use(const String& p_path);
 
 	void scan_import_changes();
+
+	void save_layout();
+
 	EditorNode();	
 	~EditorNode();
 	void get_singleton(const char* arg1, bool arg2);

+ 7 - 0
tools/editor/editor_plugin.cpp

@@ -197,6 +197,13 @@ bool EditorPlugin::get_remove_list(List<Node*> *p_list) {
 void EditorPlugin::restore_global_state() {}
 void EditorPlugin::save_global_state() {}
 
+void EditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) {
+
+}
+
+void EditorPlugin::get_window_layout(Ref<ConfigFile> p_layout){
+
+}
 
 void EditorPlugin::_bind_methods() {
 

+ 3 - 1
tools/editor/editor_plugin.h

@@ -32,7 +32,7 @@
 #include "scene/main/node.h"
 #include "scene/resources/texture.h"
 #include "undo_redo.h"
-
+#include "io/config_file.h"
 /**
 	@author Juan Linietsky <[email protected]>
 */
@@ -90,6 +90,8 @@ public:
 	virtual void apply_changes() ; // if changes are pending in editor, apply them
 	virtual void get_breakpoints(List<String> *p_breakpoints);
 	virtual bool get_remove_list(List<Node*> *p_list);
+	virtual void set_window_layout(Ref<ConfigFile> p_layout);
+	virtual void get_window_layout(Ref<ConfigFile> p_layout);
 
 	virtual void restore_global_state();
 	virtual void save_global_state();

+ 1 - 1
tools/editor/editor_run_script.cpp

@@ -18,7 +18,7 @@ void EditorScript::add_root_node(Node *p_node) {
 		return;
 	}
 
-	editor->set_edited_scene(p_node);
+//	editor->set_edited_scene(p_node);
 }
 
 Node *EditorScript::get_scene() {

+ 2 - 0
tools/editor/editor_settings.cpp

@@ -433,9 +433,11 @@ void EditorSettings::_load_defaults() {
 	set("text_editor/idle_parse_delay",2);
 	set("text_editor/create_signal_callbacks",true);
 	set("text_editor/autosave_interval_secs",0);
+
 	set("text_editor/font","");
 	hints["text_editor/font"]=PropertyInfo(Variant::STRING,"text_editor/font",PROPERTY_HINT_GLOBAL_FILE,"*.fnt");
 	set("text_editor/auto_brace_complete", false);
+	set("text_editor/restore_scripts_on_load",true);
 
 
 	set("scenetree_editor/duplicate_node_name_num_separator",0);

BIN
tools/editor/icons/icon_panel_top.png


+ 1 - 1
tools/editor/io_plugins/editor_mesh_import_plugin.cpp

@@ -105,7 +105,7 @@ public:
 	_EditorMeshImportOptions() {
 
 		generate_tangents=true;
-		generate_normals=true;
+		generate_normals=false;
 		flip_faces=false;
 		smooth_shading=false;
 		weld_vertices=true;

+ 1 - 1
tools/editor/plugins/multimesh_editor_plugin.cpp

@@ -305,7 +305,7 @@ void MultiMeshEditor::edit(MultiMeshInstance *p_multimesh) {
 void MultiMeshEditor::_browse(bool p_source) {
 
 	browsing_source=p_source;
-	std->get_tree()->set_marked(node,false);
+	std->get_scene_tree()->set_marked(node,false);
 	std->popup_centered_ratio();
 	if (p_source)
 		std->set_title("Select a Source Mesh:");

+ 240 - 141
tools/editor/plugins/script_editor_plugin.cpp

@@ -38,10 +38,12 @@
 #include "os/file_access.h"
 #include "scene/main/viewport.h"
 #include "os/keyboard.h"
-/*** SCRIPT EDITOR ****/
+#include "os/input.h"
 
+/*** SCRIPT EDITOR ****/
 
 
+#define SORT_SCRIPT_LIST
 
 void ScriptEditorQuickOpen::popup(const Vector<String>& p_functions, bool p_dontclear) {
 
@@ -118,6 +120,8 @@ void ScriptEditorQuickOpen::_notification(int p_what) {
 	if (p_what==NOTIFICATION_ENTER_TREE) {
 
 		connect("confirmed",this,"_confirmed");
+
+
 	}
 }
 
@@ -296,12 +300,11 @@ void ScriptTextEditor::_notification(int p_what) {
 
 	if (p_what==NOTIFICATION_READY) {
 
-		_update_name();
+		//emit_signal("name_changed");
 	}
 }
 
-void ScriptTextEditor::_update_name() {
-
+String ScriptTextEditor::get_name()  {
 	String name;
 
 	if (script->get_path().find("local://")==-1 && script->get_path().find("::")==-1) {
@@ -314,21 +317,20 @@ void ScriptTextEditor::_update_name() {
 	else
 		name=script->get_type()+"("+itos(script->get_instance_ID())+")";
 
+	return name;
 
-	if (name!=String(get_name())) {
+}
 
-		set_name(name);
+Ref<Texture> ScriptTextEditor::get_icon() {
 
+	if (get_parent_control() && get_parent_control()->has_icon(script->get_type(),"EditorIcons")) {
+		return get_parent_control()->get_icon(script->get_type(),"EditorIcons");
 	}
 
-	if (!has_meta("_tab_icon")) {
-		if (get_parent_control() && get_parent_control()->has_icon(script->get_type(),"EditorIcons")) {
-			set_meta("_tab_icon",get_parent_control()->get_icon(script->get_type(),"EditorIcons"));
-		}
-	}
+	return Ref<Texture>();
+}
 
 
-}
 
 void ScriptTextEditor::set_edited_script(const Ref<Script>& p_script) {
 
@@ -344,8 +346,7 @@ void ScriptTextEditor::set_edited_script(const Ref<Script>& p_script) {
 	get_text_edit()->tag_saved_version();
 
 
-	_update_name();
-
+	emit_signal("name_changed");
 	_line_col_changed();
 }
 
@@ -384,7 +385,7 @@ void ScriptTextEditor::_validate_script() {
 		te->set_line_as_marked(i,line==i);
 	}
 
-	_update_name();
+	emit_signal("name_changed");
 }
 
 
@@ -418,6 +419,10 @@ void ScriptTextEditor::_code_complete_script(const String& p_code, List<String>*
 	}
 
 }
+void ScriptTextEditor::_bind_methods() {
+
+	ADD_SIGNAL(MethodInfo("name_changed"));
+}
 
 ScriptTextEditor::ScriptTextEditor() {
 
@@ -492,11 +497,15 @@ void ScriptEditor::_close_current_tab() {
 	memdelete(current);
 	if (idx>=tab_container->get_child_count())
 		idx=tab_container->get_child_count()-1;
-	if (idx>=0)
+	if (idx>=0) {
 		tab_container->set_current_tab(idx);
+		//script_list->select(idx);
+	}
+
 
-	_update_window_menu();
-	_save_files_state();
+
+	_update_script_names();
+	EditorNode::get_singleton()->save_layout();
 
 }
 
@@ -587,10 +596,10 @@ void ScriptEditor::_res_saved_callback(const Ref<Resource>& p_res) {
 			ste->get_text_edit()->tag_saved_version();
 		}
 
-		ste->_update_name();
-
 	}
 
+	_update_script_names();
+
 }
 
 bool ScriptEditor::_test_script_times_on_disk() {
@@ -1045,7 +1054,7 @@ void ScriptEditor::_menu_option(int p_option) {
 			if (text != "")
 				editor->emit_signal("request_help", text);
 		} break;
-		case WINDOW_CLOSE: {
+		case FILE_CLOSE: {
 			if (current->get_text_edit()->get_version()!=current->get_text_edit()->get_saved_version()) {
 				erase_tab_confirm->set_text("Close and save changes?\n\""+current->get_name()+"\"");
 				erase_tab_confirm->popup_centered_minsize();
@@ -1057,16 +1066,18 @@ void ScriptEditor::_menu_option(int p_option) {
 
 			if (tab_container->get_current_tab()>0) {
 				tab_container->call_deferred("set_current_tab",tab_container->get_current_tab()-1);
+				script_list->call_deferred("select",tab_container->get_current_tab()-1);
 				tab_container->move_child(current,tab_container->get_current_tab()-1);
-				_update_window_menu();
+				_update_script_names();
 			}
 		} break;
 		case WINDOW_MOVE_RIGHT: {
 
 			if (tab_container->get_current_tab()<tab_container->get_child_count()-1) {
 				tab_container->call_deferred("set_current_tab",tab_container->get_current_tab()+1);
+				script_list->call_deferred("select",tab_container->get_current_tab()+1);
 				tab_container->move_child(current,tab_container->get_current_tab()+1);
-				_update_window_menu();
+				_update_script_names();
 			}
 
 
@@ -1076,6 +1087,8 @@ void ScriptEditor::_menu_option(int p_option) {
 			if (p_option>=WINDOW_SELECT_BASE) {
 
 				tab_container->set_current_tab(p_option-WINDOW_SELECT_BASE);
+				script_list->select(p_option-WINDOW_SELECT_BASE);
+
 			}
 		}
 	}
@@ -1096,6 +1109,8 @@ void ScriptEditor::_notification(int p_what) {
 		editor->connect("stop_pressed",this,"_editor_stop");
 		editor->connect("script_add_function_request",this,"_add_callback");
 		editor->connect("resource_saved",this,"_res_saved_callback");
+		script_list->connect("item_selected",this,"_script_selected");
+		script_split->connect("dragged",this,"_script_split_dragged");
 		autosave_timer->connect("timeout",this,"_autosave_scripts");
 		{
 			float autosave_time = EditorSettings::get_singleton()->get("text_editor/autosave_interval_secs");
@@ -1113,7 +1128,8 @@ void ScriptEditor::_notification(int p_what) {
 	}
 
 	if (p_what==NOTIFICATION_READY) {
-		_update_window_menu();
+
+		get_tree()->connect("tree_changed",this,"_tree_changed");
 	}
 
 	if (p_what==NOTIFICATION_EXIT_TREE) {
@@ -1153,10 +1169,11 @@ static const Node * _find_node_with_script(const Node* p_node, const RefPtr & p_
 
 Dictionary ScriptEditor::get_state() const {
 
-	apply_scripts();
 
-	Dictionary state;
+//	apply_scripts();
 
+	Dictionary state;
+#if 0
 	Array paths;
 	int open=-1;
 
@@ -1189,12 +1206,12 @@ Dictionary ScriptEditor::get_state() const {
 	if (open!=-1)
 		state["current"]=open;
 
-
+#endif
 	return state;
 }
 void ScriptEditor::set_state(const Dictionary& p_state) {
 
-
+#if 0
 	print_line("attempt set state: "+String(Variant(p_state)));
 
 	if (!p_state.has("sources"))
@@ -1231,6 +1248,7 @@ void ScriptEditor::set_state(const Dictionary& p_state) {
 	if (p_state.has("current")) {
 		tab_container->set_current_tab(p_state["current"]);
 	}
+#endif
 
 }
 void ScriptEditor::clear() {
@@ -1254,68 +1272,17 @@ void ScriptEditor::clear() {
 	int idx = tab_container->get_current_tab();
 	if (idx>=tab_container->get_child_count())
 		idx=tab_container->get_child_count()-1;
-	if (idx>=0)
+	if (idx>=0) {
 		tab_container->set_current_tab(idx);
-
-	_update_window_menu();
-
-
-}
-
-void ScriptEditor::_save_files_state() {
-
-	return; //no thank you
-
-	String rpath="_open_scripts_"+Globals::get_singleton()->get_resource_path();
-	rpath=rpath.replace("\\","_-_");
-	rpath=rpath.replace("/","_-_");
-	rpath=rpath.replace(":","_");
-
-	Vector<String> scripts;
-
-	for(int i=0;i<tab_container->get_child_count();i++) {
-
-		ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
-		if (!ste)
-			continue;
-
-
-		Ref<Script> script = ste->get_edited_script();
-		if (script->get_path()!="" && script->get_path().find("local://")==-1 && script->get_path().find("::")==-1) {
-
-
-			scripts.push_back(script->get_path());
-		}
+		script_list->select( script_list->find_metadata(idx) );
 	}
 
 
-	EditorSettings::get_singleton()->set(rpath,scripts);
-	EditorSettings::get_singleton()->save();
-
-}
-
-void ScriptEditor::_load_files_state() {
-	return;
-
-	String rpath="_open_scripts_"+Globals::get_singleton()->get_resource_path();
-	rpath=rpath.replace("\\","_-_");
-	rpath=rpath.replace("/","_-_");
-	rpath=rpath.replace(":","_");
 
-	if (EditorSettings::get_singleton()->has(rpath)) {
-
-		Vector<String> open_files=EditorSettings::get_singleton()->get("rpath");
-		for(int i=0;i<open_files.size();i++) {
-			Ref<Script> scr = ResourceLoader::load(open_files[i]);
-			if (!scr.is_valid())
-				continue;
-
-			editor->edit_resource(scr);
-		}
-	}
 
 }
 
+
 void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) {
 
 	for(int i=0;i<tab_container->get_child_count();i++) {
@@ -1360,11 +1327,18 @@ void ScriptEditor::_bind_methods() {
 	ObjectTypeDB::bind_method("_get_debug_tooltip",&ScriptEditor::_get_debug_tooltip);
 	ObjectTypeDB::bind_method("_autosave_scripts",&ScriptEditor::_autosave_scripts);
 	ObjectTypeDB::bind_method("_editor_settings_changed",&ScriptEditor::_editor_settings_changed);
+	ObjectTypeDB::bind_method("_update_script_names",&ScriptEditor::_update_script_names);
+	ObjectTypeDB::bind_method("_tree_changed",&ScriptEditor::_tree_changed);
+	ObjectTypeDB::bind_method("_script_selected",&ScriptEditor::_script_selected);
+	ObjectTypeDB::bind_method("_script_split_dragged",&ScriptEditor::_script_split_dragged);
 }
 
 
 void ScriptEditor::ensure_focus_current() {
 
+	if (!is_inside_tree())
+		return;
+
 	int cidx = tab_container->get_current_tab();
 	if (cidx<0 || cidx>=tab_container->get_tab_count());
 	Control *c = tab_container->get_child(cidx)->cast_to<Control>();
@@ -1376,6 +1350,13 @@ void ScriptEditor::ensure_focus_current() {
 	ste->get_text_edit()->grab_focus();
 }
 
+void ScriptEditor::_script_selected(int p_idx) {
+
+	grab_focus_block = !Input::get_singleton()->is_mouse_button_pressed(1); //amazing hack, simply amazing
+	tab_container->set_current_tab(script_list->get_item_metadata(p_idx));
+	grab_focus_block=false;
+}
+
 void ScriptEditor::ensure_select_current() {
 
 
@@ -1386,8 +1367,66 @@ void ScriptEditor::ensure_select_current() {
 			return;
 		Ref<Script> script = ste->get_edited_script();
 
-		ste->get_text_edit()->grab_focus();
+		if (!grab_focus_block && is_inside_tree())
+			ste->get_text_edit()->grab_focus();
+	}
+
+
+}
+
+void ScriptEditor::_find_scripts(Node* p_base, Node* p_current, Set<Ref<Script> > &used) {
+	if (p_current!=p_base && p_current->get_owner()!=p_base)
+		return;
+
+	if (p_current->get_script_instance()) {
+		Ref<Script> scr = p_current->get_script();
+		if (scr.is_valid())
+			used.insert(scr);
+	}
+
+	for(int i=0;i<p_current->get_child_count();i++) {
+		_find_scripts(p_base,p_current->get_child(i),used);
+	}
+
+}
+
+
+void ScriptEditor::_update_script_names() {
+
+	waiting_update_names=false;
+	Set<Ref<Script> > used;
+	Node* edited = EditorNode::get_singleton()->get_edited_scene();
+	if (edited) {
+		_find_scripts(edited,edited,used);
+	}
+
+	script_list->clear();
+	for(int i=0;i<tab_container->get_child_count();i++) {
+
+		ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
+		if (!ste)
+			continue;
+
+		String script = ste->get_name();
+		Ref<Texture> icon = ste->get_icon();
+		String path = ste->get_edited_script()->get_path();
+		script_list->add_item(script,icon);
+
+		int index = script_list->get_item_count()-1;
+
+		script_list->set_item_tooltip(index,path);
+		script_list->set_item_metadata(index,i);
+		if (used.has(ste->get_edited_script())) {
+
+			script_list->set_item_custom_bg_color(index,Color(88/255.0,88/255.0,60/255.0));
+		}
+		if (tab_container->get_current_tab()==index) {
+			script_list->select(index);
+		}
 	}
+
+	script_list->sort_items_by_text();
+
 }
 
 void ScriptEditor::edit(const Ref<Script>& p_script) {
@@ -1425,9 +1464,13 @@ void ScriptEditor::edit(const Ref<Script>& p_script) {
 
 		if (ste->get_edited_script()==p_script) {
 
-			if (tab_container->get_current_tab()!=i)
-				tab_container->set_current_tab(i);
-			ste->get_text_edit()->grab_focus();
+			if (!EditorNode::get_singleton()->is_changing_scene()) {
+				if (tab_container->get_current_tab()!=i) {
+					tab_container->set_current_tab(i);
+					script_list->select( script_list->find_metadata(i) );
+				}
+				ste->get_text_edit()->grab_focus();
+			}
 			return;
 		}
 	}
@@ -1440,9 +1483,13 @@ void ScriptEditor::edit(const Ref<Script>& p_script) {
 	tab_container->add_child(ste);
 	tab_container->set_current_tab(tab_container->get_tab_count()-1);
 
-	_update_window_menu();
-	_save_files_state();
 
+
+	_update_script_names();
+	ste->connect("name_changed",this,"_update_script_names");
+	if (!restoring_layout) {
+		EditorNode::get_singleton()->save_layout();
+	}
 }
 
 void ScriptEditor::save_external_data() {
@@ -1502,51 +1549,6 @@ void ScriptEditor::_editor_stop() {
 	debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), true );
 }
 
-void ScriptEditor::_update_window_menu() {
-
-	int idx=0;
-	for(int i=0;i<tab_container->get_child_count();i++) {
-
-		ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
-		if (!ste)
-			continue;
-		idx++;
-	}
-
-	if (idx==0) {
-		window_menu->set_disabled(true);
-		edit_menu->set_disabled(true);
-		search_menu->set_disabled(true);
-		return;
-	} else {
-
-		window_menu->set_disabled(false);
-		edit_menu->set_disabled(false);
-		search_menu->set_disabled(false);
-	}
-
-	window_menu->get_popup()->clear();
-	window_menu->get_popup()->add_item("Close",WINDOW_CLOSE,KEY_MASK_CMD|KEY_W);
-	window_menu->get_popup()->add_separator();
-	window_menu->get_popup()->add_item("Move Left",WINDOW_MOVE_LEFT,KEY_MASK_CMD|KEY_MASK_ALT|KEY_LEFT);
-	window_menu->get_popup()->add_item("Move Right",WINDOW_MOVE_RIGHT,KEY_MASK_CMD|KEY_MASK_ALT|KEY_RIGHT);
-	window_menu->get_popup()->add_separator();
-
-	idx=0;
-	for(int i=0;i<tab_container->get_child_count();i++) {
-
-		ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
-		if (!ste)
-			continue;
-		String n = ste->get_name();
-		uint32_t accel=0;
-		if (idx<9) {
-			accel=KEY_MASK_ALT|KEY_MASK_CMD|(KEY_1+idx);
-		}
-		window_menu->get_popup()->add_item(n,WINDOW_SELECT_BASE+idx,accel);
-		idx++;
-	}
-}
 
 void ScriptEditor::_add_callback(Object *p_obj, const String& p_function, const StringArray& p_args) {
 
@@ -1582,6 +1584,8 @@ void ScriptEditor::_add_callback(Object *p_obj, const String& p_function, const
 		ste->get_text_edit()->cursor_set_line(pos);
 		ste->get_text_edit()->cursor_set_column(1);
 
+		script_list->select( script_list->find_metadata(i) );
+
 		break;
 
 	}
@@ -1607,8 +1611,80 @@ void ScriptEditor::_autosave_scripts() {
 	save_external_data();
 }
 
+void ScriptEditor::_tree_changed() {
+
+	if (waiting_update_names)
+		return;
+
+	waiting_update_names=true;
+	call_deferred("_update_script_names");
+}
+
+void ScriptEditor::_script_split_dragged(float) {
+
+	EditorNode::get_singleton()->save_layout();
+}
+
+void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
+
+	if (!bool(EDITOR_DEF("text_editor/restore_scripts_on_load",true))) {
+		return;
+	}
+
+	if (!p_layout->has_section_key("ScriptEditor","open_scripts"))
+		return;
+
+	Array scripts = p_layout->get_value("ScriptEditor","open_scripts");
+
+	restoring_layout=true;
+
+	for(int i=0;i<scripts.size();i++) {
+
+		String path = scripts[i];
+		Ref<Script> scr = ResourceLoader::load(path);
+		if (scr.is_valid()) {
+			edit(scr);
+		}
+	}
+
+	if (p_layout->has_section_key("ScriptEditor","split_offset")) {
+		script_split->set_split_offset(p_layout->get_value("ScriptEditor","split_offset"));
+	}
+
+
+	restoring_layout=false;
+
+}
+
+void ScriptEditor::get_window_layout(Ref<ConfigFile> p_layout) {
+
+	Array scripts;
+
+	for(int i=0;i<tab_container->get_child_count();i++) {
+
+		ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
+		if (!ste)
+			continue;
+
+		String path = ste->get_edited_script()->get_path();
+		if (!path.is_resource_file())
+			continue;
+
+		scripts.push_back(path);
+
+	}
+
+	p_layout->set_value("ScriptEditor","open_scripts",scripts);
+	p_layout->set_value("ScriptEditor","split_offset",script_split->get_split_offset());
+
+}
+
+
+
 ScriptEditor::ScriptEditor(EditorNode *p_editor) {
 
+	restoring_layout=false;
+	waiting_update_names=false;
 	editor=p_editor;
 
 	menu_hb = memnew( HBoxContainer );
@@ -1618,17 +1694,31 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
 	add_child(v_split);
 	v_split->set_v_size_flags(SIZE_EXPAND_FILL);
 
+	script_split = memnew( HSplitContainer );
+	v_split->add_child(script_split);
+	script_split->set_v_size_flags(SIZE_EXPAND_FILL);
+
+	script_list = memnew( ItemList );
+	script_split->add_child(script_list);
+	script_list->set_custom_minimum_size(Size2(140,0));
+
 	tab_container = memnew( TabContainer );
-	v_split->add_child(tab_container);
-	tab_container->set_v_size_flags(SIZE_EXPAND_FILL);
+	tab_container->set_tabs_visible(false);
+	script_split->add_child(tab_container);
+
+
+	tab_container->set_h_size_flags(SIZE_EXPAND_FILL);
 
 	file_menu = memnew( MenuButton );
 	menu_hb->add_child(file_menu);
 	file_menu->set_text("File");
 	file_menu->get_popup()->add_item("Open",FILE_OPEN);
+	file_menu->get_popup()->add_separator();
 	file_menu->get_popup()->add_item("Save",FILE_SAVE,KEY_MASK_ALT|KEY_MASK_CMD|KEY_S);
 	file_menu->get_popup()->add_item("Save As..",FILE_SAVE_AS);
 	file_menu->get_popup()->add_item("Save All",FILE_SAVE_ALL,KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_S);
+	file_menu->get_popup()->add_separator();
+	file_menu->get_popup()->add_item("Close",FILE_CLOSE,KEY_MASK_CMD|KEY_W);
 	file_menu->get_popup()->connect("item_pressed", this,"_menu_option");
 
 	edit_menu = memnew( MenuButton );
@@ -1690,6 +1780,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
 	debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), true );
 
 
+#if 0
 	window_menu = memnew( MenuButton );
 	menu_hb->add_child(window_menu);
 	window_menu->set_text("Window");
@@ -1700,6 +1791,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
 	window_menu->get_popup()->add_separator();
 	window_menu->get_popup()->connect("item_pressed", this,"_menu_option");
 
+#endif
+
 	help_menu = memnew( MenuButton );
 	menu_hb->add_child(help_menu);
 	help_menu->set_text("Help");
@@ -1762,6 +1855,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
 	autosave_timer->set_one_shot(false);
 	add_child(autosave_timer);
 
+	grab_focus_block=false;
+
 //	debugger_gui->hide();
 
 }
@@ -1826,20 +1921,24 @@ void ScriptEditorPlugin::apply_changes() {
 
 void ScriptEditorPlugin::restore_global_state() {
 
-	if (bool(EDITOR_DEF("text_editor/restore_scripts_on_load",true))) {
-		script_editor->_load_files_state();
-	}
 
 }
 
 void ScriptEditorPlugin::save_global_state() {
 
-	if (bool(EDITOR_DEF("text_editor/restore_scripts_on_load",true))) {
-		script_editor->_save_files_state();
-	}
+}
 
+void ScriptEditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) {
+
+	script_editor->set_window_layout(p_layout);
 }
 
+void ScriptEditorPlugin::get_window_layout(Ref<ConfigFile> p_layout){
+
+	script_editor->get_window_layout(p_layout);
+}
+
+
 void ScriptEditorPlugin::get_breakpoints(List<String> *p_breakpoints) {
 
 

+ 37 - 15
tools/editor/plugins/script_editor_plugin.h

@@ -38,7 +38,7 @@
 #include "script_language.h"
 #include "tools/editor/code_editor.h"
 #include "scene/gui/split_container.h"
-
+#include "scene/gui/item_list.h"
 
 class ScriptEditorQuickOpen : public ConfirmationDialog {
 
@@ -88,6 +88,7 @@ protected:
 	virtual void _code_complete_script(const String& p_code, List<String>* r_options);
 	virtual void _load_theme_settings();
 	void _notification(int p_what);
+	static void _bind_methods();
 
 
 public:
@@ -97,7 +98,8 @@ public:
 	Vector<String> get_functions() ;
 	void set_edited_script(const Ref<Script>& p_script);
 	void reload_text();
-	void _update_name();
+	String get_name() ;
+	Ref<Texture> get_icon() ;
 
 	ScriptTextEditor();
 
@@ -115,6 +117,7 @@ class ScriptEditor : public VBoxContainer {
 		FILE_SAVE,
 		FILE_SAVE_AS,
 		FILE_SAVE_ALL,
+		FILE_CLOSE,
 		EDIT_UNDO,
 		EDIT_REDO,
 		EDIT_CUT,
@@ -123,12 +126,12 @@ class ScriptEditor : public VBoxContainer {
 		EDIT_SELECT_ALL,
 		EDIT_COMPLETE,
 		EDIT_AUTO_INDENT,
-        EDIT_TOGGLE_COMMENT,
-        EDIT_MOVE_LINE_UP,
-        EDIT_MOVE_LINE_DOWN,
-        EDIT_INDENT_RIGHT,
-        EDIT_INDENT_LEFT,
-        EDIT_CLONE_DOWN,
+		EDIT_TOGGLE_COMMENT,
+		EDIT_MOVE_LINE_UP,
+		EDIT_MOVE_LINE_DOWN,
+		EDIT_INDENT_RIGHT,
+		EDIT_INDENT_LEFT,
+		EDIT_CLONE_DOWN,
 		SEARCH_FIND,
 		SEARCH_FIND_NEXT,
 		SEARCH_REPLACE,
@@ -140,8 +143,7 @@ class ScriptEditor : public VBoxContainer {
 		DEBUG_BREAK,
 		DEBUG_CONTINUE,
 		DEBUG_SHOW,
-		HELP_CONTEXTUAL,
-		WINDOW_CLOSE,
+		HELP_CONTEXTUAL,		
 		WINDOW_MOVE_LEFT,
 		WINDOW_MOVE_RIGHT,
 		WINDOW_SELECT_BASE=100
@@ -151,12 +153,13 @@ class ScriptEditor : public VBoxContainer {
 	MenuButton *file_menu;
 	MenuButton *edit_menu;
 	MenuButton *search_menu;
-	MenuButton *window_menu;
 	MenuButton *debug_menu;
 	MenuButton *help_menu;
 	Timer *autosave_timer;
 	uint64_t idle;
 
+	ItemList *script_list;
+	HSplitContainer *script_split;
 	TabContainer *tab_container;
 	FindReplaceDialog *find_replace_dialog;
 	GotoLineDialog *goto_line_dialog;
@@ -171,6 +174,8 @@ class ScriptEditor : public VBoxContainer {
 
 	VSplitContainer *v_split;
 
+	bool restoring_layout;
+
 	String _get_debug_tooltip(const String&p_text,Node *_ste);
 
 	void _resave_scripts(const String& p_str);
@@ -180,6 +185,8 @@ class ScriptEditor : public VBoxContainer {
 
 	void _close_current_tab();
 
+	bool grab_focus_block;
+
 	ScriptEditorQuickOpen *quick_open;
 
 
@@ -199,6 +206,18 @@ class ScriptEditor : public VBoxContainer {
 	void _editor_settings_changed();
 	void _autosave_scripts();
 
+	void _update_script_names();
+
+	void _script_selected(int p_idx);
+
+	void _find_scripts(Node* p_base, Node* p_current,Set<Ref<Script> >& used);
+
+	void _tree_changed();
+
+	void _script_split_dragged(float);
+
+	bool waiting_update_names;
+
 	static ScriptEditor *script_editor;
 protected:
 	void _notification(int p_what);
@@ -206,9 +225,6 @@ protected:
 public:
 
 	static ScriptEditor *get_singleton() { return script_editor; }
-	void _save_files_state();
-	void _load_files_state();
-
 
 	void ensure_focus_current();
 	void apply_scripts() const;
@@ -222,10 +238,13 @@ public:
 
 	void get_breakpoints(List<String> *p_breakpoints);
 
-    void swap_lines(TextEdit *tx, int line1, int line2);
+	void swap_lines(TextEdit *tx, int line1, int line2);
 
 	void save_external_data();
 
+	void set_window_layout(Ref<ConfigFile> p_layout);
+	void get_window_layout(Ref<ConfigFile> p_layout);
+
 	ScriptEditor(EditorNode *p_editor);
 };
 
@@ -254,6 +273,9 @@ public:
 	virtual void restore_global_state();
 	virtual void save_global_state();
 
+	virtual void set_window_layout(Ref<ConfigFile> p_layout);
+	virtual void get_window_layout(Ref<ConfigFile> p_layout);
+
 	virtual void get_breakpoints(List<String> *p_breakpoints);
 
 

+ 1 - 1
tools/editor/property_editor.cpp

@@ -1633,7 +1633,7 @@ CustomPropertyEditor::CustomPropertyEditor() {
 	scene_tree = memnew( SceneTreeDialog );
 	add_child(scene_tree);
 	scene_tree->connect("selected", this,"_node_path_selected");
-	scene_tree->get_tree()->set_show_enabled_subscene(true);
+	scene_tree->get_scene_tree()->set_show_enabled_subscene(true);
 
 	texture_preview = memnew( TextureFrame );
 	add_child( texture_preview);

+ 1 - 0
tools/editor/scene_tree_dock.h

@@ -134,6 +134,7 @@ public:
 	void set_selected(Node *p_node, bool p_emit_selected=false);
 	void fill_path_renames(Node* p_node, Node *p_new_parent, List<Pair<NodePath,NodePath> > *p_renames);
 	void perform_node_renames(Node* p_base,List<Pair<NodePath,NodePath> > *p_renames, Map<Ref<Animation>, Set<int> > *r_rem_anims=NULL);
+	SceneTreeEditor *get_tree_editor() { return scene_tree; }
 
 	SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelection *p_editor_selection,EditorData &p_editor_data);
 };

+ 4 - 1
tools/editor/scene_tree_editor.h

@@ -125,6 +125,9 @@ public:
 
 	void update_tree() { _update_tree(); }
 
+
+	Tree* get_scene_tree() { return tree; }
+
 	SceneTreeEditor(bool p_label=true,bool p_can_rename=false, bool p_can_open_instance=false);
 	~SceneTreeEditor();
 
@@ -150,7 +153,7 @@ protected:
 	static void _bind_methods();
 public:
 
-	SceneTreeEditor *get_tree() { return tree; }
+	SceneTreeEditor *get_scene_tree() { return tree; }
 	SceneTreeDialog();
 	~SceneTreeDialog();