Browse Source

Decouple EditorInterface from EditorPlugin

- Simplify some includes in the process.
- Also exposes EditorInterface.movie_maker_enabled as a property.
Yuri Sizov 2 years ago
parent
commit
49d7041d34

+ 14 - 24
doc/classes/EditorInterface.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<class name="EditorInterface" inherits="Node" version="4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="EditorInterface" inherits="Object" version="4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
 	<brief_description>
 		Godot editor's interface.
 	</brief_description>
@@ -34,7 +34,7 @@
 				Edits the given [Script]. The line and column on which to open the script can also be specified. The script will be open with the user-configured editor for the script's language which may be an external editor.
 			</description>
 		</method>
-		<method name="get_base_control">
+		<method name="get_base_control" qualifiers="const">
 			<return type="Control" />
 			<description>
 				Returns the main container of Godot editor's window. For example, you can use it to retrieve the size of the container and place your controls accordingly.
@@ -60,20 +60,20 @@
 				Returns the current path being viewed in the [FileSystemDock].
 			</description>
 		</method>
-		<method name="get_edited_scene_root">
+		<method name="get_edited_scene_root" qualifiers="const">
 			<return type="Node" />
 			<description>
 				Returns the edited (current) scene's root [Node].
 			</description>
 		</method>
-		<method name="get_editor_main_screen">
+		<method name="get_editor_main_screen" qualifiers="const">
 			<return type="VBoxContainer" />
 			<description>
 				Returns the editor control responsible for main screen plugins and tools. Use it with plugins that implement [method EditorPlugin._has_main_screen].
 				[b]Warning:[/b] Removing and freeing this node will render a part of the editor useless and may cause a crash.
 			</description>
 		</method>
-		<method name="get_editor_paths">
+		<method name="get_editor_paths" qualifiers="const">
 			<return type="EditorPaths" />
 			<description>
 				Returns the [EditorPaths] singleton.
@@ -86,13 +86,13 @@
 				[b]Note:[/b] This value is set via the [code]interface/editor/display_scale[/code] and [code]interface/editor/custom_display_scale[/code] editor settings. Editor must be restarted for changes to be properly applied.
 			</description>
 		</method>
-		<method name="get_editor_settings">
+		<method name="get_editor_settings" qualifiers="const">
 			<return type="EditorSettings" />
 			<description>
 				Returns the editor's [EditorSettings] instance.
 			</description>
 		</method>
-		<method name="get_file_system_dock">
+		<method name="get_file_system_dock" qualifiers="const">
 			<return type="FileSystemDock" />
 			<description>
 				Returns the editor's [FileSystemDock] instance.
@@ -118,19 +118,19 @@
 				Returns the name of the scene that is being played. If no scene is currently being played, returns an empty string.
 			</description>
 		</method>
-		<method name="get_resource_filesystem">
+		<method name="get_resource_filesystem" qualifiers="const">
 			<return type="EditorFileSystem" />
 			<description>
 				Returns the editor's [EditorFileSystem] instance.
 			</description>
 		</method>
-		<method name="get_resource_previewer">
+		<method name="get_resource_previewer" qualifiers="const">
 			<return type="EditorResourcePreview" />
 			<description>
 				Returns the editor's [EditorResourcePreview] instance.
 			</description>
 		</method>
-		<method name="get_script_editor">
+		<method name="get_script_editor" qualifiers="const">
 			<return type="ScriptEditor" />
 			<description>
 				Returns the editor's [ScriptEditor] instance.
@@ -143,7 +143,7 @@
 				Returns an array containing the paths of the currently selected files (and directories) in the [FileSystemDock].
 			</description>
 		</method>
-		<method name="get_selection">
+		<method name="get_selection" qualifiers="const">
 			<return type="EditorSelection" />
 			<description>
 				Returns the editor's [EditorSelection] instance.
@@ -158,12 +158,6 @@
 				Shows the given property on the given [param object] in the editor's Inspector dock. If [param inspector_only] is [code]true[/code], plugins will not attempt to edit [param object].
 			</description>
 		</method>
-		<method name="is_movie_maker_enabled" qualifiers="const">
-			<return type="bool" />
-			<description>
-				Returns [code]true[/code] if Movie Maker mode is enabled in the editor. See also [method set_movie_maker_enabled]. See [MovieWriter] for more information.
-			</description>
-		</method>
 		<method name="is_playing_scene" qualifiers="const">
 			<return type="bool" />
 			<description>
@@ -253,13 +247,6 @@
 				Sets the editor's current main screen to the one specified in [param name]. [param name] must match the text of the tab in question exactly ([code]2D[/code], [code]3D[/code], [code]Script[/code], [code]AssetLib[/code]).
 			</description>
 		</method>
-		<method name="set_movie_maker_enabled">
-			<return type="void" />
-			<param index="0" name="enabled" type="bool" />
-			<description>
-				Sets whether Movie Maker mode is enabled in the editor. See also [method is_movie_maker_enabled]. See [MovieWriter] for more information.
-			</description>
-		</method>
 		<method name="set_plugin_enabled">
 			<return type="void" />
 			<param index="0" name="plugin" type="String" />
@@ -279,5 +266,8 @@
 		<member name="distraction_free_mode" type="bool" setter="set_distraction_free_mode" getter="is_distraction_free_mode_enabled">
 			If [code]true[/code], enables distraction-free mode which hides side docks to increase the space available for the main view.
 		</member>
+		<member name="movie_maker_enabled" type="bool" setter="set_movie_maker_enabled" getter="is_movie_maker_enabled">
+			If [code]true[/code], the Movie Maker mode is enabled in the editor. See [MovieWriter] for more information.
+		</member>
 	</members>
 </class>

+ 1 - 1
doc/classes/EditorPlugin.xml

@@ -532,7 +532,7 @@
 		<method name="get_editor_interface">
 			<return type="EditorInterface" />
 			<description>
-				Returns the [EditorInterface] object that gives you control over Godot editor's window and its functionalities.
+				Returns the [EditorInterface] singleton. It provides access to some parts of the editor GUI as well as various inner states and tools.
 			</description>
 		</method>
 		<method name="get_export_as_menu">

+ 1 - 1
doc/classes/EditorSettings.xml

@@ -9,7 +9,7 @@
 		Accessing the settings can be done using the following methods, such as:
 		[codeblocks]
 		[gdscript]
-		var settings = EditorInterface.get_editor_settings()
+		var settings = get_editor_interface().get_editor_settings()
 		# `settings.set("some/property", 10)` also works as this class overrides `_set()` internally.
 		settings.set_setting("some/property", 10)
 		# `settings.get("some/property")` also works as this class overrides `_get()` internally.

+ 437 - 0
editor/editor_interface.cpp

