Browse Source

Optimized ScriptEditor initialization when many scripts are loaded

This change avoids the editor to freeze for several seconds when a
project with lots of scripts is loaded in the editor.

It focuses on a few heavy operations previously executed on all
previously loaded scripts:
- Initialize script resource (script validation/parsing) only
on focus
- ScriptTextEditor: code editor and edit menu are added to the
scene only on focus
- Add to recent scripts only when opening new scripts
(load/save scene metadata)
PouleyKetchoupp 5 years ago
parent
commit
ccff2f2551

+ 0 - 2
editor/code_editor.cpp

@@ -1456,8 +1456,6 @@ void CodeTextEditor::set_edit_state(const Variant &p_state) {
 			text_editor->set_line_as_bookmark(bookmarks[i], true);
 			text_editor->set_line_as_bookmark(bookmarks[i], true);
 		}
 		}
 	}
 	}
-
-	text_editor->grab_focus();
 }
 }
 
 
 void CodeTextEditor::set_error(const String &p_error) {
 void CodeTextEditor::set_error(const String &p_error) {

+ 41 - 20
editor/plugins/script_editor_plugin.cpp

@@ -696,7 +696,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) {
 
 
 	Node *tselected = tab_container->get_child(selected);
 	Node *tselected = tab_container->get_child(selected);
 
 
-	ScriptEditorBase *current = Object::cast_to<ScriptEditorBase>(tab_container->get_child(selected));
+	ScriptEditorBase *current = Object::cast_to<ScriptEditorBase>(tselected);
 	if (current) {
 	if (current) {
 		Ref<Script> script = current->get_edited_resource();
 		Ref<Script> script = current->get_edited_resource();
 		if (p_save) {
 		if (p_save) {
@@ -779,8 +779,10 @@ void ScriptEditor::_close_docs_tab() {
 
 
 void ScriptEditor::_copy_script_path() {
 void ScriptEditor::_copy_script_path() {
 	ScriptEditorBase *se = _get_current_editor();
 	ScriptEditorBase *se = _get_current_editor();
-	RES script = se->get_edited_resource();
-	DisplayServer::get_singleton()->clipboard_set(script->get_path());
+	if (se) {
+		RES script = se->get_edited_resource();
+		DisplayServer::get_singleton()->clipboard_set(script->get_path());
+	}
 }
 }
 
 
 void ScriptEditor::_close_other_tabs() {
 void ScriptEditor::_close_other_tabs() {
@@ -1038,17 +1040,19 @@ void ScriptEditor::_file_dialog_action(String p_file) {
 		} break;
 		} break;
 		case FILE_SAVE_AS: {
 		case FILE_SAVE_AS: {
 			ScriptEditorBase *current = _get_current_editor();
 			ScriptEditorBase *current = _get_current_editor();
+			if (current) {
+				RES resource = current->get_edited_resource();
+				String path = ProjectSettings::get_singleton()->localize_path(p_file);
+				Error err = _save_text_file(resource, path);
 
 
-			String path = ProjectSettings::get_singleton()->localize_path(p_file);
-			Error err = _save_text_file(current->get_edited_resource(), path);
+				if (err != OK) {
+					editor->show_accept(TTR("Error saving file!"), TTR("OK"));
+					return;
+				}
 
 
-			if (err != OK) {
-				editor->show_accept(TTR("Error saving file!"), TTR("OK"));
-				return;
+				resource->set_path(path);
+				_update_script_names();
 			}
 			}
-
-			((Resource *)current->get_edited_resource().ptr())->set_path(path);
-			_update_script_names();
 		} break;
 		} break;
 		case THEME_SAVE_AS: {
 		case THEME_SAVE_AS: {
 			if (!EditorSettings::get_singleton()->save_text_editor_theme_as(p_file)) {
 			if (!EditorSettings::get_singleton()->save_text_editor_theme_as(p_file)) {
@@ -1240,13 +1244,14 @@ void ScriptEditor::_menu_option(int p_option) {
 					}
 					}
 				}
 				}
 
 
-				Ref<TextFile> text_file = current->get_edited_resource();
+				RES resource = current->get_edited_resource();
+				Ref<TextFile> text_file = resource;
 				if (text_file != nullptr) {
 				if (text_file != nullptr) {
 					current->apply_code();
 					current->apply_code();
 					_save_text_file(text_file, text_file->get_path());
 					_save_text_file(text_file, text_file->get_path());
 					break;
 					break;
 				}
 				}
-				editor->save_resource(current->get_edited_resource());
+				editor->save_resource(resource);
 
 
 			} break;
 			} break;
 			case FILE_SAVE_AS: {
 			case FILE_SAVE_AS: {
@@ -1264,7 +1269,8 @@ void ScriptEditor::_menu_option(int p_option) {
 					}
 					}
 				}
 				}
 
 
-				Ref<TextFile> text_file = current->get_edited_resource();
+				RES resource = current->get_edited_resource();
+				Ref<TextFile> text_file = resource;
 				if (text_file != nullptr) {
 				if (text_file != nullptr) {
 					file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
 					file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
 					file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
 					file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
@@ -1280,8 +1286,8 @@ void ScriptEditor::_menu_option(int p_option) {
 					break;
 					break;
 				}
 				}
 
 
-				editor->push_item(Object::cast_to<Object>(current->get_edited_resource().ptr()));
-				editor->save_resource_as(current->get_edited_resource());
+				editor->push_item(resource.ptr());
+				editor->save_resource_as(resource);
 
 
 			} break;
 			} break;
 
 
@@ -1630,6 +1636,8 @@ void ScriptEditor::ensure_select_current() {
 	if (tab_container->get_child_count() && tab_container->get_current_tab() >= 0) {
 	if (tab_container->get_child_count() && tab_container->get_current_tab() >= 0) {
 		ScriptEditorBase *se = _get_current_editor();
 		ScriptEditorBase *se = _get_current_editor();
 		if (se) {
 		if (se) {
+			se->enable_editor();
+
 			if (!grab_focus_block && is_visible_in_tree()) {
 			if (!grab_focus_block && is_visible_in_tree()) {
 				se->ensure_focus();
 				se->ensure_focus();
 			}
 			}
@@ -1974,6 +1982,11 @@ void ScriptEditor::_update_script_names() {
 			script_list->select(index);
 			script_list->select(index);
 			script_name_label->set_text(sedata_filtered[i].name);
 			script_name_label->set_text(sedata_filtered[i].name);
 			script_icon->set_texture(sedata_filtered[i].icon);
 			script_icon->set_texture(sedata_filtered[i].icon);
+			ScriptEditorBase *se = _get_current_editor();
+			if (se) {
+				se->enable_editor();
+				_update_selected_editor_menu();
+			}
 		}
 		}
 	}
 	}
 
 
@@ -2148,6 +2161,8 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
 
 
 		if ((script != nullptr && se->get_edited_resource() == p_resource) || se->get_edited_resource()->get_path() == p_resource->get_path()) {
 		if ((script != nullptr && se->get_edited_resource() == p_resource) || se->get_edited_resource()->get_path() == p_resource->get_path()) {
 			if (should_open) {
 			if (should_open) {
+				se->enable_editor();
+
 				if (tab_container->get_current_tab() != i) {
 				if (tab_container->get_current_tab() != i) {
 					_go_to_tab(i);
 					_go_to_tab(i);
 					_update_script_names();
 					_update_script_names();
@@ -2178,6 +2193,8 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
 	}
 	}
 	ERR_FAIL_COND_V(!se, false);
 	ERR_FAIL_COND_V(!se, false);
 
 
+	se->set_edited_resource(p_resource);
+
 	if (p_resource->get_class_name() != StringName("VisualScript")) {
 	if (p_resource->get_class_name() != StringName("VisualScript")) {
 		bool highlighter_set = false;
 		bool highlighter_set = false;
 		for (int i = 0; i < syntax_highlighters.size(); i++) {
 		for (int i = 0; i < syntax_highlighters.size(); i++) {
@@ -2198,7 +2215,11 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
 	}
 	}
 
 
 	tab_container->add_child(se);
 	tab_container->add_child(se);
-	se->set_edited_resource(p_resource);
+
+	if (p_grab_focus) {
+		se->enable_editor();
+	}
+
 	se->set_tooltip_request_func("_get_debug_tooltip", this);
 	se->set_tooltip_request_func("_get_debug_tooltip", this);
 	if (se->get_edit_menu()) {
 	if (se->get_edit_menu()) {
 		se->get_edit_menu()->hide();
 		se->get_edit_menu()->hide();
@@ -2208,6 +2229,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
 
 
 	if (p_grab_focus) {
 	if (p_grab_focus) {
 		_go_to_tab(tab_container->get_tab_count() - 1);
 		_go_to_tab(tab_container->get_tab_count() - 1);
+		_add_recent_script(p_resource->get_path());
 	}
 	}
 
 
 	_sort_list_on_update = true;
 	_sort_list_on_update = true;
@@ -2232,7 +2254,6 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
 	}
 	}
 
 
 	notify_script_changed(p_resource);
 	notify_script_changed(p_resource);
-	_add_recent_script(p_resource->get_path());
 	return true;
 	return true;
 }
 }
 
 
@@ -2704,7 +2725,7 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
 			if (!scr.is_valid()) {
 			if (!scr.is_valid()) {
 				continue;
 				continue;
 			}
 			}
-			if (!edit(scr)) {
+			if (!edit(scr, false)) {
 				continue;
 				continue;
 			}
 			}
 		} else {
 		} else {
@@ -2713,7 +2734,7 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
 			if (error != OK || !text_file.is_valid()) {
 			if (error != OK || !text_file.is_valid()) {
 				continue;
 				continue;
 			}
 			}
-			if (!edit(text_file)) {
+			if (!edit(text_file, false)) {
 				continue;
 				continue;
 			}
 			}
 		}
 		}

+ 1 - 0
editor/plugins/script_editor_plugin.h

@@ -134,6 +134,7 @@ public:
 	virtual RES get_edited_resource() const = 0;
 	virtual RES get_edited_resource() const = 0;
 	virtual Vector<String> get_functions() = 0;
 	virtual Vector<String> get_functions() = 0;
 	virtual void set_edited_resource(const RES &p_res) = 0;
 	virtual void set_edited_resource(const RES &p_res) = 0;
+	virtual void enable_editor() = 0;
 	virtual void reload_text() = 0;
 	virtual void reload_text() = 0;
 	virtual String get_name() = 0;
 	virtual String get_name() = 0;
 	virtual Ref<Texture2D> get_theme_icon() = 0;
 	virtual Ref<Texture2D> get_theme_icon() = 0;

+ 134 - 94
editor/plugins/script_text_editor.cpp

@@ -140,10 +140,10 @@ RES ScriptTextEditor::get_edited_resource() const {
 }
 }
 
 
 void ScriptTextEditor::set_edited_resource(const RES &p_res) {
 void ScriptTextEditor::set_edited_resource(const RES &p_res) {
-	ERR_FAIL_COND(!script.is_null());
+	ERR_FAIL_COND(script.is_valid());
+	ERR_FAIL_COND(p_res.is_null());
 
 
 	script = p_res;
 	script = p_res;
-	_set_theme_for_script();
 
 
 	code_editor->get_text_edit()->set_text(script->get_source_code());
 	code_editor->get_text_edit()->set_text(script->get_source_code());
 	code_editor->get_text_edit()->clear_undo_history();
 	code_editor->get_text_edit()->clear_undo_history();
@@ -151,6 +151,17 @@ void ScriptTextEditor::set_edited_resource(const RES &p_res) {
 
 
 	emit_signal("name_changed");
 	emit_signal("name_changed");
 	code_editor->update_line_and_column();
 	code_editor->update_line_and_column();
+}
+
+void ScriptTextEditor::enable_editor() {
+	if (editor_enabled) {
+		return;
+	}
+
+	editor_enabled = true;
+
+	_enable_code_editor();
+	_set_theme_for_script();
 
 
 	_validate_script();
 	_validate_script();
 }
 }
@@ -301,14 +312,6 @@ void ScriptTextEditor::reload_text() {
 	code_editor->update_line_and_column();
 	code_editor->update_line_and_column();
 }
 }
 
 
-void ScriptTextEditor::_notification(int p_what) {
-	switch (p_what) {
-		case NOTIFICATION_READY:
-			_load_theme_settings();
-			break;
-	}
-}
-
 void ScriptTextEditor::add_callback(const String &p_function, PackedStringArray p_args) {
 void ScriptTextEditor::add_callback(const String &p_function, PackedStringArray p_args) {
 	String code = code_editor->get_text_edit()->get_text();
 	String code = code_editor->get_text_edit()->get_text();
 	int pos = script->get_language()->find_function(p_function, code);
 	int pos = script->get_language()->find_function(p_function, code);
@@ -352,6 +355,10 @@ void ScriptTextEditor::set_edit_state(const Variant &p_state) {
 			_change_syntax_highlighter(idx);
 			_change_syntax_highlighter(idx);
 		}
 		}
 	}
 	}
+
+	if (editor_enabled) {
+		ensure_focus();
+	}
 }
 }
 
 
 void ScriptTextEditor::_convert_case(CodeTextEditor::CaseStyle p_case) {
 void ScriptTextEditor::_convert_case(CodeTextEditor::CaseStyle p_case) {
@@ -1274,23 +1281,28 @@ void ScriptTextEditor::_edit_option_toggle_inline_comment() {
 }
 }
 
 
 void ScriptTextEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
 void ScriptTextEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
+	ERR_FAIL_COND(p_highlighter.is_null());
+
 	highlighters[p_highlighter->_get_name()] = p_highlighter;
 	highlighters[p_highlighter->_get_name()] = p_highlighter;
 	highlighter_menu->add_radio_check_item(p_highlighter->_get_name());
 	highlighter_menu->add_radio_check_item(p_highlighter->_get_name());
 }
 }
 
 
 void ScriptTextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
 void ScriptTextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
+	ERR_FAIL_COND(p_highlighter.is_null());
+
+	Map<String, Ref<EditorSyntaxHighlighter>>::Element *el = highlighters.front();
+	while (el != nullptr) {
+		int highlighter_index = highlighter_menu->get_item_idx_from_text(el->key());
+		highlighter_menu->set_item_checked(highlighter_index, el->value() == p_highlighter);
+		el = el->next();
+	}
+
 	TextEdit *te = code_editor->get_text_edit();
 	TextEdit *te = code_editor->get_text_edit();
 	p_highlighter->_set_edited_resource(script);
 	p_highlighter->_set_edited_resource(script);
 	te->set_syntax_highlighter(p_highlighter);
 	te->set_syntax_highlighter(p_highlighter);
-	highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(p_highlighter->_get_name()), true);
 }
 }
 
 
 void ScriptTextEditor::_change_syntax_highlighter(int p_idx) {
 void ScriptTextEditor::_change_syntax_highlighter(int p_idx) {
-	Map<String, Ref<EditorSyntaxHighlighter>>::Element *el = highlighters.front();
-	while (el != nullptr) {
-		highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(el->key()), false);
-		el = el->next();
-	}
 	set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]);
 	set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]);
 }
 }
 
 
