Browse Source

Merge pull request #40973 from Paulb23/code_edit

Add CodeEdit and TextEdit gutter system
Rémi Verschelde 5 years ago
parent
commit
beb9ebcda0

+ 95 - 104
editor/code_editor.cpp

@@ -40,7 +40,7 @@
 #include "scene/gui/separator.h"
 #include "scene/gui/separator.h"
 #include "scene/resources/dynamic_font.h"
 #include "scene/resources/dynamic_font.h"
 
 
-void GotoLineDialog::popup_find_line(TextEdit *p_edit) {
+void GotoLineDialog::popup_find_line(CodeEdit *p_edit) {
 	text_editor = p_edit;
 	text_editor = p_edit;
 
 
 	line->set_text(itos(text_editor->cursor_get_line()));
 	line->set_text(itos(text_editor->cursor_get_line()));
@@ -113,7 +113,7 @@ void FindReplaceBar::_unhandled_input(const Ref<InputEvent> &p_event) {
 	}
 	}
 
 
 	Control *focus_owner = get_focus_owner();
 	Control *focus_owner = get_focus_owner();
-	if (text_edit->has_focus() || (focus_owner && vbc_lineedit->is_a_parent_of(focus_owner))) {
+	if (text_editor->has_focus() || (focus_owner && vbc_lineedit->is_a_parent_of(focus_owner))) {
 		bool accepted = true;
 		bool accepted = true;
 
 
 		switch (k->get_keycode()) {
 		switch (k->get_keycode()) {
@@ -135,20 +135,20 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col)
 	int line, col;
 	int line, col;
 	String text = get_search_text();
 	String text = get_search_text();
 
 
-	bool found = text_edit->search(text, p_flags, p_from_line, p_from_col, line, col);
+	bool found = text_editor->search(text, p_flags, p_from_line, p_from_col, line, col);
 
 
 	if (found) {
 	if (found) {
 		if (!preserve_cursor) {
 		if (!preserve_cursor) {
-			text_edit->unfold_line(line);
-			text_edit->cursor_set_line(line, false);
-			text_edit->cursor_set_column(col + text.length(), false);
-			text_edit->center_viewport_to_cursor();
-			text_edit->select(line, col, line, col + text.length());
+			text_editor->unfold_line(line);
+			text_editor->cursor_set_line(line, false);
+			text_editor->cursor_set_column(col + text.length(), false);
+			text_editor->center_viewport_to_cursor();
+			text_editor->select(line, col, line, col + text.length());
 		}
 		}
 
 
-		text_edit->set_search_text(text);
-		text_edit->set_search_flags(p_flags);
-		text_edit->set_current_search_result(line, col);
+		text_editor->set_search_text(text);
+		text_editor->set_search_flags(p_flags);
+		text_editor->set_current_search_result(line, col);
 
 
 		result_line = line;
 		result_line = line;
 		result_col = col;
 		result_col = col;
@@ -158,9 +158,9 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col)
 		results_count = 0;
 		results_count = 0;
 		result_line = -1;
 		result_line = -1;
 		result_col = -1;
 		result_col = -1;
-		text_edit->set_search_text("");
-		text_edit->set_search_flags(p_flags);
-		text_edit->set_current_search_result(line, col);
+		text_editor->set_search_text("");
+		text_editor->set_search_flags(p_flags);
+		text_editor->set_current_search_result(line, col);
 	}
 	}
 
 
 	_update_matches_label();
 	_update_matches_label();
@@ -169,67 +169,67 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col)
 }
 }
 
 
 void FindReplaceBar::_replace() {
 void FindReplaceBar::_replace() {
-	bool selection_enabled = text_edit->is_selection_active();
+	bool selection_enabled = text_editor->is_selection_active();
 	Point2i selection_begin, selection_end;
 	Point2i selection_begin, selection_end;
 	if (selection_enabled) {
 	if (selection_enabled) {
-		selection_begin = Point2i(text_edit->get_selection_from_line(), text_edit->get_selection_from_column());
-		selection_end = Point2i(text_edit->get_selection_to_line(), text_edit->get_selection_to_column());
+		selection_begin = Point2i(text_editor->get_selection_from_line(), text_editor->get_selection_from_column());
+		selection_end = Point2i(text_editor->get_selection_to_line(), text_editor->get_selection_to_column());
 	}
 	}
 
 
 	String replace_text = get_replace_text();
 	String replace_text = get_replace_text();
 	int search_text_len = get_search_text().length();
 	int search_text_len = get_search_text().length();
 
 
-	text_edit->begin_complex_operation();
+	text_editor->begin_complex_operation();
 	if (selection_enabled && is_selection_only()) { // To restrict search_current() to selected region
 	if (selection_enabled && is_selection_only()) { // To restrict search_current() to selected region
-		text_edit->cursor_set_line(selection_begin.width);
-		text_edit->cursor_set_column(selection_begin.height);
+		text_editor->cursor_set_line(selection_begin.width);
+		text_editor->cursor_set_column(selection_begin.height);
 	}
 	}
 
 
 	if (search_current()) {
 	if (search_current()) {
-		text_edit->unfold_line(result_line);
-		text_edit->select(result_line, result_col, result_line, result_col + search_text_len);
+		text_editor->unfold_line(result_line);
+		text_editor->select(result_line, result_col, result_line, result_col + search_text_len);
 
 
 		if (selection_enabled && is_selection_only()) {
 		if (selection_enabled && is_selection_only()) {
 			Point2i match_from(result_line, result_col);
 			Point2i match_from(result_line, result_col);
 			Point2i match_to(result_line, result_col + search_text_len);
 			Point2i match_to(result_line, result_col + search_text_len);
 			if (!(match_from < selection_begin || match_to > selection_end)) {
 			if (!(match_from < selection_begin || match_to > selection_end)) {
-				text_edit->insert_text_at_cursor(replace_text);
+				text_editor->insert_text_at_cursor(replace_text);
 				if (match_to.x == selection_end.x) { // Adjust selection bounds if necessary
 				if (match_to.x == selection_end.x) { // Adjust selection bounds if necessary
 					selection_end.y += replace_text.length() - search_text_len;
 					selection_end.y += replace_text.length() - search_text_len;
 				}
 				}
 			}
 			}
 		} else {
 		} else {
-			text_edit->insert_text_at_cursor(replace_text);
+			text_editor->insert_text_at_cursor(replace_text);
 		}
 		}
 	}
 	}
-	text_edit->end_complex_operation();
+	text_editor->end_complex_operation();
 	results_count = -1;
 	results_count = -1;
 
 
 	if (selection_enabled && is_selection_only()) {
 	if (selection_enabled && is_selection_only()) {
 		// Reselect in order to keep 'Replace' restricted to selection
 		// Reselect in order to keep 'Replace' restricted to selection
-		text_edit->select(selection_begin.x, selection_begin.y, selection_end.x, selection_end.y);
+		text_editor->select(selection_begin.x, selection_begin.y, selection_end.x, selection_end.y);
 	} else {
 	} else {
-		text_edit->deselect();
+		text_editor->deselect();
 	}
 	}
 }
 }
 
 
 void FindReplaceBar::_replace_all() {
 void FindReplaceBar::_replace_all() {
-	text_edit->disconnect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed));
+	text_editor->disconnect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed));
 	// Line as x so it gets priority in comparison, column as y.
 	// Line as x so it gets priority in comparison, column as y.
-	Point2i orig_cursor(text_edit->cursor_get_line(), text_edit->cursor_get_column());
+	Point2i orig_cursor(text_editor->cursor_get_line(), text_editor->cursor_get_column());
 	Point2i prev_match = Point2(-1, -1);
 	Point2i prev_match = Point2(-1, -1);
 
 
-	bool selection_enabled = text_edit->is_selection_active();
+	bool selection_enabled = text_editor->is_selection_active();
 	Point2i selection_begin, selection_end;
 	Point2i selection_begin, selection_end;
 	if (selection_enabled) {
 	if (selection_enabled) {
-		selection_begin = Point2i(text_edit->get_selection_from_line(), text_edit->get_selection_from_column());
-		selection_end = Point2i(text_edit->get_selection_to_line(), text_edit->get_selection_to_column());
+		selection_begin = Point2i(text_editor->get_selection_from_line(), text_editor->get_selection_from_column());
+		selection_end = Point2i(text_editor->get_selection_to_line(), text_editor->get_selection_to_column());
 	}
 	}
 
 
-	int vsval = text_edit->get_v_scroll();
+	int vsval = text_editor->get_v_scroll();
 
 
-	text_edit->cursor_set_line(0);
-	text_edit->cursor_set_column(0);
+	text_editor->cursor_set_line(0);
+	text_editor->cursor_set_column(0);
 
 
 	String replace_text = get_replace_text();
 	String replace_text = get_replace_text();
 	int search_text_len = get_search_text().length();
 	int search_text_len = get_search_text().length();
