소스 검색

Moved inspector functionality from EditorNode to InspectorDock.

Daniel J. Ramirez 7 년 전
부모
커밋
9a365a1216
6개의 변경된 파일748개의 추가작업 그리고 634개의 파일을 삭제
  1. 26 576
      editor/editor_node.cpp
  2. 11 55
      editor/editor_node.h
  3. 2 2
      editor/editor_plugin.cpp
  4. 571 0
      editor/inspector_dock.cpp
  5. 137 0
      editor/inspector_dock.h
  6. 1 1
      editor/plugins/script_editor_plugin.cpp

+ 26 - 576
editor/editor_node.cpp

@@ -295,7 +295,6 @@ void EditorNode::_notification(int p_what) {
 		get_tree()->get_root()->set_as_audio_listener_2d(false);
 		get_tree()->set_auto_accept_quit(false);
 		get_tree()->connect("files_dropped", this, "_dropped_files");
-		property_editable_warning->set_icon(gui_base->get_icon("NodeWarning", "EditorIcons"));
 	}
 
 	if (p_what == NOTIFICATION_EXIT_TREE) {
@@ -382,16 +381,6 @@ void EditorNode::_notification(int p_what) {
 		distraction_free->set_icon(gui_base->get_icon("DistractionFree", "EditorIcons"));
 		scene_tab_add->set_icon(gui_base->get_icon("Add", "EditorIcons"));
 
-		resource_new_button->set_icon(gui_base->get_icon("New", "EditorIcons"));
-		resource_load_button->set_icon(gui_base->get_icon("Load", "EditorIcons"));
-		resource_save_button->set_icon(gui_base->get_icon("Save", "EditorIcons"));
-
-		property_back->set_icon(gui_base->get_icon("Back", "EditorIcons"));
-		property_forward->set_icon(gui_base->get_icon("Forward", "EditorIcons"));
-		editor_history_menu->set_icon(gui_base->get_icon("History", "EditorIcons"));
-
-		search_button->set_icon(gui_base->get_icon("Search", "EditorIcons"));
-		object_menu->set_icon(gui_base->get_icon("Tools", "EditorIcons"));
 		// clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons")); don't have access to that node. needs to become a class property
 		update_menu->set_icon(gui_base->get_icon("Collapse", "EditorIcons"));
 		dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons"));
@@ -549,8 +538,8 @@ void EditorNode::_vp_resized() {
 
 void EditorNode::_node_renamed() {
 
-	if (inspector)
-		inspector->update_tree();
+	if (get_inspector())
+		get_inspector()->update_tree();
 }
 
 void EditorNode::_editor_select_next() {
@@ -582,38 +571,16 @@ Error EditorNode::load_resource(const String &p_scene) {
 	RES res = ResourceLoader::load(p_scene);
 	ERR_FAIL_COND_V(!res.is_valid(), ERR_CANT_OPEN);
 
-	edit_resource(res);
+	inspector_dock->edit_resource(res);
 
 	return OK;
 }
 
-void EditorNode::edit_resource(const Ref<Resource> &p_resource) {
-
-	_resource_selected(p_resource, "");
-}
-
 void EditorNode::edit_node(Node *p_node) {
 
 	push_item(p_node);
 }
 
-void EditorNode::open_resource(const String &p_type) {
-
-	file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
-
-	List<String> extensions;
-	ResourceLoader::get_recognized_extensions_for_type(p_type, &extensions);
-
-	file->clear_filters();
-	for (int i = 0; i < extensions.size(); i++) {
-
-		file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
-	}
-
-	file->popup_centered_ratio();
-	current_option = RESOURCE_LOAD;
-}
-
 void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path) {
 
 	editor_data.apply_changes_in_editors();
@@ -1145,20 +1112,6 @@ void EditorNode::_mark_unsaved_scenes() {
 void EditorNode::_dialog_action(String p_file) {
 
 	switch (current_option) {
-
-		case RESOURCE_LOAD: {
-
-			RES res = ResourceLoader::load(p_file);
-			if (res.is_null()) {
-
-				current_option = -1;
-				accept->get_ok()->set_text("Ugh");
-				accept->set_text(TTR("Failed to load resource."));
-				return;
-			};
-
-			push_item(res.operator->());
-		} break;
 		case FILE_NEW_INHERITED_SCENE: {
 
 			load_scene(p_file, false, true);
@@ -1352,7 +1305,7 @@ void EditorNode::_dialog_action(String p_file) {
 void EditorNode::push_item(Object *p_object, const String &p_property) {
 
 	if (!p_object) {
-		inspector->edit(NULL);
+		get_inspector()->edit(NULL);
 		node_dock->set_node(NULL);
 		scene_tree_dock->set_selected(NULL);
 		return;
@@ -1370,89 +1323,6 @@ void EditorNode::push_item(Object *p_object, const String &p_property) {
 	_edit_current();
 }
 
-void EditorNode::_select_history(int p_idx) {
-
-	//push it to the top, it is not correct, but it's more useful
-	ObjectID id = editor_history.get_history_obj(p_idx);
-	Object *obj = ObjectDB::get_instance(id);
-	if (!obj)
-		return;
-	push_item(obj);
-}
-
-void EditorNode::_prepare_history() {
-
-	int history_to = MAX(0, editor_history.get_history_len() - 25);
-
-	editor_history_menu->get_popup()->clear();
-
-	Ref<Texture> base_icon = gui_base->get_icon("Object", "EditorIcons");
-	Set<ObjectID> already;
-	for (int i = editor_history.get_history_len() - 1; i >= history_to; i--) {
-
-		ObjectID id = editor_history.get_history_obj(i);
-		Object *obj = ObjectDB::get_instance(id);
-		if (!obj || already.has(id)) {
-			if (history_to > 0) {
-				history_to--;
-			}
-			continue;
-		}
-
-		already.insert(id);
-
-		Ref<Texture> icon = gui_base->get_icon("Object", "EditorIcons");
-		if (gui_base->has_icon(obj->get_class(), "EditorIcons"))
-			icon = gui_base->get_icon(obj->get_class(), "EditorIcons");
-		else
-			icon = base_icon;
-
-		String text;
-		if (Object::cast_to<Resource>(obj)) {
-			Resource *r = Object::cast_to<Resource>(obj);
-			if (r->get_path().is_resource_file())
-				text = r->get_path().get_file();
-			else if (r->get_name() != String()) {
-				text = r->get_name();
-			} else {
-				text = r->get_class();
-			}
-		} else if (Object::cast_to<Node>(obj)) {
-			text = Object::cast_to<Node>(obj)->get_name();
-		} else if (obj->is_class("ScriptEditorDebuggerInspectedObject")) {
-			text = obj->call("get_title");
-		} else {
-			text = obj->get_class();
-		}
-
-		if (i == editor_history.get_history_pos()) {
-			text = "[" + text + "]";
-		}
-		editor_history_menu->get_popup()->add_icon_item(icon, text, i);
-	}
-}
-
-void EditorNode::_property_editor_forward() {
-
-	if (editor_history.next())
-		_edit_current();
-}
-void EditorNode::_property_editor_back() {
-
-	if (editor_history.previous() || editor_history.get_path_size() == 1)
-		_edit_current();
-}
-
-void EditorNode::_menu_collapseall() {
-
-	inspector->collapse_all_folding();
-}
-
-void EditorNode::_menu_expandall() {
-
-	inspector->expand_all_folding();
-}
-
 void EditorNode::_save_default_environment() {
 
 	Ref<Environment> fallback = get_tree()->get_root()->get_world()->get_fallback_environment();
@@ -1494,52 +1364,38 @@ static bool overrides_external_editor(Object *p_object) {
 	return script->get_language()->overrides_external_editor();
 }
 
-void EditorNode::_property_editable_warning_pressed() {
-
-	property_editable_warning_dialog->popup_centered_minsize();
-}
-
 void EditorNode::_edit_current() {
 
 	uint32_t current = editor_history.get_current();
 	Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
 
-	property_back->set_disabled(editor_history.is_at_beginning());
-	property_forward->set_disabled(editor_history.is_at_end());
-
 	this->current = current_obj;
-	editor_path->update_path();
-
-	String editable_warning; //none by default
-	property_editable_warning->hide(); //hide by default
 
 	if (!current_obj) {
 
 		scene_tree_dock->set_selected(NULL);
-		inspector->edit(NULL);
+		get_inspector()->edit(NULL);
 		node_dock->set_node(NULL);
-		object_menu->set_disabled(true);
+		inspector_dock->update(NULL);
 
 		_display_top_editors(false);
 
 		return;
 	}
 
-	object_menu->set_disabled(true);
-
-	bool capitalize = bool(EDITOR_GET("interface/inspector/capitalize_properties"));
+	bool capitalize = bool(EDITOR_DEF("interface/editor/capitalize_properties", true));
 	bool is_resource = current_obj->is_class("Resource");
 	bool is_node = current_obj->is_class("Node");
-	resource_save_button->set_disabled(!is_resource);
+
+	String editable_warning; //none by default
 
 	if (is_resource) {
 
 		Resource *current_res = Object::cast_to<Resource>(current_obj);
 		ERR_FAIL_COND(!current_res);
 		scene_tree_dock->set_selected(NULL);
-		inspector->edit(current_res);
+		get_inspector()->edit(current_res);
 		node_dock->set_node(NULL);
-		object_menu->set_disabled(false);
 		EditorNode::get_singleton()->get_import_dock()->set_edit_path(current_res->get_path());
 
 		int subr_idx = current_res->get_path().find("::");
@@ -1562,7 +1418,7 @@ void EditorNode::_edit_current() {
 		Node *current_node = Object::cast_to<Node>(current_obj);
 		ERR_FAIL_COND(!current_node);
 
-		inspector->edit(current_node);
+		get_inspector()->edit(current_node);
 		if (current_node->is_inside_tree()) {
 			node_dock->set_node(current_node);
 			scene_tree_dock->set_selected(current_node);
@@ -1570,7 +1426,6 @@ void EditorNode::_edit_current() {
 			node_dock->set_node(NULL);
 			scene_tree_dock->set_selected(NULL);
 		}
-		object_menu->get_popup()->clear();
 
 		if (get_edited_scene() && get_edited_scene()->get_filename() != String()) {
 			String source_scene = get_edited_scene()->get_filename();
@@ -1586,17 +1441,14 @@ void EditorNode::_edit_current() {
 			capitalize = false;
 		}
 
-		inspector->edit(current_obj);
+		get_inspector()->edit(current_obj);
 		node_dock->set_node(NULL);
 	}
 
-	if (editable_warning != String()) {
-		property_editable_warning->show(); //hide by default
-		property_editable_warning_dialog->set_text(editable_warning);
-	}
+	inspector_dock->set_warning(editable_warning);
 
-	if (inspector->is_capitalize_paths_enabled() != capitalize) {
-		inspector->set_enable_capitalize_paths(capitalize);
+	if (get_inspector()->is_capitalize_paths_enabled() != capitalize) {
+		get_inspector()->set_enable_capitalize_paths(capitalize);
 	}
 
 	/* Take care of PLUGIN EDITOR */
@@ -1654,75 +1506,8 @@ void EditorNode::_edit_current() {
 		_hide_top_editors();
 	}
 
-	object_menu->set_disabled(false);
-
-	PopupMenu *p = object_menu->get_popup();
-
-	p->clear();
-	p->add_shortcut(ED_SHORTCUT("property_editor/expand_all", TTR("Expand all properties")), EXPAND_ALL);
-	p->add_shortcut(ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse all properties")), COLLAPSE_ALL);
-	p->add_separator();
-	p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Params")), OBJECT_COPY_PARAMS);
-	p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Params")), OBJECT_PASTE_PARAMS);
-	p->add_separator();
-	p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Paste Resource")), RESOURCE_PASTE);
-	if (is_resource) {
-		p->add_shortcut(ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
-		p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Built-In")), RESOURCE_UNREF);
-	}
-
-	if (is_resource || is_node) {
-		p->add_separator();
-		p->add_shortcut(ED_SHORTCUT("property_editor/make_subresources_unique", TTR("Make Sub-Resources Unique")), OBJECT_UNIQUE_RESOURCES);
-		p->add_separator();
-		p->add_icon_shortcut(gui_base->get_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("property_editor/open_help", TTR("Open in Help")), OBJECT_REQUEST_HELP);
-	}
-
-	List<MethodInfo> methods;
-	current_obj->get_method_list(&methods);
-
-	if (!methods.empty()) {
-
-		bool found = false;
-		List<MethodInfo>::Element *I = methods.front();
-		int i = 0;
-		while (I) {
-
-			if (I->get().flags & METHOD_FLAG_EDITOR) {
-				if (!found) {
-					p->add_separator();
-					found = true;
-				}
-				p->add_item(I->get().name.capitalize(), OBJECT_METHOD_BASE + i);
-			}
-			i++;
-			I = I->next();
-		}
-	}
-
-	update_keying();
-}
-
-void EditorNode::_resource_created() {
-
-	Object *c = create_dialog->instance_selected();
-
-	ERR_FAIL_COND(!c);
-	Resource *r = Object::cast_to<Resource>(c);
-	ERR_FAIL_COND(!r);
-
-	REF res(r);
-
-	push_item(c);
-}
-
-void EditorNode::_resource_selected(const RES &p_res, const String &p_property) {
-
-	if (p_res.is_null())
-		return;
-
-	RES r = p_res;
-	push_item(r.operator->(), p_property);
+	inspector_dock->update(current_obj);
+	inspector_dock->update_keying();
 }
 
 void EditorNode::_run(bool p_current, const String &p_custom) {
@@ -2162,136 +1947,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
 			get_undo_redo()->clear_history();
 			scene_tabs->set_current_tab(cur_idx);
 
-		} break;
-		case RESOURCE_NEW: {
-
-			create_dialog->popup_create(true);
-		} break;
-		case RESOURCE_LOAD: {
-
-			open_resource();
-		} break;
-		case RESOURCE_SAVE: {
-
-			uint32_t current = editor_history.get_current();
-			Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
-
-			ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
-
-			RES current_res = RES(Object::cast_to<Resource>(current_obj));
-
-			save_resource(current_res);
-
-		} break;
-		case RESOURCE_SAVE_AS: {
-
-			uint32_t current = editor_history.get_current();
-			Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
-
-			ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
-
-			RES current_res = RES(Object::cast_to<Resource>(current_obj));
-
-			save_resource_as(current_res);
-
-		} break;
-		case RESOURCE_UNREF: {
-
-			uint32_t current = editor_history.get_current();
-			Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
-
-			ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
-
-			RES current_res = RES(Object::cast_to<Resource>(current_obj));
-			current_res->set_path("");
-			_edit_current();
-		} break;
-		case RESOURCE_COPY: {
-
-			uint32_t current = editor_history.get_current();
-			Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
-
-			ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
-
-			RES current_res = RES(Object::cast_to<Resource>(current_obj));
-
-			EditorSettings::get_singleton()->set_resource_clipboard(current_res);
-
-		} break;
-		case RESOURCE_PASTE: {
-
-			RES r = EditorSettings::get_singleton()->get_resource_clipboard();
-			if (r.is_valid()) {
-				push_item(EditorSettings::get_singleton()->get_resource_clipboard().ptr(), String());
-			}
-
-		} break;
-		case OBJECT_REQUEST_HELP: {
-
-			if (current) {
-				_editor_select(EDITOR_SCRIPT);
-				emit_signal("request_help", current->get_class());
-			}
-
-		} break;
-		case OBJECT_COPY_PARAMS: {
-
-			editor_data.apply_changes_in_editors();
-			if (current)
-				editor_data.copy_object_params(current);
-		} break;
-		case OBJECT_PASTE_PARAMS: {
-
-			editor_data.apply_changes_in_editors();
-			if (current)
-				editor_data.paste_object_params(current);
-			editor_data.get_undo_redo().clear_history();
-		} break;
-		case OBJECT_UNIQUE_RESOURCES: {
-
-			editor_data.apply_changes_in_editors();
-			if (current) {
-				List<PropertyInfo> props;
-				current->get_property_list(&props);
-				Map<RES, RES> duplicates;
-				for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
-
-					if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
-						continue;
-
-					Variant v = current->get(E->get().name);
-					if (v.is_ref()) {
-						REF ref = v;
-						if (ref.is_valid()) {
-
-							RES res = ref;
-							if (res.is_valid()) {
-
-								if (!duplicates.has(res)) {
-									duplicates[res] = res->duplicate();
-								}
-								res = duplicates[res];
-
-								current->set(E->get().name, res);
-							}
-						}
-					}
-				}
-			}
-
-			editor_data.get_undo_redo().clear_history();
-
-			_set_editing_top_editors(NULL);
-			_set_editing_top_editors(current);
-
-		} break;
-		case COLLAPSE_ALL: {
-			_menu_collapseall();
-
-		} break;
-		case EXPAND_ALL: {
-			_menu_expandall();
-
 		} break;
 		case RUN_PLAY: {
 			_menu_option_confirm(RUN_STOP, true);
@@ -2555,22 +2210,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
 		} break;
 
 		default: {
-
-			if (p_option >= OBJECT_METHOD_BASE) {
-
-				ERR_FAIL_COND(!current);
-
-				int idx = p_option - OBJECT_METHOD_BASE;
-
-				List<MethodInfo> methods;
-				current->get_method_list(&methods);
-
-				ERR_FAIL_INDEX(idx, methods.size());
-				String name = methods[idx].name;
-
-				if (current)
-					current->call(name);
-			} else if (p_option >= IMPORT_PLUGIN_BASE) {
+			if (p_option >= IMPORT_PLUGIN_BASE) {
 			}
 		}
 	}
@@ -3244,42 +2884,14 @@ SceneTreeDock *EditorNode::get_scene_tree_dock() {
 
 	return scene_tree_dock;
 }
+InspectorDock *EditorNode::get_inspector_dock() {
 
-void EditorNode::_instance_request(const Vector<String> &p_files) {
-
-	request_instance_scenes(p_files);
-}
-
-void EditorNode::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) {
-
-	AnimationPlayerEditor::singleton->get_key_editor()->insert_value_key(p_keyed, p_value, p_advance);
-}
-
-void EditorNode::_transform_keyed(Object *sp, const String &p_sub, const Transform &p_key) {
-
-	Spatial *s = Object::cast_to<Spatial>(sp);
-	if (!s)
-		return;
-	AnimationPlayerEditor::singleton->get_key_editor()->insert_transform_key(s, p_sub, p_key);
+	return inspector_dock;
 }
 
-void EditorNode::update_keying() {
-
-	bool valid = false;
-
-	if (AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) {
-
-		if (editor_history.get_path_size() >= 1) {
-
-			Object *obj = ObjectDB::get_instance(editor_history.get_path_object(0));
-			if (Object::cast_to<Node>(obj)) {
-
-				valid = true;
-			}
-		}
-	}
+void EditorNode::_instance_request(const Vector<String> &p_files) {
 
-	inspector->set_keying(valid);
+	request_instance_scenes(p_files);
 }
 
 void EditorNode::_close_messages() {
@@ -4138,7 +3750,7 @@ void EditorNode::_scene_tab_script_edited(int p_tab) {
 
 	Ref<Script> script = editor_data.get_scene_root_script(p_tab);
 	if (script.is_valid())
-		edit_resource(script);
+		inspector_dock->edit_resource(script);
 }
 
 void EditorNode::_scene_tab_closed(int p_tab) {
@@ -4236,30 +3848,6 @@ void EditorNode::_scene_tab_changed(int p_tab) {
 	editor_data.get_undo_redo().commit_action();
 }
 
-void EditorNode::_toggle_search_bar(bool p_pressed) {
-
-	inspector->set_use_filter(p_pressed);
-
-	if (p_pressed) {
-
-		search_bar->show();
-		search_box->grab_focus();
-		search_box->select_all();
-	} else {
-
-		search_bar->hide();
-	}
-}
-
-void EditorNode::_clear_search_box() {
-
-	if (search_box->get_text() == "")
-		return;
-
-	search_box->clear();
-	inspector->update_tree();
-}
-
 ToolButton *EditorNode::add_bottom_panel_item(String p_text, Control *p_item) {
 
 	ToolButton *tb = memnew(ToolButton);
@@ -4778,9 +4366,6 @@ void EditorNode::_bind_methods() {
 	ClassDB::bind_method("_tool_menu_option", &EditorNode::_tool_menu_option);
 	ClassDB::bind_method("_menu_confirm_current", &EditorNode::_menu_confirm_current);
 	ClassDB::bind_method("_dialog_action", &EditorNode::_dialog_action);
-	ClassDB::bind_method("_resource_selected", &EditorNode::_resource_selected, DEFVAL(""));
-	ClassDB::bind_method("_property_editor_forward", &EditorNode::_property_editor_forward);
-	ClassDB::bind_method("_property_editor_back", &EditorNode::_property_editor_back);
 	ClassDB::bind_method("_editor_select", &EditorNode::_editor_select);
 	ClassDB::bind_method("_node_renamed", &EditorNode::_node_renamed);
 	ClassDB::bind_method("edit_node", &EditorNode::edit_node);
@@ -4790,16 +4375,12 @@ void EditorNode::_bind_methods() {
 	ClassDB::bind_method("set_edited_scene", &EditorNode::set_edited_scene);
 	ClassDB::bind_method("open_request", &EditorNode::open_request);
 	ClassDB::bind_method("_instance_request", &EditorNode::_instance_request);
-	ClassDB::bind_method("update_keying", &EditorNode::update_keying);
-	ClassDB::bind_method("_property_keyed", &EditorNode::_property_keyed);
-	ClassDB::bind_method("_transform_keyed", &EditorNode::_transform_keyed);
 	ClassDB::bind_method("_close_messages", &EditorNode::_close_messages);
 	ClassDB::bind_method("_show_messages", &EditorNode::_show_messages);
 	ClassDB::bind_method("_vp_resized", &EditorNode::_vp_resized);
 	ClassDB::bind_method("_quick_opened", &EditorNode::_quick_opened);
 	ClassDB::bind_method("_quick_run", &EditorNode::_quick_run);
 
-	ClassDB::bind_method("_resource_created", &EditorNode::_resource_created);
 	ClassDB::bind_method("_open_recent_scene", &EditorNode::_open_recent_scene);
 
 	ClassDB::bind_method("stop_child_process", &EditorNode::stop_child_process);
@@ -4833,15 +4414,9 @@ void EditorNode::_bind_methods() {
 	ClassDB::bind_method("_discard_changes", &EditorNode::_discard_changes);
 	ClassDB::bind_method("_update_recent_scenes", &EditorNode::_update_recent_scenes);
 
-	ClassDB::bind_method("_prepare_history", &EditorNode::_prepare_history);
-	ClassDB::bind_method("_select_history", &EditorNode::_select_history);
-
-	ClassDB::bind_method("_toggle_search_bar", &EditorNode::_toggle_search_bar);
-	ClassDB::bind_method("_clear_search_box", &EditorNode::_clear_search_box);
 	ClassDB::bind_method("_clear_undo_history", &EditorNode::_clear_undo_history);
 	ClassDB::bind_method("_dropped_files", &EditorNode::_dropped_files);
 	ClassDB::bind_method("_toggle_distraction_free_mode", &EditorNode::_toggle_distraction_free_mode);
-	ClassDB::bind_method("_property_editable_warning_pressed", &EditorNode::_property_editable_warning_pressed);
 
 	ClassDB::bind_method(D_METHOD("get_gui_base"), &EditorNode::get_gui_base);
 	ClassDB::bind_method(D_METHOD("_bottom_panel_switch"), &EditorNode::_bottom_panel_switch);
@@ -4855,7 +4430,6 @@ void EditorNode::_bind_methods() {
 	ADD_SIGNAL(MethodInfo("play_pressed"));
 	ADD_SIGNAL(MethodInfo("pause_pressed"));
 	ADD_SIGNAL(MethodInfo("stop_pressed"));
-	ADD_SIGNAL(MethodInfo("request_help"));
 	ADD_SIGNAL(MethodInfo("request_help_search"));
 	ADD_SIGNAL(MethodInfo("request_help_index"));
 	ADD_SIGNAL(MethodInfo("script_add_function_request", PropertyInfo(Variant::OBJECT, "obj"), PropertyInfo(Variant::STRING, "function"), PropertyInfo(Variant::POOL_STRING_ARRAY, "args")));
@@ -5581,129 +5155,11 @@ EditorNode::EditorNode() {
 	dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(scene_tree_dock->get_index(), TTR("Scene"));
 	dock_slot[DOCK_SLOT_LEFT_BR]->hide();
 
-	VBoxContainer *prop_editor_base = memnew(VBoxContainer);
-	prop_editor_base->set_name("Inspector");
-	dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(prop_editor_base);
-	dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(prop_editor_base->get_index(), TTR("Inspector"));
-
-	HBoxContainer *prop_editor_hb = memnew(HBoxContainer);
-
-	prop_editor_base->add_child(prop_editor_hb);
-	prop_editor_vb = prop_editor_base;
-
-	resource_new_button = memnew(ToolButton);
-	resource_new_button->set_tooltip(TTR("Create a new resource in memory and edit it."));
-	resource_new_button->set_icon(gui_base->get_icon("New", "EditorIcons"));
-	prop_editor_hb->add_child(resource_new_button);
-	resource_new_button->connect("pressed", this, "_menu_option", varray(RESOURCE_NEW));
-	resource_new_button->set_focus_mode(Control::FOCUS_NONE);
-
-	resource_load_button = memnew(ToolButton);
-	resource_load_button->set_tooltip(TTR("Load an existing resource from disk and edit it."));
-	resource_load_button->set_icon(gui_base->get_icon("Load", "EditorIcons"));
-	prop_editor_hb->add_child(resource_load_button);
-	resource_load_button->connect("pressed", this, "_menu_option", varray(RESOURCE_LOAD));
-	resource_load_button->set_focus_mode(Control::FOCUS_NONE);
-
-	resource_save_button = memnew(MenuButton);
-	resource_save_button->set_tooltip(TTR("Save the currently edited resource."));
-	resource_save_button->set_icon(gui_base->get_icon("Save", "EditorIcons"));
-	prop_editor_hb->add_child(resource_save_button);
-	resource_save_button->get_popup()->add_item(TTR("Save"), RESOURCE_SAVE);
-	resource_save_button->get_popup()->add_item(TTR("Save As..."), RESOURCE_SAVE_AS);
-	resource_save_button->get_popup()->connect("id_pressed", this, "_menu_option");
-	resource_save_button->set_focus_mode(Control::FOCUS_NONE);
-	resource_save_button->set_disabled(true);
-
-	prop_editor_hb->add_spacer();
-
-	property_back = memnew(ToolButton);
-	property_back->set_icon(gui_base->get_icon("Back", "EditorIcons"));
-	property_back->set_flat(true);
-	property_back->set_tooltip(TTR("Go to the previous edited object in history."));
-	property_back->set_disabled(true);
-
-	prop_editor_hb->add_child(property_back);
-
-	property_forward = memnew(ToolButton);
-	property_forward->set_icon(gui_base->get_icon("Forward", "EditorIcons"));
-	property_forward->set_flat(true);
-	property_forward->set_tooltip(TTR("Go to the next edited object in history."));
-	property_forward->set_disabled(true);
-
-	prop_editor_hb->add_child(property_forward);
-
-	editor_history_menu = memnew(MenuButton);
-	editor_history_menu->set_tooltip(TTR("History of recently edited objects."));
-	editor_history_menu->set_icon(gui_base->get_icon("History", "EditorIcons"));
-	prop_editor_hb->add_child(editor_history_menu);
-	editor_history_menu->connect("about_to_show", this, "_prepare_history");
-	editor_history_menu->get_popup()->connect("id_pressed", this, "_select_history");
-
-	prop_editor_hb = memnew(HBoxContainer); //again...
-	prop_editor_base->add_child(prop_editor_hb);
-
-	editor_path = memnew(EditorPath(&editor_history));
-	editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-	prop_editor_hb->add_child(editor_path);
-
-	search_button = memnew(ToolButton);
-	search_button->set_toggle_mode(true);
-	search_button->set_pressed(false);
-	search_button->set_icon(gui_base->get_icon("Search", "EditorIcons"));
-	prop_editor_hb->add_child(search_button);
-	search_button->connect("toggled", this, "_toggle_search_bar");
-
-	object_menu = memnew(MenuButton);
-	object_menu->set_icon(gui_base->get_icon("Tools", "EditorIcons"));
-	prop_editor_hb->add_child(object_menu);
-	object_menu->set_tooltip(TTR("Object properties."));
-
-	create_dialog = memnew(CreateDialog);
-	gui_base->add_child(create_dialog);
-	create_dialog->set_base_type("Resource");
-	create_dialog->connect("create", this, "_resource_created");
-
-	search_bar = memnew(HBoxContainer);
-	search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-	prop_editor_base->add_child(search_bar);
-	search_bar->hide();
-
-	Label *l = memnew(Label(TTR("Search:") + " "));
-	search_bar->add_child(l);
-
-	search_box = memnew(LineEdit);
-	search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-	search_bar->add_child(search_box);
-
-	ToolButton *clear_button = memnew(ToolButton);
-	clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons"));
-	search_bar->add_child(clear_button);
-	clear_button->connect("pressed", this, "_clear_search_box");
-
-	property_editable_warning = memnew(Button);
-	property_editable_warning->set_text(TTR("Changes may be lost!"));
-	prop_editor_base->add_child(property_editable_warning);
-	property_editable_warning_dialog = memnew(AcceptDialog);
-	gui_base->add_child(property_editable_warning_dialog);
-	property_editable_warning->hide();
-	property_editable_warning->connect("pressed", this, "_property_editable_warning_pressed");
-
-	inspector = memnew(EditorInspector);
-	inspector->set_autoclear(true);
-	inspector->set_show_categories(true);
-	inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-	inspector->set_use_doc_hints(true);
-	inspector->set_hide_script(false);
-	inspector->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/inspector/capitalize_properties", true)));
-	inspector->set_use_folding(!bool(EDITOR_DEF("interface/inspector/disable_inspector_folding", false)));
-
-	//	inspector->hide_top_label();
-	inspector->register_text_enter(search_box);
+	inspector_dock = memnew(InspectorDock(this, editor_data));
+	dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(inspector_dock);
+	dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(inspector_dock->get_index(), TTR("Inspector"));
 
 	Button *property_editable_warning;
-	prop_editor_base->add_child(inspector);
-	inspector->set_undo_redo(&editor_data.get_undo_redo());
 
 	import_dock = memnew(ImportDock);
 	dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(import_dock);
@@ -5829,18 +5285,12 @@ EditorNode::EditorNode() {
 	gui_base->add_child(file_script);
 	file_script->connect("file_selected", this, "_dialog_action");
 
-	property_forward->connect("pressed", this, "_property_editor_forward");
-	property_back->connect("pressed", this, "_property_editor_back");
-
 	file_menu->get_popup()->connect("id_pressed", this, "_menu_option");
-	object_menu->get_popup()->connect("id_pressed", this, "_menu_option");
 
 	settings_menu->get_popup()->connect("id_pressed", this, "_menu_option");
 
 	file->connect("file_selected", this, "_dialog_action");
 	file_templates->connect("file_selected", this, "_dialog_action");
-	inspector->connect("resource_selected", this, "_resource_selected");
-	inspector->connect("property_keyed", this, "_property_keyed");
 
 	//plugin stuff
 

+ 11 - 55
editor/editor_node.h

@@ -40,7 +40,6 @@
 #include "editor/editor_inspector.h"
 #include "editor/editor_log.h"
 #include "editor/editor_name_dialog.h"
-#include "editor/editor_path.h"
 #include "editor/editor_plugin.h"
 #include "editor/editor_resource_preview.h"
 #include "editor/editor_run.h"
@@ -53,6 +52,7 @@
 #include "editor/filesystem_dock.h"
 #include "editor/groups_editor.h"
 #include "editor/import_dock.h"
+#include "editor/inspector_dock.h"
 #include "editor/node_dock.h"
 #include "editor/pane_drag.h"
 #include "editor/progress_dialog.h"
@@ -142,22 +142,10 @@ private:
 		EDIT_REVERT,
 		TOOLS_ORPHAN_RESOURCES,
 		TOOLS_CUSTOM,
-		RESOURCE_NEW,
-		RESOURCE_LOAD,
 		RESOURCE_SAVE,
 		RESOURCE_SAVE_AS,
-		RESOURCE_UNREF,
-		RESOURCE_COPY,
-		RESOURCE_PASTE,
-		OBJECT_COPY_PARAMS,
-		OBJECT_PASTE_PARAMS,
-		OBJECT_UNIQUE_RESOURCES,
-		OBJECT_REQUEST_HELP,
 		RUN_PLAY,
 
-		COLLAPSE_ALL,
-		EXPAND_ALL,
-
 		RUN_STOP,
 		RUN_PLAY_SCENE,
 		RUN_PLAY_NATIVE,
@@ -195,8 +183,6 @@ private:
 
 		IMPORT_PLUGIN_BASE = 100,
 
-		OBJECT_METHOD_BASE = 500,
-
 		TOOL_MENU_BASE = 1000
 	};
 
@@ -247,7 +233,6 @@ private:
 	PopupMenu *tool_menu;
 	ToolButton *export_button;
 	ToolButton *prev_scene;
-	MenuButton *object_menu;
 	ToolButton *play_button;
 	MenuButton *native_play_button;
 	ToolButton *pause_button;
@@ -264,24 +249,13 @@ private:
 	Ref<Theme> theme;
 
 	PopupMenu *recent_scenes;
-	Button *property_back;
-	Button *property_forward;
 	SceneTreeDock *scene_tree_dock;
-	EditorInspector *inspector;
-	Button *property_editable_warning;
-	AcceptDialog *property_editable_warning_dialog;
-	void _property_editable_warning_pressed();
+	InspectorDock *inspector_dock;
 	NodeDock *node_dock;
 	ImportDock *import_dock;
-	VBoxContainer *prop_editor_vb;
 	FileSystemDock *filesystem_dock;
 	EditorRunNative *run_native;
 
-	HBoxContainer *search_bar;
-	LineEdit *search_box;
-
-	CreateDialog *create_dialog;
-
 	ConfirmationDialog *confirmation;
 	ConfirmationDialog *save_confirmation;
 	ConfirmationDialog *import_confirmation;
@@ -314,11 +288,6 @@ private:
 	String defer_export_platform;
 	bool defer_export_debug;
 	Node *_last_instanced_scene;
-	EditorPath *editor_path;
-	ToolButton *resource_new_button;
-	ToolButton *resource_load_button;
-	MenuButton *resource_save_button;
-	MenuButton *editor_history_menu;
 
 	EditorLog *log;
 	CenterContainer *tabs_center;
@@ -422,23 +391,12 @@ private:
 	void _dialog_display_load_error(String p_file, Error p_error);
 
 	int current_option;
-	void _resource_created();
-	void _resource_selected(const RES &p_res, const String &p_property = "");
 	void _menu_option(int p_option);
 	void _menu_confirm_current();
 	void _menu_option_confirm(int p_option, bool p_confirmed);
 	void _tool_menu_option(int p_idx);
 	void _update_debug_options();
 
-	void _property_editor_forward();
-	void _property_editor_back();
-
-	void _menu_collapseall();
-	void _menu_expandall();
-
-	void _select_history(int p_idx);
-	void _prepare_history();
-
 	void _fs_changed();
 	void _resources_reimported(const Vector<String> &p_resources);
 	void _sources_changed(bool p_exist);
@@ -462,9 +420,6 @@ private:
 
 	void _instance_request(const Vector<String> &p_files);
 
-	void _property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance);
-	void _transform_keyed(Object *sp, const String &p_sub, const Transform &p_key);
-
 	void _hide_top_editors();
 	void _display_top_editors(bool p_display);
 	void _set_top_editors(Vector<EditorPlugin *> p_editor_plugins_over);
@@ -578,8 +533,6 @@ private:
 	void _update_layouts_menu();
 	void _layout_menu_option(int p_id);
 
-	void _toggle_search_bar(bool p_pressed);
-	void _clear_search_box();
 	void _clear_undo_history();
 
 	void _update_addon_config();
@@ -640,8 +593,8 @@ public:
 	EditorPluginList *get_editor_plugins_over() { return editor_plugins_over; }
 	EditorPluginList *get_editor_plugins_force_over() { return editor_plugins_force_over; }
 	EditorPluginList *get_editor_plugins_force_input_forwarding() { return editor_plugins_force_input_forwarding; }
-	EditorInspector *get_inspector() { return inspector; }
-	VBoxContainer *get_property_editor_vb() { return prop_editor_vb; }
+	EditorInspector *get_inspector() { return inspector_dock->get_inspector(); }
+	Container *get_inspector_dock_addon_area() { return inspector_dock->get_addon_area(); }
 
 	ProjectSettingsEditor *get_project_settings() { return project_settings; }
 
@@ -663,8 +616,8 @@ public:
 	bool is_addon_plugin_enabled(const String &p_addon) const;
 
 	void edit_node(Node *p_node);
-	void edit_resource(const Ref<Resource> &p_resource);
-	void open_resource(const String &p_type = "");
+	void edit_resource(const Ref<Resource> &p_resource) { inspector_dock->edit_resource(p_resource); };
+	void open_resource(const String &p_type) { inspector_dock->open_resource(p_type); };
 
 	void save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path);
 	void save_resource(const Ref<Resource> &p_resource);
@@ -713,6 +666,7 @@ public:
 	FileSystemDock *get_filesystem_dock();
 	ImportDock *get_import_dock();
 	SceneTreeDock *get_scene_tree_dock();
+	InspectorDock *get_inspector_dock();
 	static UndoRedo *get_undo_redo() { return &singleton->editor_data.get_undo_redo(); }
 
 	EditorSelection *get_editor_selection() { return editor_selection; }
@@ -759,8 +713,6 @@ public:
 
 	void save_layout();
 
-	void update_keying();
-
 	void open_export_template_manager();
 
 	void reload_scene(const String &p_path);
@@ -785,6 +737,10 @@ public:
 
 	void dim_editor(bool p_dimming);
 
+	void edit_current() { _edit_current(); };
+
+	void update_keying() const { inspector_dock->update_keying(); };
+
 	EditorNode();
 	~EditorNode();
 	void get_singleton(const char *arg1, bool arg2);

+ 2 - 2
editor/editor_plugin.cpp

@@ -375,7 +375,7 @@ void EditorPlugin::add_control_to_container(CustomControlContainer p_location, C
 		} break;
 		case CONTAINER_PROPERTY_EDITOR_BOTTOM: {
 
-			EditorNode::get_singleton()->get_property_editor_vb()->add_child(p_control);
+			EditorNode::get_singleton()->get_inspector_dock_addon_area()->add_child(p_control);
 
 		} break;
 	}
@@ -422,7 +422,7 @@ void EditorPlugin::remove_control_from_container(CustomControlContainer p_locati
 		} break;
 		case CONTAINER_PROPERTY_EDITOR_BOTTOM: {
 
-			EditorNode::get_singleton()->get_property_editor_vb()->remove_child(p_control);
+			EditorNode::get_singleton()->get_inspector_dock_addon_area()->remove_child(p_control);
 
 		} break;
 	}

+ 571 - 0
editor/inspector_dock.cpp

@@ -0,0 +1,571 @@
+/*************************************************************************/
+/*  inspector_dock.cpp                                                   */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "inspector_dock.h"
+
+#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "editor/plugins/animation_player_editor_plugin.h"
+
+void InspectorDock::_menu_option(int p_option) {
+	switch (p_option) {
+		case RESOURCE_SAVE: {
+			_save_resource(false);
+		} break;
+		case RESOURCE_SAVE_AS: {
+			_save_resource(true);
+		} break;
+
+		case OBJECT_REQUEST_HELP: {
+			if (current) {
+				editor->set_visible_editor(EditorNode::EDITOR_SCRIPT);
+				emit_signal("request_help", current->get_class());
+			}
+		} break;
+
+		case OBJECT_COPY_PARAMS: {
+			editor_data->apply_changes_in_editors();
+			if (current)
+				editor_data->copy_object_params(current);
+		} break;
+
+		case OBJECT_PASTE_PARAMS: {
+			editor_data->apply_changes_in_editors();
+			if (current)
+				editor_data->paste_object_params(current);
+			editor_data->get_undo_redo().clear_history();
+		} break;
+
+		case OBJECT_UNIQUE_RESOURCES: {
+			editor_data->apply_changes_in_editors();
+			if (current) {
+				List<PropertyInfo> props;
+				current->get_property_list(&props);
+				Map<RES, RES> duplicates;
+				for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+
+					if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
+						continue;
+
+					Variant v = current->get(E->get().name);
+					if (v.is_ref()) {
+						REF ref = v;
+						if (ref.is_valid()) {
+
+							RES res = ref;
+							if (res.is_valid()) {
+
+								if (!duplicates.has(res)) {
+									duplicates[res] = res->duplicate();
+								}
+								res = duplicates[res];
+
+								current->set(E->get().name, res);
+							}
+						}
+					}
+				}
+			}
+
+			editor_data->get_undo_redo().clear_history();
+
+			editor->get_editor_plugins_over()->edit(NULL);
+			editor->get_editor_plugins_over()->edit(current);
+
+		} break;
+
+		default: {
+			if (p_option >= OBJECT_METHOD_BASE) {
+				ERR_FAIL_COND(!current);
+
+				int idx = p_option - OBJECT_METHOD_BASE;
+
+				List<MethodInfo> methods;
+				current->get_method_list(&methods);
+
+				ERR_FAIL_INDEX(idx, methods.size());
+				String name = methods[idx].name;
+
+				if (current)
+					current->call(name);
+			}
+		}
+	}
+}
+
+void InspectorDock::_new_resource() {
+	new_resource_dialog->popup_create(true);
+}
+
+void InspectorDock::_load_resource(const String &p_type) {
+	load_resource_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+
+	List<String> extensions;
+	ResourceLoader::get_recognized_extensions_for_type(p_type, &extensions);
+
+	load_resource_dialog->clear_filters();
+	for (int i = 0; i < extensions.size(); i++) {
+		load_resource_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+	}
+
+	load_resource_dialog->popup_centered_ratio();
+}
+
+void InspectorDock::_resource_file_selected(String p_file) {
+	RES res = ResourceLoader::load(p_file);
+	if (res.is_null()) {
+		warning_dialog->get_ok()->set_text("Ugh");
+		warning_dialog->set_text(TTR("Failed to load resource."));
+		return;
+	};
+
+	editor->push_item(res.operator->());
+}
+
+void InspectorDock::_save_resource(bool save_as) const {
+	uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current();
+	Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
+
+	ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
+
+	RES current_res = RES(Object::cast_to<Resource>(current_obj));
+
+	if (save_as)
+		editor->save_resource_as(current_res);
+	else
+		editor->save_resource(current_res);
+}
+
+void InspectorDock::_unref_resource() const {
+	uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current();
+	Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
+
+	ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
+
+	RES current_res = RES(Object::cast_to<Resource>(current_obj));
+	current_res->set_path("");
+	editor->edit_current();
+}
+
+void InspectorDock::_copy_resource() const {
+	uint32_t current = EditorNode::get_singleton()->get_editor_history()->get_current();
+	Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
+
+	ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
+
+	RES current_res = RES(Object::cast_to<Resource>(current_obj));
+
+	EditorSettings::get_singleton()->set_resource_clipboard(current_res);
+}
+
+void InspectorDock::_paste_resource() const {
+	RES r = EditorSettings::get_singleton()->get_resource_clipboard();
+	if (r.is_valid()) {
+		editor->push_item(EditorSettings::get_singleton()->get_resource_clipboard().ptr(), String());
+	}
+}
+
+void InspectorDock::_prepare_history() {
+	EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history();
+
+	int history_to = MAX(0, editor_history->get_history_len() - 25);
+
+	history_menu->get_popup()->clear();
+
+	Ref<Texture> base_icon = get_icon("Object", "EditorIcons");
+	Set<ObjectID> already;
+	for (int i = editor_history->get_history_len() - 1; i >= history_to; i--) {
+
+		ObjectID id = editor_history->get_history_obj(i);
+		Object *obj = ObjectDB::get_instance(id);
+		if (!obj || already.has(id)) {
+			if (history_to > 0) {
+				history_to--;
+			}
+			continue;
+		}
+
+		already.insert(id);
+
+		Ref<Texture> icon = get_icon("Object", "EditorIcons");
+		if (has_icon(obj->get_class(), "EditorIcons"))
+			icon = get_icon(obj->get_class(), "EditorIcons");
+		else
+			icon = base_icon;
+
+		String text;
+		if (Object::cast_to<Resource>(obj)) {
+			Resource *r = Object::cast_to<Resource>(obj);
+			if (r->get_path().is_resource_file())
+				text = r->get_path().get_file();
+			else if (r->get_name() != String()) {
+				text = r->get_name();
+			} else {
+				text = r->get_class();
+			}
+		} else if (Object::cast_to<Node>(obj)) {
+			text = Object::cast_to<Node>(obj)->get_name();
+		} else if (obj->is_class("ScriptEditorDebuggerInspectedObject")) {
+			text = obj->call("get_title");
+		} else {
+			text = obj->get_class();
+		}
+
+		if (i == editor_history->get_history_pos()) {
+			text = "[" + text + "]";
+		}
+		history_menu->get_popup()->add_icon_item(icon, text, i);
+	}
+}
+
+void InspectorDock::_select_history(int p_idx) const {
+	//push it to the top, it is not correct, but it's more useful
+	ObjectID id = EditorNode::get_singleton()->get_editor_history()->get_history_obj(p_idx);
+	Object *obj = ObjectDB::get_instance(id);
+	if (!obj)
+		return;
+	editor->push_item(obj);
+}
+
+void InspectorDock::_resource_created() const {
+	Object *c = new_resource_dialog->instance_selected();
+
+	ERR_FAIL_COND(!c);
+	Resource *r = Object::cast_to<Resource>(c);
+	ERR_FAIL_COND(!r);
+
+	REF res(r);
+	editor->push_item(c);
+}
+
+void InspectorDock::_resource_selected(const RES &p_res, const String &p_property) const {
+	if (p_res.is_null())
+		return;
+
+	RES r = p_res;
+	editor->push_item(r.operator->(), p_property);
+}
+
+void InspectorDock::_edit_forward() {
+	if (EditorNode::get_singleton()->get_editor_history()->next())
+		editor->edit_current();
+}
+void InspectorDock::_edit_back() {
+	EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history();
+	if (editor_history->previous() || editor_history->get_path_size() == 1)
+		editor->edit_current();
+}
+
+void InspectorDock::_menu_collapseall() {
+	inspector->collapse_all_folding();
+}
+
+void InspectorDock::_menu_expandall() {
+	inspector->expand_all_folding();
+}
+
+void InspectorDock::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) {
+	AnimationPlayerEditor::singleton->get_key_editor()->insert_value_key(p_keyed, p_value, p_advance);
+}
+
+void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Transform &p_key) {
+	Spatial *s = Object::cast_to<Spatial>(sp);
+	if (!s)
+		return;
+	AnimationPlayerEditor::singleton->get_key_editor()->insert_transform_key(s, p_sub, p_key);
+}
+
+void InspectorDock::_warning_pressed() {
+	warning_dialog->get_ok()->set_text(TTR("Ok"));
+	warning_dialog->popup_centered_minsize();
+}
+
+Container *InspectorDock::get_addon_area() {
+	return this;
+}
+
+void InspectorDock::_bind_methods() {
+	ClassDB::bind_method("_menu_option", &InspectorDock::_menu_option);
+
+	ClassDB::bind_method("update_keying", &InspectorDock::update_keying);
+	ClassDB::bind_method("_property_keyed", &InspectorDock::_property_keyed);
+	ClassDB::bind_method("_transform_keyed", &InspectorDock::_transform_keyed);
+
+	ClassDB::bind_method("_new_resource", &InspectorDock::_new_resource);
+	ClassDB::bind_method("_resource_file_selected", &InspectorDock::_resource_file_selected);
+	ClassDB::bind_method("_open_resource_selector", &InspectorDock::_open_resource_selector);
+	ClassDB::bind_method("_unref_resource", &InspectorDock::_unref_resource);
+	ClassDB::bind_method("_paste_resource", &InspectorDock::_paste_resource);
+	ClassDB::bind_method("_copy_resource", &InspectorDock::_copy_resource);
+
+	ClassDB::bind_method("_select_history", &InspectorDock::_select_history);
+	ClassDB::bind_method("_prepare_history", &InspectorDock::_prepare_history);
+	ClassDB::bind_method("_resource_created", &InspectorDock::_resource_created);
+	ClassDB::bind_method("_resource_selected", &InspectorDock::_resource_selected, DEFVAL(""));
+	ClassDB::bind_method("_menu_collapseall", &InspectorDock::_menu_collapseall);
+	ClassDB::bind_method("_menu_expandall", &InspectorDock::_menu_expandall);
+	ClassDB::bind_method("_warning_pressed", &InspectorDock::_warning_pressed);
+	ClassDB::bind_method("_edit_forward", &InspectorDock::_edit_forward);
+	ClassDB::bind_method("_edit_back", &InspectorDock::_edit_back);
+
+	ADD_SIGNAL(MethodInfo("request_help"));
+}
+
+void InspectorDock::edit_resource(const Ref<Resource> &p_resource) {
+	_resource_selected(p_resource, "");
+}
+
+void InspectorDock::open_resource(const String &p_type) {
+	_load_resource(p_type);
+}
+
+void InspectorDock::set_warning(const String &p_message) {
+	warning->hide();
+	if (p_message != String()) {
+		warning->show();
+		warning_dialog->set_text(p_message);
+	}
+}
+
+void InspectorDock::clear() {
+}
+
+void InspectorDock::update(Object *p_object) {
+
+	EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history();
+	backward_button->set_disabled(editor_history->is_at_beginning());
+	forward_button->set_disabled(editor_history->is_at_end());
+
+	history_menu->set_disabled(true);
+	if (editor_history->get_history_len() > 0) {
+		history_menu->set_disabled(false);
+	}
+	editor_path->update_path();
+
+	current = p_object;
+
+	if (!p_object) {
+		object_menu->set_disabled(true);
+		warning->hide();
+		search->set_editable(false);
+
+		return;
+	}
+
+	bool is_resource = p_object->is_class("Resource");
+	bool is_node = p_object->is_class("Node");
+
+	object_menu->set_disabled(false);
+	search->set_editable(true);
+
+	PopupMenu *p = object_menu->get_popup();
+
+	p->clear();
+	p->add_shortcut(ED_SHORTCUT("property_editor/expand_all", TTR("Expand all properties")), EXPAND_ALL);
+	p->add_shortcut(ED_SHORTCUT("property_editor/collapse_all", TTR("Collapse all properties")), COLLAPSE_ALL);
+	p->add_separator();
+	if (is_resource) {
+		p->add_item(TTR("Save"), RESOURCE_SAVE);
+		p->add_item(TTR("Save As..."), RESOURCE_SAVE_AS);
+		p->add_separator();
+	}
+	p->add_shortcut(ED_SHORTCUT("property_editor/copy_params", TTR("Copy Params")), OBJECT_COPY_PARAMS);
+	p->add_shortcut(ED_SHORTCUT("property_editor/paste_params", TTR("Paste Params")), OBJECT_PASTE_PARAMS);
+	p->add_separator();
+	p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Paste Resource")), RESOURCE_PASTE);
+	if (is_resource) {
+		p->add_shortcut(ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
+		p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource", TTR("Make Built-In")), RESOURCE_UNREF);
+	}
+
+	if (is_resource || is_node) {
+		p->add_separator();
+		p->add_shortcut(ED_SHORTCUT("property_editor/make_subresources_unique", TTR("Make Sub-Resources Unique")), OBJECT_UNIQUE_RESOURCES);
+		p->add_separator();
+		p->add_icon_shortcut(get_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("property_editor/open_help", TTR("Open in Help")), OBJECT_REQUEST_HELP);
+	}
+
+	List<MethodInfo> methods;
+	p_object->get_method_list(&methods);
+
+	if (!methods.empty()) {
+
+		bool found = false;
+		List<MethodInfo>::Element *I = methods.front();
+		int i = 0;
+		while (I) {
+
+			if (I->get().flags & METHOD_FLAG_EDITOR) {
+				if (!found) {
+					p->add_separator();
+					found = true;
+				}
+				p->add_item(I->get().name.capitalize(), OBJECT_METHOD_BASE + i);
+			}
+			i++;
+			I = I->next();
+		}
+	}
+}
+
+void InspectorDock::update_keying() {
+	bool valid = false;
+
+	if (AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) {
+
+		EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history();
+		if (editor_history->get_path_size() >= 1) {
+
+			Object *obj = ObjectDB::get_instance(editor_history->get_path_object(0));
+			if (Object::cast_to<Node>(obj)) {
+
+				valid = true;
+			}
+		}
+	}
+
+	inspector->set_keying(valid);
+}
+
+InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
+	set_name("Inspector");
+	set_theme(p_editor->get_gui_base()->get_theme());
+
+	editor = p_editor;
+	editor_data = &p_editor_data;
+
+	HBoxContainer *general_options_hb = memnew(HBoxContainer);
+	add_child(general_options_hb);
+
+	resource_new_button = memnew(ToolButton);
+	resource_new_button->set_tooltip(TTR("Create a new resource in memory and edit it."));
+	resource_new_button->set_icon(get_icon("New", "EditorIcons"));
+	general_options_hb->add_child(resource_new_button);
+	resource_new_button->connect("pressed", this, "_new_resource");
+	resource_new_button->set_focus_mode(Control::FOCUS_NONE);
+
+	resource_load_button = memnew(ToolButton);
+	resource_load_button->set_tooltip(TTR("Load an existing resource from disk and edit it."));
+	resource_load_button->set_icon(get_icon("Load", "EditorIcons"));
+	general_options_hb->add_child(resource_load_button);
+	resource_load_button->connect("pressed", this, "_open_resource_selector");
+	resource_load_button->set_focus_mode(Control::FOCUS_NONE);
+
+	general_options_hb->add_spacer();
+
+	backward_button = memnew(ToolButton);
+	general_options_hb->add_child(backward_button);
+	backward_button->set_icon(get_icon("Back", "EditorIcons"));
+	backward_button->set_flat(true);
+	backward_button->set_tooltip(TTR("Go to the previous edited object in history."));
+	backward_button->set_disabled(true);
+	backward_button->connect("pressed", this, "_edit_back");
+
+	forward_button = memnew(ToolButton);
+	general_options_hb->add_child(forward_button);
+	forward_button->set_icon(get_icon("Forward", "EditorIcons"));
+	forward_button->set_flat(true);
+	forward_button->set_tooltip(TTR("Go to the next edited object in history."));
+	forward_button->set_disabled(true);
+	forward_button->connect("pressed", this, "_edit_forward");
+
+	history_menu = memnew(MenuButton);
+	history_menu->set_tooltip(TTR("History of recently edited objects."));
+	history_menu->set_icon(get_icon("History", "EditorIcons"));
+	general_options_hb->add_child(history_menu);
+	history_menu->connect("about_to_show", this, "_prepare_history");
+	history_menu->get_popup()->connect("id_pressed", this, "_select_history");
+
+	HBoxContainer *node_info_hb = memnew(HBoxContainer);
+	add_child(node_info_hb);
+
+	editor_path = memnew(EditorPath(editor->get_editor_history()));
+	editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+	node_info_hb->add_child(editor_path);
+
+	object_menu = memnew(MenuButton);
+	object_menu->set_icon(get_icon("Tools", "EditorIcons"));
+	node_info_hb->add_child(object_menu);
+	object_menu->set_tooltip(TTR("Object properties."));
+	object_menu->get_popup()->connect("id_pressed", this, "_menu_option");
+
+	new_resource_dialog = memnew(CreateDialog);
+	editor->get_gui_base()->add_child(new_resource_dialog);
+	new_resource_dialog->set_base_type("Resource");
+	new_resource_dialog->connect("create", this, "_resource_created");
+
+	search = memnew(LineEdit);
+	search->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+	add_child(search);
+
+	warning = memnew(Button);
+	add_child(warning);
+	warning->set_text(TTR("Changes may be lost!"));
+	warning->set_icon(get_icon("NodeWarning", "EditorIcons"));
+	warning->hide();
+	warning->connect("pressed", this, "_warning_pressed");
+
+	warning_dialog = memnew(AcceptDialog);
+	editor->get_gui_base()->add_child(warning_dialog);
+
+	load_resource_dialog = memnew(EditorFileDialog);
+	add_child(load_resource_dialog);
+	load_resource_dialog->set_current_dir("res://");
+	load_resource_dialog->connect("file_selected", this, "_resource_file_selected");
+
+	inspector = memnew(EditorInspector);
+	add_child(inspector);
+	inspector->set_autoclear(true);
+	inspector->set_show_categories(true);
+	inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+	inspector->set_use_doc_hints(true);
+	inspector->set_hide_script(false);
+	inspector->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/editor/capitalize_properties", true)));
+	inspector->set_use_folding(!bool(EDITOR_DEF("interface/editor/disable_inspector_folding", false)));
+	inspector->register_text_enter(search);
+	inspector->set_undo_redo(&editor_data->get_undo_redo());
+
+	inspector->set_use_filter(true); // TODO: check me
+
+	inspector->connect("resource_selected", this, "_resource_selected");
+	inspector->connect("property_keyed", this, "_property_keyed");
+}
+
+InspectorDock::~InspectorDock() {
+}
+
+// void InspectorDock::_clear_search_box() {
+
+// 	if (search_box->get_text() == "")
+// 		return;
+
+// 	search_box->clear();
+// 	inspector->update_tree();
+// }

+ 137 - 0
editor/inspector_dock.h

@@ -0,0 +1,137 @@
+/*************************************************************************/
+/*  inspector_dock.h                                                     */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef INSPECTOR_DOCK_H
+#define INSPECTOR_DOCK_H
+
+#include "editor/animation_editor.h"
+#include "editor/connections_dialog.h"
+#include "editor/create_dialog.h"
+#include "editor/editor_data.h"
+#include "editor/editor_inspector.h"
+#include "editor/editor_path.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/control.h"
+#include "scene/gui/label.h"
+#include "scene/gui/popup_menu.h"
+#include "scene/gui/tool_button.h"
+
+class EditorNode;
+
+class InspectorDock : public VBoxContainer {
+
+	GDCLASS(InspectorDock, VBoxContainer);
+
+	enum MenuOptions {
+		RESOURCE_NEW,
+		RESOURCE_LOAD,
+		RESOURCE_SAVE,
+		RESOURCE_SAVE_AS,
+		RESOURCE_UNREF,
+		RESOURCE_COPY,
+		RESOURCE_PASTE,
+		OBJECT_COPY_PARAMS,
+		OBJECT_PASTE_PARAMS,
+		OBJECT_UNIQUE_RESOURCES,
+		OBJECT_REQUEST_HELP,
+
+		COLLAPSE_ALL,
+		EXPAND_ALL,
+
+		OBJECT_METHOD_BASE = 500
+	};
+
+	EditorNode *editor;
+	EditorData *editor_data;
+
+	EditorInspector *inspector;
+
+	Object *current;
+
+	ToolButton *backward_button;
+	ToolButton *forward_button;
+
+	EditorFileDialog *load_resource_dialog;
+	CreateDialog *new_resource_dialog;
+	ToolButton *resource_new_button;
+	ToolButton *resource_load_button;
+	MenuButton *resource_save_button;
+	MenuButton *history_menu;
+	LineEdit *search;
+
+	MenuButton *object_menu;
+	EditorPath *editor_path;
+
+	Button *warning;
+	AcceptDialog *warning_dialog;
+
+	void _menu_option(int p_option);
+
+	void _new_resource();
+	void _load_resource(const String &p_type = "");
+	void _open_resource_selector() { _load_resource(); }; // just used to call from arg-less signal
+	void _resource_file_selected(String p_file);
+	void _save_resource(bool save_as) const;
+	void _unref_resource() const;
+	void _copy_resource() const;
+	void _paste_resource() const;
+
+	void _warning_pressed();
+	void _resource_created() const;
+	void _resource_selected(const RES &p_res, const String &p_property = "") const;
+	void _edit_forward();
+	void _edit_back();
+	void _menu_collapseall();
+	void _menu_expandall();
+	void _select_history(int p_idx) const;
+	void _prepare_history();
+
+	void _property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance);
+	void _transform_keyed(Object *sp, const String &p_sub, const Transform &p_key);
+
+protected:
+	static void _bind_methods();
+
+public:
+	void update_keying();
+	void edit_resource(const Ref<Resource> &p_resource);
+	void open_resource(const String &p_type);
+	void clear();
+	void set_warning(const String &p_message);
+	void update(Object *p_object);
+	Container *get_addon_area();
+	EditorInspector *get_inspector() { return inspector; }
+
+	InspectorDock(EditorNode *p_editor, EditorData &p_editor_data);
+	~InspectorDock();
+};
+
+#endif

+ 1 - 1
editor/plugins/script_editor_plugin.cpp

@@ -1188,7 +1188,7 @@ void ScriptEditor::_notification(int p_what) {
 		case NOTIFICATION_READY: {
 
 			get_tree()->connect("tree_changed", this, "_tree_changed");
-			editor->connect("request_help", this, "_request_help");
+			editor->get_inspector_dock()->connect("request_help", this, "_request_help");
 			editor->connect("request_help_search", this, "_help_search");
 			editor->connect("request_help_index", this, "_help_index");
 		} break;