@@ -1606,64 +1618,40 @@ void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p
 	context_menu->popup();
 	context_menu->popup();
 }
 }
 
 
-ScriptTextEditor::ScriptTextEditor() {
-	theme_loaded = false;
-	script_is_valid = false;
+void ScriptTextEditor::_enable_code_editor() {
+	ERR_FAIL_COND(code_editor->get_parent());
 
 
 	VSplitContainer *editor_box = memnew(VSplitContainer);
 	VSplitContainer *editor_box = memnew(VSplitContainer);
 	add_child(editor_box);
 	add_child(editor_box);
 	editor_box->set_anchors_and_margins_preset(Control::PRESET_WIDE);
 	editor_box->set_anchors_and_margins_preset(Control::PRESET_WIDE);
 	editor_box->set_v_size_flags(SIZE_EXPAND_FILL);
 	editor_box->set_v_size_flags(SIZE_EXPAND_FILL);
 
 
-	code_editor = memnew(CodeTextEditor);
 	editor_box->add_child(code_editor);
 	editor_box->add_child(code_editor);
-	code_editor->add_theme_constant_override("separation", 2);
-	code_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+	code_editor->connect("show_warnings_panel", callable_mp(this, &ScriptTextEditor::_show_warnings_panel));
 	code_editor->connect("validate_script", callable_mp(this, &ScriptTextEditor::_validate_script));
 	code_editor->connect("validate_script", callable_mp(this, &ScriptTextEditor::_validate_script));
 	code_editor->connect("load_theme_settings", callable_mp(this, &ScriptTextEditor::_load_theme_settings));
 	code_editor->connect("load_theme_settings", callable_mp(this, &ScriptTextEditor::_load_theme_settings));
-	code_editor->set_code_complete_func(_code_complete_scripts, this);
 	code_editor->get_text_edit()->connect("breakpoint_toggled", callable_mp(this, &ScriptTextEditor::_breakpoint_toggled));
 	code_editor->get_text_edit()->connect("breakpoint_toggled", callable_mp(this, &ScriptTextEditor::_breakpoint_toggled));
 	code_editor->get_text_edit()->connect("symbol_lookup", callable_mp(this, &ScriptTextEditor::_lookup_symbol));
 	code_editor->get_text_edit()->connect("symbol_lookup", callable_mp(this, &ScriptTextEditor::_lookup_symbol));
 	code_editor->get_text_edit()->connect("symbol_validate", callable_mp(this, &ScriptTextEditor::_validate_symbol));
 	code_editor->get_text_edit()->connect("symbol_validate", callable_mp(this, &ScriptTextEditor::_validate_symbol));
-	code_editor->get_text_edit()->connect("info_clicked", callable_mp(this, &ScriptTextEditor::_lookup_connections));
-	code_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+	code_editor->get_text_edit()->connect("gui_input", callable_mp(this, &ScriptTextEditor::_text_edit_gui_input));
 	code_editor->show_toggle_scripts_button();
 	code_editor->show_toggle_scripts_button();
 
 
-	warnings_panel = memnew(RichTextLabel);
 	editor_box->add_child(warnings_panel);
 	editor_box->add_child(warnings_panel);
 	warnings_panel->add_theme_font_override(
 	warnings_panel->add_theme_font_override(
 			"normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts"));
 			"normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts"));