@@ -0,0 +1,437 @@
+/**************************************************************************/
+/*  editor_interface.cpp                                                  */
+/**************************************************************************/
+/*                         This file is part of:                          */
+/*                             GODOT ENGINE                               */
+/*                        https://godotengine.org                         */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
+/*                                                                        */
+/* Permission is hereby granted, free of charge, to any person obtaining  */
+/* a copy of this software and associated documentation files (the        */
+/* "Software"), to deal in the Software without restriction, including    */
+/* without limitation the rights to use, copy, modify, merge, publish,    */
+/* distribute, sublicense, and/or sell copies of the Software, and to     */
+/* permit persons to whom the Software is furnished to do so, subject to  */
+/* the following conditions:                                              */
+/*                                                                        */
+/* The above copyright notice and this permission notice shall be         */
+/* included in all copies or substantial portions of the Software.        */
+/*                                                                        */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
+/**************************************************************************/
+
+#include "editor_interface.h"
+
+#include "editor/editor_command_palette.h"
+#include "editor/editor_node.h"
+#include "editor/editor_paths.h"
+#include "editor/editor_resource_preview.h"
+#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+#include "editor/filesystem_dock.h"
+#include "editor/inspector_dock.h"
+#include "main/main.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/control.h"
+
+EditorInterface *EditorInterface::singleton = nullptr;
+
+void EditorInterface::restart_editor(bool p_save) {
+	if (p_save) {
+		EditorNode::get_singleton()->save_all_scenes();
+	}
+	EditorNode::get_singleton()->restart_editor();
+}
+
+// Editor tools.
+
+EditorCommandPalette *EditorInterface::get_command_palette() const {
+	return EditorCommandPalette::get_singleton();
+}
+
+EditorFileSystem *EditorInterface::get_resource_file_system() const {
+	return EditorFileSystem::get_singleton();
+}
+
+EditorPaths *EditorInterface::get_editor_paths() const {
+	return EditorPaths::get_singleton();
+}
+
+EditorResourcePreview *EditorInterface::get_resource_previewer() const {
+	return EditorResourcePreview::get_singleton();
+}
+
+EditorSelection *EditorInterface::get_selection() const {
+	return EditorNode::get_singleton()->get_editor_selection();
+}
+
+Ref<EditorSettings> EditorInterface::get_editor_settings() const {
+	return EditorSettings::get_singleton();
+}
+
+TypedArray<Texture2D> EditorInterface::_make_mesh_previews(const TypedArray<Mesh> &p_meshes, int p_preview_size) {
+	Vector<Ref<Mesh>> meshes;
+
+	for (int i = 0; i < p_meshes.size(); i++) {
+		meshes.push_back(p_meshes[i]);
+	}
+
+	Vector<Ref<Texture2D>> textures = make_mesh_previews(meshes, nullptr, p_preview_size);
+	TypedArray<Texture2D> ret;
+	for (int i = 0; i < textures.size(); i++) {
+		ret.push_back(textures[i]);
+	}
+
+	return ret;
+}
+
+Vector<Ref<Texture2D>> EditorInterface::make_mesh_previews(const Vector<Ref<Mesh>> &p_meshes, Vector<Transform3D> *p_transforms, int p_preview_size) {
+	int size = p_preview_size;
+
+	RID scenario = RS::get_singleton()->scenario_create();
+
+	RID viewport = RS::get_singleton()->viewport_create();
+	RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ALWAYS);
+	RS::get_singleton()->viewport_set_scenario(viewport, scenario);
+	RS::get_singleton()->viewport_set_size(viewport, size, size);
+	RS::get_singleton()->viewport_set_transparent_background(viewport, true);
+	RS::get_singleton()->viewport_set_active(viewport, true);
+	RID viewport_texture = RS::get_singleton()->viewport_get_texture(viewport);
+
+	RID camera = RS::get_singleton()->camera_create();
+	RS::get_singleton()->viewport_attach_camera(viewport, camera);
+
+	RID light = RS::get_singleton()->directional_light_create();
+	RID light_instance = RS::get_singleton()->instance_create2(light, scenario);
+
+	RID light2 = RS::get_singleton()->directional_light_create();
+	RS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
+	RID light_instance2 = RS::get_singleton()->instance_create2(light2, scenario);
+
+	EditorProgress ep("mlib", TTR("Creating Mesh Previews"), p_meshes.size());
+
+	Vector<Ref<Texture2D>> textures;
+
+	for (int i = 0; i < p_meshes.size(); i++) {
+		Ref<Mesh> mesh = p_meshes[i];
+		if (!mesh.is_valid()) {
+			textures.push_back(Ref<Texture2D>());
+			continue;
+		}
+
+		Transform3D mesh_xform;
+		if (p_transforms != nullptr) {
+			mesh_xform = (*p_transforms)[i];
+		}
+
+		RID inst = RS::get_singleton()->instance_create2(mesh->get_rid(), scenario);
+		RS::get_singleton()->instance_set_transform(inst, mesh_xform);
+
+		AABB aabb = mesh->get_aabb();
+		Vector3 ofs = aabb.get_center();
+		aabb.position -= ofs;
+		Transform3D xform;
+		xform.basis = Basis().rotated(Vector3(0, 1, 0), -Math_PI / 6);
+		xform.basis = Basis().rotated(Vector3(1, 0, 0), Math_PI / 6) * xform.basis;
+		AABB rot_aabb = xform.xform(aabb);
+		float m = MAX(rot_aabb.size.x, rot_aabb.size.y) * 0.5;
+		if (m == 0) {
+			textures.push_back(Ref<Texture2D>());
+			continue;
+		}
+		xform.origin = -xform.basis.xform(ofs); //-ofs*m;
+		xform.origin.z -= rot_aabb.size.z * 2;
+		xform.invert();
+		xform = mesh_xform * xform;
+
+		RS::get_singleton()->camera_set_transform(camera, xform * Transform3D(Basis(), Vector3(0, 0, 3)));
+		RS::get_singleton()->camera_set_orthogonal(camera, m * 2, 0.01, 1000.0);
+
+		RS::get_singleton()->instance_set_transform(light_instance, xform * Transform3D().looking_at(Vector3(-2, -1, -1), Vector3(0, 1, 0)));
+		RS::get_singleton()->instance_set_transform(light_instance2, xform * Transform3D().looking_at(Vector3(+1, -1, -2), Vector3(0, 1, 0)));
+
+		ep.step(TTR("Thumbnail..."), i);
+		DisplayServer::get_singleton()->process_events();
+		Main::iteration();
+		Main::iteration();
+		Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture);
+		ERR_CONTINUE(!img.is_valid() || img->is_empty());
+		Ref<ImageTexture> it = ImageTexture::create_from_image(img);
+
+		RS::get_singleton()->free(inst);
+
+		textures.push_back(it);
+	}
+
+	RS::get_singleton()->free(viewport);
+	RS::get_singleton()->free(light);
+	RS::get_singleton()->free(light_instance);
+	RS::get_singleton()->free(light2);
+	RS::get_singleton()->free(light_instance2);
+	RS::get_singleton()->free(camera);
+	RS::get_singleton()->free(scenario);
+
+	return textures;
+}
+
+void EditorInterface::set_plugin_enabled(const String &p_plugin, bool p_enabled) {
+	EditorNode::get_singleton()->set_addon_plugin_enabled(p_plugin, p_enabled, true);
+}
+
+bool EditorInterface::is_plugin_enabled(const String &p_plugin) const {
+	return EditorNode::get_singleton()->is_addon_plugin_enabled(p_plugin);
+}
+
+// Editor GUI.
+
+Control *EditorInterface::get_base_control() const {
+	return EditorNode::get_singleton()->get_gui_base();
+}
+
+VBoxContainer *EditorInterface::get_editor_main_screen() const {
+	return EditorNode::get_singleton()->get_main_screen_control();
+}
+
+ScriptEditor *EditorInterface::get_script_editor() const {
+	return ScriptEditor::get_singleton();
+}
+
+void EditorInterface::set_main_screen_editor(const String &p_name) {
+	EditorNode::get_singleton()->select_editor_by_name(p_name);
+}
+
+void EditorInterface::set_distraction_free_mode(bool p_enter) {
+	EditorNode::get_singleton()->set_distraction_free_mode(p_enter);
+}
+
+bool EditorInterface::is_distraction_free_mode_enabled() const {
+	return EditorNode::get_singleton()->is_distraction_free_mode_enabled();
+}
+
+float EditorInterface::get_editor_scale() const {
+	return EDSCALE;
+}
+
+// Editor docks.
+
+FileSystemDock *EditorInterface::get_file_system_dock() const {
+	return FileSystemDock::get_singleton();
+}
+
+void EditorInterface::select_file(const String &p_file) {
+	FileSystemDock::get_singleton()->select_file(p_file);
+}
+
+Vector<String> EditorInterface::get_selected_paths() const {
+	return FileSystemDock::get_singleton()->get_selected_paths();
+}
+
+String EditorInterface::get_current_path() const {
+	return FileSystemDock::get_singleton()->get_current_path();
+}
+
+String EditorInterface::get_current_directory() const {
+	return FileSystemDock::get_singleton()->get_current_directory();
+}
+
+EditorInspector *EditorInterface::get_inspector() const {
+	return InspectorDock::get_inspector_singleton();
+}
+
+// Object/Resource/Node editing.
+
+void EditorInterface::inspect_object(Object *p_obj, const String &p_for_property, bool p_inspector_only) {
+	EditorNode::get_singleton()->push_item(p_obj, p_for_property, p_inspector_only);
+}
+
+void EditorInterface::edit_resource(const Ref<Resource> &p_resource) {
+	EditorNode::get_singleton()->edit_resource(p_resource);
+}
+
+void EditorInterface::edit_node(Node *p_node) {
+	EditorNode::get_singleton()->edit_node(p_node);
+}
+
+void EditorInterface::edit_script(const Ref<Script> &p_script, int p_line, int p_col, bool p_grab_focus) {
+	ScriptEditor::get_singleton()->edit(p_script, p_line, p_col, p_grab_focus);
+}
+
+void EditorInterface::open_scene_from_path(const String &scene_path) {
+	if (EditorNode::get_singleton()->is_changing_scene()) {
+		return;
+	}
+
+	EditorNode::get_singleton()->open_request(scene_path);
+}
+
+void EditorInterface::reload_scene_from_path(const String &scene_path) {
+	if (EditorNode::get_singleton()->is_changing_scene()) {
+		return;
+	}
+
+	EditorNode::get_singleton()->reload_scene(scene_path);
+}
+
+Node *EditorInterface::get_edited_scene_root() const {
+	return EditorNode::get_singleton()->get_edited_scene();
+}
+
+PackedStringArray EditorInterface::get_open_scenes() const {
+	PackedStringArray ret;
+	Vector<EditorData::EditedScene> scenes = EditorNode::get_editor_data().get_edited_scenes();
+
+	int scns_amount = scenes.size();
+	for (int idx_scn = 0; idx_scn < scns_amount; idx_scn++) {
+		if (scenes[idx_scn].root == nullptr) {
+			continue;
+		}
+		ret.push_back(scenes[idx_scn].root->get_scene_file_path());
+	}
+	return ret;
+}
+
+Error EditorInterface::save_scene() {
+	if (!get_edited_scene_root()) {
+		return ERR_CANT_CREATE;
+	}
+	if (get_edited_scene_root()->get_scene_file_path().is_empty()) {
+		return ERR_CANT_CREATE;
+	}
+
+	save_scene_as(get_edited_scene_root()->get_scene_file_path());
+	return OK;
+}
+
+void EditorInterface::save_scene_as(const String &p_scene, bool p_with_preview) {
+	EditorNode::get_singleton()->save_scene_to_path(p_scene, p_with_preview);
+}
+
+// Scene playback.
+
+void EditorInterface::play_main_scene() {
+	EditorNode::get_singleton()->run_play();
+}
+
+void EditorInterface::play_current_scene() {
+	EditorNode::get_singleton()->run_play_current();
+}
+
+void EditorInterface::play_custom_scene(const String &scene_path) {
+	EditorNode::get_singleton()->run_play_custom(scene_path);
+}
+
+void EditorInterface::stop_playing_scene() {
+	EditorNode::get_singleton()->run_stop();
+}
+
+bool EditorInterface::is_playing_scene() const {
+	return EditorNode::get_singleton()->is_run_playing();
+}
+
+String EditorInterface::get_playing_scene() const {
+	return EditorNode::get_singleton()->get_run_playing_scene();
+}
+
+void EditorInterface::set_movie_maker_enabled(bool p_enabled) {
+	EditorNode::get_singleton()->set_movie_maker_enabled(p_enabled);
+}
+
+bool EditorInterface::is_movie_maker_enabled() const {
+	return EditorNode::get_singleton()->is_movie_maker_enabled();
+}
+
+// Base.
+
+void EditorInterface::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("restart_editor", "save"), &EditorInterface::restart_editor, DEFVAL(true));
+
+	// Editor tools.
+
+	ClassDB::bind_method(D_METHOD("get_command_palette"), &EditorInterface::get_command_palette);
+	ClassDB::bind_method(D_METHOD("get_resource_filesystem"), &EditorInterface::get_resource_file_system);
+	ClassDB::bind_method(D_METHOD("get_editor_paths"), &EditorInterface::get_editor_paths);
+	ClassDB::bind_method(D_METHOD("get_resource_previewer"), &EditorInterface::get_resource_previewer);
+	ClassDB::bind_method(D_METHOD("get_selection"), &EditorInterface::get_selection);
+	ClassDB::bind_method(D_METHOD("get_editor_settings"), &EditorInterface::get_editor_settings);
+
+	ClassDB::bind_method(D_METHOD("make_mesh_previews", "meshes", "preview_size"), &EditorInterface::_make_mesh_previews);
+
+	ClassDB::bind_method(D_METHOD("set_plugin_enabled", "plugin", "enabled"), &EditorInterface::set_plugin_enabled);
+	ClassDB::bind_method(D_METHOD("is_plugin_enabled", "plugin"), &EditorInterface::is_plugin_enabled);
+
+	// Editor GUI.
+
+	ClassDB::bind_method(D_METHOD("get_base_control"), &EditorInterface::get_base_control);
+	ClassDB::bind_method(D_METHOD("get_editor_main_screen"), &EditorInterface::get_editor_main_screen);
+	ClassDB::bind_method(D_METHOD("get_script_editor"), &EditorInterface::get_script_editor);
+
+	ClassDB::bind_method(D_METHOD("set_main_screen_editor", "name"), &EditorInterface::set_main_screen_editor);
+	ClassDB::bind_method(D_METHOD("set_distraction_free_mode", "enter"), &EditorInterface::set_distraction_free_mode);
+	ClassDB::bind_method(D_METHOD("is_distraction_free_mode_enabled"), &EditorInterface::is_distraction_free_mode_enabled);
+
+	ClassDB::bind_method(D_METHOD("get_editor_scale"), &EditorInterface::get_editor_scale);
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distraction_free_mode"), "set_distraction_free_mode", "is_distraction_free_mode_enabled");
+
+	// Editor docks.
+
+	ClassDB::bind_method(D_METHOD("get_file_system_dock"), &EditorInterface::get_file_system_dock);
+	ClassDB::bind_method(D_METHOD("select_file", "file"), &EditorInterface::select_file);
+	ClassDB::bind_method(D_METHOD("get_selected_paths"), &EditorInterface::get_selected_paths);
+	ClassDB::bind_method(D_METHOD("get_current_path"), &EditorInterface::get_current_path);
+	ClassDB::bind_method(D_METHOD("get_current_directory"), &EditorInterface::get_current_directory);
+
+	ClassDB::bind_method(D_METHOD("get_inspector"), &EditorInterface::get_inspector);
+
+	// Object/Resource/Node editing.
+
+	ClassDB::bind_method(D_METHOD("inspect_object", "object", "for_property", "inspector_only"), &EditorInterface::inspect_object, DEFVAL(String()), DEFVAL(false));
+
+	ClassDB::bind_method(D_METHOD("edit_resource", "resource"), &EditorInterface::edit_resource);
+	ClassDB::bind_method(D_METHOD("edit_node", "node"), &EditorInterface::edit_node);
+	ClassDB::bind_method(D_METHOD("edit_script", "script", "line", "column", "grab_focus"), &EditorInterface::edit_script, DEFVAL(-1), DEFVAL(0), DEFVAL(true));
+	ClassDB::bind_method(D_METHOD("open_scene_from_path", "scene_filepath"), &EditorInterface::open_scene_from_path);
+	ClassDB::bind_method(D_METHOD("reload_scene_from_path", "scene_filepath"), &EditorInterface::reload_scene_from_path);
+
+	ClassDB::bind_method(D_METHOD("get_open_scenes"), &EditorInterface::get_open_scenes);
+	ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &EditorInterface::get_edited_scene_root);
+
+	ClassDB::bind_method(D_METHOD("save_scene"), &EditorInterface::save_scene);
+	ClassDB::bind_method(D_METHOD("save_scene_as", "path", "with_preview"), &EditorInterface::save_scene_as, DEFVAL(true));
+
+	// Scene playback.
+
+	ClassDB::bind_method(D_METHOD("play_main_scene"), &EditorInterface::play_main_scene);
+	ClassDB::bind_method(D_METHOD("play_current_scene"), &EditorInterface::play_current_scene);
+	ClassDB::bind_method(D_METHOD("play_custom_scene", "scene_filepath"), &EditorInterface::play_custom_scene);
+	ClassDB::bind_method(D_METHOD("stop_playing_scene"), &EditorInterface::stop_playing_scene);
+	ClassDB::bind_method(D_METHOD("is_playing_scene"), &EditorInterface::is_playing_scene);
+	ClassDB::bind_method(D_METHOD("get_playing_scene"), &EditorInterface::get_playing_scene);
+
+	ClassDB::bind_method(D_METHOD("set_movie_maker_enabled", "enabled"), &EditorInterface::set_movie_maker_enabled);
+	ClassDB::bind_method(D_METHOD("is_movie_maker_enabled"), &EditorInterface::is_movie_maker_enabled);
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "movie_maker_enabled"), "set_movie_maker_enabled", "is_movie_maker_enabled");
+}
+
+void EditorInterface::create() {
+	memnew(EditorInterface);
+}
+
+void EditorInterface::free() {
+	ERR_FAIL_COND(singleton == nullptr);
+	memdelete(singleton);
+}
+
+EditorInterface::EditorInterface() {
+	ERR_FAIL_COND(singleton != nullptr);
+	singleton = this;
+}

