Просмотр исходного кода

Improved text editor status bar and zooming UX.

Zi Ye 1 год назад
Родитель
Сommit
9281c441f6

+ 126 - 139
editor/code_editor.cpp

@@ -39,6 +39,8 @@
 #include "editor/plugins/script_editor_plugin.h"
 #include "editor/themes/editor_scale.h"
 #include "editor/themes/editor_theme_manager.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/separator.h"
 #include "scene/resources/font.h"
 
 void GotoLineDialog::popup_find_line(CodeEdit *p_edit) {
@@ -763,6 +765,8 @@ FindReplaceBar::FindReplaceBar() {
 
 /*** CODE EDITOR ****/
 
+static constexpr float ZOOM_FACTOR_PRESETS[7] = { 0.25f, 0.5f, 0.75f, 1.0f, 1.5f, 2.0f, 3.0f };
+
 // This function should be used to handle shortcuts that could otherwise
 // be handled too late if they weren't handled here.
 void CodeTextEditor::input(const Ref<InputEvent> &event) {
@@ -827,18 +831,21 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
 		if (mb->is_pressed() && mb->is_command_or_control_pressed()) {
 			if (mb->get_button_index() == MouseButton::WHEEL_UP) {
 				_zoom_in();
-			} else if (mb->get_button_index() == MouseButton::WHEEL_DOWN) {
+				accept_event();
+				return;
+			}
+			if (mb->get_button_index() == MouseButton::WHEEL_DOWN) {
 				_zoom_out();
+				accept_event();
+				return;
 			}
 		}
 	}
 
 	Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
 	if (magnify_gesture.is_valid()) {
-		font_size = text_editor->get_theme_font_size(SNAME("font_size"));
-		font_size *= powf(magnify_gesture->get_factor(), 0.25);
-
-		_add_font_size((int)font_size - text_editor->get_theme_font_size(SNAME("font_size")));
+		_zoom_to(zoom_factor * powf(magnify_gesture->get_factor(), 0.25f));
+		accept_event();
 		return;
 	}
 
@@ -849,40 +856,22 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
 			if (ED_IS_SHORTCUT("script_editor/zoom_in", p_event)) {
 				_zoom_in();
 				accept_event();
+				return;
 			}
 			if (ED_IS_SHORTCUT("script_editor/zoom_out", p_event)) {
 				_zoom_out();
 				accept_event();
+				return;
 			}
 			if (ED_IS_SHORTCUT("script_editor/reset_zoom", p_event)) {
-				_reset_zoom();
+				_zoom_to(1);
 				accept_event();
+				return;
 			}
 		}
 	}
 }
 