-	warnings_panel->set_custom_minimum_size(Size2(0, 100 * EDSCALE));
-	warnings_panel->set_h_size_flags(SIZE_EXPAND_FILL);
-	warnings_panel->set_meta_underline(true);
-	warnings_panel->set_selection_enabled(true);
-	warnings_panel->set_focus_mode(FOCUS_CLICK);
-	warnings_panel->hide();
-
-	code_editor->connect("show_warnings_panel", callable_mp(this, &ScriptTextEditor::_show_warnings_panel));
 	warnings_panel->connect("meta_clicked", callable_mp(this, &ScriptTextEditor::_warning_clicked));
 	warnings_panel->connect("meta_clicked", callable_mp(this, &ScriptTextEditor::_warning_clicked));
 
 
-	update_settings();
-
-	code_editor->get_text_edit()->set_callhint_settings(
-			EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"),
-			EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset"));
-
-	code_editor->get_text_edit()->set_select_identifiers_on_hover(true);
-	code_editor->get_text_edit()->set_context_menu_enabled(false);
-	code_editor->get_text_edit()->connect("gui_input", callable_mp(this, &ScriptTextEditor::_text_edit_gui_input));
-
-	context_menu = memnew(PopupMenu);
 	add_child(context_menu);
 	add_child(context_menu);
 	context_menu->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option));
 	context_menu->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option));
 
 