+ 143 - 0
editor/editor_interface.h

@@ -0,0 +1,143 @@
+/**************************************************************************/
+/*  editor_interface.h                                                    */
+/**************************************************************************/
+/*                         This file is part of:                          */
+/*                             GODOT ENGINE                               */
+/*                        https://godotengine.org                         */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
+/*                                                                        */
+/* Permission is hereby granted, free of charge, to any person obtaining  */
+/* a copy of this software and associated documentation files (the        */
+/* "Software"), to deal in the Software without restriction, including    */
+/* without limitation the rights to use, copy, modify, merge, publish,    */
+/* distribute, sublicense, and/or sell copies of the Software, and to     */
+/* permit persons to whom the Software is furnished to do so, subject to  */
+/* the following conditions:                                              */
+/*                                                                        */
+/* The above copyright notice and this permission notice shall be         */
+/* included in all copies or substantial portions of the Software.        */
+/*                                                                        */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
+/**************************************************************************/
+
+#ifndef EDITOR_INTERFACE_H
+#define EDITOR_INTERFACE_H
+
+#include "core/io/resource.h"
+#include "core/object/class_db.h"
+#include "core/object/object.h"
+#include "core/object/script_language.h"
+
+class Control;
+class EditorCommandPalette;
+class EditorFileSystem;
+class EditorInspector;
+class EditorPaths;
+class EditorResourcePreview;
+class EditorSelection;
+class EditorSettings;
+class FileSystemDock;
+class Mesh;
+class Node;
+class ScriptEditor;
+class Texture2D;
+class VBoxContainer;
+
+class EditorInterface : public Object {
+	GDCLASS(EditorInterface, Object);
+
+	static EditorInterface *singleton;
+
+	// Editor tools.
+
+	TypedArray<Texture2D> _make_mesh_previews(const TypedArray<Mesh> &p_meshes, int p_preview_size);
+
+protected:
+	static void _bind_methods();
+
+public:
+	static EditorInterface *get_singleton() { return singleton; }
+
+	void restart_editor(bool p_save = true);
+
+	// Editor tools.
+
+	EditorCommandPalette *get_command_palette() const;
+	EditorFileSystem *get_resource_file_system() const;
+	EditorPaths *get_editor_paths() const;
+	EditorResourcePreview *get_resource_previewer() const;
+	EditorSelection *get_selection() const;
+	Ref<EditorSettings> get_editor_settings() const;
+
+	Vector<Ref<Texture2D>> make_mesh_previews(const Vector<Ref<Mesh>> &p_meshes, Vector<Transform3D> *p_transforms, int p_preview_size);
+
+	void set_plugin_enabled(const String &p_plugin, bool p_enabled);
+	bool is_plugin_enabled(const String &p_plugin) const;
+
+	// Editor GUI.
+
+	Control *get_base_control() const;
+	VBoxContainer *get_editor_main_screen() const;
+	ScriptEditor *get_script_editor() const;
+
+	void set_main_screen_editor(const String &p_name);
+	void set_distraction_free_mode(bool p_enter);
+	bool is_distraction_free_mode_enabled() const;
+
+	float get_editor_scale() const;
+
+	// Editor docks.
+
+	FileSystemDock *get_file_system_dock() const;
+	void select_file(const String &p_file);
+	Vector<String> get_selected_paths() const;
+	String get_current_path() const;
+	String get_current_directory() const;
+
+	EditorInspector *get_inspector() const;
+
+	// Object/Resource/Node editing.
+
+	void inspect_object(Object *p_obj, const String &p_for_property = String(), bool p_inspector_only = false);
+
+	void edit_resource(const Ref<Resource> &p_resource);
+	void edit_node(Node *p_node);
+	void edit_script(const Ref<Script> &p_script, int p_line = -1, int p_col = 0, bool p_grab_focus = true);
+	void open_scene_from_path(const String &scene_path);
+	void reload_scene_from_path(const String &scene_path);
+
+	PackedStringArray get_open_scenes() const;
+	Node *get_edited_scene_root() const;
+
+	Error save_scene();
+	void save_scene_as(const String &p_scene, bool p_with_preview = true);
+
+	// Scene playback.
+
+	void play_main_scene();
+	void play_current_scene();
+	void play_custom_scene(const String &scene_path);
+	void stop_playing_scene();
+	bool is_playing_scene() const;
+	String get_playing_scene() const;
+
+	void set_movie_maker_enabled(bool p_enabled);
+	bool is_movie_maker_enabled() const;
+
+	// Base.
+
+	static void create();
+	static void free();
+
+	EditorInterface();
+};
+
+#endif // EDITOR_INTERFACE_H