-void CodeTextEditor::_zoom_in() {
-	font_resize_val += MAX(EDSCALE, 1.0f);
-	_zoom_changed();
-}
-
-void CodeTextEditor::_zoom_out() {
-	font_resize_val -= MAX(EDSCALE, 1.0f);
-	_zoom_changed();
-}
-
-void CodeTextEditor::_zoom_changed() {
-	if (font_resize_timer->get_time_left() == 0) {
-		font_resize_timer->start();
-	}
-}
-
-void CodeTextEditor::_reset_zoom() {
-	EditorSettings::get_singleton()->set("interface/editor/code_font_size", 14);
-	text_editor->add_theme_font_size_override("font_size", 14 * EDSCALE);
-}
-
 void CodeTextEditor::_line_col_changed() {
 	if (!code_complete_timer->is_stopped() && code_complete_timer_line != text_editor->get_caret_line()) {
 		code_complete_timer->stop();
@@ -904,9 +893,6 @@ void CodeTextEditor::_line_col_changed() {
 	sb.append(" : ");
 	sb.append(itos(positional_column + 1).lpad(3));
 
-	sb.append(" | ");
-	sb.append(text_editor->is_indent_using_spaces() ? TTR("Spaces", "Indentation") : TTR("Tabs", "Indentation"));
-
 	line_and_col_txt->set_text(sb.as_string());
 
 	if (find_replace_bar) {
@@ -1010,24 +996,6 @@ Ref<Texture2D> CodeTextEditor::_get_completion_icon(const ScriptLanguage::CodeCo
 	return tex;
 }
 
-void CodeTextEditor::_font_resize_timeout() {
-	if (_add_font_size(font_resize_val)) {
-		font_resize_val = 0;
-	}
-}
-
-bool CodeTextEditor::_add_font_size(int p_delta) {
-	int old_size = text_editor->get_theme_font_size(SNAME("font_size"));
-	int new_size = CLAMP(old_size + p_delta, 8 * EDSCALE, 96 * EDSCALE);
-
-	if (new_size != old_size) {
-		EditorSettings::get_singleton()->set("interface/editor/code_font_size", new_size / EDSCALE);
-		text_editor->add_theme_font_size_override("font_size", new_size);
-	}
-
-	return true;
-}
-
 void CodeTextEditor::update_editor_settings() {
 	// Theme: Highlighting
 	completion_font_color = EDITOR_GET("text_editor/theme/highlighting/completion_font_color");
@@ -1068,12 +1036,16 @@ void CodeTextEditor::update_editor_settings() {
 	text_editor->set_drag_and_drop_selection_enabled(EDITOR_GET("text_editor/behavior/navigation/drag_and_drop_selection"));
 
 	// Behavior: indent
-	text_editor->set_indent_using_spaces(EDITOR_GET("text_editor/behavior/indent/type"));
+	set_indent_using_spaces(EDITOR_GET("text_editor/behavior/indent/type"));
 	text_editor->set_indent_size(EDITOR_GET("text_editor/behavior/indent/size"));
 	text_editor->set_auto_indent_enabled(EDITOR_GET("text_editor/behavior/indent/auto_indent"));
 
 	// Completion
 	text_editor->set_auto_brace_completion_enabled(EDITOR_GET("text_editor/completion/auto_brace_complete"));
+	text_editor->set_code_hint_draw_below(EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"));
+	code_complete_enabled = EDITOR_GET("text_editor/completion/code_complete_enabled");
+	code_complete_timer->set_wait_time(EDITOR_GET("text_editor/completion/code_complete_delay"));
+	idle->set_wait_time(EDITOR_GET("text_editor/completion/idle_parse_delay"));
 
 	// Appearance: Guidelines
 	if (EDITOR_GET("text_editor/appearance/guidelines/show_line_length_guidelines")) {
@@ -1086,6 +1058,9 @@ void CodeTextEditor::update_editor_settings() {
 	} else {
 		text_editor->set_line_length_guidelines(TypedArray<int>());
 	}
+
+	_update_font_ligatures();
+	set_zoom_factor(zoom_factor);
 }
 
 void CodeTextEditor::set_find_replace_bar(FindReplaceBar *p_bar) {
@@ -1203,6 +1178,11 @@ void CodeTextEditor::convert_case(CaseStyle p_case) {
 	text_editor->end_complex_operation();
 }
 
+void CodeTextEditor::set_indent_using_spaces(bool p_use_spaces) {
+	text_editor->set_indent_using_spaces(p_use_spaces);
+	indentation_txt->set_text(p_use_spaces ? TTR("Spaces", "Indentation") : TTR("Tabs", "Indentation"));
+}
+
 void CodeTextEditor::move_lines_up() {
 	text_editor->begin_complex_operation();
 
@@ -1703,41 +1683,38 @@ void CodeTextEditor::goto_error() {
 }
 
 void CodeTextEditor::_update_text_editor_theme() {
+	if (!EditorThemeManager::is_generated_theme_outdated()) {
+		return;
+	}
+
 	emit_signal(SNAME("load_theme_settings"));
 
-	error->begin_bulk_theme_override();
-	error->add_theme_font_override(SNAME("font"), get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts)));
-	error->add_theme_font_size_override(SNAME("font_size"), get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts)));
-	error->add_theme_color_override(SNAME("font_color"), get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
+	error_button->set_icon(get_editor_theme_icon(SNAME("StatusError")));
+	warning_button->set_icon(get_editor_theme_icon(SNAME("NodeWarning")));
 
 	Ref<Font> status_bar_font = get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts));
 	int status_bar_font_size = get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts));
-	error->add_theme_font_override("font", status_bar_font);
-	error->add_theme_font_size_override("font_size", status_bar_font_size);
-	error->end_bulk_theme_override();
 
 	int count = status_bar->get_child_count();
 	for (int i = 0; i < count; i++) {
 		Control *n = Object::cast_to<Control>(status_bar->get_child(i));
 		if (n) {
-			n->add_theme_font_override("font", status_bar_font);
-			n->add_theme_font_size_override("font_size", status_bar_font_size);
+			n->add_theme_font_override(SNAME("font"), status_bar_font);
+			n->add_theme_font_size_override(SNAME("font_size"), status_bar_font_size);
 		}
 	}
-}
 
-void CodeTextEditor::_on_settings_change() {
-	if (EditorThemeManager::is_generated_theme_outdated() ||
-			EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor") ||
-			EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/completion")) {
-		_apply_settings_change();
-	}
-}
+	const Color &error_color = get_theme_color(SNAME("error_color"), EditorStringName(Editor));
+	const Color &warning_color = get_theme_color(SNAME("warning_color"), EditorStringName(Editor));
 
-void CodeTextEditor::_apply_settings_change() {
-	_update_text_editor_theme();
+	error->add_theme_color_override(SNAME("font_color"), error_color);
+	error_button->add_theme_color_override(SNAME("font_color"), error_color);
+	warning_button->add_theme_color_override(SNAME("font_color"), warning_color);
+
+	_update_font_ligatures();
+}
 
-	font_size = EDITOR_GET("interface/editor/code_font_size");
+void CodeTextEditor::_update_font_ligatures() {
 	int ot_mode = EDITOR_GET("interface/editor/code_font_contextual_ligatures");
 
 	Ref<FontVariation> fc = text_editor->get_theme_font(SNAME("font"));
@@ -1768,12 +1745,6 @@ void CodeTextEditor::_apply_settings_change() {
 			} break;
 		}
 	}
-
-	text_editor->set_code_hint_draw_below(EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"));
-
-	code_complete_enabled = EDITOR_GET("text_editor/completion/code_complete_enabled");
-	code_complete_timer->set_wait_time(EDITOR_GET("text_editor/completion/code_complete_delay"));
-	idle->set_wait_time(EDITOR_GET("text_editor/completion/idle_parse_delay"));
 }
 
 void CodeTextEditor::_text_changed_idle_timeout() {
@@ -1795,6 +1766,10 @@ void CodeTextEditor::_warning_button_pressed() {
 	_set_show_errors_panel(false);
 }
 
+void CodeTextEditor::_zoom_popup_id_pressed(int p_idx) {
+	_zoom_to(zoom_button->get_popup()->get_item_metadata(p_idx));
+}
+
 void CodeTextEditor::_set_show_errors_panel(bool p_show) {
 	is_errors_panel_opened = p_show;
 	emit_signal(SNAME("show_errors_panel"), p_show);
@@ -1833,32 +1808,9 @@ void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) {
 	}
 }
 
-void CodeTextEditor::_update_status_bar_theme() {
-	error_button->set_icon(get_editor_theme_icon(SNAME("StatusError")));
-	warning_button->set_icon(get_editor_theme_icon(SNAME("NodeWarning")));
-
-	error_button->begin_bulk_theme_override();
-	error_button->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
-	error_button->add_theme_font_override("font", get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts)));
-	error_button->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts)));
-	error_button->end_bulk_theme_override();
-
-	warning_button->begin_bulk_theme_override();
-	warning_button->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), EditorStringName(Editor)));
-	warning_button->add_theme_font_override("font", get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts)));
-	warning_button->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts)));
-	warning_button->end_bulk_theme_override();
-
-	line_and_col_txt->begin_bulk_theme_override();
-	line_and_col_txt->add_theme_font_override("font", get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts)));
-	line_and_col_txt->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts)));
-	line_and_col_txt->end_bulk_theme_override();
-}
-
 void CodeTextEditor::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_THEME_CHANGED: {
-			_update_status_bar_theme();
 			if (toggle_scripts_button->is_visible()) {
 				update_toggle_scripts_button();
 			}
@@ -1966,11 +1918,54 @@ void CodeTextEditor::remove_all_bookmarks() {
 	text_editor->clear_bookmarked_lines();
 }
 
+void CodeTextEditor::_zoom_in() {
+	int s = text_editor->get_theme_font_size("font_size");
+	_zoom_to(zoom_factor * (s + MAX(1.0f, EDSCALE)) / s);
+}
+
+void CodeTextEditor::_zoom_out() {
+	int s = text_editor->get_theme_font_size("font_size");
+	_zoom_to(zoom_factor * (s - MAX(1.0f, EDSCALE)) / s);
+}
+
+void CodeTextEditor::_zoom_to(float p_zoom_factor) {
+	if (zoom_factor == p_zoom_factor) {
+		return;
+	}
+
+	float old_zoom_factor = zoom_factor;
+
+	set_zoom_factor(p_zoom_factor);
+
+	if (old_zoom_factor != zoom_factor) {
+		emit_signal(SNAME("zoomed"), zoom_factor);
+	}
+}
+
+void CodeTextEditor::set_zoom_factor(float p_zoom_factor) {
+	int preset_count = sizeof(ZOOM_FACTOR_PRESETS) / sizeof(float);
+	zoom_factor = CLAMP(p_zoom_factor, ZOOM_FACTOR_PRESETS[0], ZOOM_FACTOR_PRESETS[preset_count - 1]);
+	int neutral_font_size = int(EDITOR_GET("interface/editor/code_font_size")) * EDSCALE;
+	int new_font_size = Math::round(zoom_factor * neutral_font_size);
+
+	zoom_button->set_text(itos(Math::round(zoom_factor * 100)) + " %");
+
+	if (text_editor->has_theme_font_size_override("font_size")) {
+		text_editor->remove_theme_font_size_override("font_size");
+	}
+	text_editor->add_theme_font_size_override("font_size", new_font_size);
+}
+
+float CodeTextEditor::get_zoom_factor() {
+	return zoom_factor;
+}
+
 void CodeTextEditor::_bind_methods() {
 	ADD_SIGNAL(MethodInfo("validate_script"));
 	ADD_SIGNAL(MethodInfo("load_theme_settings"));
 	ADD_SIGNAL(MethodInfo("show_errors_panel"));
 	ADD_SIGNAL(MethodInfo("show_warnings_panel"));
+	ADD_SIGNAL(MethodInfo("zoomed", PropertyInfo(Variant::FLOAT, "p_zoom_factor")));
 }
 
 void CodeTextEditor::set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func, void *p_ud) {
@@ -2004,36 +1999,6 @@ CodeTextEditor::CodeTextEditor() {
 	text_editor->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_GDSCRIPT);
 	text_editor->set_draw_bookmarks_gutter(true);
 
-	int ot_mode = EDITOR_GET("interface/editor/code_font_contextual_ligatures");
-	Ref<FontVariation> fc = text_editor->get_theme_font(SNAME("font"));
-	if (fc.is_valid()) {
-		switch (ot_mode) {
-			case 1: { // Disable ligatures.
-				Dictionary ftrs;
-				ftrs[TS->name_to_tag("calt")] = 0;
-				fc->set_opentype_features(ftrs);
-			} break;
-			case 2: { // Custom.
-				Vector<String> subtag = String(EDITOR_GET("interface/editor/code_font_custom_opentype_features")).split(",");
-				Dictionary ftrs;
-				for (int i = 0; i < subtag.size(); i++) {
-					Vector<String> subtag_a = subtag[i].split("=");
-					if (subtag_a.size() == 2) {
-						ftrs[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
-					} else if (subtag_a.size() == 1) {
-						ftrs[TS->name_to_tag(subtag_a[0])] = 1;
-					}
-				}
-				fc->set_opentype_features(ftrs);
-			} break;
-			default: { // Enabled.
-				Dictionary ftrs;
-				ftrs[TS->name_to_tag("calt")] = 1;
-				fc->set_opentype_features(ftrs);
-			} break;
-		}
-	}
-
 	text_editor->set_draw_line_numbers(true);
 	text_editor->set_highlight_matching_braces_enabled(true);
 	text_editor->set_auto_indent_enabled(true);
@@ -2047,19 +2012,18 @@ CodeTextEditor::CodeTextEditor() {
 	idle = memnew(Timer);
 	add_child(idle);
 	idle->set_one_shot(true);
-	idle->set_wait_time(EDITOR_GET("text_editor/completion/idle_parse_delay"));
 
 	code_complete_enabled = EDITOR_GET("text_editor/completion/code_complete_enabled");
 	code_complete_timer = memnew(Timer);
 	add_child(code_complete_timer);
 	code_complete_timer->set_one_shot(true);
-	code_complete_timer->set_wait_time(EDITOR_GET("text_editor/completion/code_complete_delay"));
 
 	error_line = 0;
 	error_column = 0;
 
 	toggle_scripts_button = memnew(Button);
 	toggle_scripts_button->set_flat(true);
+	toggle_scripts_button->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER);
 	toggle_scripts_button->connect("pressed", callable_mp(this, &CodeTextEditor::_toggle_scripts_pressed));
 	status_bar->add_child(toggle_scripts_button);
 	toggle_scripts_button->hide();
@@ -2097,6 +2061,29 @@ CodeTextEditor::CodeTextEditor() {
 	warning_button->set_tooltip_text(TTR("Warnings"));
 	set_warning_count(0);
 
+	status_bar->add_child(memnew(VSeparator));
+
+	// Zoom
+	zoom_button = memnew(MenuButton);
+	status_bar->add_child(zoom_button);
+	zoom_button->set_flat(true);
+	zoom_button->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER);
+	zoom_button->set_tooltip_text(TTR("Zoom factor"));
+	zoom_button->set_text("100 %");
+
+	PopupMenu *zoom_menu = zoom_button->get_popup();
+	int preset_count = sizeof(ZOOM_FACTOR_PRESETS) / sizeof(float);
+
+	for (int i = 0; i < preset_count; i++) {
+		float z = ZOOM_FACTOR_PRESETS[i];
+		zoom_menu->add_item(itos(Math::round(z * 100)) + " %");
+		zoom_menu->set_item_metadata(i, z);
+	}
+
+	zoom_menu->connect("id_pressed", callable_mp(this, &CodeTextEditor::_zoom_popup_id_pressed));
+
+	status_bar->add_child(memnew(VSeparator));
+
 	// Line and column
 	line_and_col_txt = memnew(Label);
 	status_bar->add_child(line_and_col_txt);
@@ -2104,6 +2091,15 @@ CodeTextEditor::CodeTextEditor() {
 	line_and_col_txt->set_tooltip_text(TTR("Line and column numbers."));
 	line_and_col_txt->set_mouse_filter(MOUSE_FILTER_STOP);
 
+	status_bar->add_child(memnew(VSeparator));
+
+	// Indentation
+	indentation_txt = memnew(Label);
+	status_bar->add_child(indentation_txt);
+	indentation_txt->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER);
+	indentation_txt->set_tooltip_text(TTR("Indentation"));
+	indentation_txt->set_mouse_filter(MOUSE_FILTER_STOP);
+
 	text_editor->connect("gui_input", callable_mp(this, &CodeTextEditor::_text_editor_gui_input));
 	text_editor->connect("caret_changed", callable_mp(this, &CodeTextEditor::_line_col_changed));
 	text_editor->connect("text_changed", callable_mp(this, &CodeTextEditor::_text_changed));
@@ -2122,14 +2118,5 @@ CodeTextEditor::CodeTextEditor() {
 
 	code_complete_timer->connect("timeout", callable_mp(this, &CodeTextEditor::_code_complete_timer_timeout));
 
-	font_resize_val = 0;
-	font_size = EDITOR_GET("interface/editor/code_font_size");
-	font_resize_timer = memnew(Timer);
-	add_child(font_resize_timer);
-	font_resize_timer->set_one_shot(true);
-	font_resize_timer->set_wait_time(0.07);
-	font_resize_timer->connect("timeout", callable_mp(this, &CodeTextEditor::_font_resize_timeout));
-
-	EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &CodeTextEditor::_on_settings_change));
 	add_theme_constant_override("separation", 4 * EDSCALE);
 }