-	color_panel = memnew(PopupPanel);
 	add_child(color_panel);
 	add_child(color_panel);
+
 	color_picker = memnew(ColorPicker);
 	color_picker = memnew(ColorPicker);
 	color_picker->set_deferred_mode(true);
 	color_picker->set_deferred_mode(true);
-	color_panel->add_child(color_picker);
 	color_picker->connect("color_changed", callable_mp(this, &ScriptTextEditor::_color_changed));
 	color_picker->connect("color_changed", callable_mp(this, &ScriptTextEditor::_color_changed));
 
 
+	color_panel->add_child(color_picker);
+
 	// get default color picker mode from editor settings
 	// get default color picker mode from editor settings
 	int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode");
 	int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode");
 	if (default_color_mode == 1) {
 	if (default_color_mode == 1) {
@@ -1672,12 +1660,27 @@ ScriptTextEditor::ScriptTextEditor() {
 		color_picker->set_raw_mode(true);
 		color_picker->set_raw_mode(true);
 	}
 	}
 
 
-	edit_hb = memnew(HBoxContainer);
+	quick_open = memnew(ScriptEditorQuickOpen);
+	quick_open->connect("goto_line", callable_mp(this, &ScriptTextEditor::_goto_line));
+	add_child(quick_open);
 
 
-	edit_menu = memnew(MenuButton);
-	edit_menu->set_text(TTR("Edit"));
-	edit_menu->set_switch_on_hover(true);
+	goto_line_dialog = memnew(GotoLineDialog);
+	add_child(goto_line_dialog);
+
+	add_child(connection_info_dialog);
+
+	edit_hb->add_child(search_menu);
+	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find"), SEARCH_FIND);
+	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_next"), SEARCH_FIND_NEXT);
+	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_previous"), SEARCH_FIND_PREV);
+	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace"), SEARCH_REPLACE);
+	search_menu->get_popup()->add_separator();
+	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_in_files"), SEARCH_IN_FILES);
+	search_menu->get_popup()->add_separator();
+	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/contextual_help"), HELP_CONTEXTUAL);
+	search_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option));
 
 
+	edit_hb->add_child(edit_menu);
 	edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
 	edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
 	edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
 	edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
 	edit_menu->get_popup()->add_separator();
 	edit_menu->get_popup()->add_separator();
@@ -1707,8 +1710,6 @@ ScriptTextEditor::ScriptTextEditor() {
 	edit_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option));
 	edit_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option));
 	edit_menu->get_popup()->add_separator();
 	edit_menu->get_popup()->add_separator();
 
 