+ 1 - 5
editor/editor_node.cpp

@@ -75,6 +75,7 @@
 #include "editor/editor_folding.h"
 #include "editor/editor_help.h"
 #include "editor/editor_inspector.h"
+#include "editor/editor_interface.h"
 #include "editor/editor_layouts_dialog.h"
 #include "editor/editor_log.h"
 #include "editor/editor_native_shader_source_visualizer.h"
@@ -7901,11 +7902,6 @@ EditorNode::EditorNode() {
 		print_verbose("Asset Library not available (due to using Web editor, or SSL support disabled).");
 	}
 
-	// Add interface before adding plugins.
-
-	editor_interface = memnew(EditorInterface);
-	add_child(editor_interface);
-
 	// More visually meaningful to have this later.
 	raise_bottom_panel_item(AnimationPlayerEditor::get_singleton());
 

+ 1 - 1
editor/editor_node.h

@@ -65,6 +65,7 @@ class TabContainer;
 class TextureRect;
 class TextureProgressBar;
 class Tree;
+class VBoxContainer;
 class VSplitContainer;
 class Window;
 
@@ -269,7 +270,6 @@ private:
 
 	EditorCommandPalette *command_palette = nullptr;
 	EditorExport *editor_export = nullptr;
-	EditorInterface *editor_interface = nullptr;
 	EditorLog *log = nullptr;
 	EditorNativeShaderSourceVisualizer *native_shader_source_visualizer = nullptr;
 	EditorPlugin *editor_plugin_screen = nullptr;