@@ -238,11 +238,11 @@ void FindReplaceBar::_replace_all() {
 
 
 	replace_all_mode = true;
 	replace_all_mode = true;
 
 
-	text_edit->begin_complex_operation();
+	text_editor->begin_complex_operation();
 
 
 	if (selection_enabled && is_selection_only()) {
 	if (selection_enabled && is_selection_only()) {
-		text_edit->cursor_set_line(selection_begin.width);
-		text_edit->cursor_set_column(selection_begin.height);
+		text_editor->cursor_set_line(selection_begin.width);
+		text_editor->cursor_set_column(selection_begin.height);
 	}
 	}
 	if (search_current()) {
 	if (search_current()) {
 		do {
 		do {
@@ -256,8 +256,8 @@ void FindReplaceBar::_replace_all() {
 
 
 			prev_match = Point2i(result_line, result_col + replace_text.length());
 			prev_match = Point2i(result_line, result_col + replace_text.length());
 
 
-			text_edit->unfold_line(result_line);
-			text_edit->select(result_line, result_col, result_line, match_to.y);
+			text_editor->unfold_line(result_line);
+			text_editor->select(result_line, result_col, result_line, match_to.y);
 
 
 			if (selection_enabled && is_selection_only()) {
 			if (selection_enabled && is_selection_only()) {
 				if (match_from < selection_begin || match_to > selection_end) {
 				if (match_from < selection_begin || match_to > selection_end) {
@@ -265,48 +265,48 @@ void FindReplaceBar::_replace_all() {
 				}
 				}
 
 
 				// Replace but adjust selection bounds.
 				// Replace but adjust selection bounds.
-				text_edit->insert_text_at_cursor(replace_text);
+				text_editor->insert_text_at_cursor(replace_text);
 				if (match_to.x == selection_end.x) {
 				if (match_to.x == selection_end.x) {
 					selection_end.y += replace_text.length() - search_text_len;
 					selection_end.y += replace_text.length() - search_text_len;
 				}
 				}
 
 
 			} else {
 			} else {
 				// Just replace.
 				// Just replace.
-				text_edit->insert_text_at_cursor(replace_text);
+				text_editor->insert_text_at_cursor(replace_text);
 			}
 			}
 
 
 			rc++;
 			rc++;
 		} while (search_next());
 		} while (search_next());
 	}
 	}
 
 
-	text_edit->end_complex_operation();
+	text_editor->end_complex_operation();
 
 
 	replace_all_mode = false;
 	replace_all_mode = false;
 
 
 	// Restore editor state (selection, cursor, scroll).
 	// Restore editor state (selection, cursor, scroll).
-	text_edit->cursor_set_line(orig_cursor.x);
-	text_edit->cursor_set_column(orig_cursor.y);
+	text_editor->cursor_set_line(orig_cursor.x);
+	text_editor->cursor_set_column(orig_cursor.y);
 
 
 	if (selection_enabled && is_selection_only()) {
 	if (selection_enabled && is_selection_only()) {
 		// Reselect.
 		// Reselect.
-		text_edit->select(selection_begin.x, selection_begin.y, selection_end.x, selection_end.y);
+		text_editor->select(selection_begin.x, selection_begin.y, selection_end.x, selection_end.y);
 	} else {
 	} else {
-		text_edit->deselect();
+		text_editor->deselect();
 	}
 	}
 
 
-	text_edit->set_v_scroll(vsval);
+	text_editor->set_v_scroll(vsval);
 	matches_label->add_theme_color_override("font_color", rc > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor"));
 	matches_label->add_theme_color_override("font_color", rc > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor"));
 	matches_label->set_text(vformat(TTR("%d replaced."), rc));
 	matches_label->set_text(vformat(TTR("%d replaced."), rc));
 
 
-	text_edit->call_deferred("connect", "text_changed", Callable(this, "_editor_text_changed"));
+	text_editor->call_deferred("connect", "text_changed", Callable(this, "_editor_text_changed"));
 	results_count = -1;
 	results_count = -1;
 }
 }
 
 
 void FindReplaceBar::_get_search_from(int &r_line, int &r_col) {
 void FindReplaceBar::_get_search_from(int &r_line, int &r_col) {
-	r_line = text_edit->cursor_get_line();
-	r_col = text_edit->cursor_get_column();
+	r_line = text_editor->cursor_get_line();
+	r_col = text_editor->cursor_get_column();
 
 
-	if (text_edit->is_selection_active() && is_selection_only()) {
+	if (text_editor->is_selection_active() && is_selection_only()) {
 		return;
 		return;
 	}
 	}
 
 
@@ -327,7 +327,7 @@ void FindReplaceBar::_update_results_count() {
 		return;
 		return;
 	}
 	}
 
 
-	String full_text = text_edit->get_text();
+	String full_text = text_editor->get_text();
 
 
 	int from_pos = 0;
 	int from_pos = 0;
 
 
@@ -399,7 +399,7 @@ bool FindReplaceBar::search_prev() {
 
 
 	int line, col;
 	int line, col;
 	_get_search_from(line, col);
 	_get_search_from(line, col);
-	if (text_edit->is_selection_active()) {
+	if (text_editor->is_selection_active()) {
 		col--; // Skip currently selected word.
 		col--; // Skip currently selected word.
 	}
 	}
 
 
@@ -407,9 +407,9 @@ bool FindReplaceBar::search_prev() {
 	if (col < 0) {
 	if (col < 0) {
 		line -= 1;
 		line -= 1;
 		if (line < 0) {
 		if (line < 0) {
-			line = text_edit->get_line_count() - 1;
+			line = text_editor->get_line_count() - 1;
 		}
 		}
-		col = text_edit->get_line(line).length();
+		col = text_editor->get_line(line).length();
 	}
 	}
 
 
 	return _search(flags, line, col);
 	return _search(flags, line, col);
@@ -440,9 +440,9 @@ bool FindReplaceBar::search_next() {
 
 
 	if (line == result_line && col == result_col) {
 	if (line == result_line && col == result_col) {
 		col += text.length();
 		col += text.length();
-		if (col > text_edit->get_line(line).length()) {
+		if (col > text_editor->get_line(line).length()) {
 			line += 1;
 			line += 1;
-			if (line >= text_edit->get_line_count()) {
+			if (line >= text_editor->get_line_count()) {
 				line = 0;
 				line = 0;
 			}
 			}
 			col = 0;
 			col = 0;
@@ -454,10 +454,10 @@ bool FindReplaceBar::search_next() {
 
 
 void FindReplaceBar::_hide_bar() {
 void FindReplaceBar::_hide_bar() {
 	if (replace_text->has_focus() || search_text->has_focus()) {
 	if (replace_text->has_focus() || search_text->has_focus()) {
-		text_edit->grab_focus();
+		text_editor->grab_focus();
 	}
 	}
 
 
-	text_edit->set_search_text("");
+	text_editor->set_search_text("");
 	result_line = -1;
 	result_line = -1;
 	result_col = -1;
 	result_col = -1;
 	hide();
 	hide();
@@ -477,8 +477,8 @@ void FindReplaceBar::_show_search(bool p_focus_replace, bool p_show_only) {
 		search_text->call_deferred("grab_focus");
 		search_text->call_deferred("grab_focus");
 	}
 	}
 
 
-	if (text_edit->is_selection_active() && !selection_only->is_pressed()) {
-		search_text->set_text(text_edit->get_selection_text());
+	if (text_editor->is_selection_active() && !selection_only->is_pressed()) {
+		search_text->set_text(text_editor->get_selection_text());
 	}
 	}
 
 
 	if (!get_search_text().empty()) {
 	if (!get_search_text().empty()) {
@@ -511,9 +511,9 @@ void FindReplaceBar::popup_replace() {
 		hbc_option_replace->show();
 		hbc_option_replace->show();
 	}
 	}
 
 
-	selection_only->set_pressed((text_edit->is_selection_active() && text_edit->get_selection_from_line() < text_edit->get_selection_to_line()));
+	selection_only->set_pressed((text_editor->is_selection_active() && text_editor->get_selection_from_line() < text_editor->get_selection_to_line()));
 
 
-	_show_search(is_visible() || text_edit->is_selection_active());
+	_show_search(is_visible() || text_editor->is_selection_active());
 }
 }
 
 
 void FindReplaceBar::_search_options_changed(bool p_pressed) {
 void FindReplaceBar::_search_options_changed(bool p_pressed) {
@@ -544,7 +544,7 @@ void FindReplaceBar::_search_text_entered(const String &p_text) {
 }
 }
 
 
 void FindReplaceBar::_replace_text_entered(const String &p_text) {
 void FindReplaceBar::_replace_text_entered(const String &p_text) {
-	if (selection_only->is_pressed() && text_edit->is_selection_active()) {
+	if (selection_only->is_pressed() && text_editor->is_selection_active()) {
 		_replace_all();
 		_replace_all();
 		_hide_bar();
 		_hide_bar();
 	} else if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
 	} else if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
@@ -579,10 +579,10 @@ void FindReplaceBar::set_error(const String &p_label) {
 	emit_signal("error", p_label);
 	emit_signal("error", p_label);
 }
 }
 
 
-void FindReplaceBar::set_text_edit(TextEdit *p_text_edit) {
+void FindReplaceBar::set_text_edit(CodeEdit *p_text_edit) {
 	results_count = -1;
 	results_count = -1;
-	text_edit = p_text_edit;
-	text_edit->connect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed));
+	text_editor = p_text_edit;
+	text_editor->connect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed));
 }
 }
 
 
 void FindReplaceBar::_bind_methods() {
 void FindReplaceBar::_bind_methods() {
@@ -932,11 +932,9 @@ void CodeTextEditor::update_editor_settings() {
 	text_editor->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/navigation/v_scroll_speed"));
 	text_editor->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/navigation/v_scroll_speed"));
 	text_editor->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/navigation/show_minimap"));
 	text_editor->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/navigation/show_minimap"));
 	text_editor->set_minimap_width((int)EditorSettings::get_singleton()->get("text_editor/navigation/minimap_width") * EDSCALE);
 	text_editor->set_minimap_width((int)EditorSettings::get_singleton()->get("text_editor/navigation/minimap_width") * EDSCALE);
-	text_editor->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers"));
+	text_editor->set_draw_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers"));
 	text_editor->set_line_numbers_zero_padded(EditorSettings::get_singleton()->get("text_editor/appearance/line_numbers_zero_padded"));
 	text_editor->set_line_numbers_zero_padded(EditorSettings::get_singleton()->get("text_editor/appearance/line_numbers_zero_padded"));
-	text_editor->set_bookmark_gutter_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/show_bookmark_gutter"));
-	text_editor->set_breakpoint_gutter_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/show_breakpoint_gutter"));
-	text_editor->set_draw_info_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/show_info_gutter"));
+	text_editor->set_draw_bookmarks_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/show_bookmark_gutter"));
 	text_editor->set_hiding_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding"));
 	text_editor->set_hiding_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding"));
 	text_editor->set_draw_fold_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding"));
 	text_editor->set_draw_fold_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding"));
 	text_editor->set_wrap_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/word_wrap"));
 	text_editor->set_wrap_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/word_wrap"));
@@ -1390,11 +1388,11 @@ void CodeTextEditor::goto_line_centered(int p_line) {
 }
 }
 
 
 void CodeTextEditor::set_executing_line(int p_line) {
 void CodeTextEditor::set_executing_line(int p_line) {
-	text_editor->set_executing_line(p_line);
+	text_editor->set_line_as_executing(p_line, true);
 }
 }
 
 
 void CodeTextEditor::clear_executing_line() {
 void CodeTextEditor::clear_executing_line() {
-	text_editor->clear_executing_line();
+	text_editor->clear_executing_lines();
 }
 }
 
 
 Variant CodeTextEditor::get_edit_state() {
 Variant CodeTextEditor::get_edit_state() {
@@ -1405,8 +1403,8 @@ Variant CodeTextEditor::get_edit_state() {
 	state["column"] = text_editor->cursor_get_column();
 	state["column"] = text_editor->cursor_get_column();
 	state["row"] = text_editor->cursor_get_line();
 	state["row"] = text_editor->cursor_get_line();
 
 
-	state["selection"] = get_text_edit()->is_selection_active();
-	if (get_text_edit()->is_selection_active()) {
+	state["selection"] = get_text_editor()->is_selection_active();
+	if (get_text_editor()->is_selection_active()) {
 		state["selection_from_line"] = text_editor->get_selection_from_line();
 		state["selection_from_line"] = text_editor->get_selection_from_line();
 		state["selection_from_column"] = text_editor->get_selection_from_column();
 		state["selection_from_column"] = text_editor->get_selection_from_column();
 		state["selection_to_line"] = text_editor->get_selection_to_line();
 		state["selection_to_line"] = text_editor->get_selection_to_line();
@@ -1414,8 +1412,8 @@ Variant CodeTextEditor::get_edit_state() {
 	}
 	}
 
 
 	state["folded_lines"] = text_editor->get_folded_lines();
 	state["folded_lines"] = text_editor->get_folded_lines();
-	state["breakpoints"] = text_editor->get_breakpoints_array();
-	state["bookmarks"] = text_editor->get_bookmarks_array();
+	state["breakpoints"] = text_editor->get_breakpointed_lines();
+	state["bookmarks"] = text_editor->get_bookmarked_lines();
 
 
 	Ref<EditorSyntaxHighlighter> syntax_highlighter = text_editor->get_syntax_highlighter();
 	Ref<EditorSyntaxHighlighter> syntax_highlighter = text_editor->get_syntax_highlighter();
 	state["syntax_highlighter"] = syntax_highlighter->_get_name();
 	state["syntax_highlighter"] = syntax_highlighter->_get_name();
@@ -1453,7 +1451,7 @@ void CodeTextEditor::set_edit_state(const Variant &p_state) {
 	if (state.has("bookmarks")) {
 	if (state.has("bookmarks")) {
 		Array bookmarks = state["bookmarks"];
 		Array bookmarks = state["bookmarks"];
 		for (int i = 0; i < bookmarks.size(); i++) {
 		for (int i = 0; i < bookmarks.size(); i++) {
-			text_editor->set_line_as_bookmark(bookmarks[i], true);
+			text_editor->set_line_as_bookmarked(bookmarks[i], true);
 		}
 		}
 	}
 	}
 }
 }
@@ -1591,27 +1589,26 @@ void CodeTextEditor::set_warning_nb(int p_warning_nb) {
 
 
 void CodeTextEditor::toggle_bookmark() {
 void CodeTextEditor::toggle_bookmark() {
 	int line = text_editor->cursor_get_line();
 	int line = text_editor->cursor_get_line();
-	text_editor->set_line_as_bookmark(line, !text_editor->is_line_set_as_bookmark(line));
+	text_editor->set_line_as_bookmarked(line, !text_editor->is_line_bookmarked(line));
 }
 }
 
 
 void CodeTextEditor::goto_next_bookmark() {
 void CodeTextEditor::goto_next_bookmark() {
-	List<int> bmarks;
-	text_editor->get_bookmarks(&bmarks);
+	Array bmarks = text_editor->get_bookmarked_lines();
 	if (bmarks.size() <= 0) {
 	if (bmarks.size() <= 0) {
 		return;
 		return;
 	}
 	}
 
 
 	int line = text_editor->cursor_get_line();
 	int line = text_editor->cursor_get_line();
-	if (line >= bmarks[bmarks.size() - 1]) {
+	if (line >= (int)bmarks[bmarks.size() - 1]) {
 		text_editor->unfold_line(bmarks[0]);
 		text_editor->unfold_line(bmarks[0]);
 		text_editor->cursor_set_line(bmarks[0]);
 		text_editor->cursor_set_line(bmarks[0]);
 		text_editor->center_viewport_to_cursor();
 		text_editor->center_viewport_to_cursor();
 	} else {
 	} else {
-		for (List<int>::Element *E = bmarks.front(); E; E = E->next()) {
-			int bline = E->get();
-			if (bline > line) {
-				text_editor->unfold_line(bline);
-				text_editor->cursor_set_line(bline);
+		for (int i = 0; i < bmarks.size(); i++) {
+			int bmark_line = bmarks[i];
+			if (bmark_line > line) {
+				text_editor->unfold_line(bmark_line);
+				text_editor->cursor_set_line(bmark_line);
 				text_editor->center_viewport_to_cursor();
 				text_editor->center_viewport_to_cursor();
 				return;
 				return;
 			}
 			}
@@ -1620,23 +1617,22 @@ void CodeTextEditor::goto_next_bookmark() {
 }
 }
 
 
 void CodeTextEditor::goto_prev_bookmark() {
 void CodeTextEditor::goto_prev_bookmark() {
-	List<int> bmarks;
-	text_editor->get_bookmarks(&bmarks);
+	Array bmarks = text_editor->get_bookmarked_lines();
 	if (bmarks.size() <= 0) {
 	if (bmarks.size() <= 0) {
 		return;
 		return;
 	}
 	}
 
 
 	int line = text_editor->cursor_get_line();
 	int line = text_editor->cursor_get_line();
-	if (line <= bmarks[0]) {
+	if (line <= (int)bmarks[0]) {
 		text_editor->unfold_line(bmarks[bmarks.size() - 1]);
 		text_editor->unfold_line(bmarks[bmarks.size() - 1]);
 		text_editor->cursor_set_line(bmarks[bmarks.size() - 1]);
 		text_editor->cursor_set_line(bmarks[bmarks.size() - 1]);
 		text_editor->center_viewport_to_cursor();
 		text_editor->center_viewport_to_cursor();
 	} else {
 	} else {
-		for (List<int>::Element *E = bmarks.back(); E; E = E->prev()) {
-			int bline = E->get();
-			if (bline < line) {
-				text_editor->unfold_line(bline);
-				text_editor->cursor_set_line(bline);
+		for (int i = bmarks.size(); i >= 0; i--) {
+			int bmark_line = bmarks[i];
+			if (bmark_line < line) {
+				text_editor->unfold_line(bmark_line);
+				text_editor->cursor_set_line(bmark_line);
 				text_editor->center_viewport_to_cursor();
 				text_editor->center_viewport_to_cursor();
 				return;
 				return;
 			}
 			}
@@ -1645,12 +1641,7 @@ void CodeTextEditor::goto_prev_bookmark() {
 }
 }
 
 
 void CodeTextEditor::remove_all_bookmarks() {
 void CodeTextEditor::remove_all_bookmarks() {
-	List<int> bmarks;
-	text_editor->get_bookmarks(&bmarks);
-
-	for (List<int>::Element *E = bmarks.front(); E; E = E->next()) {
-		text_editor->set_line_as_bookmark(E->get(), false);
-	}
+	text_editor->clear_bookmarked_lines();
 }
 }
 
 
 void CodeTextEditor::_bind_methods() {
 void CodeTextEditor::_bind_methods() {
@@ -1681,7 +1672,7 @@ CodeTextEditor::CodeTextEditor() {
 	ED_SHORTCUT("script_editor/zoom_out", TTR("Zoom Out"), KEY_MASK_CMD | KEY_MINUS);
 	ED_SHORTCUT("script_editor/zoom_out", TTR("Zoom Out"), KEY_MASK_CMD | KEY_MINUS);
 	ED_SHORTCUT("script_editor/reset_zoom", TTR("Reset Zoom"), KEY_MASK_CMD | KEY_0);
 	ED_SHORTCUT("script_editor/reset_zoom", TTR("Reset Zoom"), KEY_MASK_CMD | KEY_0);
 
 
-	text_editor = memnew(TextEdit);
+	text_editor = memnew(CodeEdit);
 	add_child(text_editor);
 	add_child(text_editor);
 	text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
 	text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
 
 
@@ -1693,7 +1684,7 @@ CodeTextEditor::CodeTextEditor() {
 
 
 	find_replace_bar->set_text_edit(text_editor);
 	find_replace_bar->set_text_edit(text_editor);
 
 
-	text_editor->set_show_line_numbers(true);
+	text_editor->set_draw_line_numbers(true);
 	text_editor->set_brace_matching(true);
 	text_editor->set_brace_matching(true);
 	text_editor->set_auto_indent(true);
 	text_editor->set_auto_indent(true);
 
 

+ 8 - 8
editor/code_editor.h

@@ -34,9 +34,9 @@
 #include "editor/editor_plugin.h"
 #include "editor/editor_plugin.h"
 #include "scene/gui/check_box.h"
 #include "scene/gui/check_box.h"
 #include "scene/gui/check_button.h"
 #include "scene/gui/check_button.h"
+#include "scene/gui/code_edit.h"
 #include "scene/gui/dialogs.h"
 #include "scene/gui/dialogs.h"
 #include "scene/gui/line_edit.h"
 #include "scene/gui/line_edit.h"
-#include "scene/gui/text_edit.h"
 #include "scene/main/timer.h"
 #include "scene/main/timer.h"
 
 
 class GotoLineDialog : public ConfirmationDialog {
 class GotoLineDialog : public ConfirmationDialog {
@@ -45,15 +45,15 @@ class GotoLineDialog : public ConfirmationDialog {
 	Label *line_label;
 	Label *line_label;
 	LineEdit *line;
 	LineEdit *line;
 
 
-	TextEdit *text_editor;
+	CodeEdit *text_editor;
 
 
 	virtual void ok_pressed() override;
 	virtual void ok_pressed() override;
 
 
 public:
 public:
-	void popup_find_line(TextEdit *p_edit);
+	void popup_find_line(CodeEdit *p_edit);
 	int get_line() const;
 	int get_line() const;
 
 
-	void set_text_editor(TextEdit *p_text_editor);
+	void set_text_editor(CodeEdit *p_text_editor);
 	GotoLineDialog();
 	GotoLineDialog();
 };
 };
 
 
@@ -77,7 +77,7 @@ class FindReplaceBar : public HBoxContainer {
 	HBoxContainer *hbc_button_replace;
 	HBoxContainer *hbc_button_replace;
 	HBoxContainer *hbc_option_replace;
 	HBoxContainer *hbc_option_replace;
 
 
-	TextEdit *text_edit;
+	CodeEdit *text_editor;
 
 
 	int result_line;
 	int result_line;
 	int result_col;
 	int result_col;
@@ -120,7 +120,7 @@ public:
 	bool is_selection_only() const;
 	bool is_selection_only() const;
 	void set_error(const String &p_label);
 	void set_error(const String &p_label);
 
 
-	void set_text_edit(TextEdit *p_text_edit);
+	void set_text_edit(CodeEdit *p_text_edit);
 
 
 	void popup_search(bool p_show_only = false);
 	void popup_search(bool p_show_only = false);
 	void popup_replace();
 	void popup_replace();
@@ -137,7 +137,7 @@ typedef void (*CodeTextEditorCodeCompleteFunc)(void *p_ud, const String &p_code,
 class CodeTextEditor : public VBoxContainer {
 class CodeTextEditor : public VBoxContainer {
 	GDCLASS(CodeTextEditor, VBoxContainer);
 	GDCLASS(CodeTextEditor, VBoxContainer);
 
 
-	TextEdit *text_editor;
+	CodeEdit *text_editor;
 	FindReplaceBar *find_replace_bar;
 	FindReplaceBar *find_replace_bar;
 	HBoxContainer *status_bar;
 	HBoxContainer *status_bar;
 
 
@@ -240,7 +240,7 @@ public:
 	void set_error(const String &p_error);
 	void set_error(const String &p_error);
 	void set_error_pos(int p_line, int p_column);
 	void set_error_pos(int p_line, int p_column);
 	void update_line_and_column() { _line_col_changed(); }
 	void update_line_and_column() { _line_col_changed(); }
-	TextEdit *get_text_edit() { return text_editor; }
+	CodeEdit *get_text_editor() { return text_editor; }
 	FindReplaceBar *get_find_replace_bar() { return find_replace_bar; }
 	FindReplaceBar *get_find_replace_bar() { return find_replace_bar; }
 	virtual void apply_code() {}
 	virtual void apply_code() {}
 	void goto_error();
 	void goto_error();

+ 2 - 3
editor/editor_settings.cpp

@@ -445,7 +445,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 	_initial_set("text_editor/appearance/show_line_numbers", true);
 	_initial_set("text_editor/appearance/show_line_numbers", true);
 	_initial_set("text_editor/appearance/line_numbers_zero_padded", false);
 	_initial_set("text_editor/appearance/line_numbers_zero_padded", false);
 	_initial_set("text_editor/appearance/show_bookmark_gutter", true);
 	_initial_set("text_editor/appearance/show_bookmark_gutter", true);
-	_initial_set("text_editor/appearance/show_breakpoint_gutter", true);
 	_initial_set("text_editor/appearance/show_info_gutter", true);
 	_initial_set("text_editor/appearance/show_info_gutter", true);
 	_initial_set("text_editor/appearance/code_folding", true);
 	_initial_set("text_editor/appearance/code_folding", true);
 	_initial_set("text_editor/appearance/word_wrap", false);
 	_initial_set("text_editor/appearance/word_wrap", false);
@@ -707,8 +706,8 @@ void EditorSettings::_load_default_text_editor_theme() {
 	_initial_set("text_editor/highlighting/member_variable_color", Color(0.9, 0.31, 0.35));
 	_initial_set("text_editor/highlighting/member_variable_color", Color(0.9, 0.31, 0.35));
 	_initial_set("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4));
 	_initial_set("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4));
 	_initial_set("text_editor/highlighting/bookmark_color", Color(0.08, 0.49, 0.98));
 	_initial_set("text_editor/highlighting/bookmark_color", Color(0.08, 0.49, 0.98));
-	_initial_set("text_editor/highlighting/breakpoint_color", Color(0.8, 0.8, 0.4, 0.2));
-	_initial_set("text_editor/highlighting/executing_line_color", Color(0.2, 0.8, 0.2, 0.4));
+	_initial_set("text_editor/highlighting/breakpoint_color", Color(0.9, 0.29, 0.3));
+	_initial_set("text_editor/highlighting/executing_line_color", Color(0.98, 0.89, 0.27));
 	_initial_set("text_editor/highlighting/code_folding_color", Color(0.8, 0.8, 0.8, 0.8));
 	_initial_set("text_editor/highlighting/code_folding_color", Color(0.8, 0.8, 0.8, 0.8));
 	_initial_set("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1));
 	_initial_set("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1));
 	_initial_set("text_editor/highlighting/search_result_border_color", Color(0.41, 0.61, 0.91, 0.38));
 	_initial_set("text_editor/highlighting/search_result_border_color", Color(0.41, 0.61, 0.91, 0.38));

+ 15 - 3
editor/editor_themes.cpp

@@ -868,12 +868,24 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	theme->set_constant("side_margin", "TabContainer", 0);
 	theme->set_constant("side_margin", "TabContainer", 0);
 	theme->set_icon("tab", "TextEdit", theme->get_icon("GuiTab", "EditorIcons"));
 	theme->set_icon("tab", "TextEdit", theme->get_icon("GuiTab", "EditorIcons"));
 	theme->set_icon("space", "TextEdit", theme->get_icon("GuiSpace", "EditorIcons"));
 	theme->set_icon("space", "TextEdit", theme->get_icon("GuiSpace", "EditorIcons"));
-	theme->set_icon("folded", "TextEdit", theme->get_icon("GuiTreeArrowRight", "EditorIcons"));
-	theme->set_icon("fold", "TextEdit", theme->get_icon("GuiTreeArrowDown", "EditorIcons"));
 	theme->set_color("font_color", "TextEdit", font_color);
 	theme->set_color("font_color", "TextEdit", font_color);
 	theme->set_color("caret_color", "TextEdit", font_color);
 	theme->set_color("caret_color", "TextEdit", font_color);
 	theme->set_color("selection_color", "TextEdit", font_color_selection);
 	theme->set_color("selection_color", "TextEdit", font_color_selection);
 
 
+	// CodeEdit
+	theme->set_stylebox("normal", "CodeEdit", style_widget);
+	theme->set_stylebox("focus", "CodeEdit", style_widget_hover);
+	theme->set_stylebox("read_only", "CodeEdit", style_widget_disabled);
+	theme->set_constant("side_margin", "TabContainer", 0);
+	theme->set_icon("tab", "CodeEdit", theme->get_icon("GuiTab", "EditorIcons"));
+	theme->set_icon("space", "CodeEdit", theme->get_icon("GuiSpace", "EditorIcons"));
+	theme->set_icon("folded", "CodeEdit", theme->get_icon("GuiTreeArrowRight", "EditorIcons"));
+	theme->set_icon("can_fold", "CodeEdit", theme->get_icon("GuiTreeArrowDown", "EditorIcons"));
+	theme->set_icon("executing_line", "CodeEdit", theme->get_icon("MainPlay", "EditorIcons"));
+	theme->set_color("font_color", "CodeEdit", font_color);
+	theme->set_color("caret_color", "CodeEdit", font_color);
+	theme->set_color("selection_color", "CodeEdit", font_color_selection);
+
 	// H/VSplitContainer
 	// H/VSplitContainer
 	theme->set_stylebox("bg", "VSplitContainer", make_stylebox(theme->get_icon("GuiVsplitBg", "EditorIcons"), 1, 1, 1, 1));
 	theme->set_stylebox("bg", "VSplitContainer", make_stylebox(theme->get_icon("GuiVsplitBg", "EditorIcons"), 1, 1, 1, 1));
 	theme->set_stylebox("bg", "HSplitContainer", make_stylebox(theme->get_icon("GuiHsplitBg", "EditorIcons"), 1, 1, 1, 1));
 	theme->set_stylebox("bg", "HSplitContainer", make_stylebox(theme->get_icon("GuiHsplitBg", "EditorIcons"), 1, 1, 1, 1));
@@ -1179,7 +1191,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3);
 	const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3);
 	const Color bookmark_color = Color(0.08, 0.49, 0.98);
 	const Color bookmark_color = Color(0.08, 0.49, 0.98);
 	const Color breakpoint_color = error_color;
 	const Color breakpoint_color = error_color;
-	const Color executing_line_color = Color(0.2, 0.8, 0.2, 0.4);
+	const Color executing_line_color = Color(0.98, 0.89, 0.27);
 	const Color code_folding_color = alpha3;
 	const Color code_folding_color = alpha3;
 	const Color search_result_color = alpha1;
 	const Color search_result_color = alpha1;
 	const Color search_result_border_color = Color(0.41, 0.61, 0.91, 0.38);
 	const Color search_result_border_color = Color(0.41, 0.61, 0.91, 0.38);

+ 3 - 4
editor/plugins/script_editor_plugin.cpp

@@ -1585,15 +1585,14 @@ void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) {
 			continue;
 			continue;
 		}
 		}
 
 
-		List<int> bpoints;
-		se->get_breakpoints(&bpoints);
 		String base = script->get_path();
 		String base = script->get_path();
 		if (base.begins_with("local://") || base == "") {
 		if (base.begins_with("local://") || base == "") {
 			continue;
 			continue;
 		}
 		}
 
 
-		for (List<int>::Element *E = bpoints.front(); E; E = E->next()) {
-			p_breakpoints->push_back(base + ":" + itos(E->get() + 1));
+		Array bpoints = se->get_breakpoints();
+		for (int j = 0; j < bpoints.size(); j++) {
+			p_breakpoints->push_back(base + ":" + itos((int)bpoints[j] + 1));
 		}
 		}
 	}
 	}
 }
 }

+ 1 - 1
editor/plugins/script_editor_plugin.h

@@ -151,7 +151,7 @@ public:
 	virtual void ensure_focus() = 0;
 	virtual void ensure_focus() = 0;
 	virtual void tag_saved_version() = 0;
 	virtual void tag_saved_version() = 0;
 	virtual void reload(bool p_soft) {}
 	virtual void reload(bool p_soft) {}
-	virtual void get_breakpoints(List<int> *p_breakpoints) = 0;
+	virtual Array get_breakpoints() = 0;
 	virtual void add_callback(const String &p_function, PackedStringArray p_args) = 0;
 	virtual void add_callback(const String &p_function, PackedStringArray p_args) = 0;
 	virtual void update_settings() = 0;
 	virtual void update_settings() = 0;
 	virtual void set_debugger_active(bool p_active) = 0;
 	virtual void set_debugger_active(bool p_active) = 0;

+ 152 - 91
editor/plugins/script_text_editor.cpp

@@ -111,7 +111,7 @@ ConnectionInfoDialog::ConnectionInfoDialog() {
 Vector<String> ScriptTextEditor::get_functions() {
 Vector<String> ScriptTextEditor::get_functions() {
 	String errortxt;
 	String errortxt;
 	int line = -1, col;
 	int line = -1, col;
-	TextEdit *te = code_editor->get_text_edit();
+	CodeEdit *te = code_editor->get_text_editor();
 	String text = te->get_text();
 	String text = te->get_text();
 	List<String> fnc;
 	List<String> fnc;
 
 
@@ -130,9 +130,9 @@ void ScriptTextEditor::apply_code() {
 	if (script.is_null()) {
 	if (script.is_null()) {
 		return;
 		return;
 	}
 	}
-	script->set_source_code(code_editor->get_text_edit()->get_text());
+	script->set_source_code(code_editor->get_text_editor()->get_text());
 	script->update_exports();
 	script->update_exports();
-	code_editor->get_text_edit()->get_syntax_highlighter()->update_cache();
+	code_editor->get_text_editor()->get_syntax_highlighter()->update_cache();
 }
 }
 
 
 RES ScriptTextEditor::get_edited_resource() const {
 RES ScriptTextEditor::get_edited_resource() const {
@@ -145,9 +145,9 @@ void ScriptTextEditor::set_edited_resource(const RES &p_res) {
 
 
 	script = p_res;
 	script = p_res;
 
 
-	code_editor->get_text_edit()->set_text(script->get_source_code());
-	code_editor->get_text_edit()->clear_undo_history();
-	code_editor->get_text_edit()->tag_saved_version();
+	code_editor->get_text_editor()->set_text(script->get_source_code());
+	code_editor->get_text_editor()->clear_undo_history();
+	code_editor->get_text_editor()->tag_saved_version();
 
 
 	emit_signal("name_changed");
 	emit_signal("name_changed");
 	code_editor->update_line_and_column();
 	code_editor->update_line_and_column();
@@ -167,9 +167,19 @@ void ScriptTextEditor::enable_editor() {
 }
 }
 
 
 void ScriptTextEditor::_load_theme_settings() {
 void ScriptTextEditor::_load_theme_settings() {
-	TextEdit *text_edit = code_editor->get_text_edit();
+	CodeEdit *text_edit = code_editor->get_text_editor();
 	text_edit->clear_keywords();
 	text_edit->clear_keywords();
 
 
+	Color updated_safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color");
+	if (updated_safe_line_number_color != safe_line_number_color) {
+		safe_line_number_color = updated_safe_line_number_color;
+		for (int i = 0; i < text_edit->get_line_count(); i++) {
+			if (text_edit->get_line_gutter_item_color(i, line_number_gutter) != default_line_number_color) {
+				text_edit->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color);
+			}
+		}
+	}
+
 	Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
 	Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
 	Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
 	Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color");
 	Color completion_selected_color = EDITOR_GET("text_editor/highlighting/completion_selected_color");
 	Color completion_selected_color = EDITOR_GET("text_editor/highlighting/completion_selected_color");
@@ -178,7 +188,6 @@ void ScriptTextEditor::_load_theme_settings() {
 	Color completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color");
 	Color completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color");
 	Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
 	Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
 	Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color");
 	Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color");
-	Color safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color");
 	Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color");
 	Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color");
 	Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color");
 	Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color");
 	Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color");
 	Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color");
@@ -203,7 +212,6 @@ void ScriptTextEditor::_load_theme_settings() {
 	text_edit->add_theme_color_override("completion_font_color", completion_font_color);
 	text_edit->add_theme_color_override("completion_font_color", completion_font_color);
 	text_edit->add_theme_color_override("font_color", text_color);
 	text_edit->add_theme_color_override("font_color", text_color);
 	text_edit->add_theme_color_override("line_number_color", line_number_color);
 	text_edit->add_theme_color_override("line_number_color", line_number_color);
-	text_edit->add_theme_color_override("safe_line_number_color", safe_line_number_color);
 	text_edit->add_theme_color_override("caret_color", caret_color);
 	text_edit->add_theme_color_override("caret_color", caret_color);
 	text_edit->add_theme_color_override("caret_background_color", caret_background_color);
 	text_edit->add_theme_color_override("caret_background_color", caret_background_color);
 	text_edit->add_theme_color_override("font_color_selected", text_selected_color);
 	text_edit->add_theme_color_override("font_color_selected", text_selected_color);
@@ -233,7 +241,7 @@ void ScriptTextEditor::_set_theme_for_script() {
 		return;
 		return;
 	}
 	}
 
 
-	TextEdit *text_edit = code_editor->get_text_edit();
+	CodeEdit *text_edit = code_editor->get_text_editor();
 	text_edit->get_syntax_highlighter()->update_cache();
 	text_edit->get_syntax_highlighter()->update_cache();
 
 
 	/* add keywords for auto completion */
 	/* add keywords for auto completion */
@@ -284,10 +292,10 @@ void ScriptTextEditor::_show_warnings_panel(bool p_show) {
 
 
 void ScriptTextEditor::_warning_clicked(Variant p_line) {
 void ScriptTextEditor::_warning_clicked(Variant p_line) {
 	if (p_line.get_type() == Variant::INT) {
 	if (p_line.get_type() == Variant::INT) {
-		code_editor->get_text_edit()->cursor_set_line(p_line.operator int64_t());
+		code_editor->get_text_editor()->cursor_set_line(p_line.operator int64_t());
 	} else if (p_line.get_type() == Variant::DICTIONARY) {
 	} else if (p_line.get_type() == Variant::DICTIONARY) {
 		Dictionary meta = p_line.operator Dictionary();
 		Dictionary meta = p_line.operator Dictionary();
-		code_editor->get_text_edit()->insert_at("# warning-ignore:" + meta["code"].operator String(), meta["line"].operator int64_t() - 1);
+		code_editor->get_text_editor()->insert_at("# warning-ignore:" + meta["code"].operator String(), meta["line"].operator int64_t() - 1);
 		_validate_script();
 		_validate_script();
 	}
 	}
 }
 }
@@ -295,7 +303,7 @@ void ScriptTextEditor::_warning_clicked(Variant p_line) {
 void ScriptTextEditor::reload_text() {
 void ScriptTextEditor::reload_text() {
 	ERR_FAIL_COND(script.is_null());
 	ERR_FAIL_COND(script.is_null());
 
 
-	TextEdit *te = code_editor->get_text_edit();
+	CodeEdit *te = code_editor->get_text_editor();
 	int column = te->cursor_get_column();
 	int column = te->cursor_get_column();
 	int row = te->cursor_get_line();
 	int row = te->cursor_get_line();
 	int h = te->get_h_scroll();
 	int h = te->get_h_scroll();
@@ -313,20 +321,20 @@ void ScriptTextEditor::reload_text() {
 }
 }
 
 
 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_editor()->get_text();
 	int pos = script->get_language()->find_function(p_function, code);
 	int pos = script->get_language()->find_function(p_function, code);
 	if (pos == -1) {
 	if (pos == -1) {
 		//does not exist
 		//does not exist
-		code_editor->get_text_edit()->deselect();
-		pos = code_editor->get_text_edit()->get_line_count() + 2;
+		code_editor->get_text_editor()->deselect();
+		pos = code_editor->get_text_editor()->get_line_count() + 2;
 		String func = script->get_language()->make_function("", p_function, p_args);
 		String func = script->get_language()->make_function("", p_function, p_args);
 		//code=code+func;
 		//code=code+func;
-		code_editor->get_text_edit()->cursor_set_line(pos + 1);
-		code_editor->get_text_edit()->cursor_set_column(1000000); //none shall be that big
-		code_editor->get_text_edit()->insert_text_at_cursor("\n\n" + func);
+		code_editor->get_text_editor()->cursor_set_line(pos + 1);
+		code_editor->get_text_editor()->cursor_set_column(1000000); //none shall be that big
+		code_editor->get_text_editor()->insert_text_at_cursor("\n\n" + func);
 	}
 	}
-	code_editor->get_text_edit()->cursor_set_line(pos);
-	code_editor->get_text_edit()->cursor_set_column(1);
+	code_editor->get_text_editor()->cursor_set_line(pos);
+	code_editor->get_text_editor()->cursor_set_column(1);
 }
 }
 
 
 bool ScriptTextEditor::show_members_overview() {
 bool ScriptTextEditor::show_members_overview() {
@@ -334,12 +342,13 @@ bool ScriptTextEditor::show_members_overview() {
 }
 }
 
 
 void ScriptTextEditor::update_settings() {
 void ScriptTextEditor::update_settings() {
+	code_editor->get_text_editor()->set_gutter_draw(connection_gutter, EditorSettings::get_singleton()->get("text_editor/appearance/show_info_gutter"));
 	code_editor->update_editor_settings();
 	code_editor->update_editor_settings();
 }
 }
 
 
 bool ScriptTextEditor::is_unsaved() {
 bool ScriptTextEditor::is_unsaved() {
 	const bool unsaved =
 	const bool unsaved =
-			code_editor->get_text_edit()->get_version() != code_editor->get_text_edit()->get_saved_version() ||
+			code_editor->get_text_editor()->get_version() != code_editor->get_text_editor()->get_saved_version() ||
 			script->get_path().empty(); // In memory.
 			script->get_path().empty(); // In memory.
 	return unsaved;
 	return unsaved;
 }
 }
@@ -385,7 +394,7 @@ void ScriptTextEditor::convert_indent_to_tabs() {
 }
 }
 
 
 void ScriptTextEditor::tag_saved_version() {
 void ScriptTextEditor::tag_saved_version() {
-	code_editor->get_text_edit()->tag_saved_version();
+	code_editor->get_text_editor()->tag_saved_version();
 }
 }
 
 
 void ScriptTextEditor::goto_line(int p_line, bool p_with_error) {
 void ScriptTextEditor::goto_line(int p_line, bool p_with_error) {
@@ -409,7 +418,7 @@ void ScriptTextEditor::clear_executing_line() {
 }
 }
 
 
 void ScriptTextEditor::ensure_focus() {
 void ScriptTextEditor::ensure_focus() {
-	code_editor->get_text_edit()->grab_focus();
+	code_editor->get_text_editor()->grab_focus();
 }
 }
 
 
 String ScriptTextEditor::get_name() {
 String ScriptTextEditor::get_name() {
@@ -443,7 +452,7 @@ Ref<Texture2D> ScriptTextEditor::get_theme_icon() {
 void ScriptTextEditor::_validate_script() {
 void ScriptTextEditor::_validate_script() {
 	String errortxt;
 	String errortxt;
 	int line = -1, col;
 	int line = -1, col;
-	TextEdit *te = code_editor->get_text_edit();
+	CodeEdit *te = code_editor->get_text_editor();
 
 
 	String text = te->get_text();
 	String text = te->get_text();
 	List<String> fnc;
 	List<String> fnc;
@@ -540,16 +549,16 @@ void ScriptTextEditor::_validate_script() {
 		te->set_line_as_marked(i, line == i);
 		te->set_line_as_marked(i, line == i);
 		if (highlight_safe) {
 		if (highlight_safe) {
 			if (safe_lines.has(i + 1)) {
 			if (safe_lines.has(i + 1)) {
-				te->set_line_as_safe(i, true);
+				te->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color);
 				last_is_safe = true;
 				last_is_safe = true;
 			} else if (last_is_safe && (te->is_line_comment(i) || te->get_line(i).strip_edges().empty())) {
 			} else if (last_is_safe && (te->is_line_comment(i) || te->get_line(i).strip_edges().empty())) {
-				te->set_line_as_safe(i, true);
+				te->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color);
 			} else {
 			} else {
-				te->set_line_as_safe(i, false);
+				te->set_line_gutter_item_color(i, line_number_gutter, default_line_number_color);
 				last_is_safe = false;
 				last_is_safe = false;
 			}
 			}
 		} else {
 		} else {
-			te->set_line_as_safe(i, false);
+			te->set_line_gutter_item_color(line, 1, default_line_number_color);
 		}
 		}
 	}
 	}
 
 
@@ -566,7 +575,7 @@ void ScriptTextEditor::_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_next_bookmark"), BOOKMARK_GOTO_NEXT);
 	bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV);
 	bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV);
 
 
-	Array bookmark_list = code_editor->get_text_edit()->get_bookmarks_array();
+	Array bookmark_list = code_editor->get_text_editor()->get_bookmarked_lines();
 	if (bookmark_list.size() == 0) {
 	if (bookmark_list.size() == 0) {
 		return;
 		return;
 	}
 	}
@@ -576,7 +585,7 @@ void ScriptTextEditor::_update_bookmark_list() {
 	for (int i = 0; i < bookmark_list.size(); i++) {
 	for (int i = 0; i < bookmark_list.size(); i++) {
 		// Strip edges to remove spaces or tabs.
 		// Strip edges to remove spaces or tabs.
 		// Also replace any tabs by spaces, since we can't print tabs in the menu.
 		// Also replace any tabs by spaces, since we can't print tabs in the menu.
-		String line = code_editor->get_text_edit()->get_line(bookmark_list[i]).replace("\t", "  ").strip_edges();
+		String line = code_editor->get_text_editor()->get_line(bookmark_list[i]).replace("\t", "  ").strip_edges();
 
 
 		// Limit the size of the line if too big.
 		// Limit the size of the line if too big.
 		if (line.length() > 50) {
 		if (line.length() > 50) {
@@ -593,7 +602,7 @@ void ScriptTextEditor::_bookmark_item_pressed(int p_idx) {
 		_edit_option(bookmarks_menu->get_item_id(p_idx));
 		_edit_option(bookmarks_menu->get_item_id(p_idx));
 	} else {
 	} else {
 		code_editor->goto_line(bookmarks_menu->get_item_metadata(p_idx));
 		code_editor->goto_line(bookmarks_menu->get_item_metadata(p_idx));
-		code_editor->get_text_edit()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred().
+		code_editor->get_text_editor()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred().
 	}
 	}
 }
 }
 
 
@@ -704,7 +713,7 @@ void ScriptTextEditor::_code_complete_script(const String &p_code, List<ScriptCo
 	String hint;
 	String hint;
 	Error err = script->get_language()->complete_code(p_code, script->get_path(), base, r_options, r_force, hint);
 	Error err = script->get_language()->complete_code(p_code, script->get_path(), base, r_options, r_force, hint);
 	if (err == OK) {
 	if (err == OK) {
-		code_editor->get_text_edit()->set_code_hint(hint);
+		code_editor->get_text_editor()->set_code_hint(hint);
 	}
 	}
 }
 }
 
 
@@ -717,7 +726,7 @@ void ScriptTextEditor::_update_breakpoint_list() {
 	breakpoints_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_breakpoint"), DEBUG_GOTO_NEXT_BREAKPOINT);
 	breakpoints_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_breakpoint"), DEBUG_GOTO_NEXT_BREAKPOINT);
 	breakpoints_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_breakpoint"), DEBUG_GOTO_PREV_BREAKPOINT);
 	breakpoints_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_breakpoint"), DEBUG_GOTO_PREV_BREAKPOINT);
 
 
-	Array breakpoint_list = code_editor->get_text_edit()->get_breakpoints_array();
+	Array breakpoint_list = code_editor->get_text_editor()->get_breakpointed_lines();
 	if (breakpoint_list.size() == 0) {
 	if (breakpoint_list.size() == 0) {
 		return;
 		return;
 	}
 	}
@@ -727,7 +736,7 @@ void ScriptTextEditor::_update_breakpoint_list() {
 	for (int i = 0; i < breakpoint_list.size(); i++) {
 	for (int i = 0; i < breakpoint_list.size(); i++) {
 		// Strip edges to remove spaces or tabs.
 		// Strip edges to remove spaces or tabs.
 		// Also replace any tabs by spaces, since we can't print tabs in the menu.
 		// Also replace any tabs by spaces, since we can't print tabs in the menu.
-		String line = code_editor->get_text_edit()->get_line(breakpoint_list[i]).replace("\t", "  ").strip_edges();
+		String line = code_editor->get_text_editor()->get_line(breakpoint_list[i]).replace("\t", "  ").strip_edges();
 
 
 		// Limit the size of the line if too big.
 		// Limit the size of the line if too big.
 		if (line.length() > 50) {
 		if (line.length() > 50) {
@@ -744,12 +753,12 @@ void ScriptTextEditor::_breakpoint_item_pressed(int p_idx) {
 		_edit_option(breakpoints_menu->get_item_id(p_idx));
 		_edit_option(breakpoints_menu->get_item_id(p_idx));
 	} else {
 	} else {
 		code_editor->goto_line(breakpoints_menu->get_item_metadata(p_idx));
 		code_editor->goto_line(breakpoints_menu->get_item_metadata(p_idx));
-		code_editor->get_text_edit()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred().
+		code_editor->get_text_editor()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred().
 	}
 	}
 }
 }
 
 
 void ScriptTextEditor::_breakpoint_toggled(int p_row) {
 void ScriptTextEditor::_breakpoint_toggled(int p_row) {
-	EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), p_row + 1, code_editor->get_text_edit()->is_line_set_as_breakpoint(p_row));
+	EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), p_row + 1, code_editor->get_text_editor()->is_line_breakpointed(p_row));
 }
 }
 
 
 void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_column) {
 void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_column) {
@@ -771,7 +780,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
 			EditorNode::get_singleton()->load_resource(p_symbol);
 			EditorNode::get_singleton()->load_resource(p_symbol);
 		}
 		}
 
 
-	} else if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK) {
+	} else if (script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK) {
 		_goto_line(p_row);
 		_goto_line(p_row);
 
 
 		result.class_name = result.class_name.trim_prefix("_");
 		result.class_name = result.class_name.trim_prefix("_");
@@ -866,7 +875,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
 }
 }
 
 
 void ScriptTextEditor::_validate_symbol(const String &p_symbol) {
 void ScriptTextEditor::_validate_symbol(const String &p_symbol) {
-	TextEdit *text_edit = code_editor->get_text_edit();
+	CodeEdit *text_edit = code_editor->get_text_editor();
 
 
 	Node *base = get_tree()->get_edited_scene_root();
 	Node *base = get_tree()->get_edited_scene_root();
 	if (base) {
 	if (base) {
@@ -874,7 +883,7 @@ void ScriptTextEditor::_validate_symbol(const String &p_symbol) {
 	}
 	}
 
 
 	ScriptLanguage::LookupResult result;
 	ScriptLanguage::LookupResult result;
-	if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || (ProjectSettings::get_singleton()->has_autoload(p_symbol) && ProjectSettings::get_singleton()->get_autoload(p_symbol).is_singleton)) {
+	if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || (ProjectSettings::get_singleton()->has_autoload(p_symbol) && ProjectSettings::get_singleton()->get_autoload(p_symbol).is_singleton)) {
 		text_edit->set_highlighted_word(p_symbol);
 		text_edit->set_highlighted_word(p_symbol);
 	} else if (p_symbol.is_rel_path()) {
 	} else if (p_symbol.is_rel_path()) {
 		String path = _get_absolute_path(p_symbol);
 		String path = _get_absolute_path(p_symbol);
@@ -902,8 +911,15 @@ void ScriptTextEditor::update_toggle_scripts_button() {
 }
 }
 
 
 void ScriptTextEditor::_update_connected_methods() {
 void ScriptTextEditor::_update_connected_methods() {
-	TextEdit *text_edit = code_editor->get_text_edit();
-	text_edit->clear_info_icons();
+	CodeEdit *text_edit = code_editor->get_text_editor();
+	for (int i = 0; i < text_edit->get_line_count(); i++) {
+		if (text_edit->get_line_gutter_metadata(i, connection_gutter) == "") {
+			continue;
+		}
+		text_edit->set_line_gutter_metadata(i, connection_gutter, "");
+		text_edit->set_line_gutter_icon(i, connection_gutter, nullptr);
+		text_edit->set_line_gutter_clickable(i, connection_gutter, false);
+	}
 	missing_connections.clear();
 	missing_connections.clear();
 
 
 	if (!script_is_valid) {
 	if (!script_is_valid) {
@@ -943,8 +959,10 @@ void ScriptTextEditor::_update_connected_methods() {
 				for (int j = 0; j < functions.size(); j++) {
 				for (int j = 0; j < functions.size(); j++) {
 					String name = functions[j].get_slice(":", 0);
 					String name = functions[j].get_slice(":", 0);
 					if (name == connection.callable.get_method()) {
 					if (name == connection.callable.get_method()) {
-						line = functions[j].get_slice(":", 1).to_int();
-						text_edit->set_line_info_icon(line - 1, get_parent_control()->get_theme_icon("Slot", "EditorIcons"), connection.callable.get_method());
+						line = functions[j].get_slice(":", 1).to_int() - 1;
+						text_edit->set_line_gutter_metadata(line, connection_gutter, connection.callable.get_method());
+						text_edit->set_line_gutter_icon(line, connection_gutter, get_parent_control()->get_theme_icon("Slot", "EditorIcons"));
+						text_edit->set_line_gutter_clickable(line, connection_gutter, true);
 						methods_found.insert(connection.callable.get_method());
 						methods_found.insert(connection.callable.get_method());
 						break;
 						break;
 					}
 					}
@@ -974,18 +992,41 @@ void ScriptTextEditor::_update_connected_methods() {
 	}
 	}
 }
 }
 
 
-void ScriptTextEditor::_lookup_connections(int p_row, String p_method) {
+void ScriptTextEditor::_update_gutter_indexes() {
+	for (int i = 0; i < code_editor->get_text_editor()->get_gutter_count(); i++) {
+		if (code_editor->get_text_editor()->get_gutter_name(i) == "connection_gutter") {
+			connection_gutter = i;
+			continue;
+		}
+
+		if (code_editor->get_text_editor()->get_gutter_name(i) == "line_numbers") {
+			line_number_gutter = i;
+			continue;
+		}
+	}
+}
+
+void ScriptTextEditor::_gutter_clicked(int p_line, int p_gutter) {
+	if (p_gutter != connection_gutter) {
+		return;
+	}
+
+	String method = code_editor->get_text_editor()->get_line_gutter_metadata(p_line, p_gutter);
+	if (method == "") {
+		return;
+	}
+
 	Node *base = get_tree()->get_edited_scene_root();
 	Node *base = get_tree()->get_edited_scene_root();
 	if (!base) {
 	if (!base) {
 		return;
 		return;
 	}
 	}
 
 
 	Vector<Node *> nodes = _find_all_node_for_script(base, base, script);
 	Vector<Node *> nodes = _find_all_node_for_script(base, base, script);
-	connection_info_dialog->popup_connections(p_method, nodes);
+	connection_info_dialog->popup_connections(method, nodes);
 }
 }
 
 
 void ScriptTextEditor::_edit_option(int p_op) {
 void ScriptTextEditor::_edit_option(int p_op) {
-	TextEdit *tx = code_editor->get_text_edit();
+	CodeEdit *tx = code_editor->get_text_editor();
 
 
 	switch (p_op) {
 	switch (p_op) {
 		case EDIT_UNDO: {
 		case EDIT_UNDO: {
@@ -1109,7 +1150,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
 		} break;
 		} break;
 		case EDIT_EVALUATE: {
 		case EDIT_EVALUATE: {
 			Expression expression;
 			Expression expression;
-			Vector<String> lines = code_editor->get_text_edit()->get_selection_text().split("\n");
+			Vector<String> lines = code_editor->get_text_editor()->get_selection_text().split("\n");
 			PackedStringArray results;
 			PackedStringArray results;
 
 
 			for (int i = 0; i < lines.size(); i++) {
 			for (int i = 0; i < lines.size(); i++) {
@@ -1128,9 +1169,9 @@ void ScriptTextEditor::_edit_option(int p_op) {
 				}
 				}
 			}
 			}
 
 
-			code_editor->get_text_edit()->begin_complex_operation(); //prevents creating a two-step undo
-			code_editor->get_text_edit()->insert_text_at_cursor(String("\n").join(results));
-			code_editor->get_text_edit()->end_complex_operation();
+			code_editor->get_text_editor()->begin_complex_operation(); //prevents creating a two-step undo
+			code_editor->get_text_editor()->insert_text_at_cursor(String("\n").join(results));
+			code_editor->get_text_editor()->end_complex_operation();
 		} break;
 		} break;
 		case SEARCH_FIND: {
 		case SEARCH_FIND: {
 			code_editor->get_find_replace_bar()->popup_search();
 			code_editor->get_find_replace_bar()->popup_search();
@@ -1145,14 +1186,14 @@ void ScriptTextEditor::_edit_option(int p_op) {
 			code_editor->get_find_replace_bar()->popup_replace();
 			code_editor->get_find_replace_bar()->popup_replace();
 		} break;
 		} break;
 		case SEARCH_IN_FILES: {
 		case SEARCH_IN_FILES: {
-			String selected_text = code_editor->get_text_edit()->get_selection_text();
+			String selected_text = code_editor->get_text_editor()->get_selection_text();
 
 
 			// Yep, because it doesn't make sense to instance this dialog for every single script open...
 			// Yep, because it doesn't make sense to instance this dialog for every single script open...
 			// So this will be delegated to the ScriptEditor.
 			// So this will be delegated to the ScriptEditor.
 			emit_signal("search_in_files_requested", selected_text);
 			emit_signal("search_in_files_requested", selected_text);
 		} break;
 		} break;
 		case REPLACE_IN_FILES: {
 		case REPLACE_IN_FILES: {
-			String selected_text = code_editor->get_text_edit()->get_selection_text();
+			String selected_text = code_editor->get_text_editor()->get_selection_text();
 
 
 			emit_signal("replace_in_files_requested", selected_text);
 			emit_signal("replace_in_files_requested", selected_text);
 		} break;
 		} break;
@@ -1177,24 +1218,22 @@ void ScriptTextEditor::_edit_option(int p_op) {
 		} break;
 		} break;
 		case DEBUG_TOGGLE_BREAKPOINT: {
 		case DEBUG_TOGGLE_BREAKPOINT: {
 			int line = tx->cursor_get_line();
 			int line = tx->cursor_get_line();
-			bool dobreak = !tx->is_line_set_as_breakpoint(line);
+			bool dobreak = !tx->is_line_breakpointed(line);
 			tx->set_line_as_breakpoint(line, dobreak);
 			tx->set_line_as_breakpoint(line, dobreak);
 			EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak);
 			EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak);
 		} break;
 		} break;
 		case DEBUG_REMOVE_ALL_BREAKPOINTS: {
 		case DEBUG_REMOVE_ALL_BREAKPOINTS: {
-			List<int> bpoints;
-			tx->get_breakpoints(&bpoints);
+			Array bpoints = tx->get_breakpointed_lines();
 
 
-			for (List<int>::Element *E = bpoints.front(); E; E = E->next()) {
-				int line = E->get();
-				bool dobreak = !tx->is_line_set_as_breakpoint(line);
+			for (int i = 0; i < bpoints.size(); i++) {
+				int line = bpoints[i];
+				bool dobreak = !tx->is_line_breakpointed(line);
 				tx->set_line_as_breakpoint(line, dobreak);
 				tx->set_line_as_breakpoint(line, dobreak);
 				EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak);
 				EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak);
 			}
 			}
 		} break;
 		} break;
 		case DEBUG_GOTO_NEXT_BREAKPOINT: {
 		case DEBUG_GOTO_NEXT_BREAKPOINT: {
-			List<int> bpoints;
-			tx->get_breakpoints(&bpoints);
+			Array bpoints = tx->get_breakpointed_lines();
 			if (bpoints.size() <= 0) {
 			if (bpoints.size() <= 0) {
 				return;
 				return;
 			}
 			}
@@ -1202,13 +1241,13 @@ void ScriptTextEditor::_edit_option(int p_op) {
 			int line = tx->cursor_get_line();
 			int line = tx->cursor_get_line();
 
 
 			// wrap around
 			// wrap around
-			if (line >= bpoints[bpoints.size() - 1]) {
+			if (line >= (int)bpoints[bpoints.size() - 1]) {
 				tx->unfold_line(bpoints[0]);
 				tx->unfold_line(bpoints[0]);
 				tx->cursor_set_line(bpoints[0]);
 				tx->cursor_set_line(bpoints[0]);
 				tx->center_viewport_to_cursor();
 				tx->center_viewport_to_cursor();
 			} else {
 			} else {
-				for (List<int>::Element *E = bpoints.front(); E; E = E->next()) {
-					int bline = E->get();
+				for (int i = 0; i < bpoints.size(); i++) {
+					int bline = bpoints[i];
 					if (bline > line) {
 					if (bline > line) {
 						tx->unfold_line(bline);
 						tx->unfold_line(bline);
 						tx->cursor_set_line(bline);
 						tx->cursor_set_line(bline);
@@ -1220,21 +1259,20 @@ void ScriptTextEditor::_edit_option(int p_op) {
 
 
 		} break;
 		} break;
 		case DEBUG_GOTO_PREV_BREAKPOINT: {
 		case DEBUG_GOTO_PREV_BREAKPOINT: {
-			List<int> bpoints;
-			tx->get_breakpoints(&bpoints);
+			Array bpoints = tx->get_breakpointed_lines();
 			if (bpoints.size() <= 0) {
 			if (bpoints.size() <= 0) {
 				return;
 				return;
 			}
 			}
 
 
 			int line = tx->cursor_get_line();
 			int line = tx->cursor_get_line();
 			// wrap around
 			// wrap around
-			if (line <= bpoints[0]) {
+			if (line <= (int)bpoints[0]) {
 				tx->unfold_line(bpoints[bpoints.size() - 1]);
 				tx->unfold_line(bpoints[bpoints.size() - 1]);
 				tx->cursor_set_line(bpoints[bpoints.size() - 1]);
 				tx->cursor_set_line(bpoints[bpoints.size() - 1]);
 				tx->center_viewport_to_cursor();
 				tx->center_viewport_to_cursor();
 			} else {
 			} else {
-				for (List<int>::Element *E = bpoints.back(); E; E = E->prev()) {
-					int bline = E->get();
+				for (int i = bpoints.size(); i >= 0; i--) {
+					int bline = bpoints[i];
 					if (bline < line) {
 					if (bline < line) {
 						tx->unfold_line(bline);
 						tx->unfold_line(bline);
 						tx->cursor_set_line(bline);
 						tx->cursor_set_line(bline);
@@ -1303,7 +1341,7 @@ void ScriptTextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_hig
 		el = el->next();
 		el = el->next();
 	}
 	}
 
 
-	TextEdit *te = code_editor->get_text_edit();
+	CodeEdit *te = code_editor->get_text_editor();
 	p_highlighter->_set_edited_resource(script);
 	p_highlighter->_set_edited_resource(script);
 	te->set_syntax_highlighter(p_highlighter);
 	te->set_syntax_highlighter(p_highlighter);
 }
 }
@@ -1312,6 +1350,16 @@ void ScriptTextEditor::_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)]);
 }
 }
 
 
+void ScriptTextEditor::_notification(int p_what) {
+	switch (p_what) {
+		case NOTIFICATION_THEME_CHANGED: {
+			code_editor->get_text_editor()->set_gutter_width(connection_gutter, code_editor->get_text_editor()->get_row_height());
+		} break;
+		default:
+			break;
+	}
+}
+
 void ScriptTextEditor::_bind_methods() {
 void ScriptTextEditor::_bind_methods() {
 	ClassDB::bind_method("_update_connected_methods", &ScriptTextEditor::_update_connected_methods);
 	ClassDB::bind_method("_update_connected_methods", &ScriptTextEditor::_update_connected_methods);
 
 
@@ -1331,7 +1379,7 @@ void ScriptTextEditor::clear_edit_menu() {
 }
 }
 
 
 void ScriptTextEditor::reload(bool p_soft) {
 void ScriptTextEditor::reload(bool p_soft) {
-	TextEdit *te = code_editor->get_text_edit();
+	CodeEdit *te = code_editor->get_text_editor();
 	Ref<Script> scr = script;
 	Ref<Script> scr = script;
 	if (scr.is_null()) {
 	if (scr.is_null()) {
 		return;
 		return;
@@ -1342,12 +1390,12 @@ void ScriptTextEditor::reload(bool p_soft) {
 	scr->get_language()->reload_tool_script(scr, soft);
 	scr->get_language()->reload_tool_script(scr, soft);
 }
 }
 
 
-void ScriptTextEditor::get_breakpoints(List<int> *p_breakpoints) {
-	code_editor->get_text_edit()->get_breakpoints(p_breakpoints);
+Array ScriptTextEditor::get_breakpoints() {
+	return code_editor->get_text_editor()->get_breakpointed_lines();
 }
 }
 
 
 void ScriptTextEditor::set_tooltip_request_func(String p_method, Object *p_obj) {
 void ScriptTextEditor::set_tooltip_request_func(String p_method, Object *p_obj) {
-	code_editor->get_text_edit()->set_tooltip_request_func(p_obj, p_method, this);
+	code_editor->get_text_editor()->set_tooltip_request_func(p_obj, p_method, this);
 }
 }
 
 
 void ScriptTextEditor::set_debugger_active(bool p_active) {
 void ScriptTextEditor::set_debugger_active(bool p_active) {
@@ -1393,7 +1441,7 @@ static Node *_find_script_node(Node *p_edited_scene, Node *p_current_node, const
 void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
 void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
 	Dictionary d = p_data;
 	Dictionary d = p_data;
 
 
-	TextEdit *te = code_editor->get_text_edit();
+	CodeEdit *te = code_editor->get_text_editor();
 	int row, col;
 	int row, col;
 	te->_get_mouse_pos(p_point, row, col);
 	te->_get_mouse_pos(p_point, row, col);
 
 
@@ -1466,7 +1514,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 	Point2 local_pos;
 	Point2 local_pos;
 	bool create_menu = false;
 	bool create_menu = false;
 
 
-	TextEdit *tx = code_editor->get_text_edit();
+	CodeEdit *tx = code_editor->get_text_editor();
 	if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
 	if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
 		local_pos = mb->get_global_position() - tx->get_global_position();
 		local_pos = mb->get_global_position() - tx->get_global_position();
 		create_menu = true;
 		create_menu = true;
@@ -1519,7 +1567,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 				base = _find_node_for_script(base, base, script);
 				base = _find_node_for_script(base, base, script);
 			}
 			}
 			ScriptLanguage::LookupResult result;
 			ScriptLanguage::LookupResult result;
-			if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), word_at_pos, script->get_path(), base, result) == OK) {
+			if (script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_lookup_completion(), word_at_pos, script->get_path(), base, result) == OK) {
 				open_docs = true;
 				open_docs = true;
 			}
 			}
 		}
 		}
@@ -1567,17 +1615,17 @@ void ScriptTextEditor::_color_changed(const Color &p_color) {
 		new_args = String("(" + rtos(p_color.r) + ", " + rtos(p_color.g) + ", " + rtos(p_color.b) + ", " + rtos(p_color.a) + ")");
 		new_args = String("(" + rtos(p_color.r) + ", " + rtos(p_color.g) + ", " + rtos(p_color.b) + ", " + rtos(p_color.a) + ")");
 	}
 	}
 
 
-	String line = code_editor->get_text_edit()->get_line(color_position.x);
+	String line = code_editor->get_text_editor()->get_line(color_position.x);
 	int color_args_pos = line.find(color_args, color_position.y);
 	int color_args_pos = line.find(color_args, color_position.y);
 	String line_with_replaced_args = line;
 	String line_with_replaced_args = line;
 	line_with_replaced_args.erase(color_args_pos, color_args.length());
 	line_with_replaced_args.erase(color_args_pos, color_args.length());
 	line_with_replaced_args = line_with_replaced_args.insert(color_args_pos, new_args);
 	line_with_replaced_args = line_with_replaced_args.insert(color_args_pos, new_args);
 
 
 	color_args = new_args;
 	color_args = new_args;
-	code_editor->get_text_edit()->begin_complex_operation();
-	code_editor->get_text_edit()->set_line(color_position.x, line_with_replaced_args);
-	code_editor->get_text_edit()->end_complex_operation();
-	code_editor->get_text_edit()->update();
+	code_editor->get_text_editor()->begin_complex_operation();
+	code_editor->get_text_editor()->set_line(color_position.x, line_with_replaced_args);
+	code_editor->get_text_editor()->end_complex_operation();
+	code_editor->get_text_editor()->update();
 }
 }
 
 
 void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos) {
 void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos) {
@@ -1636,12 +1684,15 @@ void ScriptTextEditor::_enable_code_editor() {
 	code_editor->connect("show_warnings_panel", callable_mp(this, &ScriptTextEditor::_show_warnings_panel));
 	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->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_validate", callable_mp(this, &ScriptTextEditor::_validate_symbol));
-	code_editor->get_text_edit()->connect("info_clicked", callable_mp(this, &ScriptTextEditor::_lookup_connections));
-	code_editor->get_text_edit()->connect("gui_input", callable_mp(this, &ScriptTextEditor::_text_edit_gui_input));
+	code_editor->get_text_editor()->connect("breakpoint_toggled", callable_mp(this, &ScriptTextEditor::_breakpoint_toggled));
+	code_editor->get_text_editor()->connect("symbol_lookup", callable_mp(this, &ScriptTextEditor::_lookup_symbol));
+	code_editor->get_text_editor()->connect("symbol_validate", callable_mp(this, &ScriptTextEditor::_validate_symbol));
+	code_editor->get_text_editor()->connect("gutter_added", callable_mp(this, &ScriptTextEditor::_update_gutter_indexes));
+	code_editor->get_text_editor()->connect("gutter_removed", callable_mp(this, &ScriptTextEditor::_update_gutter_indexes));
+	code_editor->get_text_editor()->connect("gutter_clicked", callable_mp(this, &ScriptTextEditor::_gutter_clicked));
+	code_editor->get_text_editor()->connect("gui_input", callable_mp(this, &ScriptTextEditor::_text_edit_gui_input));
 	code_editor->show_toggle_scripts_button();
 	code_editor->show_toggle_scripts_button();
+	_update_gutter_indexes();
 
 
 	editor_box->add_child(warnings_panel);
 	editor_box->add_child(warnings_panel);
 	warnings_panel->add_theme_font_override(
 	warnings_panel->add_theme_font_override(
@@ -1758,6 +1809,16 @@ ScriptTextEditor::ScriptTextEditor() {
 	code_editor->set_code_complete_func(_code_complete_scripts, this);
 	code_editor->set_code_complete_func(_code_complete_scripts, this);
 	code_editor->set_v_size_flags(SIZE_EXPAND_FILL);
 	code_editor->set_v_size_flags(SIZE_EXPAND_FILL);
 
 
+	code_editor->get_text_editor()->set_draw_breakpoints_gutter(true);
+	code_editor->get_text_editor()->set_draw_executing_lines_gutter(true);
+
+	connection_gutter = 1;
+	code_editor->get_text_editor()->add_gutter(connection_gutter);
+	code_editor->get_text_editor()->set_gutter_name(connection_gutter, "connection_gutter");
+	code_editor->get_text_editor()->set_gutter_draw(connection_gutter, false);
+	code_editor->get_text_editor()->set_gutter_overwritable(connection_gutter, true);
+	code_editor->get_text_editor()->set_gutter_type(connection_gutter, TextEdit::GUTTER_TPYE_ICON);
+
 	warnings_panel = memnew(RichTextLabel);
 	warnings_panel = memnew(RichTextLabel);
 	warnings_panel->set_custom_minimum_size(Size2(0, 100 * EDSCALE));
 	warnings_panel->set_custom_minimum_size(Size2(0, 100 * EDSCALE));
 	warnings_panel->set_h_size_flags(SIZE_EXPAND_FILL);
 	warnings_panel->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1768,12 +1829,12 @@ ScriptTextEditor::ScriptTextEditor() {
 
 
 	update_settings();
 	update_settings();
 
 
-	code_editor->get_text_edit()->set_callhint_settings(
+	code_editor->get_text_editor()->set_callhint_settings(
 			EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"),
 			EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"),
 			EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset"));
 			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_editor()->set_select_identifiers_on_hover(true);
+	code_editor->get_text_editor()->set_context_menu_enabled(false);
 
 
 	context_menu = memnew(PopupMenu);
 	context_menu = memnew(PopupMenu);
 
 
@@ -1816,7 +1877,7 @@ ScriptTextEditor::ScriptTextEditor() {
 
 
 	connection_info_dialog = memnew(ConnectionInfoDialog);
 	connection_info_dialog = memnew(ConnectionInfoDialog);
 
 
-	code_editor->get_text_edit()->set_drag_forwarding(this);
+	code_editor->get_text_editor()->set_drag_forwarding(this);
 }
 }
 
 
 ScriptTextEditor::~ScriptTextEditor() {
 ScriptTextEditor::~ScriptTextEditor() {

+ 10 - 3
editor/plugins/script_text_editor.h

@@ -81,6 +81,14 @@ class ScriptTextEditor : public ScriptEditorBase {
 	ScriptEditorQuickOpen *quick_open = nullptr;
 	ScriptEditorQuickOpen *quick_open = nullptr;
 	ConnectionInfoDialog *connection_info_dialog = nullptr;
 	ConnectionInfoDialog *connection_info_dialog = nullptr;
 
 
+	int connection_gutter = -1;
+	void _gutter_clicked(int p_line, int p_gutter);
+	void _update_gutter_indexes();
+
+	int line_number_gutter = -1;
+	Color default_line_number_color = Color(1, 1, 1);
+	Color safe_line_number_color = Color(1, 1, 1);
+
 	PopupPanel *color_panel = nullptr;
 	PopupPanel *color_panel = nullptr;
 	ColorPicker *color_picker = nullptr;
 	ColorPicker *color_picker = nullptr;
 	Vector2 color_position;
 	Vector2 color_position;
@@ -154,6 +162,7 @@ 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;
@@ -169,8 +178,6 @@ protected:
 	void _lookup_symbol(const String &p_symbol, int p_row, int p_column);
 	void _lookup_symbol(const String &p_symbol, int p_row, int p_column);
 	void _validate_symbol(const String &p_symbol);
 	void _validate_symbol(const String &p_symbol);
 
 
-	void _lookup_connections(int p_row, String p_method);
-
 	void _convert_case(CodeTextEditor::CaseStyle p_case);
 	void _convert_case(CodeTextEditor::CaseStyle p_case);
 
 
 	Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
 	Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
@@ -211,7 +218,7 @@ public:
 	virtual void clear_executing_line() override;
 	virtual void clear_executing_line() override;
 
 
 	virtual void reload(bool p_soft) override;
 	virtual void reload(bool p_soft) override;
-	virtual void get_breakpoints(List<int> *p_breakpoints) override;
+	virtual Array get_breakpoints() override;
 
 
 	virtual void add_callback(const String &p_function, PackedStringArray p_args) override;
 	virtual void add_callback(const String &p_function, PackedStringArray p_args) override;
 	virtual void update_settings() override;
 	virtual void update_settings() override;

+ 61 - 78
editor/plugins/shader_editor_plugin.cpp

@@ -55,8 +55,8 @@ void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader) {
 
 
 	_load_theme_settings();
 	_load_theme_settings();
 
 
-	get_text_edit()->set_text(p_shader->get_code());
-	get_text_edit()->clear_undo_history();
+	get_text_editor()->set_text(p_shader->get_code());
+	get_text_editor()->clear_undo_history();
 
 
 	_validate_script();
 	_validate_script();
 	_line_col_changed();
 	_line_col_changed();
@@ -65,7 +65,7 @@ void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader) {
 void ShaderTextEditor::reload_text() {
 void ShaderTextEditor::reload_text() {
 	ERR_FAIL_COND(shader.is_null());
 	ERR_FAIL_COND(shader.is_null());
 
 
-	TextEdit *te = get_text_edit();
+	CodeEdit *te = get_text_editor();
 	int column = te->cursor_get_column();
 	int column = te->cursor_get_column();
 	int row = te->cursor_get_line();
 	int row = te->cursor_get_line();
 	int h = te->get_h_scroll();
 	int h = te->get_h_scroll();
@@ -107,29 +107,29 @@ void ShaderTextEditor::_load_theme_settings() {
 	Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
 	Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color");
 	Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
 	Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color");
 
 
-	get_text_edit()->add_theme_color_override("background_color", background_color);
-	get_text_edit()->add_theme_color_override("completion_background_color", completion_background_color);
-	get_text_edit()->add_theme_color_override("completion_selected_color", completion_selected_color);
-	get_text_edit()->add_theme_color_override("completion_existing_color", completion_existing_color);
-	get_text_edit()->add_theme_color_override("completion_scroll_color", completion_scroll_color);
-	get_text_edit()->add_theme_color_override("completion_font_color", completion_font_color);
-	get_text_edit()->add_theme_color_override("font_color", text_color);
-	get_text_edit()->add_theme_color_override("line_number_color", line_number_color);
-	get_text_edit()->add_theme_color_override("caret_color", caret_color);
-	get_text_edit()->add_theme_color_override("caret_background_color", caret_background_color);
-	get_text_edit()->add_theme_color_override("font_color_selected", text_selected_color);
-	get_text_edit()->add_theme_color_override("selection_color", selection_color);
-	get_text_edit()->add_theme_color_override("brace_mismatch_color", brace_mismatch_color);
-	get_text_edit()->add_theme_color_override("current_line_color", current_line_color);
-	get_text_edit()->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
-	get_text_edit()->add_theme_color_override("word_highlighted_color", word_highlighted_color);
-	get_text_edit()->add_theme_color_override("mark_color", mark_color);
-	get_text_edit()->add_theme_color_override("bookmark_color", bookmark_color);
-	get_text_edit()->add_theme_color_override("breakpoint_color", breakpoint_color);
-	get_text_edit()->add_theme_color_override("executing_line_color", executing_line_color);
-	get_text_edit()->add_theme_color_override("code_folding_color", code_folding_color);
-	get_text_edit()->add_theme_color_override("search_result_color", search_result_color);
-	get_text_edit()->add_theme_color_override("search_result_border_color", search_result_border_color);
+	get_text_editor()->add_theme_color_override("background_color", background_color);
+	get_text_editor()->add_theme_color_override("completion_background_color", completion_background_color);
+	get_text_editor()->add_theme_color_override("completion_selected_color", completion_selected_color);
+	get_text_editor()->add_theme_color_override("completion_existing_color", completion_existing_color);
+	get_text_editor()->add_theme_color_override("completion_scroll_color", completion_scroll_color);
+	get_text_editor()->add_theme_color_override("completion_font_color", completion_font_color);
+	get_text_editor()->add_theme_color_override("font_color", text_color);
+	get_text_editor()->add_theme_color_override("line_number_color", line_number_color);
+	get_text_editor()->add_theme_color_override("caret_color", caret_color);
+	get_text_editor()->add_theme_color_override("caret_background_color", caret_background_color);
+	get_text_editor()->add_theme_color_override("font_color_selected", text_selected_color);
+	get_text_editor()->add_theme_color_override("selection_color", selection_color);
+	get_text_editor()->add_theme_color_override("brace_mismatch_color", brace_mismatch_color);
+	get_text_editor()->add_theme_color_override("current_line_color", current_line_color);
+	get_text_editor()->add_theme_color_override("line_length_guideline_color", line_length_guideline_color);
+	get_text_editor()->add_theme_color_override("word_highlighted_color", word_highlighted_color);
+	get_text_editor()->add_theme_color_override("mark_color", mark_color);
+	get_text_editor()->add_theme_color_override("bookmark_color", bookmark_color);
+	get_text_editor()->add_theme_color_override("breakpoint_color", breakpoint_color);
+	get_text_editor()->add_theme_color_override("executing_line_color", executing_line_color);
+	get_text_editor()->add_theme_color_override("code_folding_color", code_folding_color);
+	get_text_editor()->add_theme_color_override("search_result_color", search_result_color);
+	get_text_editor()->add_theme_color_override("search_result_border_color", search_result_border_color);
 
 
 	syntax_highlighter->set_number_color(EDITOR_GET("text_editor/highlighting/number_color"));
 	syntax_highlighter->set_number_color(EDITOR_GET("text_editor/highlighting/number_color"));
 	syntax_highlighter->set_symbol_color(EDITOR_GET("text_editor/highlighting/symbol_color"));
 	syntax_highlighter->set_symbol_color(EDITOR_GET("text_editor/highlighting/symbol_color"));
@@ -176,7 +176,7 @@ void ShaderTextEditor::_load_theme_settings() {
 }
 }
 
 
 void ShaderTextEditor::_check_shader_mode() {
 void ShaderTextEditor::_check_shader_mode() {
-	String type = ShaderLanguage::get_shader_type(get_text_edit()->get_text());
+	String type = ShaderLanguage::get_shader_type(get_text_editor()->get_text());
 
 
 	Shader::Mode mode;
 	Shader::Mode mode;
 
 
@@ -189,7 +189,7 @@ void ShaderTextEditor::_check_shader_mode() {
 	}
 	}
 
 
 	if (shader->get_mode() != mode) {
 	if (shader->get_mode() != mode) {
-		shader->set_code(get_text_edit()->get_text());
+		shader->set_code(get_text_editor()->get_text());
 		_load_theme_settings();
 		_load_theme_settings();
 	}
 	}
 }
 }
@@ -207,13 +207,13 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptCo
 
 
 	sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type, r_options, calltip);
 	sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type, r_options, calltip);
 
 
-	get_text_edit()->set_code_hint(calltip);
+	get_text_editor()->set_code_hint(calltip);
 }
 }
 
 
 void ShaderTextEditor::_validate_script() {
 void ShaderTextEditor::_validate_script() {
 	_check_shader_mode();
 	_check_shader_mode();
 
 
-	String code = get_text_edit()->get_text();
+	String code = get_text_editor()->get_text();
 	//List<StringName> params;
 	//List<StringName> params;
 	//shader->get_param_list(&params);
 	//shader->get_param_list(&params);
 
 
@@ -225,14 +225,14 @@ void ShaderTextEditor::_validate_script() {
 		String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
 		String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
 		set_error(error_text);
 		set_error(error_text);
 		set_error_pos(sl.get_error_line() - 1, 0);
 		set_error_pos(sl.get_error_line() - 1, 0);
-		for (int i = 0; i < get_text_edit()->get_line_count(); i++) {
-			get_text_edit()->set_line_as_marked(i, false);
+		for (int i = 0; i < get_text_editor()->get_line_count(); i++) {
+			get_text_editor()->set_line_as_marked(i, false);
 		}
 		}
-		get_text_edit()->set_line_as_marked(sl.get_error_line() - 1, true);
+		get_text_editor()->set_line_as_marked(sl.get_error_line() - 1, true);
 
 
 	} else {
 	} else {
-		for (int i = 0; i < get_text_edit()->get_line_count(); i++) {
-			get_text_edit()->set_line_as_marked(i, false);
+		for (int i = 0; i < get_text_editor()->get_line_count(); i++) {
+			get_text_editor()->set_line_as_marked(i, false);
 		}
 		}
 		set_error("");
 		set_error("");
 	}
 	}
@@ -245,7 +245,7 @@ void ShaderTextEditor::_bind_methods() {
 
 
 ShaderTextEditor::ShaderTextEditor() {
 ShaderTextEditor::ShaderTextEditor() {
 	syntax_highlighter.instance();
 	syntax_highlighter.instance();
-	get_text_edit()->set_syntax_highlighter(syntax_highlighter);
+	get_text_editor()->set_syntax_highlighter(syntax_highlighter);
 }
 }
 
 
 /*** SCRIPT EDITOR ******/
 /*** SCRIPT EDITOR ******/
@@ -253,22 +253,22 @@ ShaderTextEditor::ShaderTextEditor() {
 void ShaderEditor::_menu_option(int p_option) {
 void ShaderEditor::_menu_option(int p_option) {
 	switch (p_option) {
 	switch (p_option) {
 		case EDIT_UNDO: {
 		case EDIT_UNDO: {
-			shader_editor->get_text_edit()->undo();
+			shader_editor->get_text_editor()->undo();
 		} break;
 		} break;
 		case EDIT_REDO: {
 		case EDIT_REDO: {
-			shader_editor->get_text_edit()->redo();
+			shader_editor->get_text_editor()->redo();
 		} break;
 		} break;
 		case EDIT_CUT: {
 		case EDIT_CUT: {
-			shader_editor->get_text_edit()->cut();
+			shader_editor->get_text_editor()->cut();
 		} break;
 		} break;
 		case EDIT_COPY: {
 		case EDIT_COPY: {
-			shader_editor->get_text_edit()->copy();
+			shader_editor->get_text_editor()->copy();
 		} break;
 		} break;
 		case EDIT_PASTE: {
 		case EDIT_PASTE: {
-			shader_editor->get_text_edit()->paste();
+			shader_editor->get_text_editor()->paste();
 		} break;
 		} break;
 		case EDIT_SELECT_ALL: {
 		case EDIT_SELECT_ALL: {
-			shader_editor->get_text_edit()->select_all();
+			shader_editor->get_text_editor()->select_all();
 		} break;
 		} break;
 		case EDIT_MOVE_LINE_UP: {
 		case EDIT_MOVE_LINE_UP: {
 			shader_editor->move_lines_up();
 			shader_editor->move_lines_up();
@@ -281,7 +281,7 @@ void ShaderEditor::_menu_option(int p_option) {
 				return;
 				return;
 			}
 			}
 
 
-			TextEdit *tx = shader_editor->get_text_edit();
+			CodeEdit *tx = shader_editor->get_text_editor();
 			tx->indent_left();
 			tx->indent_left();
 
 
 		} break;
 		} break;
@@ -290,7 +290,7 @@ void ShaderEditor::_menu_option(int p_option) {
 				return;
 				return;
 			}
 			}
 
 
-			TextEdit *tx = shader_editor->get_text_edit();
+			CodeEdit *tx = shader_editor->get_text_editor();
 			tx->indent_right();
 			tx->indent_right();
 
 
 		} break;
 		} break;
@@ -309,7 +309,7 @@ void ShaderEditor::_menu_option(int p_option) {
 
 
 		} break;
 		} break;
 		case EDIT_COMPLETE: {
 		case EDIT_COMPLETE: {
-			shader_editor->get_text_edit()->query_code_comple();
+			shader_editor->get_text_editor()->query_code_comple();
 		} break;
 		} break;
 		case SEARCH_FIND: {
 		case SEARCH_FIND: {
 			shader_editor->get_find_replace_bar()->popup_search();
 			shader_editor->get_find_replace_bar()->popup_search();
@@ -324,7 +324,7 @@ void ShaderEditor::_menu_option(int p_option) {
 			shader_editor->get_find_replace_bar()->popup_replace();
 			shader_editor->get_find_replace_bar()->popup_replace();
 		} break;
 		} break;
 		case SEARCH_GOTO_LINE: {
 		case SEARCH_GOTO_LINE: {
-			goto_line_dialog->popup_find_line(shader_editor->get_text_edit());
+			goto_line_dialog->popup_find_line(shader_editor->get_text_editor());
 		} break;
 		} break;
 		case BOOKMARK_TOGGLE: {
 		case BOOKMARK_TOGGLE: {
 			shader_editor->toggle_bookmark();
 			shader_editor->toggle_bookmark();
@@ -343,7 +343,7 @@ void ShaderEditor::_menu_option(int p_option) {
 		} break;
 		} break;
 	}
 	}
 	if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) {
 	if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) {
-		shader_editor->get_text_edit()->call_deferred("grab_focus");
+		shader_editor->get_text_editor()->call_deferred("grab_focus");
 	}
 	}
 }
 }
 
 
@@ -358,28 +358,11 @@ void ShaderEditor::_params_changed() {
 }
 }
 
 
 void ShaderEditor::_editor_settings_changed() {
 void ShaderEditor::_editor_settings_changed() {
-	shader_editor->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/completion/auto_brace_complete"));
-	shader_editor->get_text_edit()->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/cursor/scroll_past_end_of_file"));
-	shader_editor->get_text_edit()->set_indent_size(EditorSettings::get_singleton()->get("text_editor/indent/size"));
-	shader_editor->get_text_edit()->set_indent_using_spaces(EditorSettings::get_singleton()->get("text_editor/indent/type"));
-	shader_editor->get_text_edit()->set_auto_indent(EditorSettings::get_singleton()->get("text_editor/indent/auto_indent"));
-	shader_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs"));
-	shader_editor->get_text_edit()->set_draw_spaces(EditorSettings::get_singleton()->get("text_editor/indent/draw_spaces"));
-	shader_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers"));
-	shader_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences"));
-	shader_editor->get_text_edit()->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_current_line"));
-	shader_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink"));
-	shader_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
-	shader_editor->get_text_edit()->add_theme_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing"));
-	shader_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
-	shader_editor->get_text_edit()->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/navigation/smooth_scrolling"));
-	shader_editor->get_text_edit()->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/navigation/v_scroll_speed"));
-	shader_editor->get_text_edit()->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/navigation/show_minimap"));
-	shader_editor->get_text_edit()->set_minimap_width((int)EditorSettings::get_singleton()->get("text_editor/navigation/minimap_width") * EDSCALE);
-	shader_editor->get_text_edit()->set_show_line_length_guidelines(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_length_guidelines"));
-	shader_editor->get_text_edit()->set_line_length_guideline_soft_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_soft_column"));
-	shader_editor->get_text_edit()->set_line_length_guideline_hard_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_hard_column"));
-	shader_editor->get_text_edit()->set_breakpoint_gutter_enabled(false);
+	shader_editor->update_editor_settings();
+
+	shader_editor->get_text_editor()->add_theme_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing"));
+	shader_editor->get_text_editor()->set_draw_breakpoints_gutter(false);
+	shader_editor->get_text_editor()->set_draw_executing_lines_gutter(false);
 }
 }
 
 
 void ShaderEditor::_bind_methods() {
 void ShaderEditor::_bind_methods() {
@@ -466,7 +449,7 @@ void ShaderEditor::save_external_data(const String &p_str) {
 void ShaderEditor::apply_shaders() {
 void ShaderEditor::apply_shaders() {
 	if (shader.is_valid()) {
 	if (shader.is_valid()) {
 		String shader_code = shader->get_code();
 		String shader_code = shader->get_code();
-		String editor_code = shader_editor->get_text_edit()->get_text();
+		String editor_code = shader_editor->get_text_editor()->get_text();
 		if (shader_code != editor_code) {
 		if (shader_code != editor_code) {
 			shader->set_code(editor_code);
 			shader->set_code(editor_code);
 			shader->set_edited(true);
 			shader->set_edited(true);
@@ -480,7 +463,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 	if (mb.is_valid()) {
 	if (mb.is_valid()) {
 		if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
 		if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
 			int col, row;
 			int col, row;
-			TextEdit *tx = shader_editor->get_text_edit();
+			CodeEdit *tx = shader_editor->get_text_editor();
 			tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
 			tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
 			tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
 			tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
 
 
@@ -507,7 +490,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 
 
 	Ref<InputEventKey> k = ev;
 	Ref<InputEventKey> k = ev;
 	if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) {
 	if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) {
-		TextEdit *tx = shader_editor->get_text_edit();
+		CodeEdit *tx = shader_editor->get_text_editor();
 		_make_context_menu(tx->is_selection_active(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos()));
 		_make_context_menu(tx->is_selection_active(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos()));
 		context_menu->grab_focus();
 		context_menu->grab_focus();
 	}
 	}
@@ -521,7 +504,7 @@ void ShaderEditor::_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_next_bookmark"), BOOKMARK_GOTO_NEXT);
 	bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV);
 	bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV);
 
 
-	Array bookmark_list = shader_editor->get_text_edit()->get_bookmarks_array();
+	Array bookmark_list = shader_editor->get_text_editor()->get_bookmarked_lines();
 	if (bookmark_list.size() == 0) {
 	if (bookmark_list.size() == 0) {
 		return;
 		return;
 	}
 	}
@@ -529,7 +512,7 @@ void ShaderEditor::_update_bookmark_list() {
 	bookmarks_menu->add_separator();
 	bookmarks_menu->add_separator();
 
 
 	for (int i = 0; i < bookmark_list.size(); i++) {
 	for (int i = 0; i < bookmark_list.size(); i++) {
-		String line = shader_editor->get_text_edit()->get_line(bookmark_list[i]).strip_edges();
+		String line = shader_editor->get_text_editor()->get_line(bookmark_list[i]).strip_edges();
 		// Limit the size of the line if too big.
 		// Limit the size of the line if too big.
 		if (line.length() > 50) {
 		if (line.length() > 50) {
 			line = line.substr(0, 50);
 			line = line.substr(0, 50);
@@ -581,13 +564,13 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
 	shader_editor->connect("script_changed", callable_mp(this, &ShaderEditor::apply_shaders));
 	shader_editor->connect("script_changed", callable_mp(this, &ShaderEditor::apply_shaders));
 	EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &ShaderEditor::_editor_settings_changed));
 	EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &ShaderEditor::_editor_settings_changed));
 
 
-	shader_editor->get_text_edit()->set_callhint_settings(
+	shader_editor->get_text_editor()->set_callhint_settings(
 			EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"),
 			EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"),
 			EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset"));
 			EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset"));
 
 
-	shader_editor->get_text_edit()->set_select_identifiers_on_hover(true);
-	shader_editor->get_text_edit()->set_context_menu_enabled(false);
-	shader_editor->get_text_edit()->connect("gui_input", callable_mp(this, &ShaderEditor::_text_edit_gui_input));
+	shader_editor->get_text_editor()->set_select_identifiers_on_hover(true);
+	shader_editor->get_text_editor()->set_context_menu_enabled(false);
+	shader_editor->get_text_editor()->connect("gui_input", callable_mp(this, &ShaderEditor::_text_edit_gui_input));
 
 
 	shader_editor->update_editor_settings();
 	shader_editor->update_editor_settings();
 
 

+ 23 - 22
editor/plugins/text_editor.cpp

@@ -50,7 +50,7 @@ void TextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlight
 		el = el->next();
 		el = el->next();
 	}
 	}
 
 
-	TextEdit *te = code_editor->get_text_edit();
+	CodeEdit *te = code_editor->get_text_editor();
 	te->set_syntax_highlighter(p_highlighter);
 	te->set_syntax_highlighter(p_highlighter);
 }
 }
 
 
@@ -59,7 +59,7 @@ void TextEditor::_change_syntax_highlighter(int p_idx) {
 }
 }
 
 
 void TextEditor::_load_theme_settings() {
 void TextEditor::_load_theme_settings() {
-	TextEdit *text_edit = code_editor->get_text_edit();
+	CodeEdit *text_edit = code_editor->get_text_editor();
 	text_edit->get_syntax_highlighter()->update_cache();
 	text_edit->get_syntax_highlighter()->update_cache();
 
 
 	Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
 	Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
@@ -147,9 +147,9 @@ void TextEditor::set_edited_resource(const RES &p_res) {
 
 
 	text_file = p_res;
 	text_file = p_res;
 
 
-	code_editor->get_text_edit()->set_text(text_file->get_text());
-	code_editor->get_text_edit()->clear_undo_history();
-	code_editor->get_text_edit()->tag_saved_version();
+	code_editor->get_text_editor()->set_text(text_file->get_text());
+	code_editor->get_text_editor()->clear_undo_history();
+	code_editor->get_text_editor()->tag_saved_version();
 
 
 	emit_signal("name_changed");
 	emit_signal("name_changed");
 	code_editor->update_line_and_column();
 	code_editor->update_line_and_column();
@@ -171,13 +171,14 @@ void TextEditor::add_callback(const String &p_function, PackedStringArray p_args
 void TextEditor::set_debugger_active(bool p_active) {
 void TextEditor::set_debugger_active(bool p_active) {
 }
 }
 
 
-void TextEditor::get_breakpoints(List<int> *p_breakpoints) {
+Array TextEditor::get_breakpoints() {
+	return Array();
 }
 }
 
 
 void TextEditor::reload_text() {
 void TextEditor::reload_text() {
 	ERR_FAIL_COND(text_file.is_null());
 	ERR_FAIL_COND(text_file.is_null());
 
 
-	TextEdit *te = code_editor->get_text_edit();
+	CodeEdit *te = code_editor->get_text_editor();
 	int column = te->cursor_get_column();
 	int column = te->cursor_get_column();
 	int row = te->cursor_get_line();
 	int row = te->cursor_get_line();
 	int h = te->get_h_scroll();
 	int h = te->get_h_scroll();
@@ -207,7 +208,7 @@ void TextEditor::_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_next_bookmark"), BOOKMARK_GOTO_NEXT);
 	bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV);
 	bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV);
 
 
-	Array bookmark_list = code_editor->get_text_edit()->get_bookmarks_array();
+	Array bookmark_list = code_editor->get_text_editor()->get_bookmarked_lines();
 	if (bookmark_list.size() == 0) {
 	if (bookmark_list.size() == 0) {
 		return;
 		return;
 	}
 	}
@@ -215,7 +216,7 @@ void TextEditor::_update_bookmark_list() {
 	bookmarks_menu->add_separator();
 	bookmarks_menu->add_separator();
 
 
 	for (int i = 0; i < bookmark_list.size(); i++) {
 	for (int i = 0; i < bookmark_list.size(); i++) {
-		String line = code_editor->get_text_edit()->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.
 		// Limit the size of the line if too big.
 		if (line.length() > 50) {
 		if (line.length() > 50) {
 			line = line.substr(0, 50);
 			line = line.substr(0, 50);
@@ -235,12 +236,12 @@ void TextEditor::_bookmark_item_pressed(int p_idx) {
 }
 }
 
 
 void TextEditor::apply_code() {
 void TextEditor::apply_code() {
-	text_file->set_text(code_editor->get_text_edit()->get_text());
+	text_file->set_text(code_editor->get_text_editor()->get_text());
 }
 }
 
 
 bool TextEditor::is_unsaved() {
 bool TextEditor::is_unsaved() {
 	const bool unsaved =
 	const bool unsaved =
-			code_editor->get_text_edit()->get_version() != code_editor->get_text_edit()->get_saved_version() ||
+			code_editor->get_text_editor()->get_version() != code_editor->get_text_editor()->get_saved_version() ||
 			text_file->get_path().empty(); // In memory.
 			text_file->get_path().empty(); // In memory.
 	return unsaved;
 	return unsaved;
 }
 }
@@ -280,7 +281,7 @@ void TextEditor::convert_indent_to_tabs() {
 }
 }
 
 
 void TextEditor::tag_saved_version() {
 void TextEditor::tag_saved_version() {
-	code_editor->get_text_edit()->tag_saved_version();
+	code_editor->get_text_editor()->tag_saved_version();
 }
 }
 
 
 void TextEditor::goto_line(int p_line, bool p_with_error) {
 void TextEditor::goto_line(int p_line, bool p_with_error) {
@@ -300,7 +301,7 @@ void TextEditor::clear_executing_line() {
 }
 }
 
 
 void TextEditor::ensure_focus() {
 void TextEditor::ensure_focus() {
-	code_editor->get_text_edit()->grab_focus();
+	code_editor->get_text_editor()->grab_focus();
 }
 }
 
 
 Vector<String> TextEditor::get_functions() {
 Vector<String> TextEditor::get_functions() {
@@ -316,7 +317,7 @@ void TextEditor::update_settings() {
 }
 }
 
 
 void TextEditor::set_tooltip_request_func(String p_method, Object *p_obj) {
 void TextEditor::set_tooltip_request_func(String p_method, Object *p_obj) {
-	code_editor->get_text_edit()->set_tooltip_request_func(p_obj, p_method, this);
+	code_editor->get_text_editor()->set_tooltip_request_func(p_obj, p_method, this);
 }
 }
 
 
 Control *TextEditor::get_edit_menu() {
 Control *TextEditor::get_edit_menu() {
@@ -328,7 +329,7 @@ void TextEditor::clear_edit_menu() {
 }
 }
 
 
 void TextEditor::_edit_option(int p_op) {
 void TextEditor::_edit_option(int p_op) {
-	TextEdit *tx = code_editor->get_text_edit();
+	CodeEdit *tx = code_editor->get_text_editor();
 
 
 	switch (p_op) {
 	switch (p_op) {
 		case EDIT_UNDO: {
 		case EDIT_UNDO: {
@@ -416,14 +417,14 @@ void TextEditor::_edit_option(int p_op) {
 			code_editor->get_find_replace_bar()->popup_replace();
 			code_editor->get_find_replace_bar()->popup_replace();
 		} break;
 		} break;
 		case SEARCH_IN_FILES: {
 		case SEARCH_IN_FILES: {
-			String selected_text = code_editor->get_text_edit()->get_selection_text();
+			String selected_text = code_editor->get_text_editor()->get_selection_text();
 
 
 			// Yep, because it doesn't make sense to instance this dialog for every single script open...
 			// Yep, because it doesn't make sense to instance this dialog for every single script open...
 			// So this will be delegated to the ScriptEditor.
 			// So this will be delegated to the ScriptEditor.
 			emit_signal("search_in_files_requested", selected_text);
 			emit_signal("search_in_files_requested", selected_text);
 		} break;
 		} break;
 		case REPLACE_IN_FILES: {
 		case REPLACE_IN_FILES: {
-			String selected_text = code_editor->get_text_edit()->get_selection_text();
+			String selected_text = code_editor->get_text_editor()->get_selection_text();
 
 
 			emit_signal("replace_in_files_requested", selected_text);
 			emit_signal("replace_in_files_requested", selected_text);
 		} break;
 		} break;
@@ -470,7 +471,7 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 	if (mb.is_valid()) {
 	if (mb.is_valid()) {
 		if (mb->get_button_index() == BUTTON_RIGHT) {
 		if (mb->get_button_index() == BUTTON_RIGHT) {
 			int col, row;
 			int col, row;
-			TextEdit *tx = code_editor->get_text_edit();
+			CodeEdit *tx = code_editor->get_text_editor();
 			tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
 			tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
 
 
 			tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
 			tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
@@ -503,7 +504,7 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 
 
 	Ref<InputEventKey> k = ev;
 	Ref<InputEventKey> k = ev;
 	if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) {
 	if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) {
-		TextEdit *tx = code_editor->get_text_edit();
+		CodeEdit *tx = code_editor->get_text_editor();
 		int line = tx->cursor_get_line();
 		int line = tx->cursor_get_line();
 		_make_context_menu(tx->is_selection_active(), tx->can_fold(line), tx->is_folded(line), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos()));
 		_make_context_menu(tx->is_selection_active(), tx->can_fold(line), tx->is_folded(line), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos()));
 		context_menu->grab_focus();
 		context_menu->grab_focus();
@@ -552,8 +553,8 @@ TextEditor::TextEditor() {
 
 
 	update_settings();
 	update_settings();
 
 
-	code_editor->get_text_edit()->set_context_menu_enabled(false);
-	code_editor->get_text_edit()->connect("gui_input", callable_mp(this, &TextEditor::_text_edit_gui_input));
+	code_editor->get_text_editor()->set_context_menu_enabled(false);
+	code_editor->get_text_editor()->connect("gui_input", callable_mp(this, &TextEditor::_text_edit_gui_input));
 
 
 	context_menu = memnew(PopupMenu);
 	context_menu = memnew(PopupMenu);
 	add_child(context_menu);
 	add_child(context_menu);
@@ -649,7 +650,7 @@ TextEditor::TextEditor() {
 	goto_line_dialog = memnew(GotoLineDialog);
 	goto_line_dialog = memnew(GotoLineDialog);
 	add_child(goto_line_dialog);
 	add_child(goto_line_dialog);
 
 
-	code_editor->get_text_edit()->set_drag_forwarding(this);
+	code_editor->get_text_editor()->set_drag_forwarding(this);
 }
 }
 
 
 TextEditor::~TextEditor() {
 TextEditor::~TextEditor() {

+ 1 - 1
editor/plugins/text_editor.h

@@ -119,7 +119,7 @@ public:
 	virtual Variant get_edit_state() override;
 	virtual Variant get_edit_state() override;
 	virtual void set_edit_state(const Variant &p_state) override;
 	virtual void set_edit_state(const Variant &p_state) override;
 	virtual Vector<String> get_functions() override;
 	virtual Vector<String> get_functions() override;
-	virtual void get_breakpoints(List<int> *p_breakpoints) override;
+	virtual Array get_breakpoints() override;
 	virtual void goto_line(int p_line, bool p_with_error = false) override;
 	virtual void goto_line(int p_line, bool p_with_error = false) override;
 	void goto_line_selection(int p_line, int p_begin, int p_end);
 	void goto_line_selection(int p_line, int p_begin, int p_end);
 	virtual void set_executing_line(int p_line) override;
 	virtual void set_executing_line(int p_line) override;

+ 6 - 6
editor/plugins/visual_shader_editor_plugin.cpp

@@ -935,7 +935,7 @@ void VisualShaderEditor::_update_graph() {
 		}
 		}
 
 
 		if (is_expression) {
 		if (is_expression) {
-			TextEdit *expression_box = memnew(TextEdit);
+			CodeEdit *expression_box = memnew(CodeEdit);
 			Ref<CodeHighlighter> expression_syntax_highlighter;
 			Ref<CodeHighlighter> expression_syntax_highlighter;
 			expression_syntax_highlighter.instance();
 			expression_syntax_highlighter.instance();
 			expression_node->set_control(expression_box, 0);
 			expression_node->set_control(expression_box, 0);
@@ -968,7 +968,7 @@ void VisualShaderEditor::_update_graph() {
 
 
 			expression_box->set_text(expression);
 			expression_box->set_text(expression);
 			expression_box->set_context_menu_enabled(false);
 			expression_box->set_context_menu_enabled(false);
-			expression_box->set_show_line_numbers(true);
+			expression_box->set_draw_line_numbers(true);
 
 
 			expression_box->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_expression_focus_out), varray(expression_box, nodes[n_i]));
 			expression_box->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_expression_focus_out), varray(expression_box, nodes[n_i]));
 		}
 		}
@@ -1186,14 +1186,14 @@ void VisualShaderEditor::_remove_output_port(int p_node, int p_port) {
 	undo_redo->commit_action();
 	undo_redo->commit_action();
 }
 }
 
 
-void VisualShaderEditor::_expression_focus_out(Object *text_edit, int p_node) {
+void VisualShaderEditor::_expression_focus_out(Object *code_edit, int p_node) {
 	VisualShader::Type type = get_current_shader_type();
 	VisualShader::Type type = get_current_shader_type();
 	Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node);
 	Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node);
 	if (node.is_null()) {
 	if (node.is_null()) {
 		return;
 		return;
 	}
 	}
 
 
-	TextEdit *expression_box = Object::cast_to<TextEdit>(text_edit);
+	CodeEdit *expression_box = Object::cast_to<CodeEdit>(code_edit);
 
 
 	if (node->get_expression() == expression_box->get_text()) {
 	if (node->get_expression() == expression_box->get_text()) {
 		return;
 		return;
@@ -2550,14 +2550,14 @@ VisualShaderEditor::VisualShaderEditor() {
 	preview_vbox = memnew(VBoxContainer);
 	preview_vbox = memnew(VBoxContainer);
 	preview_vbox->set_visible(preview_showed);
 	preview_vbox->set_visible(preview_showed);
 	main_box->add_child(preview_vbox);
 	main_box->add_child(preview_vbox);
-	preview_text = memnew(TextEdit);
+	preview_text = memnew(CodeEdit);
 	syntax_highlighter.instance();
 	syntax_highlighter.instance();
 	preview_vbox->add_child(preview_text);
 	preview_vbox->add_child(preview_text);
 	preview_text->set_h_size_flags(SIZE_EXPAND_FILL);
 	preview_text->set_h_size_flags(SIZE_EXPAND_FILL);
 	preview_text->set_v_size_flags(SIZE_EXPAND_FILL);
 	preview_text->set_v_size_flags(SIZE_EXPAND_FILL);
 	preview_text->set_custom_minimum_size(Size2(400 * EDSCALE, 0));
 	preview_text->set_custom_minimum_size(Size2(400 * EDSCALE, 0));
 	preview_text->set_syntax_highlighter(syntax_highlighter);
 	preview_text->set_syntax_highlighter(syntax_highlighter);
-	preview_text->set_show_line_numbers(true);
+	preview_text->set_draw_line_numbers(true);
 	preview_text->set_readonly(true);
 	preview_text->set_readonly(true);
 
 
 	error_text = memnew(Label);
 	error_text = memnew(Label);

+ 2 - 2
editor/plugins/visual_shader_editor_plugin.h

@@ -115,7 +115,7 @@ class VisualShaderEditor : public VBoxContainer {
 	bool pending_update_preview;
 	bool pending_update_preview;
 	bool shader_error;
 	bool shader_error;
 	VBoxContainer *preview_vbox;
 	VBoxContainer *preview_vbox;
-	TextEdit *preview_text;
+	CodeEdit *preview_text;
 	Ref<CodeHighlighter> syntax_highlighter;
 	Ref<CodeHighlighter> syntax_highlighter;
 	Label *error_text;
 	Label *error_text;
 
 
@@ -304,7 +304,7 @@ class VisualShaderEditor : public VBoxContainer {
 	void _change_output_port_type(int p_type, int p_node, int p_port);
 	void _change_output_port_type(int p_type, int p_node, int p_port);
 	void _change_output_port_name(const String &p_text, Object *line_edit, int p_node, int p_port);
 	void _change_output_port_name(const String &p_text, Object *line_edit, int p_node, int p_port);
 
 
-	void _expression_focus_out(Object *text_edit, int p_node);
+	void _expression_focus_out(Object *code_edit, int p_node);
 
 
 	void _set_node_size(int p_type, int p_node, const Size2 &p_size);
 	void _set_node_size(int p_type, int p_node, const Size2 &p_size);
 	void _node_resized(const Vector2 &p_new_size, int p_type, int p_node);
 	void _node_resized(const Vector2 &p_new_size, int p_type, int p_node);

+ 4 - 2
modules/visual_script/visual_script_editor.cpp

@@ -2682,7 +2682,8 @@ void VisualScriptEditor::reload(bool p_soft) {
 	_update_graph();
 	_update_graph();
 }
 }
 
 
-void VisualScriptEditor::get_breakpoints(List<int> *p_breakpoints) {
+Array VisualScriptEditor::get_breakpoints() {
+	Array breakpoints;
 	List<StringName> functions;
 	List<StringName> functions;
 	script->get_function_list(&functions);
 	script->get_function_list(&functions);
 	for (List<StringName>::Element *E = functions.front(); E; E = E->next()) {
 	for (List<StringName>::Element *E = functions.front(); E; E = E->next()) {
@@ -2691,10 +2692,11 @@ void VisualScriptEditor::get_breakpoints(List<int> *p_breakpoints) {
 		for (List<int>::Element *F = nodes.front(); F; F = F->next()) {
 		for (List<int>::Element *F = nodes.front(); F; F = F->next()) {
 			Ref<VisualScriptNode> vsn = script->get_node(E->get(), F->get());
 			Ref<VisualScriptNode> vsn = script->get_node(E->get(), F->get());
 			if (vsn->is_breakpoint()) {
 			if (vsn->is_breakpoint()) {
-				p_breakpoints->push_back(F->get() - 1); //subtract 1 because breakpoints in text start from zero
+				breakpoints.push_back(F->get() - 1); //subtract 1 because breakpoints in text start from zero
 			}
 			}
 		}
 		}
 	}
 	}
+	return breakpoints;
 }
 }
 
 
 void VisualScriptEditor::add_callback(const String &p_function, PackedStringArray p_args) {
 void VisualScriptEditor::add_callback(const String &p_function, PackedStringArray p_args) {

+ 1 - 1
modules/visual_script/visual_script_editor.h

@@ -312,7 +312,7 @@ public:
 	virtual void ensure_focus() override;
 	virtual void ensure_focus() override;
 	virtual void tag_saved_version() override;
 	virtual void tag_saved_version() override;
 	virtual void reload(bool p_soft) override;
 	virtual void reload(bool p_soft) override;
-	virtual void get_breakpoints(List<int> *p_breakpoints) override;
+	virtual Array get_breakpoints() override;
 	virtual void add_callback(const String &p_function, PackedStringArray p_args) override;
 	virtual void add_callback(const String &p_function, PackedStringArray p_args) override;
 	virtual void update_settings() override;
 	virtual void update_settings() override;
 	virtual bool show_members_overview() override;
 	virtual bool show_members_overview() override;

+ 444 - 0
scene/gui/code_edit.cpp

@@ -0,0 +1,444 @@
+/*************************************************************************/
+/*  code_edit.cpp                                                        */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "code_edit.h"
+
+void CodeEdit::_notification(int p_what) {
+	switch (p_what) {
+		case NOTIFICATION_THEME_CHANGED:
+		case NOTIFICATION_ENTER_TREE: {
+			set_gutter_width(main_gutter, cache.row_height);
+			set_gutter_width(line_number_gutter, (line_number_digits + 1) * cache.font->get_char_size('0').width);
+			set_gutter_width(fold_gutter, cache.row_height / 1.2);
+
+			breakpoint_color = get_theme_color("breakpoint_color");
+			breakpoint_icon = get_theme_icon("breakpoint");
+
+			bookmark_color = get_theme_color("bookmark_color");
+			bookmark_icon = get_theme_icon("bookmark");
+
+			executing_line_color = get_theme_color("executing_line_color");
+			executing_line_icon = get_theme_icon("executing_line");
+
+			line_number_color = get_theme_color("line_number_color");
+
+			folding_color = get_theme_color("code_folding_color");
+			can_fold_icon = get_theme_icon("can_fold");
+			folded_icon = get_theme_icon("folded");
+		} break;
+		case NOTIFICATION_DRAW: {
+		} break;
+	}
+}
+
+/* Main Gutter */
+void CodeEdit::_update_draw_main_gutter() {
+	set_gutter_draw(main_gutter, draw_breakpoints || draw_bookmarks || draw_executing_lines);
+}
+
+void CodeEdit::set_draw_breakpoints_gutter(bool p_draw) {
+	draw_breakpoints = p_draw;
+	set_gutter_clickable(main_gutter, p_draw);
+	_update_draw_main_gutter();
+}
+
+bool CodeEdit::is_drawing_breakpoints_gutter() const {
+	return draw_breakpoints;
+}
+
+void CodeEdit::set_draw_bookmarks_gutter(bool p_draw) {
+	draw_bookmarks = p_draw;
+	_update_draw_main_gutter();
+}
+
+bool CodeEdit::is_drawing_bookmarks_gutter() const {
+	return draw_bookmarks;
+}
+
+void CodeEdit::set_draw_executing_lines_gutter(bool p_draw) {
+	draw_executing_lines = p_draw;
+	_update_draw_main_gutter();
+}
+
+bool CodeEdit::is_drawing_executing_lines_gutter() const {
+	return draw_executing_lines;
+}
+
+void CodeEdit::_main_gutter_draw_callback(int p_line, int p_gutter, const Rect2 &p_region) {
+	if (draw_breakpoints && is_line_breakpointed(p_line)) {
+		int padding = p_region.size.x / 6;
+
+		Rect2 breakpoint_region = p_region;
+		breakpoint_region.position += Point2(padding, padding);
+		breakpoint_region.size -= Point2(padding, padding) * 2;
+		breakpoint_icon->draw_rect(get_canvas_item(), breakpoint_region, false, breakpoint_color);
+	}
+
+	if (draw_bookmarks && is_line_bookmarked(p_line)) {
+		int horizontal_padding = p_region.size.x / 2;
+		int vertical_padding = p_region.size.y / 4;
+
+		Rect2 bookmark_region = p_region;
+		bookmark_region.position += Point2(horizontal_padding, 0);
+		bookmark_region.size -= Point2(horizontal_padding * 1.1, vertical_padding);
+		bookmark_icon->draw_rect(get_canvas_item(), bookmark_region, false, bookmark_color);
+	}
+
+	if (draw_executing_lines && is_line_executing(p_line)) {
+		int horizontal_padding = p_region.size.x / 10;
+		int vertical_padding = p_region.size.y / 4;
+
+		Rect2 executing_line_region = p_region;
+		executing_line_region.position += Point2(horizontal_padding, vertical_padding);
+		executing_line_region.size -= Point2(horizontal_padding, vertical_padding) * 2;
+		executing_line_icon->draw_rect(get_canvas_item(), executing_line_region, false, executing_line_color);
+	}
+}
+
+// Breakpoints
+void CodeEdit::set_line_as_breakpoint(int p_line, bool p_breakpointed) {
+	int mask = get_line_gutter_metadata(p_line, main_gutter);
+	set_line_gutter_metadata(p_line, main_gutter, p_breakpointed ? mask | MAIN_GUTTER_BREAKPOINT : mask & ~MAIN_GUTTER_BREAKPOINT);
+	if (p_breakpointed) {
+		breakpointed_lines[p_line] = true;
+	} else if (breakpointed_lines.has(p_line)) {
+		breakpointed_lines.erase(p_line);
+	}
+	emit_signal("breakpoint_toggled", p_line);
+}
+
+bool CodeEdit::is_line_breakpointed(int p_line) const {
+	return (int)get_line_gutter_metadata(p_line, main_gutter) & MAIN_GUTTER_BREAKPOINT;
+}
+
+void CodeEdit::clear_breakpointed_lines() {
+	for (int i = 0; i < get_line_count(); i++) {
+		if (is_line_breakpointed(i)) {
+			set_line_as_breakpoint(i, false);
+		}
+	}
+}
+
+Array CodeEdit::get_breakpointed_lines() const {
+	Array ret;
+	for (int i = 0; i < get_line_count(); i++) {
+		if (is_line_breakpointed(i)) {
+			ret.append(i);
+		}
+	}
+	return ret;
+}
+
+// Bookmarks
+void CodeEdit::set_line_as_bookmarked(int p_line, bool p_bookmarked) {
+	int mask = get_line_gutter_metadata(p_line, main_gutter);
+	set_line_gutter_metadata(p_line, main_gutter, p_bookmarked ? mask | MAIN_GUTTER_BOOKMARK : mask & ~MAIN_GUTTER_BOOKMARK);
+}
+
+bool CodeEdit::is_line_bookmarked(int p_line) const {
+	return (int)get_line_gutter_metadata(p_line, main_gutter) & MAIN_GUTTER_BOOKMARK;
+}
+
+void CodeEdit::clear_bookmarked_lines() {
+	for (int i = 0; i < get_line_count(); i++) {
+		if (is_line_bookmarked(i)) {
+			set_line_as_bookmarked(i, false);
+		}
+	}
+}
+
+Array CodeEdit::get_bookmarked_lines() const {
+	Array ret;
+	for (int i = 0; i < get_line_count(); i++) {
+		if (is_line_bookmarked(i)) {
+			ret.append(i);
+		}
+	}
+	return ret;
+}
+
+// executing lines
+void CodeEdit::set_line_as_executing(int p_line, bool p_executing) {
+	int mask = get_line_gutter_metadata(p_line, main_gutter);
+	set_line_gutter_metadata(p_line, main_gutter, p_executing ? mask | MAIN_GUTTER_EXECUTING : mask & ~MAIN_GUTTER_EXECUTING);
+}
+
+bool CodeEdit::is_line_executing(int p_line) const {
+	return (int)get_line_gutter_metadata(p_line, main_gutter) & MAIN_GUTTER_EXECUTING;
+}
+
+void CodeEdit::clear_executing_lines() {
+	for (int i = 0; i < get_line_count(); i++) {
+		if (is_line_executing(i)) {
+			set_line_as_executing(i, false);
+		}
+	}
+}
+
+Array CodeEdit::get_executing_lines() const {
+	Array ret;
+	for (int i = 0; i < get_line_count(); i++) {
+		if (is_line_executing(i)) {
+			ret.append(i);
+		}
+	}
+	return ret;
+}
+
+/* Line numbers */
+void CodeEdit::set_draw_line_numbers(bool p_draw) {
+	set_gutter_draw(line_number_gutter, p_draw);
+}
+
+bool CodeEdit::is_draw_line_numbers_enabled() const {
+	return is_gutter_drawn(line_number_gutter);
+}
+
+void CodeEdit::set_line_numbers_zero_padded(bool p_zero_padded) {
+	p_zero_padded ? line_number_padding = "0" : line_number_padding = " ";
+	update();
+}
+
+bool CodeEdit::is_line_numbers_zero_padded() const {
+	return line_number_padding == "0";
+}
+
+void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2 &p_region) {
+	String fc = String::num(p_line + 1).lpad(line_number_digits, line_number_padding);
+
+	int yofs = p_region.position.y + (cache.row_height - cache.font->get_height()) / 2;
+	Color number_color = get_line_gutter_item_color(p_line, line_number_gutter);
+	if (number_color == Color(1, 1, 1)) {
+		number_color = line_number_color;
+	}
+	cache.font->draw(get_canvas_item(), Point2(p_region.position.x, yofs + cache.font->get_ascent()), fc, number_color);
+}
+
+/* Fold Gutter */
+void CodeEdit::set_draw_fold_gutter(bool p_draw) {
+	set_gutter_draw(fold_gutter, p_draw);
+}
+
+bool CodeEdit::is_drawing_fold_gutter() const {
+	return is_gutter_drawn(fold_gutter);
+}
+
+void CodeEdit::_fold_gutter_draw_callback(int p_line, int p_gutter, Rect2 p_region) {
+	if (!can_fold(p_line) && !is_folded(p_line)) {
+		set_line_gutter_clickable(p_line, fold_gutter, false);
+		return;
+	}
+	set_line_gutter_clickable(p_line, fold_gutter, true);
+
+	int horizontal_padding = p_region.size.x / 10;
+	int vertical_padding = p_region.size.y / 6;
+
+	p_region.position += Point2(horizontal_padding, vertical_padding);
+	p_region.size -= Point2(horizontal_padding, vertical_padding) * 2;
+
+	if (can_fold(p_line)) {
+		can_fold_icon->draw_rect(get_canvas_item(), p_region, false, folding_color);
+		return;
+	}
+	folded_icon->draw_rect(get_canvas_item(), p_region, false, folding_color);
+}
+
+void CodeEdit::_bind_methods() {
+	/* Main Gutter */
+	ClassDB::bind_method(D_METHOD("_main_gutter_draw_callback"), &CodeEdit::_main_gutter_draw_callback);
+
+	ClassDB::bind_method(D_METHOD("set_draw_breakpoints_gutter", "enable"), &CodeEdit::set_draw_breakpoints_gutter);
+	ClassDB::bind_method(D_METHOD("is_drawing_breakpoints_gutter"), &CodeEdit::is_drawing_breakpoints_gutter);
+
+	ClassDB::bind_method(D_METHOD("set_draw_bookmarks_gutter", "enable"), &CodeEdit::set_draw_bookmarks_gutter);
+	ClassDB::bind_method(D_METHOD("is_drawing_bookmarks_gutter"), &CodeEdit::is_drawing_bookmarks_gutter);
+
+	ClassDB::bind_method(D_METHOD("set_draw_executing_lines_gutter", "enable"), &CodeEdit::set_draw_executing_lines_gutter);
+	ClassDB::bind_method(D_METHOD("is_drawing_executing_lines_gutter"), &CodeEdit::is_drawing_executing_lines_gutter);
+
+	// Breakpoints
+	ClassDB::bind_method(D_METHOD("set_line_as_breakpoint", "line", "breakpointed"), &CodeEdit::set_line_as_breakpoint);
+	ClassDB::bind_method(D_METHOD("is_line_breakpointed", "line"), &CodeEdit::is_line_breakpointed);
+	ClassDB::bind_method(D_METHOD("clear_breakpointed_lines"), &CodeEdit::clear_breakpointed_lines);
+	ClassDB::bind_method(D_METHOD("get_breakpointed_lines"), &CodeEdit::get_breakpointed_lines);
+
+	// Bookmarks
+	ClassDB::bind_method(D_METHOD("set_line_as_bookmarked", "line", "bookmarked"), &CodeEdit::set_line_as_bookmarked);
+	ClassDB::bind_method(D_METHOD("is_line_bookmarked", "line"), &CodeEdit::is_line_bookmarked);
+	ClassDB::bind_method(D_METHOD("clear_bookmarked_lines"), &CodeEdit::clear_bookmarked_lines);
+	ClassDB::bind_method(D_METHOD("get_bookmarked_lines"), &CodeEdit::get_bookmarked_lines);
+
+	// executing lines
+	ClassDB::bind_method(D_METHOD("set_line_as_executing", "line", "executing"), &CodeEdit::set_line_as_executing);
+	ClassDB::bind_method(D_METHOD("is_line_executing", "line"), &CodeEdit::is_line_executing);
+	ClassDB::bind_method(D_METHOD("clear_executing_lines"), &CodeEdit::clear_executing_lines);
+	ClassDB::bind_method(D_METHOD("get_executing_lines"), &CodeEdit::get_executing_lines);
+
+	/* Line numbers */
+	ClassDB::bind_method(D_METHOD("_line_number_draw_callback"), &CodeEdit::_line_number_draw_callback);
+
+	ClassDB::bind_method(D_METHOD("set_draw_line_numbers", "enable"), &CodeEdit::set_draw_line_numbers);
+	ClassDB::bind_method(D_METHOD("is_draw_line_numbers_enabled"), &CodeEdit::is_draw_line_numbers_enabled);
+	ClassDB::bind_method(D_METHOD("set_line_numbers_zero_padded", "enable"), &CodeEdit::set_line_numbers_zero_padded);
+	ClassDB::bind_method(D_METHOD("is_line_numbers_zero_padded"), &CodeEdit::is_line_numbers_zero_padded);
+
+	/* Fold Gutter */
+	ClassDB::bind_method(D_METHOD("_fold_gutter_draw_callback"), &CodeEdit::_fold_gutter_draw_callback);
+
+	ClassDB::bind_method(D_METHOD("set_draw_fold_gutter", "enable"), &CodeEdit::set_draw_fold_gutter);
+	ClassDB::bind_method(D_METHOD("is_drawing_fold_gutter"), &CodeEdit::is_drawing_fold_gutter);
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_breakpoints_gutter"), "set_draw_breakpoints_gutter", "is_drawing_breakpoints_gutter");
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_bookmarks"), "set_draw_bookmarks_gutter", "is_drawing_bookmarks_gutter");
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_executing_lines"), "set_draw_executing_lines_gutter", "is_drawing_executing_lines_gutter");
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_line_numbers"), "set_draw_line_numbers", "is_draw_line_numbers_enabled");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "zero_pad_line_numbers"), "set_line_numbers_zero_padded", "is_line_numbers_zero_padded");
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_fold_gutter"), "set_draw_fold_gutter", "is_drawing_fold_gutter");
+
+	ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "line")));
+}
+
+void CodeEdit::_gutter_clicked(int p_line, int p_gutter) {
+	if (p_gutter == main_gutter) {
+		if (draw_breakpoints) {
+			set_line_as_breakpoint(p_line, !is_line_breakpointed(p_line));
+		}
+		return;
+	}
+
+	if (p_gutter == line_number_gutter) {
+		cursor_set_line(p_line);
+		return;
+	}
+
+	if (p_gutter == fold_gutter) {
+		if (is_folded(p_line)) {
+			unfold_line(p_line);
+		} else if (can_fold(p_line)) {
+			fold_line(p_line);
+		}
+		return;
+	}
+}
+
+void CodeEdit::_lines_edited_from(int p_from_line, int p_to_line) {
+	if (p_from_line == p_to_line) {
+		return;
+	}
+
+	int lc = get_line_count();
+	line_number_digits = 1;
+	while (lc /= 10) {
+		line_number_digits++;
+	}
+	set_gutter_width(line_number_gutter, (line_number_digits + 1) * cache.font->get_char_size('0').width);
+
+	int from_line = MIN(p_from_line, p_to_line);
+	int line_count = (p_to_line - p_from_line);
+	List<int> breakpoints;
+	breakpointed_lines.get_key_list(&breakpoints);
+	for (const List<int>::Element *E = breakpoints.front(); E; E = E->next()) {
+		int line = E->get();
+		if (line <= from_line) {
+			continue;
+		}
+		breakpointed_lines.erase(line);
+
+		emit_signal("breakpoint_toggled", line);
+		if (line_count > 0 || line >= p_from_line) {
+			emit_signal("breakpoint_toggled", line + line_count);
+			breakpointed_lines[line + line_count] = true;
+			continue;
+		}
+	}
+}
+
+void CodeEdit::_update_gutter_indexes() {
+	for (int i = 0; i < get_gutter_count(); i++) {
+		if (get_gutter_name(i) == "main_gutter") {
+			main_gutter = i;
+			continue;
+		}
+
+		if (get_gutter_name(i) == "line_numbers") {
+			line_number_gutter = i;
+			continue;
+		}
+
+		if (get_gutter_name(i) == "fold_gutter") {
+			fold_gutter = i;
+			continue;
+		}
+	}
+}
+
+CodeEdit::CodeEdit() {
+	/* Gutters */
+	int gutter_idx = 0;
+
+	/* Main Gutter */
+	add_gutter();
+	set_gutter_name(gutter_idx, "main_gutter");
+	set_gutter_draw(gutter_idx, false);
+	set_gutter_overwritable(gutter_idx, true);
+	set_gutter_type(gutter_idx, GUTTER_TPYE_CUSTOM);
+	set_gutter_custom_draw(gutter_idx, this, "_main_gutter_draw_callback");
+	gutter_idx++;
+
+	/* Line numbers */
+	add_gutter();
+	set_gutter_name(gutter_idx, "line_numbers");
+	set_gutter_draw(gutter_idx, false);
+	set_gutter_type(gutter_idx, GUTTER_TPYE_CUSTOM);
+	set_gutter_custom_draw(gutter_idx, this, "_line_number_draw_callback");
+	gutter_idx++;
+
+	/* Fold Gutter */
+	add_gutter();
+	set_gutter_name(gutter_idx, "fold_gutter");
+	set_gutter_draw(gutter_idx, false);
+	set_gutter_type(gutter_idx, GUTTER_TPYE_CUSTOM);
+	set_gutter_custom_draw(gutter_idx, this, "_fold_gutter_draw_callback");
+	gutter_idx++;
+
+	connect("lines_edited_from", callable_mp(this, &CodeEdit::_lines_edited_from));
+	connect("gutter_clicked", callable_mp(this, &CodeEdit::_gutter_clicked));
+
+	connect("gutter_added", callable_mp(this, &CodeEdit::_update_gutter_indexes));
+	connect("gutter_removed", callable_mp(this, &CodeEdit::_update_gutter_indexes));
+	_update_gutter_indexes();
+}
+
+CodeEdit::~CodeEdit() {
+}

+ 135 - 0
scene/gui/code_edit.h

@@ -0,0 +1,135 @@
+/*************************************************************************/
+/*  code_edit.h                                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef CODEEDIT_H
+#define CODEEDIT_H
+
+#include "scene/gui/text_edit.h"
+
+class CodeEdit : public TextEdit {
+	GDCLASS(CodeEdit, TextEdit)
+
+private:
+	/* Main Gutter */
+	enum MainGutterType {
+		MAIN_GUTTER_BREAKPOINT = 0x01,
+		MAIN_GUTTER_BOOKMARK = 0x02,
+		MAIN_GUTTER_EXECUTING = 0x04
+	};
+
+	int main_gutter = -1;
+	void _update_draw_main_gutter();
+	void _main_gutter_draw_callback(int p_line, int p_gutter, const Rect2 &p_region);
+
+	// breakpoints
+	HashMap<int, bool> breakpointed_lines;
+	bool draw_breakpoints = false;
+	Color breakpoint_color = Color(1, 1, 1);
+	Ref<Texture2D> breakpoint_icon = Ref<Texture2D>();
+
+	// bookmarks
+	bool draw_bookmarks = false;
+	Color bookmark_color = Color(1, 1, 1);
+	Ref<Texture2D> bookmark_icon = Ref<Texture2D>();
+
+	// executing lines
+	bool draw_executing_lines = false;
+	Color executing_line_color = Color(1, 1, 1);
+	Ref<Texture2D> executing_line_icon = Ref<Texture2D>();
+
+	/* Line numbers */
+	int line_number_gutter = -1;
+	int line_number_digits = 0;
+	String line_number_padding = " ";
+	Color line_number_color = Color(1, 1, 1);
+	void _line_number_draw_callback(int p_line, int p_gutter, const Rect2 &p_region);
+
+	/* Fold Gutter */
+	int fold_gutter = -1;
+	bool draw_fold_gutter = false;
+	Color folding_color = Color(1, 1, 1);
+	Ref<Texture2D> can_fold_icon = Ref<Texture2D>();
+	Ref<Texture2D> folded_icon = Ref<Texture2D>();
+	void _fold_gutter_draw_callback(int p_line, int p_gutter, Rect2 p_region);
+
+	void _gutter_clicked(int p_line, int p_gutter);
+	void _lines_edited_from(int p_from_line, int p_to_line);
+
+	void _update_gutter_indexes();
+
+protected:
+	void _notification(int p_what);
+
+	static void _bind_methods();
+
+public:
+	/* Main Gutter */
+	void set_draw_breakpoints_gutter(bool p_draw);
+	bool is_drawing_breakpoints_gutter() const;
+
+	void set_draw_bookmarks_gutter(bool p_draw);
+	bool is_drawing_bookmarks_gutter() const;
+
+	void set_draw_executing_lines_gutter(bool p_draw);
+	bool is_drawing_executing_lines_gutter() const;
+
+	// breakpoints
+	void set_line_as_breakpoint(int p_line, bool p_breakpointed);
+	bool is_line_breakpointed(int p_line) const;
+	void clear_breakpointed_lines();
+	Array get_breakpointed_lines() const;
+
+	// bookmarks
+	void set_line_as_bookmarked(int p_line, bool p_bookmarked);
+	bool is_line_bookmarked(int p_line) const;
+	void clear_bookmarked_lines();
+	Array get_bookmarked_lines() const;
+
+	// executing lines
+	void set_line_as_executing(int p_line, bool p_executing);
+	bool is_line_executing(int p_line) const;
+	void clear_executing_lines();
+	Array get_executing_lines() const;
+
+	/* Line numbers */
+	void set_draw_line_numbers(bool p_draw);
+	bool is_draw_line_numbers_enabled() const;
+	void set_line_numbers_zero_padded(bool p_zero_padded);
+	bool is_line_numbers_zero_padded() const;
+
+	/* Fold gutter */
+	void set_draw_fold_gutter(bool p_draw);
+	bool is_drawing_fold_gutter() const;
+
+	CodeEdit();
+	~CodeEdit();
+};
+
+#endif // CODEEDIT_H

File diff suppressed because it is too large
+ 317 - 459
scene/gui/text_edit.cpp


+ 139 - 142
scene/gui/text_edit.h

@@ -41,28 +41,53 @@ class TextEdit : public Control {
 	GDCLASS(TextEdit, Control);
 	GDCLASS(TextEdit, Control);
 
 
 public:
 public:
+	enum GutterType {
+		GUTTER_TYPE_STRING,
+		GUTTER_TPYE_ICON,
+		GUTTER_TPYE_CUSTOM
+	};
+
+private:
+	struct GutterInfo {
+		GutterType type = GutterType::GUTTER_TYPE_STRING;
+		String name = "";
+		int width = 24;
+		bool draw = true;
+		bool clickable = false;
+		bool overwritable = false;
+
+		ObjectID custom_draw_obj = ObjectID();
+		StringName custom_draw_callback;
+	};
+	Vector<GutterInfo> gutters;
+	int gutters_width = 0;
+	int gutter_padding = 0;
+
+	void _update_gutter_width();
+
 	class Text {
 	class Text {
 	public:
 	public:
+		struct Gutter {
+			Variant metadata;
+			bool clickable = false;
+
+			Ref<Texture2D> icon = Ref<Texture2D>();
+			String text = "";
+			Color color = Color(1, 1, 1);
+		};
+
 		struct Line {
 		struct Line {
+			Vector<Gutter> gutters;
+
 			int width_cache : 24;
 			int width_cache : 24;
 			bool marked : 1;
 			bool marked : 1;
-			bool breakpoint : 1;
-			bool bookmark : 1;
 			bool hidden : 1;
 			bool hidden : 1;
-			bool safe : 1;
-			bool has_info : 1;
 			int wrap_amount_cache : 24;
 			int wrap_amount_cache : 24;
-			Ref<Texture2D> info_icon;
-			String info;
 			String data;
 			String data;
 			Line() {
 			Line() {
 				width_cache = 0;
 				width_cache = 0;
 				marked = false;
 				marked = false;
-				breakpoint = false;
-				bookmark = false;
 				hidden = false;
 				hidden = false;
-				safe = false;
-				has_info = false;
 				wrap_amount_cache = 0;
 				wrap_amount_cache = 0;
 			}
 			}
 		};
 		};
@@ -70,7 +95,8 @@ public:
 	private:
 	private:
 		mutable Vector<Line> text;
 		mutable Vector<Line> text;
 		Ref<Font> font;
 		Ref<Font> font;
-		int indent_size;
+		int indent_size = 4;
+		int gutter_count = 0;
 
 
 		void _update_line_cache(int p_line) const;
 		void _update_line_cache(int p_line) const;
 
 
@@ -85,38 +111,37 @@ public:
 		void set(int p_line, const String &p_text);
 		void set(int p_line, const String &p_text);
 		void set_marked(int p_line, bool p_marked) { text.write[p_line].marked = p_marked; }
 		void set_marked(int p_line, bool p_marked) { text.write[p_line].marked = p_marked; }
 		bool is_marked(int p_line) const { return text[p_line].marked; }
 		bool is_marked(int p_line) const { return text[p_line].marked; }
-		void set_bookmark(int p_line, bool p_bookmark) { text.write[p_line].bookmark = p_bookmark; }
-		bool is_bookmark(int p_line) const { return text[p_line].bookmark; }
-		void set_breakpoint(int p_line, bool p_breakpoint) { text.write[p_line].breakpoint = p_breakpoint; }
-		bool is_breakpoint(int p_line) const { return text[p_line].breakpoint; }
 		void set_hidden(int p_line, bool p_hidden) { text.write[p_line].hidden = p_hidden; }
 		void set_hidden(int p_line, bool p_hidden) { text.write[p_line].hidden = p_hidden; }
 		bool is_hidden(int p_line) const { return text[p_line].hidden; }
 		bool is_hidden(int p_line) const { return text[p_line].hidden; }
-		void set_safe(int p_line, bool p_safe) { text.write[p_line].safe = p_safe; }
-		bool is_safe(int p_line) const { return text[p_line].safe; }
-		void set_info_icon(int p_line, Ref<Texture2D> p_icon, String p_info) {
-			if (p_icon.is_null()) {
-				text.write[p_line].has_info = false;
-				return;
-			}
-			text.write[p_line].info_icon = p_icon;
-			text.write[p_line].info = p_info;
-			text.write[p_line].has_info = true;
-		}
-		bool has_info_icon(int p_line) const { return text[p_line].has_info; }
-		const Ref<Texture2D> &get_info_icon(int p_line) const { return text[p_line].info_icon; }
-		const String &get_info(int p_line) const { return text[p_line].info; }
 		void insert(int p_at, const String &p_text);
 		void insert(int p_at, const String &p_text);
 		void remove(int p_at);
 		void remove(int p_at);
 		int size() const { return text.size(); }
 		int size() const { return text.size(); }
 		void clear();
 		void clear();
 		void clear_width_cache();
 		void clear_width_cache();
 		void clear_wrap_cache();
 		void clear_wrap_cache();
-		void clear_info_icons();
 		_FORCE_INLINE_ const String &operator[](int p_line) const { return text[p_line].data; }
 		_FORCE_INLINE_ const String &operator[](int p_line) const { return text[p_line].data; }
-		Text() { indent_size = 4; }
+
+		/* Gutters. */
+		void add_gutter(int p_at);
+		void remove_gutter(int p_gutter);
+		void move_gutters(int p_from_line, int p_to_line);
+
+		void set_line_gutter_metadata(int p_line, int p_gutter, const Variant &p_metadata) { text.write[p_line].gutters.write[p_gutter].metadata = p_metadata; }
+		const Variant &get_line_gutter_metadata(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].metadata; }
+
+		void set_line_gutter_text(int p_line, int p_gutter, const String &p_text) { text.write[p_line].gutters.write[p_gutter].text = p_text; }
+		const String &get_line_gutter_text(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].text; }
+
+		void set_line_gutter_icon(int p_line, int p_gutter, Ref<Texture2D> p_icon) { text.write[p_line].gutters.write[p_gutter].icon = p_icon; }
+		const Ref<Texture2D> &get_line_gutter_icon(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].icon; }
+
+		void set_line_gutter_item_color(int p_line, int p_gutter, const Color &p_color) { text.write[p_line].gutters.write[p_gutter].color = p_color; }
+		const Color &get_line_gutter_item_color(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].color; }
+
+		void set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable) { text.write[p_line].gutters.write[p_gutter].clickable = p_clickable; }
+		bool is_line_gutter_clickable(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].clickable; }
 	};
 	};
 
 
-private:
 	struct Cursor {
 	struct Cursor {
 		int last_fit_x;
 		int last_fit_x;
 		int line, column; ///< cursor
 		int line, column; ///< cursor
@@ -169,60 +194,6 @@ private:
 		}
 		}
 	} selection;
 	} selection;
 
 
-	struct Cache {
-		Ref<Texture2D> tab_icon;
-		Ref<Texture2D> space_icon;
-		Ref<Texture2D> can_fold_icon;
-		Ref<Texture2D> folded_icon;
-		Ref<Texture2D> folded_eol_icon;
-		Ref<Texture2D> executing_icon;
-		Ref<StyleBox> style_normal;
-		Ref<StyleBox> style_focus;
-		Ref<StyleBox> style_readonly;
-		Ref<Font> font;
-		Color completion_background_color;
-		Color completion_selected_color;
-		Color completion_existing_color;
-		Color completion_font_color;
-		Color caret_color;
-		Color caret_background_color;
-		Color line_number_color;
-		Color safe_line_number_color;
-		Color font_color;
-		Color font_color_selected;
-		Color font_color_readonly;
-		Color selection_color;
-		Color mark_color;
-		Color bookmark_color;
-		Color breakpoint_color;
-		Color executing_line_color;
-		Color code_folding_color;
-		Color current_line_color;
-		Color line_length_guideline_color;
-		Color brace_mismatch_color;
-		Color word_highlighted_color;
-		Color search_result_color;
-		Color search_result_border_color;
-		Color background_color;
-
-		int row_height;
-		int line_spacing;
-		int line_number_w;
-		int breakpoint_gutter_width;
-		int fold_gutter_width;
-		int info_gutter_width;
-		int minimap_width;
-		Cache() {
-			row_height = 0;
-			line_spacing = 0;
-			line_number_w = 0;
-			breakpoint_gutter_width = 0;
-			fold_gutter_width = 0;
-			info_gutter_width = 0;
-			minimap_width = 0;
-		}
-	} cache;
-
 	Map<int, Dictionary> syntax_highlighting_cache;
 	Map<int, Dictionary> syntax_highlighting_cache;
 
 
 	struct TextOperation {
 	struct TextOperation {
@@ -318,19 +289,10 @@ private:
 	bool cursor_changed_dirty;
 	bool cursor_changed_dirty;
 	bool text_changed_dirty;
 	bool text_changed_dirty;
 	bool undo_enabled;
 	bool undo_enabled;
-	bool line_numbers;
-	bool line_numbers_zero_padded;
 	bool line_length_guidelines;
 	bool line_length_guidelines;
 	int line_length_guideline_soft_col;
 	int line_length_guideline_soft_col;
 	int line_length_guideline_hard_col;
 	int line_length_guideline_hard_col;
-	bool draw_bookmark_gutter;
-	bool draw_breakpoint_gutter;
-	int breakpoint_gutter_width;
-	bool draw_fold_gutter;
-	int fold_gutter_width;
 	bool hiding_enabled;
 	bool hiding_enabled;
-	bool draw_info_gutter;
-	int info_gutter_width;
 	bool draw_minimap;
 	bool draw_minimap;
 	int minimap_width;
 	int minimap_width;
 	Point2 minimap_char_size;
 	Point2 minimap_char_size;
@@ -385,11 +347,8 @@ private:
 
 
 	bool context_menu_enabled;
 	bool context_menu_enabled;
 	bool shortcut_keys_enabled;
 	bool shortcut_keys_enabled;
-
 	bool virtual_keyboard_enabled = true;
 	bool virtual_keyboard_enabled = true;
 
 
-	int executing_line;
-
 	void _generate_context_menu();
 	void _generate_context_menu();
 
 
 	int get_visible_rows() const;
 	int get_visible_rows() const;
@@ -447,8 +406,6 @@ private:
 	Size2 get_minimum_size() const override;
 	Size2 get_minimum_size() const override;
 	int _get_control_height() const;
 	int _get_control_height() const;
 
 
-	int get_row_height() const;
-
 	void _reset_caret_blink_timer();
 	void _reset_caret_blink_timer();
 	void _toggle_draw_caret();
 	void _toggle_draw_caret();
 
 
@@ -480,6 +437,44 @@ private:
 	int _calculate_spaces_till_next_right_indent(int column);
 	int _calculate_spaces_till_next_right_indent(int column);
 
 
 protected:
 protected:
+	struct Cache {
+		Ref<Texture2D> tab_icon;
+		Ref<Texture2D> space_icon;
+		Ref<Texture2D> folded_eol_icon;
+		Ref<StyleBox> style_normal;
+		Ref<StyleBox> style_focus;
+		Ref<StyleBox> style_readonly;
+		Ref<Font> font;
+		Color completion_background_color;
+		Color completion_selected_color;
+		Color completion_existing_color;
+		Color completion_font_color;
+		Color caret_color;
+		Color caret_background_color;
+		Color font_color;
+		Color font_color_selected;
+		Color font_color_readonly;
+		Color selection_color;
+		Color mark_color;
+		Color code_folding_color;
+		Color current_line_color;
+		Color line_length_guideline_color;
+		Color brace_mismatch_color;
+		Color word_highlighted_color;
+		Color search_result_color;
+		Color search_result_border_color;
+		Color background_color;
+
+		int row_height;
+		int line_spacing;
+		int minimap_width;
+		Cache() {
+			row_height = 0;
+			line_spacing = 0;
+			minimap_width = 0;
+		}
+	} cache;
+
 	virtual String get_tooltip(const Point2 &p_pos) const override;
 	virtual String get_tooltip(const Point2 &p_pos) const override;
 
 
 	void _insert_text(int p_line, int p_char, const String &p_text, int *r_end_line = nullptr, int *r_end_char = nullptr);
 	void _insert_text(int p_line, int p_char, const String &p_text, int *r_end_line = nullptr, int *r_end_char = nullptr);
@@ -494,9 +489,51 @@ protected:
 	static void _bind_methods();
 	static void _bind_methods();
 
 
 public:
 public:
+	/* Syntax Highlighting. */
 	Ref<SyntaxHighlighter> get_syntax_highlighter();
 	Ref<SyntaxHighlighter> get_syntax_highlighter();
 	void set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighter);
 	void set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighter);
 
 
+	/* Gutters. */
+	void add_gutter(int p_at = -1);
+	void remove_gutter(int p_gutter);
+	int get_gutter_count() const;
+
+	void set_gutter_name(int p_gutter, const String &p_name);
+	String get_gutter_name(int p_gutter) const;
+
+	void set_gutter_type(int p_gutter, GutterType p_type);
+	GutterType get_gutter_type(int p_gutter) const;
+
+	void set_gutter_width(int p_gutter, int p_width);
+	int get_gutter_width(int p_gutter) const;
+
+	void set_gutter_draw(int p_gutter, bool p_draw);
+	bool is_gutter_drawn(int p_gutter) const;
+
+	void set_gutter_clickable(int p_gutter, bool p_clickable);
+	bool is_gutter_clickable(int p_gutter) const;
+
+	void set_gutter_overwritable(int p_gutter, bool p_overwritable);
+	bool is_gutter_overwritable(int p_gutter) const;
+
+	void set_gutter_custom_draw(int p_gutter, Object *p_object, const StringName &p_callback);
+
+	// Line gutters.
+	void set_line_gutter_metadata(int p_line, int p_gutter, const Variant &p_metadata);
+	Variant get_line_gutter_metadata(int p_line, int p_gutter) const;
+
+	void set_line_gutter_text(int p_line, int p_gutter, const String &p_text);
+	String get_line_gutter_text(int p_line, int p_gutter) const;
+
+	void set_line_gutter_icon(int p_line, int p_gutter, Ref<Texture2D> p_icon);
+	Ref<Texture2D> get_line_gutter_icon(int p_line, int p_gutter) const;
+
+	void set_line_gutter_item_color(int p_line, int p_gutter, const Color &p_color);
+	Color get_line_gutter_item_color(int p_line, int p_gutter);
+
+	void set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable);
+	bool is_line_gutter_clickable(int p_line, int p_gutter) const;
+
 	enum MenuItems {
 	enum MenuItems {
 		MENU_CUT,
 		MENU_CUT,
 		MENU_COPY,
 		MENU_COPY,
@@ -534,22 +571,6 @@ public:
 	void insert_at(const String &p_text, int at);
 	void insert_at(const String &p_text, int at);
 	int get_line_count() const;
 	int get_line_count() const;
 	void set_line_as_marked(int p_line, bool p_marked);
 	void set_line_as_marked(int p_line, bool p_marked);
-	void set_line_as_bookmark(int p_line, bool p_bookmark);
-	bool is_line_set_as_bookmark(int p_line) const;
-	void get_bookmarks(List<int> *p_bookmarks) const;
-	Array get_bookmarks_array() const;
-	void set_line_as_breakpoint(int p_line, bool p_breakpoint);
-	bool is_line_set_as_breakpoint(int p_line) const;
-	void set_executing_line(int p_line);
-	void clear_executing_line();
-	void set_line_as_safe(int p_line, bool p_safe);
-	bool is_line_set_as_safe(int p_line) const;
-	void get_breakpoints(List<int> *p_breakpoints) const;
-	Array get_breakpoints_array() const;
-	void remove_breakpoints();
-
-	void set_line_info_icon(int p_line, Ref<Texture2D> p_icon, String p_info = "");
-	void clear_info_icons();
 
 
 	void set_line_as_hidden(int p_line, bool p_hidden);
 	void set_line_as_hidden(int p_line, bool p_hidden);
 	bool is_line_hidden(int p_line) const;
 	bool is_line_hidden(int p_line) const;
@@ -569,6 +590,7 @@ public:
 	String get_text();
 	String get_text();
 	String get_line(int line) const;
 	String get_line(int line) const;
 	void set_line(int line, String new_text);
 	void set_line(int line, String new_text);
+	int get_row_height() const;
 	void backspace_at_cursor();
 	void backspace_at_cursor();
 
 
 	void indent_left();
 	void indent_left();
@@ -690,39 +712,13 @@ public:
 
 
 	void menu_option(int p_option);
 	void menu_option(int p_option);
 
 
-	void set_show_line_numbers(bool p_show);
-	bool is_show_line_numbers_enabled() const;
-
 	void set_highlight_current_line(bool p_enabled);
 	void set_highlight_current_line(bool p_enabled);
 	bool is_highlight_current_line_enabled() const;
 	bool is_highlight_current_line_enabled() const;
 
 
-	void set_line_numbers_zero_padded(bool p_zero_padded);
-
 	void set_show_line_length_guidelines(bool p_show);
 	void set_show_line_length_guidelines(bool p_show);
 	void set_line_length_guideline_soft_column(int p_column);
 	void set_line_length_guideline_soft_column(int p_column);
 	void set_line_length_guideline_hard_column(int p_column);
 	void set_line_length_guideline_hard_column(int p_column);
 
 
-	void set_bookmark_gutter_enabled(bool p_draw);
-	bool is_bookmark_gutter_enabled() const;
-
-	void set_breakpoint_gutter_enabled(bool p_draw);
-	bool is_breakpoint_gutter_enabled() const;
-
-	void set_breakpoint_gutter_width(int p_gutter_width);
-	int get_breakpoint_gutter_width() const;
-
-	void set_draw_fold_gutter(bool p_draw);
-	bool is_drawing_fold_gutter() const;
-
-	void set_fold_gutter_width(int p_gutter_width);
-	int get_fold_gutter_width() const;
-
-	void set_draw_info_gutter(bool p_draw);
-	bool is_drawing_info_gutter() const;
-
-	void set_info_gutter_width(int p_gutter_width);
-	int get_info_gutter_width() const;
-
 	void set_draw_minimap(bool p_draw);
 	void set_draw_minimap(bool p_draw);
 	bool is_drawing_minimap() const;
 	bool is_drawing_minimap() const;
 
 
@@ -764,6 +760,7 @@ public:
 	~TextEdit();
 	~TextEdit();
 };
 };
 
 
+VARIANT_ENUM_CAST(TextEdit::GutterType);
 VARIANT_ENUM_CAST(TextEdit::MenuItems);
 VARIANT_ENUM_CAST(TextEdit::MenuItems);
 VARIANT_ENUM_CAST(TextEdit::SearchFlags);
 VARIANT_ENUM_CAST(TextEdit::SearchFlags);
 
 

+ 2 - 0
scene/register_scene_types.cpp

@@ -81,6 +81,7 @@
 #include "scene/gui/center_container.h"
 #include "scene/gui/center_container.h"
 #include "scene/gui/check_box.h"
 #include "scene/gui/check_box.h"
 #include "scene/gui/check_button.h"
 #include "scene/gui/check_button.h"
+#include "scene/gui/code_edit.h"
 #include "scene/gui/color_picker.h"
 #include "scene/gui/color_picker.h"
 #include "scene/gui/color_rect.h"
 #include "scene/gui/color_rect.h"
 #include "scene/gui/control.h"
 #include "scene/gui/control.h"
@@ -351,6 +352,7 @@ void register_scene_types() {
 	ClassDB::register_class<Tree>();
 	ClassDB::register_class<Tree>();
 
 
 	ClassDB::register_class<TextEdit>();
 	ClassDB::register_class<TextEdit>();
+	ClassDB::register_class<CodeEdit>();
 	ClassDB::register_class<SyntaxHighlighter>();
 	ClassDB::register_class<SyntaxHighlighter>();
 	ClassDB::register_class<CodeHighlighter>();
 	ClassDB::register_class<CodeHighlighter>();
 
 

BIN
scene/resources/default_theme/bookmark.png


+ 44 - 7
scene/resources/default_theme/default_theme.cpp

@@ -382,8 +382,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
 
 
 	theme->set_icon("tab", "TextEdit", make_icon(tab_png));
 	theme->set_icon("tab", "TextEdit", make_icon(tab_png));
 	theme->set_icon("space", "TextEdit", make_icon(space_png));
 	theme->set_icon("space", "TextEdit", make_icon(space_png));
-	theme->set_icon("folded", "TextEdit", make_icon(arrow_right_png));
-	theme->set_icon("fold", "TextEdit", make_icon(arrow_down_png));
 
 
 	theme->set_font("font", "TextEdit", Ref<Font>());
 	theme->set_font("font", "TextEdit", Ref<Font>());
 
 
@@ -398,16 +396,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
 	theme->set_color("font_color_readonly", "TextEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f));
 	theme->set_color("font_color_readonly", "TextEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f));
 	theme->set_color("selection_color", "TextEdit", font_color_selection);
 	theme->set_color("selection_color", "TextEdit", font_color_selection);
 	theme->set_color("mark_color", "TextEdit", Color(1.0, 0.4, 0.4, 0.4));
 	theme->set_color("mark_color", "TextEdit", Color(1.0, 0.4, 0.4, 0.4));
-	theme->set_color("bookmark_color", "TextEdit", Color(0.08, 0.49, 0.98));
-	theme->set_color("breakpoint_color", "TextEdit", Color(0.8, 0.8, 0.4, 0.2));
-	theme->set_color("executing_line_color", "TextEdit", Color(0.2, 0.8, 0.2, 0.4));
 	theme->set_color("code_folding_color", "TextEdit", Color(0.8, 0.8, 0.8, 0.8));
 	theme->set_color("code_folding_color", "TextEdit", Color(0.8, 0.8, 0.8, 0.8));
 	theme->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8));
 	theme->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8));
 	theme->set_color("caret_color", "TextEdit", control_font_color);
 	theme->set_color("caret_color", "TextEdit", control_font_color);
 	theme->set_color("caret_background_color", "TextEdit", Color(0, 0, 0));
 	theme->set_color("caret_background_color", "TextEdit", Color(0, 0, 0));
 	theme->set_color("brace_mismatch_color", "TextEdit", Color(1, 0.2, 0.2));
 	theme->set_color("brace_mismatch_color", "TextEdit", Color(1, 0.2, 0.2));
-	theme->set_color("line_number_color", "TextEdit", Color(0.67, 0.67, 0.67, 0.4));
-	theme->set_color("safe_line_number_color", "TextEdit", Color(0.67, 0.78, 0.67, 0.6));
 	theme->set_color("word_highlighted_color", "TextEdit", Color(0.8, 0.9, 0.9, 0.15));
 	theme->set_color("word_highlighted_color", "TextEdit", Color(0.8, 0.9, 0.9, 0.15));
 
 
 	theme->set_constant("completion_lines", "TextEdit", 7);
 	theme->set_constant("completion_lines", "TextEdit", 7);
@@ -415,6 +408,50 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
 	theme->set_constant("completion_scroll_width", "TextEdit", 3);
 	theme->set_constant("completion_scroll_width", "TextEdit", 3);
 	theme->set_constant("line_spacing", "TextEdit", 4 * scale);
 	theme->set_constant("line_spacing", "TextEdit", 4 * scale);
 
 
+	// CodeEdit
+	theme->set_stylebox("normal", "CodeEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0));
+	theme->set_stylebox("focus", "CodeEdit", focus);
+	theme->set_stylebox("read_only", "CodeEdit", make_stylebox(tree_bg_disabled_png, 4, 4, 4, 4, 0, 0, 0, 0));
+	theme->set_stylebox("completion", "CodeEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0));
+
+	theme->set_icon("tab", "CodeEdit", make_icon(tab_png));
+	theme->set_icon("space", "CodeEdit", make_icon(space_png));
+	theme->set_icon("breakpoint", "CodeEdit", make_icon(graph_port_png));
+	theme->set_icon("bookmark", "CodeEdit", make_icon(bookmark_png));
+	theme->set_icon("executing_line", "CodeEdit", make_icon(arrow_right_png));
+	theme->set_icon("can_fold", "CodeEdit", make_icon(arrow_down_png));
+	theme->set_icon("folded", "CodeEdit", make_icon(arrow_right_png));
+
+	theme->set_font("font", "CodeEdit", Ref<Font>());
+
+	theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0));
+	theme->set_color("completion_background_color", "CodeEdit", Color(0.17, 0.16, 0.2));
+	theme->set_color("completion_selected_color", "CodeEdit", Color(0.26, 0.26, 0.27));
+	theme->set_color("completion_existing_color", "CodeEdit", Color(0.87, 0.87, 0.87, 0.13));
+	theme->set_color("completion_scroll_color", "CodeEdit", control_font_color_pressed);
+	theme->set_color("completion_font_color", "CodeEdit", Color(0.67, 0.67, 0.67));
+	theme->set_color("font_color", "CodeEdit", control_font_color);
+	theme->set_color("font_color_selected", "CodeEdit", Color(0, 0, 0));
+	theme->set_color("font_color_readonly", "CodeEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f));
+	theme->set_color("selection_color", "CodeEdit", font_color_selection);
+	theme->set_color("mark_color", "CodeEdit", Color(1.0, 0.4, 0.4, 0.4));
+	theme->set_color("bookmark_color", "CodeEdit", Color(0.5, 0.64, 1, 0.8));
+	theme->set_color("breakpoint_color", "CodeEdit", Color(0.9, 0.29, 0.3));
+	theme->set_color("executing_line_color", "CodeEdit", Color(0.98, 0.89, 0.27));
+	theme->set_color("code_folding_color", "CodeEdit", Color(0.8, 0.8, 0.8, 0.8));
+	theme->set_color("current_line_color", "CodeEdit", Color(0.25, 0.25, 0.26, 0.8));
+	theme->set_color("caret_color", "CodeEdit", control_font_color);
+	theme->set_color("caret_background_color", "CodeEdit", Color(0, 0, 0));
+	theme->set_color("brace_mismatch_color", "CodeEdit", Color(1, 0.2, 0.2));
+	theme->set_color("line_number_color", "CodeEdit", Color(0.67, 0.67, 0.67, 0.4));
+	theme->set_color("safe_line_number_color", "CodeEdit", Color(0.67, 0.78, 0.67, 0.6));
+	theme->set_color("word_highlighted_color", "CodeEdit", Color(0.8, 0.9, 0.9, 0.15));
+
+	theme->set_constant("completion_lines", "CodeEdit", 7);
+	theme->set_constant("completion_max_width", "CodeEdit", 50);
+	theme->set_constant("completion_scroll_width", "CodeEdit", 3);
+	theme->set_constant("line_spacing", "CodeEdit", 4 * scale);
+
 	Ref<Texture2D> empty_icon = memnew(ImageTexture);
 	Ref<Texture2D> empty_icon = memnew(ImageTexture);
 
 
 	// HScrollBar
 	// HScrollBar

+ 4 - 0
scene/resources/default_theme/theme_data.h

@@ -10,6 +10,10 @@ static const unsigned char arrow_right_png[] = {
 	0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x2e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x17, 0x3c, 0xf8, 0xf, 0x82, 0xf7, 0x13, 0x70, 0x48, 0x3c, 0xf8, 0xf2, 0x50, 0x1b, 0x43, 0x2, 0xa, 0xaf, 0xbe, 0xe0, 0xc6, 0x2e, 0xf1, 0xff, 0xe1, 0x7c, 0x12, 0x24, 0x10, 0x46, 0x11, 0xb6, 0x1c, 0xe1, 0x5c, 0xa, 0x0, 0x0, 0xe0, 0x14, 0x48, 0xb1, 0x3d, 0x1b, 0x7a, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
 	0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x2e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x17, 0x3c, 0xf8, 0xf, 0x82, 0xf7, 0x13, 0x70, 0x48, 0x3c, 0xf8, 0xf2, 0x50, 0x1b, 0x43, 0x2, 0xa, 0xaf, 0xbe, 0xe0, 0xc6, 0x2e, 0xf1, 0xff, 0xe1, 0x7c, 0x12, 0x24, 0x10, 0x46, 0x11, 0xb6, 0x1c, 0xe1, 0x5c, 0xa, 0x0, 0x0, 0xe0, 0x14, 0x48, 0xb1, 0x3d, 0x1b, 0x7a, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
 };
 };
 
 
+static const unsigned char bookmark_png[] = {
+	0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x4, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0x8, 0x7c, 0x8, 0x64, 0x88, 0x0, 0x0, 0x0, 0x57, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xed, 0x93, 0x31, 0xa, 0xc0, 0x30, 0xc, 0x3, 0xa5, 0xd0, 0xff, 0x7f, 0x59, 0x1d, 0x8a, 0x42, 0x8, 0x9, 0x95, 0xc9, 0xd2, 0xa1, 0x9a, 0x8c, 0xf1, 0xdd, 0x62, 0x1b, 0x38, 0xc, 0x87, 0x5a, 0x5, 0xae, 0x79, 0xde, 0x2, 0x1, 0x80, 0x94, 0x39, 0x48, 0x76, 0x49, 0x17, 0xa4, 0xf0, 0x24, 0x61, 0x2b, 0x51, 0x8b, 0xfc, 0x82, 0xcf, 0xb, 0x48, 0x7a, 0xdf, 0x75, 0x81, 0xf, 0xe5, 0x29, 0xf7, 0x92, 0x6b, 0x3, 0x1a, 0x1e, 0xda, 0x7c, 0x3d, 0x77, 0x21, 0x7b, 0xa8, 0x74, 0x2e, 0xcb, 0xd, 0xc8, 0x75, 0x13, 0x28, 0x9, 0xed, 0xc2, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
 static const unsigned char button_disabled_png[] = {
 static const unsigned char button_disabled_png[] = {
 	0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xc7, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6c, 0xd0, 0x81, 0x66, 0x43, 0x31, 0x14, 0x87, 0xf1, 0xf, 0x5, 0x17, 0xb8, 0x28, 0x2e, 0x8, 0x71, 0xf3, 0x6, 0x19, 0xb6, 0xb9, 0xcb, 0xac, 0x95, 0xa4, 0xb7, 0xad, 0x6a, 0xd5, 0x68, 0x5f, 0xe4, 0x3e, 0x76, 0x1e, 0xe1, 0xbf, 0x21, 0xa6, 0xab, 0xf8, 0x1, 0x7c, 0x9c, 0x73, 0xe, 0xac, 0xe8, 0xe8, 0x19, 0x30, 0x58, 0xc6, 0xca, 0x62, 0x18, 0xe8, 0xe9, 0x58, 0x41, 0xc7, 0x1a, 0x87, 0x27, 0x10, 0x49, 0xe4, 0x5f, 0x89, 0x48, 0xc0, 0xe3, 0x58, 0xd3, 0x41, 0x8f, 0xb, 0xcb, 0xbd, 0x7c, 0xeb, 0xbf, 0x7b, 0x9, 0xb, 0x8e, 0x1e, 0x6, 0xfc, 0xad, 0x64, 0x6d, 0xb5, 0x79, 0xb0, 0x55, 0xd6, 0xad, 0xe0, 0x19, 0xc0, 0x10, 0xae, 0xda, 0x34, 0x5c, 0x45, 0xc0, 0x80, 0x25, 0x5e, 0xf4, 0xd5, 0x70, 0x11, 0x11, 0xb, 0x23, 0xe9, 0xac, 0xcf, 0x86, 0xb3, 0x48, 0x8c, 0x30, 0x92, 0x4f, 0xa, 0xd, 0x27, 0x91, 0x6b, 0x70, 0xd4, 0x47, 0xc3, 0xf1, 0x2f, 0x48, 0x7, 0x4d, 0xd, 0x87, 0x3a, 0xc2, 0x12, 0x67, 0xbd, 0x37, 0xcc, 0x75, 0x49, 0x43, 0xd8, 0xe9, 0xad, 0x61, 0x57, 0xcf, 0x1c, 0xf0, 0xfb, 0x32, 0xe9, 0xf5, 0xc9, 0xa4, 0x7d, 0x7d, 0x54, 0x8f, 0x7b, 0x59, 0xe6, 0x92, 0x14, 0x1f, 0x24, 0xcd, 0x3f, 0x7b, 0x6b, 0xa, 0xe, 0x6a, 0x82, 0x91, 0x45, 0x30, 0xba, 0x1, 0x4a, 0x51, 0xc4, 0x35, 0x1f, 0xe5, 0xa1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
 	0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xc7, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6c, 0xd0, 0x81, 0x66, 0x43, 0x31, 0x14, 0x87, 0xf1, 0xf, 0x5, 0x17, 0xb8, 0x28, 0x2e, 0x8, 0x71, 0xf3, 0x6, 0x19, 0xb6, 0xb9, 0xcb, 0xac, 0x95, 0xa4, 0xb7, 0xad, 0x6a, 0xd5, 0x68, 0x5f, 0xe4, 0x3e, 0x76, 0x1e, 0xe1, 0xbf, 0x21, 0xa6, 0xab, 0xf8, 0x1, 0x7c, 0x9c, 0x73, 0xe, 0xac, 0xe8, 0xe8, 0x19, 0x30, 0x58, 0xc6, 0xca, 0x62, 0x18, 0xe8, 0xe9, 0x58, 0x41, 0xc7, 0x1a, 0x87, 0x27, 0x10, 0x49, 0xe4, 0x5f, 0x89, 0x48, 0xc0, 0xe3, 0x58, 0xd3, 0x41, 0x8f, 0xb, 0xcb, 0xbd, 0x7c, 0xeb, 0xbf, 0x7b, 0x9, 0xb, 0x8e, 0x1e, 0x6, 0xfc, 0xad, 0x64, 0x6d, 0xb5, 0x79, 0xb0, 0x55, 0xd6, 0xad, 0xe0, 0x19, 0xc0, 0x10, 0xae, 0xda, 0x34, 0x5c, 0x45, 0xc0, 0x80, 0x25, 0x5e, 0xf4, 0xd5, 0x70, 0x11, 0x11, 0xb, 0x23, 0xe9, 0xac, 0xcf, 0x86, 0xb3, 0x48, 0x8c, 0x30, 0x92, 0x4f, 0xa, 0xd, 0x27, 0x91, 0x6b, 0x70, 0xd4, 0x47, 0xc3, 0xf1, 0x2f, 0x48, 0x7, 0x4d, 0xd, 0x87, 0x3a, 0xc2, 0x12, 0x67, 0xbd, 0x37, 0xcc, 0x75, 0x49, 0x43, 0xd8, 0xe9, 0xad, 0x61, 0x57, 0xcf, 0x1c, 0xf0, 0xfb, 0x32, 0xe9, 0xf5, 0xc9, 0xa4, 0x7d, 0x7d, 0x54, 0x8f, 0x7b, 0x59, 0xe6, 0x92, 0x14, 0x1f, 0x24, 0xcd, 0x3f, 0x7b, 0x6b, 0xa, 0xe, 0x6a, 0x82, 0x91, 0x45, 0x30, 0xba, 0x1, 0x4a, 0x51, 0xc4, 0x35, 0x1f, 0xe5, 0xa1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
 };
 };

+ 4 - 4
scene/resources/syntax_highlighter.cpp

@@ -53,13 +53,13 @@ Dictionary SyntaxHighlighter::get_line_syntax_highlighting(int p_line) {
 	return color_map;
 	return color_map;
 }
 }
 
 
-void SyntaxHighlighter::_line_edited_from(int p_line) {
+void SyntaxHighlighter::_lines_edited_from(int p_from_line, int p_to_line) {
 	if (highlighting_cache.size() < 1) {
 	if (highlighting_cache.size() < 1) {
 		return;
 		return;
 	}
 	}
 
 
 	int cache_size = highlighting_cache.back()->key();
 	int cache_size = highlighting_cache.back()->key();
-	for (int i = p_line - 1; i <= cache_size; i++) {
+	for (int i = MIN(p_from_line, p_to_line) - 1; i <= cache_size; i++) {
 		if (highlighting_cache.has(i)) {
 		if (highlighting_cache.has(i)) {
 			highlighting_cache.erase(i);
 			highlighting_cache.erase(i);
 		}
 		}
@@ -93,7 +93,7 @@ void SyntaxHighlighter::update_cache() {
 
 
 void SyntaxHighlighter::set_text_edit(TextEdit *p_text_edit) {
 void SyntaxHighlighter::set_text_edit(TextEdit *p_text_edit) {
 	if (text_edit && ObjectDB::get_instance(text_edit_instance_id)) {
 	if (text_edit && ObjectDB::get_instance(text_edit_instance_id)) {
-		text_edit->disconnect("line_edited_from", callable_mp(this, &SyntaxHighlighter::_line_edited_from));
+		text_edit->disconnect("lines_edited_from", callable_mp(this, &SyntaxHighlighter::_lines_edited_from));
 	}
 	}
 
 
 	text_edit = p_text_edit;
 	text_edit = p_text_edit;
@@ -101,7 +101,7 @@ void SyntaxHighlighter::set_text_edit(TextEdit *p_text_edit) {
 		return;
 		return;
 	}
 	}
 	text_edit_instance_id = text_edit->get_instance_id();
 	text_edit_instance_id = text_edit->get_instance_id();
-	text_edit->connect("line_edited_from", callable_mp(this, &SyntaxHighlighter::_line_edited_from));
+	text_edit->connect("lines_edited_from", callable_mp(this, &SyntaxHighlighter::_lines_edited_from));
 	update_cache();
 	update_cache();
 }
 }
 
 

+ 1 - 1
scene/resources/syntax_highlighter.h

@@ -40,7 +40,7 @@ class SyntaxHighlighter : public Resource {
 
 
 private:
 private:
 	Map<int, Dictionary> highlighting_cache;
 	Map<int, Dictionary> highlighting_cache;
-	void _line_edited_from(int p_line);
+	void _lines_edited_from(int p_from_line, int p_to_line);
 
 
 protected:
 protected:
 	ObjectID text_edit_instance_id; // For validity check
 	ObjectID text_edit_instance_id; // For validity check

Some files were not shown because too many files changed in this diff