-	PopupMenu *convert_case = memnew(PopupMenu);
-	convert_case->set_name("convert_case");
 	edit_menu->get_popup()->add_child(convert_case);
 	edit_menu->get_popup()->add_child(convert_case);
 	edit_menu->get_popup()->add_submenu_item(TTR("Convert Case"), "convert_case");
 	edit_menu->get_popup()->add_submenu_item(TTR("Convert Case"), "convert_case");
 	convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_uppercase", TTR("Uppercase"), KEY_MASK_SHIFT | KEY_F4), EDIT_TO_UPPERCASE);
 	convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_uppercase", TTR("Uppercase"), KEY_MASK_SHIFT | KEY_F4), EDIT_TO_UPPERCASE);
@@ -1716,12 +1717,73 @@ ScriptTextEditor::ScriptTextEditor() {
 	convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize"), KEY_MASK_SHIFT | KEY_F6), EDIT_CAPITALIZE);
 	convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize"), KEY_MASK_SHIFT | KEY_F6), EDIT_CAPITALIZE);
 	convert_case->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option));
 	convert_case->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option));
 
 
-	highlighter_menu = memnew(PopupMenu);
-	highlighter_menu->set_name("highlighter_menu");
 	edit_menu->get_popup()->add_child(highlighter_menu);
 	edit_menu->get_popup()->add_child(highlighter_menu);
 	edit_menu->get_popup()->add_submenu_item(TTR("Syntax Highlighter"), "highlighter_menu");
 	edit_menu->get_popup()->add_submenu_item(TTR("Syntax Highlighter"), "highlighter_menu");
 	highlighter_menu->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_change_syntax_highlighter));
 	highlighter_menu->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_change_syntax_highlighter));
 
 
+	_load_theme_settings();
+
+	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace_in_files"), REPLACE_IN_FILES);
+	edit_hb->add_child(goto_menu);
+	goto_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_function"), SEARCH_LOCATE_FUNCTION);
+	goto_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_line"), SEARCH_GOTO_LINE);
+	goto_menu->get_popup()->add_separator();
+
+	goto_menu->get_popup()->add_child(bookmarks_menu);
+	goto_menu->get_popup()->add_submenu_item(TTR("Bookmarks"), "Bookmarks");
+	_update_bookmark_list();
+	bookmarks_menu->connect("about_to_popup", callable_mp(this, &ScriptTextEditor::_update_bookmark_list));
+	bookmarks_menu->connect("index_pressed", callable_mp(this, &ScriptTextEditor::_bookmark_item_pressed));
+
+	goto_menu->get_popup()->add_child(breakpoints_menu);
+	goto_menu->get_popup()->add_submenu_item(TTR("Breakpoints"), "Breakpoints");
+	_update_breakpoint_list();
+	breakpoints_menu->connect("about_to_popup", callable_mp(this, &ScriptTextEditor::_update_breakpoint_list));
+	breakpoints_menu->connect("index_pressed", callable_mp(this, &ScriptTextEditor::_breakpoint_item_pressed));
+
+	goto_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option));
+}
+
+ScriptTextEditor::ScriptTextEditor() {
+	code_editor = memnew(CodeTextEditor);
+	code_editor->add_theme_constant_override("separation", 2);
+	code_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+	code_editor->set_code_complete_func(_code_complete_scripts, this);
+	code_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+
+	warnings_panel = memnew(RichTextLabel);
+	warnings_panel->set_custom_minimum_size(Size2(0, 100 * EDSCALE));
+	warnings_panel->set_h_size_flags(SIZE_EXPAND_FILL);
+	warnings_panel->set_meta_underline(true);
+	warnings_panel->set_selection_enabled(true);
+	warnings_panel->set_focus_mode(FOCUS_CLICK);
+	warnings_panel->hide();
+
+	update_settings();
+
+	code_editor->get_text_edit()->set_callhint_settings(
+			EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"),
+			EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset"));
+
+	code_editor->get_text_edit()->set_select_identifiers_on_hover(true);
+	code_editor->get_text_edit()->set_context_menu_enabled(false);
+
+	context_menu = memnew(PopupMenu);
+
+	color_panel = memnew(PopupPanel);
+
+	edit_hb = memnew(HBoxContainer);
+
+	edit_menu = memnew(MenuButton);
+	edit_menu->set_text(TTR("Edit"));
+	edit_menu->set_switch_on_hover(true);
+
+	convert_case = memnew(PopupMenu);
+	convert_case->set_name("convert_case");
+
+	highlighter_menu = memnew(PopupMenu);
+	highlighter_menu->set_name("highlighter_menu");
+
 	Ref<EditorPlainTextSyntaxHighlighter> plain_highlighter;
 	Ref<EditorPlainTextSyntaxHighlighter> plain_highlighter;
 	plain_highlighter.instance();
 	plain_highlighter.instance();
 	add_syntax_highlighter(plain_highlighter);
 	add_syntax_highlighter(plain_highlighter);
@@ -1732,64 +1794,42 @@ ScriptTextEditor::ScriptTextEditor() {
 	set_syntax_highlighter(highlighter);
 	set_syntax_highlighter(highlighter);
 
 
 	search_menu = memnew(MenuButton);
 	search_menu = memnew(MenuButton);
-	edit_hb->add_child(search_menu);
 	search_menu->set_text(TTR("Search"));
 	search_menu->set_text(TTR("Search"));
 	search_menu->set_switch_on_hover(true);
 	search_menu->set_switch_on_hover(true);
 
 
-	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find"), SEARCH_FIND);
-	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_next"), SEARCH_FIND_NEXT);
-	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_previous"), SEARCH_FIND_PREV);
-	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace"), SEARCH_REPLACE);
-	search_menu->get_popup()->add_separator();
-	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_in_files"), SEARCH_IN_FILES);
-	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace_in_files"), REPLACE_IN_FILES);
-	search_menu->get_popup()->add_separator();
-	search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/contextual_help"), HELP_CONTEXTUAL);
-	search_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option));
-
-	edit_hb->add_child(edit_menu);
-
-	MenuButton *goto_menu = memnew(MenuButton);
-	edit_hb->add_child(goto_menu);
+	goto_menu = memnew(MenuButton);
 	goto_menu->set_text(TTR("Go To"));
 	goto_menu->set_text(TTR("Go To"));
 	goto_menu->set_switch_on_hover(true);
 	goto_menu->set_switch_on_hover(true);
-	goto_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option));
-
-	goto_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_function"), SEARCH_LOCATE_FUNCTION);
-	goto_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_line"), SEARCH_GOTO_LINE);
-	goto_menu->get_popup()->add_separator();
 
 
 	bookmarks_menu = memnew(PopupMenu);
 	bookmarks_menu = memnew(PopupMenu);
 	bookmarks_menu->set_name("Bookmarks");
 	bookmarks_menu->set_name("Bookmarks");