+ 2 - 2
editor/editor_paths.cpp

@@ -91,8 +91,7 @@ String EditorPaths::get_feature_profiles_dir() const {
 }
 
 void EditorPaths::create() {
-	ERR_FAIL_COND(singleton != nullptr);
-	memnew(EditorPaths());
+	memnew(EditorPaths);
 }
 
 void EditorPaths::free() {
@@ -111,6 +110,7 @@ void EditorPaths::_bind_methods() {
 }
 
 EditorPaths::EditorPaths() {
+	ERR_FAIL_COND(singleton != nullptr);
 	singleton = this;
 
 	project_data_dir = ProjectSettings::get_singleton()->get_project_data_path();

+ 3 - 357
editor/editor_plugin.cpp

@@ -31,15 +31,13 @@
 #include "editor_plugin.h"
 
 #include "editor/debugger/editor_debugger_node.h"
-#include "editor/editor_command_palette.h"
+#include "editor/editor_file_system.h"
+#include "editor/editor_inspector.h"
+#include "editor/editor_interface.h"
 #include "editor/editor_node.h"
-#include "editor/editor_paths.h"
-#include "editor/editor_resource_preview.h"
-#include "editor/editor_settings.h"
 #include "editor/editor_translation_parser.h"
 #include "editor/editor_undo_redo_manager.h"
 #include "editor/export/editor_export.h"
-#include "editor/filesystem_dock.h"
 #include "editor/gui/editor_title_bar.h"
 #include "editor/import/editor_import_plugin.h"
 #include "editor/import/resource_importer_scene.h"
@@ -51,362 +49,10 @@
 #include "editor/plugins/script_editor_plugin.h"
 #include "editor/project_settings_editor.h"
 #include "editor/scene_tree_dock.h"
-#include "main/main.h"
 #include "scene/3d/camera_3d.h"
 #include "scene/gui/popup_menu.h"
 #include "servers/rendering_server.h"
 
-TypedArray<Texture2D> EditorInterface::_make_mesh_previews(const TypedArray<Mesh> &p_meshes, int p_preview_size) {
-	Vector<Ref<Mesh>> meshes;
-
-	for (int i = 0; i < p_meshes.size(); i++) {
-		meshes.push_back(p_meshes[i]);
-	}
-
-	Vector<Ref<Texture2D>> textures = make_mesh_previews(meshes, nullptr, p_preview_size);
-	TypedArray<Texture2D> ret;
-	for (int i = 0; i < textures.size(); i++) {
-		ret.push_back(textures[i]);
-	}
-
-	return ret;
-}
-
-Vector<Ref<Texture2D>> EditorInterface::make_mesh_previews(const Vector<Ref<Mesh>> &p_meshes, Vector<Transform3D> *p_transforms, int p_preview_size) {
-	int size = p_preview_size;
-
-	RID scenario = RS::get_singleton()->scenario_create();
-
-	RID viewport = RS::get_singleton()->viewport_create();
-	RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ALWAYS);
-	RS::get_singleton()->viewport_set_scenario(viewport, scenario);
-	RS::get_singleton()->viewport_set_size(viewport, size, size);
-	RS::get_singleton()->viewport_set_transparent_background(viewport, true);
-	RS::get_singleton()->viewport_set_active(viewport, true);
-	RID viewport_texture = RS::get_singleton()->viewport_get_texture(viewport);
-
-	RID camera = RS::get_singleton()->camera_create();
-	RS::get_singleton()->viewport_attach_camera(viewport, camera);
-
-	RID light = RS::get_singleton()->directional_light_create();
-	RID light_instance = RS::get_singleton()->instance_create2(light, scenario);
-
-	RID light2 = RS::get_singleton()->directional_light_create();
-	RS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
-	RID light_instance2 = RS::get_singleton()->instance_create2(light2, scenario);
-
-	EditorProgress ep("mlib", TTR("Creating Mesh Previews"), p_meshes.size());
-
-	Vector<Ref<Texture2D>> textures;
-
-	for (int i = 0; i < p_meshes.size(); i++) {
-		Ref<Mesh> mesh = p_meshes[i];
-		if (!mesh.is_valid()) {
-			textures.push_back(Ref<Texture2D>());
-			continue;
-		}
-
-		Transform3D mesh_xform;
-		if (p_transforms != nullptr) {
-			mesh_xform = (*p_transforms)[i];
-		}
-
-		RID inst = RS::get_singleton()->instance_create2(mesh->get_rid(), scenario);
-		RS::get_singleton()->instance_set_transform(inst, mesh_xform);
-
-		AABB aabb = mesh->get_aabb();
-		Vector3 ofs = aabb.get_center();
-		aabb.position -= ofs;
-		Transform3D xform;
-		xform.basis = Basis().rotated(Vector3(0, 1, 0), -Math_PI / 6);
-		xform.basis = Basis().rotated(Vector3(1, 0, 0), Math_PI / 6) * xform.basis;
-		AABB rot_aabb = xform.xform(aabb);
-		float m = MAX(rot_aabb.size.x, rot_aabb.size.y) * 0.5;
-		if (m == 0) {
-			textures.push_back(Ref<Texture2D>());
-			continue;
-		}
-		xform.origin = -xform.basis.xform(ofs); //-ofs*m;
-		xform.origin.z -= rot_aabb.size.z * 2;
-		xform.invert();
-		xform = mesh_xform * xform;
-
-		RS::get_singleton()->camera_set_transform(camera, xform * Transform3D(Basis(), Vector3(0, 0, 3)));
-		RS::get_singleton()->camera_set_orthogonal(camera, m * 2, 0.01, 1000.0);
-
-		RS::get_singleton()->instance_set_transform(light_instance, xform * Transform3D().looking_at(Vector3(-2, -1, -1), Vector3(0, 1, 0)));
-		RS::get_singleton()->instance_set_transform(light_instance2, xform * Transform3D().looking_at(Vector3(+1, -1, -2), Vector3(0, 1, 0)));
-
-		ep.step(TTR("Thumbnail..."), i);
-		DisplayServer::get_singleton()->process_events();
-		Main::iteration();
-		Main::iteration();
-		Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture);
-		ERR_CONTINUE(!img.is_valid() || img->is_empty());
-		Ref<ImageTexture> it = ImageTexture::create_from_image(img);
-
-		RS::get_singleton()->free(inst);
-
-		textures.push_back(it);
-	}
-
-	RS::get_singleton()->free(viewport);
-	RS::get_singleton()->free(light);
-	RS::get_singleton()->free(light_instance);
-	RS::get_singleton()->free(light2);
-	RS::get_singleton()->free(light_instance2);
-	RS::get_singleton()->free(camera);
-	RS::get_singleton()->free(scenario);
-
-	return textures;
-}
-
-void EditorInterface::set_main_screen_editor(const String &p_name) {
-	EditorNode::get_singleton()->select_editor_by_name(p_name);
-}
-
-VBoxContainer *EditorInterface::get_editor_main_screen() {
-	return EditorNode::get_singleton()->get_main_screen_control();
-}
-
-void EditorInterface::edit_resource(const Ref<Resource> &p_resource) {
-	EditorNode::get_singleton()->edit_resource(p_resource);
-}
-
-void EditorInterface::edit_node(Node *p_node) {
-	EditorNode::get_singleton()->edit_node(p_node);
-}
-
-void EditorInterface::edit_script(const Ref<Script> &p_script, int p_line, int p_col, bool p_grab_focus) {
-	ScriptEditor::get_singleton()->edit(p_script, p_line, p_col, p_grab_focus);
-}
-
-void EditorInterface::open_scene_from_path(const String &scene_path) {
-	if (EditorNode::get_singleton()->is_changing_scene()) {
-		return;
-	}
-
-	EditorNode::get_singleton()->open_request(scene_path);
-}
-
-void EditorInterface::reload_scene_from_path(const String &scene_path) {
-	if (EditorNode::get_singleton()->is_changing_scene()) {
-		return;
-	}
-
-	EditorNode::get_singleton()->reload_scene(scene_path);
-}
-
-void EditorInterface::play_main_scene() {
-	EditorNode::get_singleton()->run_play();
-}
-
-void EditorInterface::play_current_scene() {
-	EditorNode::get_singleton()->run_play_current();
-}
-
-void EditorInterface::play_custom_scene(const String &scene_path) {
-	EditorNode::get_singleton()->run_play_custom(scene_path);
-}
-
-void EditorInterface::stop_playing_scene() {
-	EditorNode::get_singleton()->run_stop();
-}
-
-bool EditorInterface::is_playing_scene() const {
-	return EditorNode::get_singleton()->is_run_playing();
-}
-
-String EditorInterface::get_playing_scene() const {
-	return EditorNode::get_singleton()->get_run_playing_scene();
-}
-
-Node *EditorInterface::get_edited_scene_root() {
-	return EditorNode::get_singleton()->get_edited_scene();
-}
-
-PackedStringArray EditorInterface::get_open_scenes() const {
-	PackedStringArray ret;
-	Vector<EditorData::EditedScene> scenes = EditorNode::get_editor_data().get_edited_scenes();
-
-	int scns_amount = scenes.size();
-	for (int idx_scn = 0; idx_scn < scns_amount; idx_scn++) {
-		if (scenes[idx_scn].root == nullptr) {
-			continue;
-		}
-		ret.push_back(scenes[idx_scn].root->get_scene_file_path());
-	}
-	return ret;
-}
-
-ScriptEditor *EditorInterface::get_script_editor() {
-	return ScriptEditor::get_singleton();
-}
-
-void EditorInterface::select_file(const String &p_file) {
-	FileSystemDock::get_singleton()->select_file(p_file);
-}
-
-Vector<String> EditorInterface::get_selected_paths() const {
-	return FileSystemDock::get_singleton()->get_selected_paths();
-}
-
-String EditorInterface::get_current_path() const {
-	return FileSystemDock::get_singleton()->get_current_path();
-}
-
-String EditorInterface::get_current_directory() const {
-	return FileSystemDock::get_singleton()->get_current_directory();
-}
-
-void EditorInterface::inspect_object(Object *p_obj, const String &p_for_property, bool p_inspector_only) {
-	EditorNode::get_singleton()->push_item(p_obj, p_for_property, p_inspector_only);
-}
-
-EditorFileSystem *EditorInterface::get_resource_file_system() {
-	return EditorFileSystem::get_singleton();
-}
-
-FileSystemDock *EditorInterface::get_file_system_dock() {
-	return FileSystemDock::get_singleton();
-}
-
-EditorSelection *EditorInterface::get_selection() {
-	return EditorNode::get_singleton()->get_editor_selection();
-}
-
-Ref<EditorSettings> EditorInterface::get_editor_settings() {
-	return EditorSettings::get_singleton();
-}
-EditorPaths *EditorInterface::get_editor_paths() {
-	return EditorPaths::get_singleton();
-}
-
-EditorResourcePreview *EditorInterface::get_resource_previewer() {
-	return EditorResourcePreview::get_singleton();
-}
-
-Control *EditorInterface::get_base_control() {
-	return EditorNode::get_singleton()->get_gui_base();
-}
-
-float EditorInterface::get_editor_scale() const {
-	return EDSCALE;
-}
-
-void EditorInterface::set_plugin_enabled(const String &p_plugin, bool p_enabled) {
-	EditorNode::get_singleton()->set_addon_plugin_enabled(p_plugin, p_enabled, true);
-}
-
-bool EditorInterface::is_plugin_enabled(const String &p_plugin) const {
-	return EditorNode::get_singleton()->is_addon_plugin_enabled(p_plugin);
-}
-
-void EditorInterface::set_movie_maker_enabled(bool p_enabled) {
-	EditorNode::get_singleton()->set_movie_maker_enabled(p_enabled);
-}
-
-bool EditorInterface::is_movie_maker_enabled() const {
-	return EditorNode::get_singleton()->is_movie_maker_enabled();
-}
-
-EditorInspector *EditorInterface::get_inspector() const {
-	return InspectorDock::get_inspector_singleton();
-}
-
-Error EditorInterface::save_scene() {
-	if (!get_edited_scene_root()) {
-		return ERR_CANT_CREATE;
-	}
-	if (get_edited_scene_root()->get_scene_file_path().is_empty()) {
-		return ERR_CANT_CREATE;
-	}
-
-	save_scene_as(get_edited_scene_root()->get_scene_file_path());
-	return OK;
-}
-
-void EditorInterface::save_scene_as(const String &p_scene, bool p_with_preview) {
-	EditorNode::get_singleton()->save_scene_to_path(p_scene, p_with_preview);
-}
-
-void EditorInterface::set_distraction_free_mode(bool p_enter) {
-	EditorNode::get_singleton()->set_distraction_free_mode(p_enter);
-}
-
-void EditorInterface::restart_editor(bool p_save) {
-	if (p_save) {
-		EditorNode::get_singleton()->save_all_scenes();
-	}
-	EditorNode::get_singleton()->restart_editor();
-}
-
-bool EditorInterface::is_distraction_free_mode_enabled() const {
-	return EditorNode::get_singleton()->is_distraction_free_mode_enabled();
-}
-
-EditorCommandPalette *EditorInterface::get_command_palette() const {
-	return EditorCommandPalette::get_singleton();
-}
-
-EditorInterface *EditorInterface::singleton = nullptr;
-
-void EditorInterface::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("inspect_object", "object", "for_property", "inspector_only"), &EditorInterface::inspect_object, DEFVAL(String()), DEFVAL(false));
-	ClassDB::bind_method(D_METHOD("get_selection"), &EditorInterface::get_selection);
-	ClassDB::bind_method(D_METHOD("get_editor_settings"), &EditorInterface::get_editor_settings);
-	ClassDB::bind_method(D_METHOD("get_script_editor"), &EditorInterface::get_script_editor);
-	ClassDB::bind_method(D_METHOD("get_base_control"), &EditorInterface::get_base_control);
-	ClassDB::bind_method(D_METHOD("get_editor_scale"), &EditorInterface::get_editor_scale);
-	ClassDB::bind_method(D_METHOD("edit_resource", "resource"), &EditorInterface::edit_resource);
-	ClassDB::bind_method(D_METHOD("edit_node", "node"), &EditorInterface::edit_node);
-	ClassDB::bind_method(D_METHOD("edit_script", "script", "line", "column", "grab_focus"), &EditorInterface::edit_script, DEFVAL(-1), DEFVAL(0), DEFVAL(true));
-	ClassDB::bind_method(D_METHOD("open_scene_from_path", "scene_filepath"), &EditorInterface::open_scene_from_path);
-	ClassDB::bind_method(D_METHOD("reload_scene_from_path", "scene_filepath"), &EditorInterface::reload_scene_from_path);
-	ClassDB::bind_method(D_METHOD("play_main_scene"), &EditorInterface::play_main_scene);
-	ClassDB::bind_method(D_METHOD("play_current_scene"), &EditorInterface::play_current_scene);
-	ClassDB::bind_method(D_METHOD("play_custom_scene", "scene_filepath"), &EditorInterface::play_custom_scene);
-	ClassDB::bind_method(D_METHOD("stop_playing_scene"), &EditorInterface::stop_playing_scene);
-	ClassDB::bind_method(D_METHOD("is_playing_scene"), &EditorInterface::is_playing_scene);
-	ClassDB::bind_method(D_METHOD("get_playing_scene"), &EditorInterface::get_playing_scene);
-	ClassDB::bind_method(D_METHOD("get_open_scenes"), &EditorInterface::get_open_scenes);
-	ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &EditorInterface::get_edited_scene_root);
-	ClassDB::bind_method(D_METHOD("get_resource_previewer"), &EditorInterface::get_resource_previewer);
-	ClassDB::bind_method(D_METHOD("get_resource_filesystem"), &EditorInterface::get_resource_file_system);
-	ClassDB::bind_method(D_METHOD("get_editor_main_screen"), &EditorInterface::get_editor_main_screen);
-	ClassDB::bind_method(D_METHOD("make_mesh_previews", "meshes", "preview_size"), &EditorInterface::_make_mesh_previews);
-	ClassDB::bind_method(D_METHOD("select_file", "file"), &EditorInterface::select_file);
-	ClassDB::bind_method(D_METHOD("get_selected_paths"), &EditorInterface::get_selected_paths);
-	ClassDB::bind_method(D_METHOD("get_current_path"), &EditorInterface::get_current_path);
-	ClassDB::bind_method(D_METHOD("get_current_directory"), &EditorInterface::get_current_directory);
-	ClassDB::bind_method(D_METHOD("get_file_system_dock"), &EditorInterface::get_file_system_dock);
-	ClassDB::bind_method(D_METHOD("get_editor_paths"), &EditorInterface::get_editor_paths);
-	ClassDB::bind_method(D_METHOD("get_command_palette"), &EditorInterface::get_command_palette);
-
-	ClassDB::bind_method(D_METHOD("set_plugin_enabled", "plugin", "enabled"), &EditorInterface::set_plugin_enabled);
-	ClassDB::bind_method(D_METHOD("is_plugin_enabled", "plugin"), &EditorInterface::is_plugin_enabled);
-
-	ClassDB::bind_method(D_METHOD("set_movie_maker_enabled", "enabled"), &EditorInterface::set_movie_maker_enabled);
-	ClassDB::bind_method(D_METHOD("is_movie_maker_enabled"), &EditorInterface::is_movie_maker_enabled);
-
-	ClassDB::bind_method(D_METHOD("get_inspector"), &EditorInterface::get_inspector);
-
-	ClassDB::bind_method(D_METHOD("save_scene"), &EditorInterface::save_scene);
-	ClassDB::bind_method(D_METHOD("save_scene_as", "path", "with_preview"), &EditorInterface::save_scene_as, DEFVAL(true));
-	ClassDB::bind_method(D_METHOD("restart_editor", "save"), &EditorInterface::restart_editor, DEFVAL(true));
-
-	ClassDB::bind_method(D_METHOD("set_main_screen_editor", "name"), &EditorInterface::set_main_screen_editor);
-	ClassDB::bind_method(D_METHOD("set_distraction_free_mode", "enter"), &EditorInterface::set_distraction_free_mode);
-	ClassDB::bind_method(D_METHOD("is_distraction_free_mode_enabled"), &EditorInterface::is_distraction_free_mode_enabled);
-
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distraction_free_mode"), "set_distraction_free_mode", "is_distraction_free_mode_enabled");
-}
-
-EditorInterface::EditorInterface() {
-	singleton = this;
-}
-
-///////////////////////////////////////////
 void EditorPlugin::add_custom_type(const String &p_type, const String &p_base, const Ref<Script> &p_script, const Ref<Texture2D> &p_icon) {
 	EditorNode::get_editor_data().add_custom_type(p_type, p_base, p_script, p_icon);
 }