+ 16 - 13
editor/code_editor.h

@@ -40,6 +40,8 @@
 #include "scene/gui/line_edit.h"
 #include "scene/main/timer.h"
 
+class MenuButton;
+
 class GotoLineDialog : public ConfirmationDialog {
 	GDCLASS(GotoLineDialog, ConfirmationDialog);
 
@@ -156,7 +158,9 @@ class CodeTextEditor : public VBoxContainer {
 	Button *error_button = nullptr;
 	Button *warning_button = nullptr;
 
+	MenuButton *zoom_button = nullptr;
 	Label *line_and_col_txt = nullptr;
+	Label *indentation_txt = nullptr;
 
 	Label *info = nullptr;
 	Timer *idle = nullptr;
@@ -164,29 +168,19 @@ class CodeTextEditor : public VBoxContainer {
 	Timer *code_complete_timer = nullptr;
 	int code_complete_timer_line = 0;
 
-	Timer *font_resize_timer = nullptr;
-	int font_resize_val;
-	real_t font_size;
+	float zoom_factor = 1.0f;
 
 	Label *error = nullptr;
 	int error_line;
 	int error_column;
 
-	void _on_settings_change();
-	void _apply_settings_change();
-
 	void _update_text_editor_theme();
+	void _update_font_ligatures();
 	void _complete_request();
 	Ref<Texture2D> _get_completion_icon(const ScriptLanguage::CodeCompletionOption &p_option);
-	void _font_resize_timeout();
-	bool _add_font_size(int p_delta);
 
 	virtual void input(const Ref<InputEvent> &event) override;
 	void _text_editor_gui_input(const Ref<InputEvent> &p_event);
-	void _zoom_in();
-	void _zoom_out();
-	void _zoom_changed();
-	void _reset_zoom();
 
 	Color completion_font_color;
 	Color completion_string_color;
@@ -195,13 +189,17 @@ class CodeTextEditor : public VBoxContainer {
 	CodeTextEditorCodeCompleteFunc code_complete_func;
 	void *code_complete_ud = nullptr;
 
+	void _zoom_in();
+	void _zoom_out();
+	void _zoom_to(float p_zoom_factor);
+
 	void _error_button_pressed();
 	void _warning_button_pressed();
 	void _set_show_errors_panel(bool p_show);
 	void _set_show_warnings_panel(bool p_show);
 	void _error_pressed(const Ref<InputEvent> &p_event);
 
-	void _update_status_bar_theme();
+	void _zoom_popup_id_pressed(int p_idx);
 
 	void _toggle_scripts_pressed();
 
@@ -234,6 +232,8 @@ public:
 	};
 	void convert_case(CaseStyle p_case);
 
+	void set_indent_using_spaces(bool p_use_spaces);
+
 	void move_lines_up();
 	void move_lines_down();
 	void delete_lines();
@@ -273,6 +273,9 @@ public:
 	void goto_prev_bookmark();
 	void remove_all_bookmarks();
 
+	void set_zoom_factor(float p_zoom_factor);
+	float get_zoom_factor();
+
 	void set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func, void *p_ud);
 
 	void validate_script();

+ 40 - 6
editor/plugins/script_editor_plugin.cpp

@@ -38,6 +38,7 @@
 #include "core/os/keyboard.h"
 #include "core/os/os.h"
 #include "core/version.h"
+#include "editor/code_editor.h"
 #include "editor/debugger/editor_debugger_node.h"
 #include "editor/debugger/script_editor_debugger.h"
 #include "editor/editor_command_palette.h"
@@ -1639,7 +1640,7 @@ void ScriptEditor::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_ENTER_TREE: {
 			EditorRunBar::get_singleton()->connect("stop_pressed", callable_mp(this, &ScriptEditor::_editor_stop));
-			_editor_settings_changed();
+			_apply_editor_settings();
 			[[fallthrough]];
 		}
 
@@ -2481,6 +2482,12 @@ bool ScriptEditor::edit(const Ref<Resource> &p_resource, int p_line, int p_col,
 	se->connect("replace_in_files_requested", callable_mp(this, &ScriptEditor::_on_replace_in_files_requested));
 	se->connect("go_to_method", callable_mp(this, &ScriptEditor::script_goto_method));
 
+	CodeTextEditor *cte = se->get_code_editor();
+	if (cte) {
+		cte->set_zoom_factor(zoom_factor);
+		cte->connect("zoomed", callable_mp(this, &ScriptEditor::_set_zoom_factor));
+	}
+
 	//test for modification, maybe the script was not edited but was loaded
 
 	_test_script_times_on_disk(p_resource);
@@ -2779,11 +2786,16 @@ void ScriptEditor::_save_layout() {
 }
 
 void ScriptEditor::_editor_settings_changed() {
-	if (!EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor") &&
+	if (!EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor") &&
+			!EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor") &&
 			!EditorSettings::get_singleton()->check_changed_settings_in_group("docks/filesystem")) {
 		return;
 	}
 
+	_apply_editor_settings();
+}
+
+void ScriptEditor::_apply_editor_settings() {
 	textfile_extensions.clear();
 	const Vector<String> textfile_ext = ((String)(EDITOR_GET("docks/filesystem/textfile_extensions"))).split(",", false);
 	for (const String &E : textfile_ext) {
@@ -2808,6 +2820,11 @@ void ScriptEditor::_editor_settings_changed() {
 		EditorSettings::get_singleton()->load_text_editor_theme();
 	}
 
+	_update_script_colors();
+	_update_script_names();
+
+	ScriptServer::set_reload_scripts_on_save(EDITOR_GET("text_editor/behavior/files/auto_reload_and_parse_scripts_on_save"));
+
 	for (int i = 0; i < tab_container->get_tab_count(); i++) {
 		ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_tab_control(i));
 		if (!se) {
@@ -2816,10 +2833,6 @@ void ScriptEditor::_editor_settings_changed() {
 
 		se->update_settings();
 	}
-	_update_script_colors();
-	_update_script_names();
-
-	ScriptServer::set_reload_scripts_on_save(EDITOR_GET("text_editor/behavior/files/auto_reload_and_parse_scripts_on_save"));
 }
 
 void ScriptEditor::_filesystem_changed() {
@@ -3322,6 +3335,8 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
 		}
 	}
 
+	_set_zoom_factor(p_layout->get_value("ScriptEditor", "zoom_factor", 1.0f));
+
 	restoring_layout = false;
 
 	_update_script_names();
@@ -3371,6 +3386,7 @@ void ScriptEditor::get_window_layout(Ref<ConfigFile> p_layout) {
 	p_layout->set_value("ScriptEditor", "open_help", helps);
 	p_layout->set_value("ScriptEditor", "script_split_offset", script_split->get_split_offset());
 	p_layout->set_value("ScriptEditor", "list_split_offset", list_split->get_split_offset());
+	p_layout->set_value("ScriptEditor", "zoom_factor", zoom_factor);
 
 	// Save the cache.
 	script_editor_cache->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("script_editor_cache.cfg"));
@@ -3806,6 +3822,24 @@ void ScriptEditor::_on_find_in_files_modified_files(PackedStringArray paths) {
 	_update_modified_scripts_for_external_editor();
 }
 
+void ScriptEditor::_set_zoom_factor(float p_zoom_factor) {
+	if (zoom_factor == p_zoom_factor) {
+		return;
+	}
+	zoom_factor = p_zoom_factor;
+	for (int i = 0; i < tab_container->get_tab_count(); i++) {
+		ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_tab_control(i));
+		if (se) {
+			CodeTextEditor *cte = se->get_code_editor();
+			if (cte) {
+				if (zoom_factor != cte->get_zoom_factor()) {
+					cte->set_zoom_factor(zoom_factor);
+				}
+			}
+		}
+	}
+}
+
 void ScriptEditor::_window_changed(bool p_visible) {
 	make_floating->set_visible(!p_visible);
 	is_floating = p_visible;

+ 7 - 0
editor/plugins/script_editor_plugin.h

@@ -38,6 +38,7 @@
 #include "scene/resources/syntax_highlighter.h"
 #include "scene/resources/text_file.h"
 
+class CodeTextEditor;
 class EditorFileDialog;
 class EditorHelpSearch;
 class FindReplaceBar;
@@ -192,6 +193,7 @@ public:
 	virtual void set_find_replace_bar(FindReplaceBar *p_bar) = 0;
 
 	virtual Control *get_base_editor() const = 0;
+	virtual CodeTextEditor *get_code_editor() const = 0;
 
 	virtual void validate() = 0;
 
@@ -306,6 +308,8 @@ class ScriptEditor : public PanelContainer {
 
 	String current_theme;
 
+	float zoom_factor = 1.0f;
+
 	TextureRect *script_icon = nullptr;
 	Label *script_name_label = nullptr;
 
@@ -420,6 +424,7 @@ class ScriptEditor : public PanelContainer {
 	void _save_editor_state(ScriptEditorBase *p_editor);
 	void _save_layout();
 	void _editor_settings_changed();
+	void _apply_editor_settings();
 	void _filesystem_changed();
 	void _files_moved(const String &p_old_file, const String &p_new_file);
 	void _file_removed(const String &p_file);
@@ -491,6 +496,8 @@ class ScriptEditor : public PanelContainer {
 	void _start_find_in_files(bool with_replace);
 	void _on_find_in_files_modified_files(PackedStringArray paths);
 
+	void _set_zoom_factor(float p_zoom_factor);
+
 	void _window_changed(bool p_visible);
 
 	static void _open_script_request(const String &p_path);

+ 6 - 4
editor/plugins/script_text_editor.cpp

@@ -1393,11 +1393,11 @@ void ScriptTextEditor::_edit_option(int p_op) {
 			trim_trailing_whitespace();
 		} break;
 		case EDIT_CONVERT_INDENT_TO_SPACES: {
-			tx->set_indent_using_spaces(true);
+			code_editor->set_indent_using_spaces(true);
 			convert_indent();
 		} break;
 		case EDIT_CONVERT_INDENT_TO_TABS: {
-			tx->set_indent_using_spaces(false);
+			code_editor->set_indent_using_spaces(false);
 			convert_indent();
 		} break;
 		case EDIT_PICK_COLOR: {
@@ -1691,6 +1691,10 @@ Control *ScriptTextEditor::get_base_editor() const {
 	return code_editor->get_text_editor();
 }
 
+CodeTextEditor *ScriptTextEditor::get_code_editor() const {
+	return code_editor;
+}
+
 Variant ScriptTextEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
 	return Variant();
 }
@@ -2374,8 +2378,6 @@ ScriptTextEditor::ScriptTextEditor() {
 
 	update_settings();
 
-	code_editor->get_text_editor()->set_code_hint_draw_below(EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"));
-
 	code_editor->get_text_editor()->set_symbol_lookup_on_click_enabled(true);
 	code_editor->get_text_editor()->set_context_menu_enabled(false);
 

+ 1 - 0
editor/plugins/script_text_editor.h

@@ -256,6 +256,7 @@ public:
 	static void register_editor();
 
 	virtual Control *get_base_editor() const override;
+	virtual CodeTextEditor *get_code_editor() const override;
 
 	virtual void validate() override;
 

+ 27 - 2
editor/plugins/shader_editor_plugin.cpp

@@ -143,7 +143,6 @@ void ShaderEditorPlugin::edit(Object *p_object) {
 		es.shader_editor = memnew(TextShaderEditor);
 		es.shader_editor->edit(si);
 		shader_tabs->add_child(es.shader_editor);
-		es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list));
 	} else {
 		Shader *s = Object::cast_to<Shader>(p_object);
 		for (uint32_t i = 0; i < edited_shaders.size(); i++) {
@@ -163,7 +162,16 @@ void ShaderEditorPlugin::edit(Object *p_object) {
 			es.shader_editor = memnew(TextShaderEditor);
 			shader_tabs->add_child(es.shader_editor);
 			es.shader_editor->edit(s);
-			es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list));
+		}
+	}
+
+	if (es.shader_editor) {
+		es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list));
+
+		CodeTextEditor *cte = es.shader_editor->get_code_editor();
+		if (cte) {
+			cte->set_zoom_factor(text_shader_zoom_factor);
+			cte->connect("zoomed", callable_mp(this, &ShaderEditorPlugin::_set_text_shader_zoom_factor));
 		}
 	}
 
@@ -244,6 +252,8 @@ void ShaderEditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) {
 
 	_update_shader_list();
 	_shader_selected(selected_shader_idx);
+
+	_set_text_shader_zoom_factor(p_layout->get_value("ShaderEditor", "text_shader_zoom_factor", 1.0f));
 }
 
 void ShaderEditorPlugin::get_window_layout(Ref<ConfigFile> p_layout) {
@@ -290,6 +300,7 @@ void ShaderEditorPlugin::get_window_layout(Ref<ConfigFile> p_layout) {
 	p_layout->set_value("ShaderEditor", "open_shaders", shaders);
 	p_layout->set_value("ShaderEditor", "split_offset", main_split->get_split_offset());
 	p_layout->set_value("ShaderEditor", "selected_shader", selected_shader);
+	p_layout->set_value("ShaderEditor", "text_shader_zoom_factor", text_shader_zoom_factor);
 }
 
 String ShaderEditorPlugin::get_unsaved_status(const String &p_for_scene) const {
@@ -590,6 +601,20 @@ void ShaderEditorPlugin::_window_changed(bool p_visible) {
 	make_floating->set_visible(!p_visible);
 }
 
+void ShaderEditorPlugin::_set_text_shader_zoom_factor(float p_zoom_factor) {
+	if (text_shader_zoom_factor != p_zoom_factor) {
+		text_shader_zoom_factor = p_zoom_factor;
+		for (const EditedShader &edited_shader : edited_shaders) {
+			if (edited_shader.shader_editor) {
+				CodeTextEditor *cte = edited_shader.shader_editor->get_code_editor();
+				if (cte && cte->get_zoom_factor() != text_shader_zoom_factor) {
+					cte->set_zoom_factor(text_shader_zoom_factor);
+				}
+			}
+		}
+	}
+}
+
 void ShaderEditorPlugin::_file_removed(const String &p_removed_file) {
 	for (uint32_t i = 0; i < edited_shaders.size(); i++) {
 		if (edited_shaders[i].path == p_removed_file) {

+ 4 - 0
editor/plugins/shader_editor_plugin.h

@@ -86,6 +86,8 @@ class ShaderEditorPlugin : public EditorPlugin {
 
 	ShaderCreateDialog *shader_create_dialog = nullptr;
 
+	float text_shader_zoom_factor = 1.0f;
+
 	void _update_shader_list();
 	void _shader_selected(int p_index);
 	void _shader_list_clicked(int p_item, Vector2 p_local_mouse_pos, MouseButton p_mouse_button_index);
@@ -106,6 +108,8 @@ class ShaderEditorPlugin : public EditorPlugin {
 
 	void _window_changed(bool p_visible);
 
+	void _set_text_shader_zoom_factor(float p_zoom_factor);
+
 protected:
 	void _notification(int p_what);
 

+ 6 - 2
editor/plugins/text_editor.cpp

@@ -150,6 +150,10 @@ Control *TextEditor::get_base_editor() const {
 	return code_editor->get_text_editor();
 }
 
+CodeTextEditor *TextEditor::get_code_editor() const {
+	return code_editor;
+}
+
 PackedInt32Array TextEditor::get_breakpoints() {
 	return PackedInt32Array();
 }
@@ -419,11 +423,11 @@ void TextEditor::_edit_option(int p_op) {
 			trim_trailing_whitespace();
 		} break;
 		case EDIT_CONVERT_INDENT_TO_SPACES: {
-			tx->set_indent_using_spaces(true);
+			code_editor->set_indent_using_spaces(true);
 			convert_indent();
 		} break;
 		case EDIT_CONVERT_INDENT_TO_TABS: {
-			tx->set_indent_using_spaces(false);
+			code_editor->set_indent_using_spaces(false);
 			convert_indent();
 		} break;
 		case EDIT_TO_UPPERCASE: {

+ 1 - 0
editor/plugins/text_editor.h

@@ -152,6 +152,7 @@ public:
 	virtual void validate() override;
 
 	virtual Control *get_base_editor() const override;
+	virtual CodeTextEditor *get_code_editor() const override;
 
 	static void register_editor();
 

+ 83 - 83
editor/plugins/text_shader_editor.cpp

@@ -628,100 +628,100 @@ ShaderTextEditor::ShaderTextEditor() {
 /*** SCRIPT EDITOR ******/
 
 void TextShaderEditor::_menu_option(int p_option) {
-	shader_editor->get_text_editor()->apply_ime();
+	code_editor->get_text_editor()->apply_ime();
 
 	switch (p_option) {
 		case EDIT_UNDO: {
-			shader_editor->get_text_editor()->undo();
+			code_editor->get_text_editor()->undo();
 		} break;
 		case EDIT_REDO: {
-			shader_editor->get_text_editor()->redo();
+			code_editor->get_text_editor()->redo();
 		} break;
 		case EDIT_CUT: {
-			shader_editor->get_text_editor()->cut();
+			code_editor->get_text_editor()->cut();
 		} break;
 		case EDIT_COPY: {
-			shader_editor->get_text_editor()->copy();
+			code_editor->get_text_editor()->copy();
 		} break;
 		case EDIT_PASTE: {
-			shader_editor->get_text_editor()->paste();
+			code_editor->get_text_editor()->paste();
 		} break;
 		case EDIT_SELECT_ALL: {
-			shader_editor->get_text_editor()->select_all();
+			code_editor->get_text_editor()->select_all();
 		} break;
 		case EDIT_MOVE_LINE_UP: {
-			shader_editor->move_lines_up();
+			code_editor->move_lines_up();
 		} break;
 		case EDIT_MOVE_LINE_DOWN: {
-			shader_editor->move_lines_down();
+			code_editor->move_lines_down();
 		} break;
 		case EDIT_INDENT: {
 			if (shader.is_null() && shader_inc.is_null()) {
 				return;
 			}
-			shader_editor->get_text_editor()->indent_lines();
+			code_editor->get_text_editor()->indent_lines();
 		} break;
 		case EDIT_UNINDENT: {
 			if (shader.is_null() && shader_inc.is_null()) {
 				return;
 			}
-			shader_editor->get_text_editor()->unindent_lines();
+			code_editor->get_text_editor()->unindent_lines();
 		} break;
 		case EDIT_DELETE_LINE: {
-			shader_editor->delete_lines();
+			code_editor->delete_lines();
 		} break;
 		case EDIT_DUPLICATE_SELECTION: {
-			shader_editor->duplicate_selection();
+			code_editor->duplicate_selection();
 		} break;
 		case EDIT_DUPLICATE_LINES: {
-			shader_editor->get_text_editor()->duplicate_lines();
+			code_editor->get_text_editor()->duplicate_lines();
 		} break;
 		case EDIT_TOGGLE_WORD_WRAP: {
-			TextEdit::LineWrappingMode wrap = shader_editor->get_text_editor()->get_line_wrapping_mode();
-			shader_editor->get_text_editor()->set_line_wrapping_mode(wrap == TextEdit::LINE_WRAPPING_BOUNDARY ? TextEdit::LINE_WRAPPING_NONE : TextEdit::LINE_WRAPPING_BOUNDARY);
+			TextEdit::LineWrappingMode wrap = code_editor->get_text_editor()->get_line_wrapping_mode();
+			code_editor->get_text_editor()->set_line_wrapping_mode(wrap == TextEdit::LINE_WRAPPING_BOUNDARY ? TextEdit::LINE_WRAPPING_NONE : TextEdit::LINE_WRAPPING_BOUNDARY);
 		} break;
 		case EDIT_TOGGLE_COMMENT: {
 			if (shader.is_null() && shader_inc.is_null()) {
 				return;
 			}
-			shader_editor->toggle_inline_comment("//");
+			code_editor->toggle_inline_comment("//");
 		} break;
 		case EDIT_COMPLETE: {
-			shader_editor->get_text_editor()->request_code_completion();
+			code_editor->get_text_editor()->request_code_completion();
 		} break;
 		case SEARCH_FIND: {
-			shader_editor->get_find_replace_bar()->popup_search();
+			code_editor->get_find_replace_bar()->popup_search();
 		} break;
 		case SEARCH_FIND_NEXT: {
-			shader_editor->get_find_replace_bar()->search_next();
+			code_editor->get_find_replace_bar()->search_next();
 		} break;
 		case SEARCH_FIND_PREV: {
-			shader_editor->get_find_replace_bar()->search_prev();
+			code_editor->get_find_replace_bar()->search_prev();
 		} break;
 		case SEARCH_REPLACE: {
-			shader_editor->get_find_replace_bar()->popup_replace();
+			code_editor->get_find_replace_bar()->popup_replace();
 		} break;
 		case SEARCH_GOTO_LINE: {
-			goto_line_dialog->popup_find_line(shader_editor->get_text_editor());
+			goto_line_dialog->popup_find_line(code_editor->get_text_editor());
 		} break;
 		case BOOKMARK_TOGGLE: {
-			shader_editor->toggle_bookmark();
+			code_editor->toggle_bookmark();
 		} break;
 		case BOOKMARK_GOTO_NEXT: {
-			shader_editor->goto_next_bookmark();
+			code_editor->goto_next_bookmark();
 		} break;
 		case BOOKMARK_GOTO_PREV: {
-			shader_editor->goto_prev_bookmark();
+			code_editor->goto_prev_bookmark();
 		} break;
 		case BOOKMARK_REMOVE_ALL: {
-			shader_editor->remove_all_bookmarks();
+			code_editor->remove_all_bookmarks();
 		} break;
 		case HELP_DOCS: {
 			OS::get_singleton()->shell_open(vformat("%s/tutorials/shaders/shader_reference/index.html", VERSION_DOCS_URL));
 		} break;
 	}
 	if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) {
-		callable_mp((Control *)shader_editor->get_text_editor(), &Control::grab_focus).call_deferred();
+		callable_mp((Control *)code_editor->get_text_editor(), &Control::grab_focus).call_deferred();
 	}
 }
 
@@ -740,14 +740,16 @@ void TextShaderEditor::_notification(int p_what) {
 }
 
 void TextShaderEditor::_editor_settings_changed() {
-	if (!EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor")) {
+	if (!EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor") &&
+			!EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor")) {
 		return;
 	}
-	shader_editor->update_editor_settings();
 
-	shader_editor->get_text_editor()->add_theme_constant_override("line_spacing", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
-	shader_editor->get_text_editor()->set_draw_breakpoints_gutter(false);
-	shader_editor->get_text_editor()->set_draw_executing_lines_gutter(false);
+	_apply_editor_settings();
+}
+
+void TextShaderEditor::_apply_editor_settings() {
+	code_editor->update_editor_settings();
 
 	trim_trailing_whitespace_on_save = EDITOR_GET("text_editor/behavior/files/trim_trailing_whitespace_on_save");
 }
@@ -758,7 +760,7 @@ void TextShaderEditor::_show_warnings_panel(bool p_show) {
 
 void TextShaderEditor::_warning_clicked(Variant p_line) {
 	if (p_line.get_type() == Variant::INT) {
-		shader_editor->get_text_editor()->set_caret_line(p_line.operator int64_t());
+		code_editor->get_text_editor()->set_caret_line(p_line.operator int64_t());
 	}
 }
 
@@ -773,7 +775,7 @@ void TextShaderEditor::ensure_select_current() {
 }
 
 void TextShaderEditor::goto_line_selection(int p_line, int p_begin, int p_end) {
-	shader_editor->goto_line_selection(p_line, p_begin, p_end);
+	code_editor->goto_line_selection(p_line, p_begin, p_end);
 }
 
 void TextShaderEditor::_project_settings_changed() {
@@ -812,8 +814,8 @@ void TextShaderEditor::_update_warnings(bool p_validate) {
 		saved_warning_flags = (uint32_t)ShaderWarning::get_flags_from_codemap(saved_warnings);
 	}
 
-	if (p_validate && changed && shader_editor && shader_editor->get_edited_shader().is_valid()) {
-		shader_editor->validate_script();
+	if (p_validate && changed && code_editor && code_editor->get_edited_shader().is_valid()) {
+		code_editor->validate_script();
 	}
 }
 
@@ -848,22 +850,22 @@ void TextShaderEditor::_reload_shader_from_disk() {
 	Ref<Shader> rel_shader = ResourceLoader::load(shader->get_path(), shader->get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE);
 	ERR_FAIL_COND(!rel_shader.is_valid());
 
-	shader_editor->set_block_shader_changed(true);
+	code_editor->set_block_shader_changed(true);
 	shader->set_code(rel_shader->get_code());
-	shader_editor->set_block_shader_changed(false);
+	code_editor->set_block_shader_changed(false);
 	shader->set_last_modified_time(rel_shader->get_last_modified_time());
-	shader_editor->reload_text();
+	code_editor->reload_text();
 }
 
 void TextShaderEditor::_reload_shader_include_from_disk() {
 	Ref<ShaderInclude> rel_shader_include = ResourceLoader::load(shader_inc->get_path(), shader_inc->get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE);
 	ERR_FAIL_COND(!rel_shader_include.is_valid());
 
-	shader_editor->set_block_shader_changed(true);
+	code_editor->set_block_shader_changed(true);
 	shader_inc->set_code(rel_shader_include->get_code());
-	shader_editor->set_block_shader_changed(false);
+	code_editor->set_block_shader_changed(false);
 	shader_inc->set_last_modified_time(rel_shader_include->get_last_modified_time());
-	shader_editor->reload_text();
+	code_editor->reload_text();
 }
 
 void TextShaderEditor::_reload() {
@@ -886,7 +888,7 @@ void TextShaderEditor::edit(const Ref<Shader> &p_shader) {
 	shader = p_shader;
 	shader_inc = Ref<ShaderInclude>();
 
-	shader_editor->set_edited_shader(shader);
+	code_editor->set_edited_shader(shader);
 }
 
 void TextShaderEditor::edit(const Ref<ShaderInclude> &p_shader_inc) {
@@ -901,7 +903,7 @@ void TextShaderEditor::edit(const Ref<ShaderInclude> &p_shader_inc) {
 	shader_inc = p_shader_inc;
 	shader = Ref<Shader>();
 
-	shader_editor->set_edited_shader_include(p_shader_inc);
+	code_editor->set_edited_shader_include(p_shader_inc);
 }
 
 void TextShaderEditor::save_external_data(const String &p_str) {
@@ -916,7 +918,7 @@ void TextShaderEditor::save_external_data(const String &p_str) {
 
 	apply_shaders();
 
-	Ref<Shader> edited_shader = shader_editor->get_edited_shader();
+	Ref<Shader> edited_shader = code_editor->get_edited_shader();
 	if (edited_shader.is_valid()) {
 		ResourceSaver::save(edited_shader);
 	}
@@ -924,56 +926,56 @@ void TextShaderEditor::save_external_data(const String &p_str) {
 		ResourceSaver::save(shader);
 	}
 
-	Ref<ShaderInclude> edited_shader_inc = shader_editor->get_edited_shader_include();
+	Ref<ShaderInclude> edited_shader_inc = code_editor->get_edited_shader_include();
 	if (edited_shader_inc.is_valid()) {
 		ResourceSaver::save(edited_shader_inc);
 	}
 	if (shader_inc.is_valid() && shader_inc != edited_shader_inc) {
 		ResourceSaver::save(shader_inc);
 	}
-	shader_editor->get_text_editor()->tag_saved_version();
+	code_editor->get_text_editor()->tag_saved_version();
 
 	disk_changed->hide();
 }
 
 void TextShaderEditor::trim_trailing_whitespace() {
-	shader_editor->trim_trailing_whitespace();
+	code_editor->trim_trailing_whitespace();
 }
 
 void TextShaderEditor::validate_script() {
-	shader_editor->_validate_script();
+	code_editor->_validate_script();
 }
 
 bool TextShaderEditor::is_unsaved() const {
-	return shader_editor->get_text_editor()->get_saved_version() != shader_editor->get_text_editor()->get_version();
+	return code_editor->get_text_editor()->get_saved_version() != code_editor->get_text_editor()->get_version();
 }
 
 void TextShaderEditor::tag_saved_version() {
-	shader_editor->get_text_editor()->tag_saved_version();
+	code_editor->get_text_editor()->tag_saved_version();
 }
 
 void TextShaderEditor::apply_shaders() {
-	String editor_code = shader_editor->get_text_editor()->get_text();
+	String editor_code = code_editor->get_text_editor()->get_text();
 	if (shader.is_valid()) {
 		String shader_code = shader->get_code();
-		if (shader_code != editor_code || dependencies_version != shader_editor->get_dependencies_version()) {
-			shader_editor->set_block_shader_changed(true);
+		if (shader_code != editor_code || dependencies_version != code_editor->get_dependencies_version()) {
+			code_editor->set_block_shader_changed(true);
 			shader->set_code(editor_code);
-			shader_editor->set_block_shader_changed(false);
+			code_editor->set_block_shader_changed(false);
 			shader->set_edited(true);
 		}
 	}
 	if (shader_inc.is_valid()) {
 		String shader_inc_code = shader_inc->get_code();
-		if (shader_inc_code != editor_code || dependencies_version != shader_editor->get_dependencies_version()) {
-			shader_editor->set_block_shader_changed(true);
+		if (shader_inc_code != editor_code || dependencies_version != code_editor->get_dependencies_version()) {
+			code_editor->set_block_shader_changed(true);
 			shader_inc->set_code(editor_code);
-			shader_editor->set_block_shader_changed(false);
+			code_editor->set_block_shader_changed(false);
 			shader_inc->set_edited(true);
 		}
 	}
 
-	dependencies_version = shader_editor->get_dependencies_version();
+	dependencies_version = code_editor->get_dependencies_version();
 }
 
 void TextShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
@@ -981,7 +983,7 @@ void TextShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 
 	if (mb.is_valid()) {
 		if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) {
-			CodeEdit *tx = shader_editor->get_text_editor();
+			CodeEdit *tx = code_editor->get_text_editor();
 
 			tx->apply_ime();
 
@@ -1014,7 +1016,7 @@ void TextShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 
 	Ref<InputEventKey> k = ev;
 	if (k.is_valid() && k->is_pressed() && k->is_action("ui_menu", true)) {
-		CodeEdit *tx = shader_editor->get_text_editor();
+		CodeEdit *tx = code_editor->get_text_editor();
 		tx->adjust_viewport_to_caret();
 		_make_context_menu(tx->has_selection(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->get_caret_draw_pos()));
 		context_menu->grab_focus();
@@ -1029,7 +1031,7 @@ void TextShaderEditor::_update_bookmark_list() {
 	bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT);
 	bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV);
 
-	PackedInt32Array bookmark_list = shader_editor->get_text_editor()->get_bookmarked_lines();
+	PackedInt32Array bookmark_list = code_editor->get_text_editor()->get_bookmarked_lines();
 	if (bookmark_list.size() == 0) {
 		return;
 	}
@@ -1037,7 +1039,7 @@ void TextShaderEditor::_update_bookmark_list() {
 	bookmarks_menu->add_separator();
 
 	for (int i = 0; i < bookmark_list.size(); i++) {
-		String line = shader_editor->get_text_editor()->get_line(bookmark_list[i]).strip_edges();
+		String line = code_editor->get_text_editor()->get_line(bookmark_list[i]).strip_edges();
 		// Limit the size of the line if too big.
 		if (line.length() > 50) {
 			line = line.substr(0, 50);
@@ -1052,7 +1054,7 @@ void TextShaderEditor::_bookmark_item_pressed(int p_idx) {
 	if (p_idx < 4) { // Any item before the separator.
 		_menu_option(bookmarks_menu->get_item_id(p_idx));
 	} else {
-		shader_editor->goto_line(bookmarks_menu->get_item_metadata(p_idx));
+		code_editor->goto_line(bookmarks_menu->get_item_metadata(p_idx));
 	}
 }
 
@@ -1083,26 +1085,26 @@ void TextShaderEditor::_make_context_menu(bool p_selection, Vector2 p_position)
 TextShaderEditor::TextShaderEditor() {
 	_update_warnings(false);
 
-	shader_editor = memnew(ShaderTextEditor);
+	code_editor = memnew(ShaderTextEditor);
 
-	shader_editor->connect("script_validated", callable_mp(this, &TextShaderEditor::_script_validated));
+	code_editor->connect("script_validated", callable_mp(this, &TextShaderEditor::_script_validated));
 
-	shader_editor->set_v_size_flags(SIZE_EXPAND_FILL);
-	shader_editor->add_theme_constant_override("separation", 0);
-	shader_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
+	code_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+	code_editor->add_theme_constant_override("separation", 0);
+	code_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
 
-	shader_editor->connect("show_warnings_panel", callable_mp(this, &TextShaderEditor::_show_warnings_panel));
-	shader_editor->connect("script_changed", callable_mp(this, &TextShaderEditor::apply_shaders));
+	code_editor->connect("show_warnings_panel", callable_mp(this, &TextShaderEditor::_show_warnings_panel));
+	code_editor->connect("script_changed", callable_mp(this, &TextShaderEditor::apply_shaders));
 	EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &TextShaderEditor::_editor_settings_changed));
 	ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &TextShaderEditor::_project_settings_changed));
 
-	shader_editor->get_text_editor()->set_code_hint_draw_below(EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"));
-
-	shader_editor->get_text_editor()->set_symbol_lookup_on_click_enabled(true);
-	shader_editor->get_text_editor()->set_context_menu_enabled(false);
-	shader_editor->get_text_editor()->connect("gui_input", callable_mp(this, &TextShaderEditor::_text_edit_gui_input));
+	code_editor->get_text_editor()->set_symbol_lookup_on_click_enabled(true);
+	code_editor->get_text_editor()->set_context_menu_enabled(false);
+	code_editor->get_text_editor()->set_draw_breakpoints_gutter(false);
+	code_editor->get_text_editor()->set_draw_executing_lines_gutter(false);
+	code_editor->get_text_editor()->connect("gui_input", callable_mp(this, &TextShaderEditor::_text_edit_gui_input));
 
-	shader_editor->update_editor_settings();
+	code_editor->update_editor_settings();
 
 	context_menu = memnew(PopupMenu);
 	add_child(context_menu);
@@ -1184,12 +1186,12 @@ TextShaderEditor::TextShaderEditor() {
 	main_container->add_child(editor_box);
 	editor_box->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
 	editor_box->set_v_size_flags(SIZE_EXPAND_FILL);
-	editor_box->add_child(shader_editor);
+	editor_box->add_child(code_editor);
 
 	FindReplaceBar *bar = memnew(FindReplaceBar);
 	main_container->add_child(bar);
 	bar->hide();
-	shader_editor->set_find_replace_bar(bar);
+	code_editor->set_find_replace_bar(bar);
 
 	warnings_panel = memnew(RichTextLabel);
 	warnings_panel->set_custom_minimum_size(Size2(0, 100 * EDSCALE));
@@ -1201,7 +1203,7 @@ TextShaderEditor::TextShaderEditor() {
 	warnings_panel->hide();
 	warnings_panel->connect("meta_clicked", callable_mp(this, &TextShaderEditor::_warning_clicked));
 	editor_box->add_child(warnings_panel);
-	shader_editor->set_warnings_panel(warnings_panel);
+	code_editor->set_warnings_panel(warnings_panel);
 
 	goto_line_dialog = memnew(GotoLineDialog);
 	add_child(goto_line_dialog);
@@ -1221,8 +1223,6 @@ TextShaderEditor::TextShaderEditor() {
 	disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave");
 	disk_changed->connect("custom_action", callable_mp(this, &TextShaderEditor::save_external_data));
 
-	trim_trailing_whitespace_on_save = EDITOR_GET("text_editor/behavior/files/trim_trailing_whitespace_on_save");
-
 	add_child(disk_changed);
 
 	_editor_settings_changed();

+ 3 - 1
editor/plugins/text_shader_editor.h

@@ -148,7 +148,7 @@ class TextShaderEditor : public MarginContainer {
 	ConfirmationDialog *erase_tab_confirm = nullptr;
 	ConfirmationDialog *disk_changed = nullptr;
 
-	ShaderTextEditor *shader_editor = nullptr;
+	ShaderTextEditor *code_editor = nullptr;
 	bool compilation_success = true;
 
 	void _menu_option(int p_option);
@@ -156,6 +156,7 @@ class TextShaderEditor : public MarginContainer {
 	mutable Ref<ShaderInclude> shader_inc;
 
 	void _editor_settings_changed();
+	void _apply_editor_settings();
 	void _project_settings_changed();
 
 	void _check_for_external_edit();
@@ -197,6 +198,7 @@ public:
 	void validate_script();
 	bool is_unsaved() const;
 	void tag_saved_version();
+	ShaderTextEditor *get_code_editor() { return code_editor; }
 
 	virtual Size2 get_minimum_size() const override { return Size2(0, 200); }