-	goto_menu->get_popup()->add_child(bookmarks_menu);
-	goto_menu->get_popup()->add_submenu_item(TTR("Bookmarks"), "Bookmarks");
-	_update_bookmark_list();
-	bookmarks_menu->connect("about_to_popup", callable_mp(this, &ScriptTextEditor::_update_bookmark_list));
-	bookmarks_menu->connect("index_pressed", callable_mp(this, &ScriptTextEditor::_bookmark_item_pressed));
 
 
 	breakpoints_menu = memnew(PopupMenu);
 	breakpoints_menu = memnew(PopupMenu);
 	breakpoints_menu->set_name("Breakpoints");
 	breakpoints_menu->set_name("Breakpoints");
-	goto_menu->get_popup()->add_child(breakpoints_menu);
-	goto_menu->get_popup()->add_submenu_item(TTR("Breakpoints"), "Breakpoints");
-	_update_breakpoint_list();
-	breakpoints_menu->connect("about_to_popup", callable_mp(this, &ScriptTextEditor::_update_breakpoint_list));
-	breakpoints_menu->connect("index_pressed", callable_mp(this, &ScriptTextEditor::_breakpoint_item_pressed));
-
-	quick_open = memnew(ScriptEditorQuickOpen);
-	add_child(quick_open);
-	quick_open->connect("goto_line", callable_mp(this, &ScriptTextEditor::_goto_line));
-
-	goto_line_dialog = memnew(GotoLineDialog);
-	add_child(goto_line_dialog);
 
 
 	connection_info_dialog = memnew(ConnectionInfoDialog);
 	connection_info_dialog = memnew(ConnectionInfoDialog);