+ 1 - 82
editor/editor_plugin.h

@@ -38,101 +38,20 @@
 class Node3D;
 class Button;
 class PopupMenu;
-class EditorCommandPalette;
 class EditorDebuggerPlugin;
 class EditorExport;
 class EditorExportPlugin;
-class EditorFileSystem;
 class EditorImportPlugin;
-class EditorInspector;
 class EditorInspectorPlugin;
+class EditorInterface;
 class EditorNode3DGizmoPlugin;
-class EditorPaths;
 class EditorResourceConversionPlugin;
-class EditorResourcePreview;
 class EditorSceneFormatImporter;
 class EditorScenePostImportPlugin;
-class EditorSelection;
-class EditorSettings;
 class EditorToolAddons;
 class EditorTranslationParserPlugin;
 class EditorUndoRedoManager;
-class FileSystemDock;
 class ScriptCreateDialog;
-class ScriptEditor;
-class VBoxContainer;
-
-class EditorInterface : public Node {
-	GDCLASS(EditorInterface, Node);
-
-protected:
-	static void _bind_methods();
-	static EditorInterface *singleton;
-
-	TypedArray<Texture2D> _make_mesh_previews(const TypedArray<Mesh> &p_meshes, int p_preview_size);
-
-public:
-	static EditorInterface *get_singleton() { return singleton; }
-
-	VBoxContainer *get_editor_main_screen();
-	void edit_resource(const Ref<Resource> &p_resource);
-	void edit_node(Node *p_node);
-	void edit_script(const Ref<Script> &p_script, int p_line = -1, int p_col = 0, bool p_grab_focus = true);
-	void open_scene_from_path(const String &scene_path);
-	void reload_scene_from_path(const String &scene_path);
-
-	void play_main_scene();
-	void play_current_scene();
-	void play_custom_scene(const String &scene_path);
-	void stop_playing_scene();
-	bool is_playing_scene() const;
-	String get_playing_scene() const;
-
-	Node *get_edited_scene_root();
-	PackedStringArray get_open_scenes() const;
-	ScriptEditor *get_script_editor();
-
-	EditorCommandPalette *get_command_palette() const;
-
-	void select_file(const String &p_file);
-	Vector<String> get_selected_paths() const;
-	String get_current_path() const;
-	String get_current_directory() const;
-
-	void inspect_object(Object *p_obj, const String &p_for_property = String(), bool p_inspector_only = false);
-
-	EditorSelection *get_selection();
-	//EditorImportExport *get_import_export();
-	Ref<EditorSettings> get_editor_settings();
-	EditorPaths *get_editor_paths();
-	EditorResourcePreview *get_resource_previewer();
-	EditorFileSystem *get_resource_file_system();
-
-	FileSystemDock *get_file_system_dock();
-
-	Control *get_base_control();
-	float get_editor_scale() const;
-
-	void set_plugin_enabled(const String &p_plugin, bool p_enabled);
-	bool is_plugin_enabled(const String &p_plugin) const;
-
-	void set_movie_maker_enabled(bool p_enabled);
-	bool is_movie_maker_enabled() const;
-
-	EditorInspector *get_inspector() const;
-
-	Error save_scene();
-	void save_scene_as(const String &p_scene, bool p_with_preview = true);
-	void restart_editor(bool p_save = true);
-
-	Vector<Ref<Texture2D>> make_mesh_previews(const Vector<Ref<Mesh>> &p_meshes, Vector<Transform3D> *p_transforms, int p_preview_size);
-
-	void set_main_screen_editor(const String &p_name);
-	void set_distraction_free_mode(bool p_enter);
-	bool is_distraction_free_mode_enabled() const;
-
-	EditorInterface();
-};
 
 class EditorPlugin : public Node {
 	GDCLASS(EditorPlugin, Node);

+ 1 - 0
editor/editor_run_script.cpp

@@ -30,6 +30,7 @@
 
 #include "editor_run_script.h"
 
+#include "editor/editor_interface.h"
 #include "editor/editor_node.h"
 
 void EditorScript::add_root_node(Node *p_node) {

+ 3 - 1
editor/editor_run_script.h

@@ -31,9 +31,11 @@
 #ifndef EDITOR_RUN_SCRIPT_H
 #define EDITOR_RUN_SCRIPT_H
 
+#include "core/object/gdvirtual.gen.inc"
 #include "core/object/ref_counted.h"
-#include "editor/editor_plugin.h"
+#include "core/object/script_language.h"
 
+class EditorInterface;
 class EditorNode;
 
 class EditorScript : public RefCounted {

+ 2 - 1
editor/gui/scene_tree_editor.h

@@ -31,10 +31,11 @@
 #ifndef SCENE_TREE_EDITOR_H
 #define SCENE_TREE_EDITOR_H
 
-#include "editor/editor_data.h"
 #include "scene/gui/dialogs.h"
 #include "scene/gui/tree.h"
 
+class EditorSelection;
+
 class SceneTreeEditor : public Control {
 	GDCLASS(SceneTreeEditor, Control);
 

+ 1 - 0
editor/plugins/canvas_item_editor_plugin.h

@@ -40,6 +40,7 @@ class CanvasItemEditorViewport;
 class ConfirmationDialog;
 class EditorData;
 class EditorZoomWidget;
+class EditorSelection;
 class HScrollBar;
 class HSplitContainer;
 class MenuButton;

+ 1 - 0
editor/plugins/control_editor_plugin.h

@@ -45,6 +45,7 @@
 #include "scene/gui/separator.h"
 #include "scene/gui/texture_rect.h"
 
+class EditorSelection;
 class GridContainer;
 
 // Inspector controls.

+ 2 - 1
editor/plugins/curve_editor_plugin.cpp

@@ -34,6 +34,7 @@
 #include "core/core_string_names.h"
 #include "core/input/input.h"
 #include "core/os/keyboard.h"
+#include "editor/editor_interface.h"
 #include "editor/editor_node.h"
 #include "editor/editor_scale.h"
 #include "editor/editor_settings.h"
@@ -780,7 +781,7 @@ CurveEditorPlugin::CurveEditorPlugin() {
 	curve_plugin.instantiate();
 	EditorInspector::add_inspector_plugin(curve_plugin);
 
-	get_editor_interface()->get_resource_previewer()->add_preview_generator(memnew(CurvePreviewGenerator));
+	EditorInterface::get_singleton()->get_resource_previewer()->add_preview_generator(memnew(CurvePreviewGenerator));
 }
 
 //-----------------------------------

+ 2 - 1
editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp

@@ -30,6 +30,7 @@
 
 #include "gpu_particles_collision_sdf_editor_plugin.h"
 
+#include "editor/editor_interface.h"
 #include "editor/editor_node.h"
 #include "editor/gui/editor_file_dialog.h"
 
@@ -193,7 +194,7 @@ GPUParticlesCollisionSDF3DEditorPlugin::GPUParticlesCollisionSDF3DEditorPlugin()
 	probe_file->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
 	probe_file->add_filter("*.exr");
 	probe_file->connect("file_selected", callable_mp(this, &GPUParticlesCollisionSDF3DEditorPlugin::_sdf_save_path_and_bake));
-	get_editor_interface()->get_base_control()->add_child(probe_file);
+	EditorInterface::get_singleton()->get_base_control()->add_child(probe_file);
 	probe_file->set_title(TTR("Select path for SDF Texture"));
 
 	GPUParticlesCollisionSDF3D::bake_begin_function = bake_func_begin;

+ 1 - 0
editor/plugins/mesh_library_editor_plugin.cpp

@@ -30,6 +30,7 @@
 
 #include "mesh_library_editor_plugin.h"
 
+#include "editor/editor_interface.h"
 #include "editor/editor_node.h"
 #include "editor/editor_settings.h"
 #include "editor/gui/editor_file_dialog.h"

+ 1 - 0
editor/plugins/node_3d_editor_plugin.h

@@ -44,6 +44,7 @@ class ColorPickerButton;
 class ConfirmationDialog;
 class DirectionalLight3D;
 class EditorData;
+class EditorSelection;
 class EditorSpinSlider;
 class HSplitContainer;
 class LineEdit;

+ 1 - 0
editor/plugins/resource_preloader_editor_plugin.cpp

@@ -32,6 +32,7 @@
 
 #include "core/config/project_settings.h"
 #include "core/io/resource_loader.h"
+#include "editor/editor_interface.h"
 #include "editor/editor_node.h"
 #include "editor/editor_scale.h"
 #include "editor/editor_settings.h"

+ 2 - 1
editor/plugins/tiles/tiles_editor_plugin.cpp

@@ -34,6 +34,7 @@
 
 #include "core/os/mutex.h"
 
+#include "editor/editor_interface.h"
 #include "editor/editor_node.h"
 #include "editor/editor_scale.h"
 #include "editor/editor_settings.h"
@@ -209,7 +210,7 @@ void TilesEditorPlugin::make_visible(bool p_visible) {
 }
 
 bool TilesEditorPlugin::is_tile_map_selected() {
-	TypedArray<Node> selection = get_editor_interface()->get_selection()->get_selected_nodes();
+	TypedArray<Node> selection = EditorInterface::get_singleton()->get_selection()->get_selected_nodes();
 	if (selection.size() == 1 && Object::cast_to<TileMap>(selection[0])) {
 		return true;
 	}

+ 2 - 1
editor/plugins/voxel_gi_editor_plugin.cpp

@@ -30,6 +30,7 @@
 
 #include "voxel_gi_editor_plugin.h"
 
+#include "editor/editor_interface.h"
 #include "editor/editor_node.h"
 #include "editor/gui/editor_file_dialog.h"
 
@@ -190,7 +191,7 @@ VoxelGIEditorPlugin::VoxelGIEditorPlugin() {
 	probe_file->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
 	probe_file->add_filter("*.res");
 	probe_file->connect("file_selected", callable_mp(this, &VoxelGIEditorPlugin::_voxel_gi_save_path_and_bake));
-	get_editor_interface()->get_base_control()->add_child(probe_file);
+	EditorInterface::get_singleton()->get_base_control()->add_child(probe_file);
 	probe_file->set_title(TTR("Select path for VoxelGI Data File"));
 
 	VoxelGI::bake_begin_function = bake_func_begin;

+ 5 - 0
editor/register_editor_types.cpp

@@ -35,6 +35,7 @@
 #include "editor/editor_command_palette.h"
 #include "editor/editor_feature_profile.h"
 #include "editor/editor_file_system.h"
+#include "editor/editor_interface.h"
 #include "editor/editor_node.h"
 #include "editor/editor_paths.h"
 #include "editor/editor_resource_picker.h"
@@ -230,10 +231,14 @@ void register_editor_types() {
 
 	GLOBAL_DEF("editor/version_control/plugin_name", "");
 	GLOBAL_DEF("editor/version_control/autoload_on_startup", false);
+
+	EditorInterface::create();
 }
 
 void unregister_editor_types() {
 	EditorNode::cleanup();
+	EditorInterface::free();
+
 	if (EditorPaths::get_singleton()) {
 		EditorPaths::free();
 	}

+ 2 - 1
editor/scene_tree_dock.h

@@ -31,12 +31,13 @@
 #ifndef SCENE_TREE_DOCK_H
 #define SCENE_TREE_DOCK_H
 
-#include "editor/editor_data.h"
 #include "editor/gui/scene_tree_editor.h"
 #include "editor/script_create_dialog.h"
 #include "scene/gui/box_container.h"
 #include "scene/resources/animation.h"
 
+class EditorData;
+class EditorSelection;
 class EditorQuickOpen;
 class MenuButton;
 class ReparentDialog;

+ 2 - 1
modules/multiplayer/editor/multiplayer_editor_plugin.cpp

@@ -34,6 +34,7 @@
 #include "editor_network_profiler.h"
 #include "replication_editor.h"
 
+#include "editor/editor_interface.h"
 #include "editor/editor_node.h"
 
 void MultiplayerEditorDebugger::_bind_methods() {
@@ -119,7 +120,7 @@ MultiplayerEditorPlugin::MultiplayerEditorPlugin() {
 }
 
 void MultiplayerEditorPlugin::_open_request(const String &p_path) {
-	get_editor_interface()->open_scene_from_path(p_path);
+	EditorInterface::get_singleton()->open_scene_from_path(p_path);
 }
 
 void MultiplayerEditorPlugin::_notification(int p_what) {