-	add_child(connection_info_dialog);
 
 
 	code_editor->get_text_edit()->set_drag_forwarding(this);
 	code_editor->get_text_edit()->set_drag_forwarding(this);
 }
 }
 
 
 ScriptTextEditor::~ScriptTextEditor() {
 ScriptTextEditor::~ScriptTextEditor() {
 	highlighters.clear();
 	highlighters.clear();
+
+	if (!editor_enabled) {
+		memdelete(code_editor);
+		memdelete(warnings_panel);
+		memdelete(context_menu);
+		memdelete(color_panel);
+		memdelete(edit_hb);
+		memdelete(edit_menu);
+		memdelete(convert_case);
+		memdelete(highlighter_menu);
+		memdelete(search_menu);
+		memdelete(goto_menu);
+		memdelete(bookmarks_menu);
+		memdelete(breakpoints_menu);
+		memdelete(connection_info_dialog);
+	}
 }
 }
 
 
 static ScriptEditorBase *create_editor(const RES &p_resource) {
 static ScriptEditorBase *create_editor(const RES &p_resource) {

+ 24 - 19
editor/plugins/script_text_editor.h

@@ -39,8 +39,8 @@
 class ConnectionInfoDialog : public AcceptDialog {
 class ConnectionInfoDialog : public AcceptDialog {
 	GDCLASS(ConnectionInfoDialog, AcceptDialog);
 	GDCLASS(ConnectionInfoDialog, AcceptDialog);
 
 
-	Label *method;
-	Tree *tree;
+	Label *method = nullptr;
+	Tree *tree = nullptr;
 
 
 	virtual void ok_pressed() override;
 	virtual void ok_pressed() override;
 
 
@@ -53,11 +53,12 @@ public:
 class ScriptTextEditor : public ScriptEditorBase {
 class ScriptTextEditor : public ScriptEditorBase {
 	GDCLASS(ScriptTextEditor, ScriptEditorBase);
 	GDCLASS(ScriptTextEditor, ScriptEditorBase);
 
 
-	CodeTextEditor *code_editor;
-	RichTextLabel *warnings_panel;
+	CodeTextEditor *code_editor = nullptr;
+	RichTextLabel *warnings_panel = nullptr;
 
 
 	Ref<Script> script;
 	Ref<Script> script;
-	bool script_is_valid;
+	bool script_is_valid = false;
+	bool editor_enabled = false;
 
 
 	Vector<String> functions;
 	Vector<String> functions;
 
 
@@ -65,25 +66,27 @@ class ScriptTextEditor : public ScriptEditorBase {
 
 
 	Vector<String> member_keywords;
 	Vector<String> member_keywords;
 
 
-	HBoxContainer *edit_hb;
+	HBoxContainer *edit_hb = nullptr;
 
 
-	MenuButton *edit_menu;
-	MenuButton *search_menu;
-	PopupMenu *bookmarks_menu;
-	PopupMenu *breakpoints_menu;
-	PopupMenu *highlighter_menu;
-	PopupMenu *context_menu;
+	MenuButton *edit_menu = nullptr;
+	MenuButton *search_menu = nullptr;
+	MenuButton *goto_menu = nullptr;
+	PopupMenu *bookmarks_menu = nullptr;
+	PopupMenu *breakpoints_menu = nullptr;
+	PopupMenu *highlighter_menu = nullptr;
+	PopupMenu *context_menu = nullptr;
+	PopupMenu *convert_case = nullptr;
 
 
-	GotoLineDialog *goto_line_dialog;
-	ScriptEditorQuickOpen *quick_open;
-	ConnectionInfoDialog *connection_info_dialog;
+	GotoLineDialog *goto_line_dialog = nullptr;
+	ScriptEditorQuickOpen *quick_open = nullptr;
+	ConnectionInfoDialog *connection_info_dialog = nullptr;
 
 
-	PopupPanel *color_panel;
-	ColorPicker *color_picker;
+	PopupPanel *color_panel = nullptr;
+	ColorPicker *color_picker = nullptr;
 	Vector2 color_position;
 	Vector2 color_position;
 	String color_args;
 	String color_args;
 
 
-	bool theme_loaded;
+	bool theme_loaded = false;
 
 
 	enum {
 	enum {
 		EDIT_UNDO,
 		EDIT_UNDO,
@@ -132,6 +135,8 @@ class ScriptTextEditor : public ScriptEditorBase {
 		LOOKUP_SYMBOL,
 		LOOKUP_SYMBOL,
 	};
 	};
 
 
+	void _enable_code_editor();
+
 protected:
 protected:
 	void _update_breakpoint_list();
 	void _update_breakpoint_list();
 	void _breakpoint_item_pressed(int p_idx);
 	void _breakpoint_item_pressed(int p_idx);
@@ -149,7 +154,6 @@ protected:
 	void _show_warnings_panel(bool p_show);
 	void _show_warnings_panel(bool p_show);
 	void _warning_clicked(Variant p_line);
 	void _warning_clicked(Variant p_line);
 
 
-	void _notification(int p_what);
 	static void _bind_methods();
 	static void _bind_methods();
 
 
 	Map<String, Ref<EditorSyntaxHighlighter>> highlighters;
 	Map<String, Ref<EditorSyntaxHighlighter>> highlighters;
@@ -185,6 +189,7 @@ public:
 	virtual void apply_code() override;
 	virtual void apply_code() override;
 	virtual RES get_edited_resource() const override;
 	virtual RES get_edited_resource() const override;
 	virtual void set_edited_resource(const RES &p_res) override;
 	virtual void set_edited_resource(const RES &p_res) override;
+	virtual void enable_editor() override;
 	virtual Vector<String> get_functions() override;
 	virtual Vector<String> get_functions() override;
 	virtual void reload_text() override;
 	virtual void reload_text() override;
 	virtual String get_name() override;
 	virtual String get_name() override;

+ 26 - 16
editor/plugins/text_editor.cpp

@@ -34,22 +34,27 @@
 #include "editor/editor_node.h"
 #include "editor/editor_node.h"
 
 
 void TextEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
 void TextEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
+	ERR_FAIL_COND(p_highlighter.is_null());
+
 	highlighters[p_highlighter->_get_name()] = p_highlighter;
 	highlighters[p_highlighter->_get_name()] = p_highlighter;
 	highlighter_menu->add_radio_check_item(p_highlighter->_get_name());
 	highlighter_menu->add_radio_check_item(p_highlighter->_get_name());
 }
 }
 
 
 void TextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
 void TextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) {
-	TextEdit *te = code_editor->get_text_edit();
-	te->set_syntax_highlighter(p_highlighter);
-	highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(p_highlighter->_get_name()), true);
-}
+	ERR_FAIL_COND(p_highlighter.is_null());
 
 
-void TextEditor::_change_syntax_highlighter(int p_idx) {
 	Map<String, Ref<EditorSyntaxHighlighter>>::Element *el = highlighters.front();
 	Map<String, Ref<EditorSyntaxHighlighter>>::Element *el = highlighters.front();
 	while (el != nullptr) {
 	while (el != nullptr) {
-		highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(el->key()), false);
+		int highlighter_index = highlighter_menu->get_item_idx_from_text(el->key());
+		highlighter_menu->set_item_checked(highlighter_index, el->value() == p_highlighter);
 		el = el->next();
 		el = el->next();
 	}
 	}
+
+	TextEdit *te = code_editor->get_text_edit();
+	te->set_syntax_highlighter(p_highlighter);
+}
+
+void TextEditor::_change_syntax_highlighter(int p_idx) {
 	set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]);
 	set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]);
 }
 }
 
 
@@ -126,7 +131,7 @@ String TextEditor::get_name() {
 }
 }
 
 
 Ref<Texture2D> TextEditor::get_theme_icon() {
 Ref<Texture2D> TextEditor::get_theme_icon() {
-	return EditorNode::get_singleton()->get_object_icon(text_file.operator->(), "");
+	return EditorNode::get_singleton()->get_object_icon(text_file.ptr(), "");
 }
 }
 
 
 RES TextEditor::get_edited_resource() const {
 RES TextEditor::get_edited_resource() const {
@@ -134,7 +139,8 @@ RES TextEditor::get_edited_resource() const {
 }
 }
 
 
 void TextEditor::set_edited_resource(const RES &p_res) {
 void TextEditor::set_edited_resource(const RES &p_res) {
-	ERR_FAIL_COND(!text_file.is_null());
+	ERR_FAIL_COND(text_file.is_valid());
+	ERR_FAIL_COND(p_res.is_null());
 
 
 	text_file = p_res;
 	text_file = p_res;
 
 
@@ -146,6 +152,16 @@ void TextEditor::set_edited_resource(const RES &p_res) {
 	code_editor->update_line_and_column();
 	code_editor->update_line_and_column();
 }
 }
 
 
+void TextEditor::enable_editor() {
+	if (editor_enabled) {
+		return;
+	}
+
+	editor_enabled = true;
+
+	_load_theme_settings();
+}
+
 void TextEditor::add_callback(const String &p_function, PackedStringArray p_args) {
 void TextEditor::add_callback(const String &p_function, PackedStringArray p_args) {
 }
 }
 
 
@@ -237,6 +253,8 @@ void TextEditor::set_edit_state(const Variant &p_state) {
 			_change_syntax_highlighter(idx);
 			_change_syntax_highlighter(idx);
 		}
 		}
 	}
 	}
+
+	ensure_focus();
 }
 }
 
 
 void TextEditor::trim_trailing_whitespace() {
 void TextEditor::trim_trailing_whitespace() {
@@ -303,14 +321,6 @@ void TextEditor::clear_edit_menu() {
 	memdelete(edit_hb);
 	memdelete(edit_hb);
 }
 }
 
 
-void TextEditor::_notification(int p_what) {
-	switch (p_what) {
-		case NOTIFICATION_READY:
-			_load_theme_settings();
-			break;
-	}
-}
-
 void TextEditor::_edit_option(int p_op) {
 void TextEditor::_edit_option(int p_op) {
 	TextEdit *tx = code_editor->get_text_edit();
 	TextEdit *tx = code_editor->get_text_edit();
 
 

+ 10 - 11
editor/plugins/text_editor.h

@@ -37,18 +37,19 @@ class TextEditor : public ScriptEditorBase {
 	GDCLASS(TextEditor, ScriptEditorBase);
 	GDCLASS(TextEditor, ScriptEditorBase);
 
 
 private:
 private:
-	CodeTextEditor *code_editor;
+	CodeTextEditor *code_editor = nullptr;
 
 
 	Ref<TextFile> text_file;
 	Ref<TextFile> text_file;
+	bool editor_enabled = false;
 
 
-	HBoxContainer *edit_hb;
-	MenuButton *edit_menu;
-	PopupMenu *highlighter_menu;
-	MenuButton *search_menu;
-	PopupMenu *bookmarks_menu;
-	PopupMenu *context_menu;
+	HBoxContainer *edit_hb = nullptr;
+	MenuButton *edit_menu = nullptr;
+	PopupMenu *highlighter_menu = nullptr;
+	MenuButton *search_menu = nullptr;
+	PopupMenu *bookmarks_menu = nullptr;
+	PopupMenu *context_menu = nullptr;
 
 
-	GotoLineDialog *goto_line_dialog;
+	GotoLineDialog *goto_line_dialog = nullptr;
 
 
 	enum {
 	enum {
 		EDIT_UNDO,
 		EDIT_UNDO,
@@ -88,8 +89,6 @@ private:
 protected:
 protected:
 	static void _bind_methods();
 	static void _bind_methods();
 
 
-	void _notification(int p_what);
-
 	void _edit_option(int p_op);
 	void _edit_option(int p_op);
 	void _make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded, Vector2 p_position);
 	void _make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded, Vector2 p_position);
 	void _text_edit_gui_input(const Ref<InputEvent> &ev);
 	void _text_edit_gui_input(const Ref<InputEvent> &ev);
@@ -113,7 +112,7 @@ public:
 	virtual Ref<Texture2D> get_theme_icon() override;
 	virtual Ref<Texture2D> get_theme_icon() override;
 	virtual RES get_edited_resource() const override;
 	virtual RES get_edited_resource() const override;
 	virtual void set_edited_resource(const RES &p_res) override;
 	virtual void set_edited_resource(const RES &p_res) override;
-	void set_edited_file(const Ref<TextFile> &p_file);
+	virtual void enable_editor() override;
 	virtual void reload_text() override;
 	virtual void reload_text() override;
 	virtual void apply_code() override;
 	virtual void apply_code() override;
 	virtual bool is_unsaved() override;
 	virtual bool is_unsaved() override;

+ 5 - 0
modules/visual_script/visual_script_editor.cpp

@@ -2513,6 +2513,8 @@ RES VisualScriptEditor::get_edited_resource() const {
 }
 }
 
 
 void VisualScriptEditor::set_edited_resource(const RES &p_res) {
 void VisualScriptEditor::set_edited_resource(const RES &p_res) {
+	ERR_FAIL_COND(script.is_valid());
+	ERR_FAIL_COND(p_res.is_null());
 	script = p_res;
 	script = p_res;
 	signal_editor->script = script;
 	signal_editor->script = script;
 	signal_editor->undo_redo = undo_redo;
 	signal_editor->undo_redo = undo_redo;
@@ -2533,6 +2535,9 @@ void VisualScriptEditor::set_edited_resource(const RES &p_res) {
 	_update_members();
 	_update_members();
 }
 }
 
 
+void VisualScriptEditor::enable_editor() {
+}
+
 Vector<String> VisualScriptEditor::get_functions() {
 Vector<String> VisualScriptEditor::get_functions() {
 	return Vector<String>();
 	return Vector<String>();
 }
 }

+ 1 - 0
modules/visual_script/visual_script_editor.h

@@ -294,6 +294,7 @@ public:
 	virtual void apply_code() override;
 	virtual void apply_code() override;
 	virtual RES get_edited_resource() const override;
 	virtual RES get_edited_resource() const override;
 	virtual void set_edited_resource(const RES &p_res) override;
 	virtual void set_edited_resource(const RES &p_res) override;
+	virtual void enable_editor() override;
 	virtual Vector<String> get_functions() override;
 	virtual Vector<String> get_functions() override;
 	virtual void reload_text() override;
 	virtual void reload_text() override;
 	virtual String get_name() override;
 	virtual String get_name() override;