瀏覽代碼

Add main_gutter (breakpoints, bookmarks, execution lines) to code_edit

Paulb23 5 年之前
父節點
當前提交
4d7df24d46

+ 24 - 30
editor/code_editor.cpp

@@ -934,8 +934,7 @@ void CodeTextEditor::update_editor_settings() {
 	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_draw_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_bookmarks_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/show_bookmark_gutter"));
 	text_editor->set_draw_info_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/show_info_gutter"));
 	text_editor->set_draw_info_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/show_info_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"));
@@ -1390,11 +1389,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() {
@@ -1414,8 +1413,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 +1452,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 +1590,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 +1618,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 +1642,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() {
@@ -1694,6 +1686,8 @@ CodeTextEditor::CodeTextEditor() {
 	find_replace_bar->set_text_edit(text_editor);
 	find_replace_bar->set_text_edit(text_editor);
 
 
 	text_editor->set_draw_line_numbers(true);
 	text_editor->set_draw_line_numbers(true);
+	text_editor->set_draw_breakpoints_gutter(true);
+	text_editor->set_draw_executing_lines_gutter(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);
 
 

+ 2 - 2
editor/editor_settings.cpp

@@ -707,8 +707,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));

+ 2 - 1
editor/editor_themes.cpp

@@ -883,6 +883,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	theme->set_icon("space", "CodeEdit", theme->get_icon("GuiSpace", "EditorIcons"));
 	theme->set_icon("space", "CodeEdit", theme->get_icon("GuiSpace", "EditorIcons"));
 	theme->set_icon("folded", "CodeEdit", theme->get_icon("GuiTreeArrowRight", "EditorIcons"));
 	theme->set_icon("folded", "CodeEdit", theme->get_icon("GuiTreeArrowRight", "EditorIcons"));
 	theme->set_icon("fold", "CodeEdit", theme->get_icon("GuiTreeArrowDown", "EditorIcons"));
 	theme->set_icon("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("font_color", "CodeEdit", font_color);
 	theme->set_color("caret_color", "CodeEdit", font_color);
 	theme->set_color("caret_color", "CodeEdit", font_color);
 	theme->set_color("selection_color", "CodeEdit", font_color_selection);
 	theme->set_color("selection_color", "CodeEdit", font_color_selection);
@@ -1192,7 +1193,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;

+ 18 - 21
editor/plugins/script_text_editor.cpp

@@ -566,7 +566,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_editor()->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;
 	}
 	}
@@ -717,7 +717,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_editor()->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;
 	}
 	}
@@ -749,7 +749,7 @@ void ScriptTextEditor::_breakpoint_item_pressed(int p_idx) {
 }
 }
 
 
 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_editor()->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) {
@@ -1177,24 +1177,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 +1200,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 +1218,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);
@@ -1342,8 +1339,8 @@ 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_editor()->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) {

+ 1 - 1
editor/plugins/script_text_editor.h

@@ -211,7 +211,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;

+ 2 - 2
editor/plugins/shader_editor_plugin.cpp

@@ -379,7 +379,7 @@ void ShaderEditor::_editor_settings_changed() {
 	shader_editor->get_text_editor()->set_show_line_length_guidelines(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_length_guidelines"));
 	shader_editor->get_text_editor()->set_show_line_length_guidelines(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_length_guidelines"));
 	shader_editor->get_text_editor()->set_line_length_guideline_soft_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_soft_column"));
 	shader_editor->get_text_editor()->set_line_length_guideline_soft_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_soft_column"));
 	shader_editor->get_text_editor()->set_line_length_guideline_hard_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_hard_column"));
 	shader_editor->get_text_editor()->set_line_length_guideline_hard_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_hard_column"));
-	shader_editor->get_text_editor()->set_breakpoint_gutter_enabled(false);
+	shader_editor->get_text_editor()->set_draw_breakpoints_gutter(false);
 }
 }
 
 
 void ShaderEditor::_bind_methods() {
 void ShaderEditor::_bind_methods() {
@@ -521,7 +521,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_editor()->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;
 	}
 	}

+ 3 - 2
editor/plugins/text_editor.cpp

@@ -171,7 +171,8 @@ 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() {
@@ -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_editor()->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;
 	}
 	}

+ 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;

+ 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;

+ 259 - 12
scene/gui/code_edit.cpp

@@ -34,8 +34,18 @@ void CodeEdit::_notification(int p_what) {
 	switch (p_what) {
 	switch (p_what) {
 		case NOTIFICATION_THEME_CHANGED:
 		case NOTIFICATION_THEME_CHANGED:
 		case NOTIFICATION_ENTER_TREE: {
 		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(line_number_gutter, (line_number_digits + 1) * cache.font->get_char_size('0').width);
 
 
+			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");
 			line_number_color = get_theme_color("line_number_color");
 		} break;
 		} break;
 		case NOTIFICATION_DRAW: {
 		case NOTIFICATION_DRAW: {
@@ -43,6 +53,160 @@ void CodeEdit::_notification(int p_what) {
 	}
 	}
 }
 }
 
 
+/* 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 */
 /* Line numbers */
 void CodeEdit::set_draw_line_numbers(bool p_draw) {
 void CodeEdit::set_draw_line_numbers(bool p_draw) {
 	set_gutter_draw(line_number_gutter, p_draw);
 	set_gutter_draw(line_number_gutter, p_draw);
@@ -69,6 +233,36 @@ void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2
 }
 }
 
 
 void CodeEdit::_bind_methods() {
 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 */
 	/* Line numbers */
 	ClassDB::bind_method(D_METHOD("_line_number_draw_callback"), &CodeEdit::_line_number_draw_callback);
 	ClassDB::bind_method(D_METHOD("_line_number_draw_callback"), &CodeEdit::_line_number_draw_callback);
 
 
@@ -77,11 +271,28 @@ void CodeEdit::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_line_numbers_zero_padded", "enable"), &CodeEdit::set_line_numbers_zero_padded);
 	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);
 	ClassDB::bind_method(D_METHOD("is_line_numbers_zero_padded"), &CodeEdit::is_line_numbers_zero_padded);
 
 
+	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, "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, "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) {
 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) {
 	if (p_gutter == line_number_gutter) {
 		cursor_set_line(p_line);
 		cursor_set_line(p_line);
 		return;
 		return;
@@ -89,21 +300,44 @@ void CodeEdit::_gutter_clicked(int p_line, int p_gutter) {
 }
 }
 
 
 void CodeEdit::_lines_edited_from(int p_from_line, int p_to_line) {
 void CodeEdit::_lines_edited_from(int p_from_line, int p_to_line) {
-	int line_count = get_line_count();
-	if (line_count != cached_line_count) {
-		int lc = line_count;
-		line_number_digits = 1;
-		while (lc /= 10) {
-			line_number_digits++;
+	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;
 		}
 		}
-		set_gutter_width(line_number_gutter, (line_number_digits + 1) * cache.font->get_char_size('0').width);
+		breakpointed_lines.erase(line);
 
 
-		cached_line_count = line_count;
+		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() {
 void CodeEdit::_update_gutter_indexes() {
 	for (int i = 0; i < get_gutter_count(); i++) {
 	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") {
 		if (get_gutter_name(i) == "line_numbers") {
 			line_number_gutter = i;
 			line_number_gutter = i;
 			continue;
 			continue;
@@ -112,12 +346,25 @@ void CodeEdit::_update_gutter_indexes() {
 }
 }
 
 
 CodeEdit::CodeEdit() {
 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 */
 	/* Line numbers */
 	add_gutter();
 	add_gutter();
-	set_gutter_name(0, "line_numbers");
-	set_gutter_draw(0, false);
-	set_gutter_type(0, GUTTER_TPYE_CUSTOM);
-	set_gutter_custom_draw(0, this, "_line_number_draw_callback");
+	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++;
 
 
 	connect("lines_edited_from", callable_mp(this, &CodeEdit::_lines_edited_from));
 	connect("lines_edited_from", callable_mp(this, &CodeEdit::_lines_edited_from));
 	connect("gutter_clicked", callable_mp(this, &CodeEdit::_gutter_clicked));
 	connect("gutter_clicked", callable_mp(this, &CodeEdit::_gutter_clicked));

+ 54 - 1
scene/gui/code_edit.h

@@ -37,7 +37,32 @@ class CodeEdit : public TextEdit {
 	GDCLASS(CodeEdit, TextEdit)
 	GDCLASS(CodeEdit, TextEdit)
 
 
 private:
 private:
-	int cached_line_count = 0;
+	/* 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 */
 	/* Line numbers */
 	int line_number_gutter = -1;
 	int line_number_gutter = -1;
@@ -57,6 +82,34 @@ protected:
 	static void _bind_methods();
 	static void _bind_methods();
 
 
 public:
 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 */
 	/* Line numbers */
 	void set_draw_line_numbers(bool p_draw);
 	void set_draw_line_numbers(bool p_draw);
 	bool is_draw_line_numbers_enabled() const;
 	bool is_draw_line_numbers_enabled() const;

+ 17 - 251
scene/gui/text_edit.cpp

@@ -203,8 +203,6 @@ void TextEdit::Text::insert(int p_at, const String &p_text) {
 	line.gutters.resize(gutter_count);
 	line.gutters.resize(gutter_count);
 	line.marked = false;
 	line.marked = false;
 	line.safe = false;
 	line.safe = false;
-	line.breakpoint = false;
-	line.bookmark = false;
 	line.hidden = false;
 	line.hidden = false;
 	line.has_info = false;
 	line.has_info = false;
 	line.width_cache = -1;
 	line.width_cache = -1;
@@ -280,10 +278,6 @@ void TextEdit::_update_scrollbars() {
 	int visible_width = size.width - cache.style_normal->get_minimum_size().width;
 	int visible_width = size.width - cache.style_normal->get_minimum_size().width;
 	int total_width = text.get_max_width(true) + vmin.x + gutters_width + gutter_padding;
 	int total_width = text.get_max_width(true) + vmin.x + gutters_width + gutter_padding;
 
 
-	if (draw_breakpoint_gutter || draw_bookmark_gutter) {
-		total_width += cache.breakpoint_gutter_width;
-	}
-
 	if (draw_info_gutter) {
 	if (draw_info_gutter) {
 		total_width += cache.info_gutter_width;
 		total_width += cache.info_gutter_width;
 	}
 	}
@@ -582,13 +576,6 @@ void TextEdit::_notification(int p_what) {
 				draw_caret = false;
 				draw_caret = false;
 			}
 			}
 
 
-			if (draw_breakpoint_gutter || draw_bookmark_gutter) {
-				breakpoint_gutter_width = (get_row_height() * 55) / 100;
-				cache.breakpoint_gutter_width = breakpoint_gutter_width;
-			} else {
-				cache.breakpoint_gutter_width = 0;
-			}
-
 			if (draw_info_gutter) {
 			if (draw_info_gutter) {
 				info_gutter_width = (get_row_height());
 				info_gutter_width = (get_row_height());
 				cache.info_gutter_width = info_gutter_width;
 				cache.info_gutter_width = info_gutter_width;
@@ -612,7 +599,7 @@ void TextEdit::_notification(int p_what) {
 
 
 			RID ci = get_canvas_item();
 			RID ci = get_canvas_item();
 			RenderingServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true);
 			RenderingServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true);
-			int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width;
+			int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding + cache.fold_gutter_width + cache.info_gutter_width;
 
 
 			int xmargin_end = size.width - cache.style_normal->get_margin(MARGIN_RIGHT) - cache.minimap_width;
 			int xmargin_end = size.width - cache.style_normal->get_margin(MARGIN_RIGHT) - cache.minimap_width;
 			// Let's do it easy for now.
 			// Let's do it easy for now.
@@ -1107,41 +1094,11 @@ void TextEdit::_notification(int p_what) {
 							gutter_offset += gutter.width;
 							gutter_offset += gutter.width;
 						}
 						}
 
 
-						if (text.is_breakpoint(line) && !draw_breakpoint_gutter) {
-#ifdef TOOLS_ENABLED
-							RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.breakpoint_color);
-#else
-							RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.breakpoint_color);
-#endif
-						}
-
-						// Draw bookmark marker.
-						if (text.is_bookmark(line)) {
-							if (draw_bookmark_gutter) {
-								int vertical_gap = (get_row_height() * 40) / 100;
-								int horizontal_gap = (cache.breakpoint_gutter_width * 30) / 100;
-								int marker_radius = get_row_height() - (vertical_gap * 2);
-								RenderingServer::get_singleton()->canvas_item_add_circle(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + horizontal_gap - 2 + marker_radius / 2, ofs_y + vertical_gap + marker_radius / 2), marker_radius, Color(cache.bookmark_color.r, cache.bookmark_color.g, cache.bookmark_color.b));
-							}
-						}
-
-						// Draw breakpoint marker.
-						if (text.is_breakpoint(line)) {
-							if (draw_breakpoint_gutter) {
-								int vertical_gap = (get_row_height() * 40) / 100;
-								int horizontal_gap = (cache.breakpoint_gutter_width * 30) / 100;
-								int marker_height = get_row_height() - (vertical_gap * 2);
-								int marker_width = cache.breakpoint_gutter_width - (horizontal_gap * 2);
-								// No transparency on marker.
-								RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + horizontal_gap - 2, ofs_y + vertical_gap, marker_width, marker_height), Color(cache.breakpoint_color.r, cache.breakpoint_color.g, cache.breakpoint_color.b));
-							}
-						}
-
 						// Draw info icons.
 						// Draw info icons.
 						if (draw_info_gutter && text.has_info_icon(line)) {
 						if (draw_info_gutter && text.has_info_icon(line)) {
 							int vertical_gap = (get_row_height() * 40) / 100;
 							int vertical_gap = (get_row_height() * 40) / 100;
 							int horizontal_gap = (cache.info_gutter_width * 30) / 100;
 							int horizontal_gap = (cache.info_gutter_width * 30) / 100;
-							int gutter_left = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + cache.breakpoint_gutter_width;
+							int gutter_left = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width;
 
 
 							Ref<Texture2D> info_icon = text.get_info_icon(line);
 							Ref<Texture2D> info_icon = text.get_info_icon(line);
 							// Ensure the icon fits the gutter size.
 							// Ensure the icon fits the gutter size.
@@ -1162,28 +1119,10 @@ void TextEdit::_notification(int p_what) {
 							draw_texture_rect(info_icon, Rect2(icon_pos, icon_size));
 							draw_texture_rect(info_icon, Rect2(icon_pos, icon_size));
 						}
 						}
 
 
-						// Draw execution marker.
-						if (executing_line == line) {
-							if (draw_breakpoint_gutter) {
-								int icon_extra_size = 4;
-								int vertical_gap = (get_row_height() * 40) / 100;
-								int horizontal_gap = (cache.breakpoint_gutter_width * 30) / 100;
-								int marker_height = get_row_height() - (vertical_gap * 2) + icon_extra_size;
-								int marker_width = cache.breakpoint_gutter_width - (horizontal_gap * 2) + icon_extra_size;
-								cache.executing_icon->draw_rect(ci, Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + horizontal_gap - 2 - icon_extra_size / 2, ofs_y + vertical_gap - icon_extra_size / 2, marker_width, marker_height), false, Color(cache.executing_line_color.r, cache.executing_line_color.g, cache.executing_line_color.b));
-							} else {
-#ifdef TOOLS_ENABLED
-								RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.executing_line_color);
-#else
-								RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.executing_line_color);
-#endif
-							}
-						}
-
 						// Draw fold markers.
 						// Draw fold markers.
 						if (draw_fold_gutter) {
 						if (draw_fold_gutter) {
 							int horizontal_gap = (cache.fold_gutter_width * 30) / 100;
 							int horizontal_gap = (cache.fold_gutter_width * 30) / 100;
-							int gutter_left = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + cache.breakpoint_gutter_width + cache.info_gutter_width;
+							int gutter_left = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + cache.info_gutter_width;
 							if (is_folded(line)) {
 							if (is_folded(line)) {
 								int xofs = horizontal_gap - (cache.can_fold_icon->get_width()) / 2;
 								int xofs = horizontal_gap - (cache.can_fold_icon->get_width()) / 2;
 								int yofs = (get_row_height() - cache.folded_icon->get_height()) / 2;
 								int yofs = (get_row_height() - cache.folded_icon->get_height()) / 2;
@@ -1869,12 +1808,6 @@ void TextEdit::backspace_at_cursor() {
 	if (is_line_hidden(cursor.line)) {
 	if (is_line_hidden(cursor.line)) {
 		set_line_as_hidden(prev_line, true);
 		set_line_as_hidden(prev_line, true);
 	}
 	}
-	if (is_line_set_as_breakpoint(cursor.line)) {
-		if (!text.is_breakpoint(prev_line)) {
-			emit_signal("breakpoint_toggled", prev_line);
-		}
-		set_line_as_breakpoint(prev_line, true);
-	}
 
 
 	if (text.has_info_icon(cursor.line)) {
 	if (text.has_info_icon(cursor.line)) {
 		set_line_info_icon(prev_line, text.get_info_icon(cursor.line), text.get_info(cursor.line));
 		set_line_info_icon(prev_line, text.get_info_icon(cursor.line), text.get_info(cursor.line));
@@ -2067,7 +2000,7 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co
 		row = text.size() - 1;
 		row = text.size() - 1;
 		col = text[row].size();
 		col = text[row].size();
 	} else {
 	} else {
-		int colx = p_mouse.x - (cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width);
+		int colx = p_mouse.x - (cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding + cache.fold_gutter_width + cache.info_gutter_width);
 		colx += cursor.x_ofs;
 		colx += cursor.x_ofs;
 		col = get_char_pos_for_line(colx, row, wrap_index);
 		col = get_char_pos_for_line(colx, row, wrap_index);
 		if (is_wrap_enabled() && wrap_index < times_line_wraps(row)) {
 		if (is_wrap_enabled() && wrap_index < times_line_wraps(row)) {
@@ -2112,7 +2045,7 @@ Vector2i TextEdit::_get_cursor_pixel_pos() {
 
 
 	// Calculate final pixel position
 	// Calculate final pixel position
 	int y = (row - get_v_scroll_offset() + 1 /*Bottom of line*/) * get_row_height();
 	int y = (row - get_v_scroll_offset() + 1 /*Bottom of line*/) * get_row_height();
-	int x = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width - cursor.x_ofs;
+	int x = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding + cache.fold_gutter_width + cache.info_gutter_width - cursor.x_ofs;
 	int ix = 0;
 	int ix = 0;
 	while (ix < rows2[0].size() && ix < cursor.column) {
 	while (ix < rows2[0].size() && ix < cursor.column) {
 		if (cache.font != nullptr) {
 		if (cache.font != nullptr) {
@@ -2261,20 +2194,10 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 					left_margin += gutters[i].width;
 					left_margin += gutters[i].width;
 				}
 				}
 
 
-				// Toggle breakpoint on gutter click.
-				if (draw_breakpoint_gutter) {
-					int gutter = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width;
-					if (mb->get_position().x > gutter - 6 && mb->get_position().x <= gutter + cache.breakpoint_gutter_width - 3) {
-						set_line_as_breakpoint(row, !is_line_set_as_breakpoint(row));
-						emit_signal("breakpoint_toggled", row);
-						return;
-					}
-				}
-
 				// Emit info clicked.
 				// Emit info clicked.
 				if (draw_info_gutter && text.has_info_icon(row)) {
 				if (draw_info_gutter && text.has_info_icon(row)) {
 					left_margin = cache.style_normal->get_margin(MARGIN_LEFT);
 					left_margin = cache.style_normal->get_margin(MARGIN_LEFT);
-					int gutter_left = left_margin + gutters_width + cache.breakpoint_gutter_width;
+					int gutter_left = left_margin + gutters_width;
 					if (mb->get_position().x > gutter_left - 6 && mb->get_position().x <= gutter_left + cache.info_gutter_width - 3) {
 					if (mb->get_position().x > gutter_left - 6 && mb->get_position().x <= gutter_left + cache.info_gutter_width - 3) {
 						emit_signal("info_clicked", row, text.get_info(row));
 						emit_signal("info_clicked", row, text.get_info(row));
 						return;
 						return;
@@ -2284,7 +2207,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 				// Toggle fold on gutter click if can.
 				// Toggle fold on gutter click if can.
 				if (draw_fold_gutter) {
 				if (draw_fold_gutter) {
 					left_margin = cache.style_normal->get_margin(MARGIN_LEFT);
 					left_margin = cache.style_normal->get_margin(MARGIN_LEFT);
-					int gutter_left = left_margin + gutters_width + cache.breakpoint_gutter_width + cache.info_gutter_width;
+					int gutter_left = left_margin + gutters_width + cache.info_gutter_width;
 					if (mb->get_position().x > gutter_left - 6 && mb->get_position().x <= gutter_left + cache.fold_gutter_width - 3) {
 					if (mb->get_position().x > gutter_left - 6 && mb->get_position().x <= gutter_left + cache.fold_gutter_width - 3) {
 						if (is_folded(row)) {
 						if (is_folded(row)) {
 							unfold_line(row);
 							unfold_line(row);
@@ -2298,7 +2221,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 				// Unfold on folded icon click.
 				// Unfold on folded icon click.
 				if (is_folded(row)) {
 				if (is_folded(row)) {
 					int line_width = text.get_line_width(row);
 					int line_width = text.get_line_width(row);
-					line_width += cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding + cache.breakpoint_gutter_width + cache.info_gutter_width + cache.fold_gutter_width - cursor.x_ofs;
+					line_width += cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding + cache.info_gutter_width + cache.fold_gutter_width - cursor.x_ofs;
 					if (mb->get_position().x > line_width - 3 && mb->get_position().x <= line_width + cache.folded_eol_icon->get_width() + 3) {
 					if (mb->get_position().x > line_width - 3 && mb->get_position().x <= line_width + cache.folded_eol_icon->get_width() + 3) {
 						unfold_line(row);
 						unfold_line(row);
 						return;
 						return;
@@ -3858,30 +3781,15 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i
 
 
 	Vector<String> substrings = p_text.replace("\r", "").split("\n");
 	Vector<String> substrings = p_text.replace("\r", "").split("\n");
 
 
-	/* STEP 2: Fire breakpoint_toggled signals. */
-
 	// Is this just a new empty line?
 	// Is this just a new empty line?
 	bool shift_first_line = p_char == 0 && p_text.replace("\r", "") == "\n";
 	bool shift_first_line = p_char == 0 && p_text.replace("\r", "") == "\n";
 
 
-	int i = p_line + !shift_first_line;
-	int lines = substrings.size() - 1;
-	for (; i < text.size(); i++) {
-		if (text.is_breakpoint(i)) {
-			if ((i - lines < p_line || !text.is_breakpoint(i - lines)) || (i - lines == p_line && !shift_first_line)) {
-				emit_signal("breakpoint_toggled", i);
-			}
-			if (i + lines >= text.size() || !text.is_breakpoint(i + lines)) {
-				emit_signal("breakpoint_toggled", i + lines);
-			}
-		}
-	}
-
-	/* STEP 3: Add spaces if the char is greater than the end of the line. */
+	/* STEP 2: Add spaces if the char is greater than the end of the line. */
 	while (p_char > text[p_line].length()) {
 	while (p_char > text[p_line].length()) {
 		text.set(p_line, text[p_line] + String::chr(' '));
 		text.set(p_line, text[p_line] + String::chr(' '));
 	}
 	}
 
 
-	/* STEP 4: Separate dest string in pre and post text. */
+	/* STEP 3: Separate dest string in pre and post text. */
 
 
 	String preinsert_text = text[p_line].substr(0, p_char);
 	String preinsert_text = text[p_line].substr(0, p_char);
 	String postinsert_text = text[p_line].substr(p_char, text[p_line].size());
 	String postinsert_text = text[p_line].substr(p_char, text[p_line].size());
@@ -3902,13 +3810,11 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i
 
 
 	if (shift_first_line) {
 	if (shift_first_line) {
 		text.move_gutters(p_line, p_line + 1);
 		text.move_gutters(p_line, p_line + 1);
-		text.set_breakpoint(p_line + 1, text.is_breakpoint(p_line));
 		text.set_hidden(p_line + 1, text.is_hidden(p_line));
 		text.set_hidden(p_line + 1, text.is_hidden(p_line));
 		if (text.has_info_icon(p_line)) {
 		if (text.has_info_icon(p_line)) {
 			text.set_info_icon(p_line + 1, text.get_info_icon(p_line), text.get_info(p_line));
 			text.set_info_icon(p_line + 1, text.get_info_icon(p_line), text.get_info(p_line));
 		}
 		}
 
 
-		text.set_breakpoint(p_line, false);
 		text.set_hidden(p_line, false);
 		text.set_hidden(p_line, false);
 		text.set_info_icon(p_line, nullptr, "");
 		text.set_info_icon(p_line, nullptr, "");
 	}
 	}
@@ -3961,19 +3867,6 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li
 	String pre_text = text[p_from_line].substr(0, p_from_column);
 	String pre_text = text[p_from_line].substr(0, p_from_column);
 	String post_text = text[p_to_line].substr(p_to_column, text[p_to_line].length());
 	String post_text = text[p_to_line].substr(p_to_column, text[p_to_line].length());
 
 
-	int lines = p_to_line - p_from_line;
-
-	for (int i = p_from_line + 1; i < text.size(); i++) {
-		if (text.is_breakpoint(i)) {
-			if (i + lines >= text.size() || !text.is_breakpoint(i + lines)) {
-				emit_signal("breakpoint_toggled", i);
-			}
-			if (i > p_to_line && (i - lines < 0 || !text.is_breakpoint(i - lines))) {
-				emit_signal("breakpoint_toggled", i - lines);
-			}
-		}
-	}
-
 	for (int i = p_from_line; i < p_to_line; i++) {
 	for (int i = p_from_line; i < p_to_line; i++) {
 		text.remove(p_from_line + 1);
 		text.remove(p_from_line + 1);
 	}
 	}
@@ -4181,7 +4074,7 @@ int TextEdit::get_total_visible_rows() const {
 }
 }
 
 
 void TextEdit::_update_wrap_at() {
 void TextEdit::_update_wrap_at() {
-	wrap_at = get_size().width - cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding - cache.breakpoint_gutter_width - cache.fold_gutter_width - cache.info_gutter_width - cache.minimap_width - wrap_right_offset;
+	wrap_at = get_size().width - cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding - cache.fold_gutter_width - cache.info_gutter_width - cache.minimap_width - wrap_right_offset;
 	update_cursor_wrap_offset();
 	update_cursor_wrap_offset();
 	text.clear_wrap_cache();
 	text.clear_wrap_cache();
 
 
@@ -4216,7 +4109,7 @@ void TextEdit::adjust_viewport_to_cursor() {
 		set_line_as_last_visible(cur_line, cur_wrap);
 		set_line_as_last_visible(cur_line, cur_wrap);
 	}
 	}
 
 
-	int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding - cache.breakpoint_gutter_width - cache.fold_gutter_width - cache.info_gutter_width - cache.minimap_width;
+	int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding - cache.fold_gutter_width - cache.info_gutter_width - cache.minimap_width;
 	if (v_scroll->is_visible_in_tree()) {
 	if (v_scroll->is_visible_in_tree()) {
 		visible_width -= v_scroll->get_combined_minimum_size().width;
 		visible_width -= v_scroll->get_combined_minimum_size().width;
 	}
 	}
@@ -4251,7 +4144,7 @@ void TextEdit::center_viewport_to_cursor() {
 	}
 	}
 
 
 	set_line_as_center_visible(cursor.line, get_cursor_wrap_index());
 	set_line_as_center_visible(cursor.line, get_cursor_wrap_index());
-	int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding - cache.breakpoint_gutter_width - cache.fold_gutter_width - cache.info_gutter_width - cache.minimap_width;
+	int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding - cache.fold_gutter_width - cache.info_gutter_width - cache.minimap_width;
 	if (v_scroll->is_visible_in_tree()) {
 	if (v_scroll->is_visible_in_tree()) {
 		visible_width -= v_scroll->get_combined_minimum_size().width;
 		visible_width -= v_scroll->get_combined_minimum_size().width;
 	}
 	}
@@ -4698,7 +4591,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
 		return CURSOR_POINTING_HAND;
 		return CURSOR_POINTING_HAND;
 	}
 	}
 
 
-	int gutter = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width;
+	int gutter = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + cache.fold_gutter_width + cache.info_gutter_width;
 	if ((completion_active && completion_rect.has_point(p_pos))) {
 	if ((completion_active && completion_rect.has_point(p_pos))) {
 		return CURSOR_ARROW;
 		return CURSOR_ARROW;
 	}
 	}
@@ -4722,14 +4615,9 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
 
 
 		left_margin += gutters_width;
 		left_margin += gutters_width;
 
 
-		// Breakpoint icon.
-		if (draw_breakpoint_gutter && p_pos.x > left_margin - 6 && p_pos.x <= left_margin + cache.breakpoint_gutter_width - 3) {
-			return CURSOR_POINTING_HAND;
-		}
-
 		// Info icons.
 		// Info icons.
-		int gutter_left = left_margin + cache.breakpoint_gutter_width + cache.info_gutter_width;
-		if (draw_info_gutter && p_pos.x > left_margin + cache.breakpoint_gutter_width - 6 && p_pos.x <= gutter_left - 3) {
+		int gutter_left = left_margin + cache.info_gutter_width;
+		if (draw_info_gutter && p_pos.x > left_margin - 6 && p_pos.x <= gutter_left - 3) {
 			if (text.has_info_icon(row)) {
 			if (text.has_info_icon(row)) {
 				return CURSOR_POINTING_HAND;
 				return CURSOR_POINTING_HAND;
 			}
 			}
@@ -4757,7 +4645,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
 		// EOL fold icon.
 		// EOL fold icon.
 		if (is_folded(row)) {
 		if (is_folded(row)) {
 			int line_width = text.get_line_width(row);
 			int line_width = text.get_line_width(row);
-			line_width += cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width - cursor.x_ofs;
+			line_width += cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding + cache.fold_gutter_width + cache.info_gutter_width - cursor.x_ofs;
 			if (p_pos.x > line_width - 3 && p_pos.x <= line_width + cache.folded_eol_icon->get_width() + 3) {
 			if (p_pos.x > line_width - 3 && p_pos.x <= line_width + cache.folded_eol_icon->get_width() + 3) {
 				return CURSOR_POINTING_HAND;
 				return CURSOR_POINTING_HAND;
 			}
 			}
@@ -4968,9 +4856,6 @@ void TextEdit::_update_caches() {
 	cache.mark_color = get_theme_color("mark_color");
 	cache.mark_color = get_theme_color("mark_color");
 	cache.current_line_color = get_theme_color("current_line_color");
 	cache.current_line_color = get_theme_color("current_line_color");
 	cache.line_length_guideline_color = get_theme_color("line_length_guideline_color");
 	cache.line_length_guideline_color = get_theme_color("line_length_guideline_color");
-	cache.bookmark_color = get_theme_color("bookmark_color");
-	cache.breakpoint_color = get_theme_color("breakpoint_color");
-	cache.executing_line_color = get_theme_color("executing_line_color");
 	cache.code_folding_color = get_theme_color("code_folding_color");
 	cache.code_folding_color = get_theme_color("code_folding_color");
 	cache.brace_mismatch_color = get_theme_color("brace_mismatch_color");
 	cache.brace_mismatch_color = get_theme_color("brace_mismatch_color");
 	cache.word_highlighted_color = get_theme_color("word_highlighted_color");
 	cache.word_highlighted_color = get_theme_color("word_highlighted_color");
@@ -4988,7 +4873,6 @@ void TextEdit::_update_caches() {
 	cache.folded_icon = get_theme_icon("folded");
 	cache.folded_icon = get_theme_icon("folded");
 	cache.can_fold_icon = get_theme_icon("fold");
 	cache.can_fold_icon = get_theme_icon("fold");
 	cache.folded_eol_icon = get_theme_icon("GuiEllipsis", "EditorIcons");
 	cache.folded_eol_icon = get_theme_icon("GuiEllipsis", "EditorIcons");
-	cache.executing_icon = get_theme_icon("MainPlay", "EditorIcons");
 	text.set_font(cache.font);
 	text.set_font(cache.font);
 	text.clear_width_cache();
 	text.clear_width_cache();
 
 
@@ -5632,84 +5516,6 @@ bool TextEdit::is_line_set_as_safe(int p_line) const {
 	return text.is_safe(p_line);
 	return text.is_safe(p_line);
 }
 }
 
 
-void TextEdit::set_executing_line(int p_line) {
-	ERR_FAIL_INDEX(p_line, text.size());
-	executing_line = p_line;
-	update();
-}
-
-void TextEdit::clear_executing_line() {
-	executing_line = -1;
-	update();
-}
-
-bool TextEdit::is_line_set_as_bookmark(int p_line) const {
-	ERR_FAIL_INDEX_V(p_line, text.size(), false);
-	return text.is_bookmark(p_line);
-}
-
-void TextEdit::set_line_as_bookmark(int p_line, bool p_bookmark) {
-	ERR_FAIL_INDEX(p_line, text.size());
-	text.set_bookmark(p_line, p_bookmark);
-	update();
-}
-
-void TextEdit::get_bookmarks(List<int> *p_bookmarks) const {
-	for (int i = 0; i < text.size(); i++) {
-		if (text.is_bookmark(i)) {
-			p_bookmarks->push_back(i);
-		}
-	}
-}
-
-Array TextEdit::get_bookmarks_array() const {
-	Array arr;
-	for (int i = 0; i < text.size(); i++) {
-		if (text.is_bookmark(i)) {
-			arr.append(i);
-		}
-	}
-	return arr;
-}
-
-bool TextEdit::is_line_set_as_breakpoint(int p_line) const {
-	ERR_FAIL_INDEX_V(p_line, text.size(), false);
-	return text.is_breakpoint(p_line);
-}
-
-void TextEdit::set_line_as_breakpoint(int p_line, bool p_breakpoint) {
-	ERR_FAIL_INDEX(p_line, text.size());
-	text.set_breakpoint(p_line, p_breakpoint);
-	update();
-}
-
-void TextEdit::get_breakpoints(List<int> *p_breakpoints) const {
-	for (int i = 0; i < text.size(); i++) {
-		if (text.is_breakpoint(i)) {
-			p_breakpoints->push_back(i);
-		}
-	}
-}
-
-Array TextEdit::get_breakpoints_array() const {
-	Array arr;
-	for (int i = 0; i < text.size(); i++) {
-		if (text.is_breakpoint(i)) {
-			arr.append(i);
-		}
-	}
-	return arr;
-}
-
-void TextEdit::remove_breakpoints() {
-	for (int i = 0; i < text.size(); i++) {
-		if (text.is_breakpoint(i)) {
-			/* Should "breakpoint_toggled" be fired when breakpoints are removed this way? */
-			text.set_breakpoint(i, false);
-		}
-	}
-}
-
 void TextEdit::set_line_info_icon(int p_line, Ref<Texture2D> p_icon, String p_info) {
 void TextEdit::set_line_info_icon(int p_line, Ref<Texture2D> p_icon, String p_info) {
 	ERR_FAIL_INDEX(p_line, text.size());
 	ERR_FAIL_INDEX(p_line, text.size());
 	text.set_info_icon(p_line, p_icon, p_info);
 	text.set_info_icon(p_line, p_icon, p_info);
@@ -6797,33 +6603,6 @@ void TextEdit::set_line_length_guideline_hard_column(int p_column) {
 	update();
 	update();
 }
 }
 
 
-void TextEdit::set_bookmark_gutter_enabled(bool p_draw) {
-	draw_bookmark_gutter = p_draw;
-	update();
-}
-
-bool TextEdit::is_bookmark_gutter_enabled() const {
-	return draw_bookmark_gutter;
-}
-
-void TextEdit::set_breakpoint_gutter_enabled(bool p_draw) {
-	draw_breakpoint_gutter = p_draw;
-	update();
-}
-
-bool TextEdit::is_breakpoint_gutter_enabled() const {
-	return draw_breakpoint_gutter;
-}
-
-void TextEdit::set_breakpoint_gutter_width(int p_gutter_width) {
-	breakpoint_gutter_width = p_gutter_width;
-	update();
-}
-
-int TextEdit::get_breakpoint_gutter_width() const {
-	return cache.breakpoint_gutter_width;
-}
-
 void TextEdit::set_draw_fold_gutter(bool p_draw) {
 void TextEdit::set_draw_fold_gutter(bool p_draw) {
 	draw_fold_gutter = p_draw;
 	draw_fold_gutter = p_draw;
 	update();
 	update();
@@ -7070,8 +6849,6 @@ void TextEdit::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("is_drawing_tabs"), &TextEdit::is_drawing_tabs);
 	ClassDB::bind_method(D_METHOD("is_drawing_tabs"), &TextEdit::is_drawing_tabs);
 	ClassDB::bind_method(D_METHOD("set_draw_spaces"), &TextEdit::set_draw_spaces);
 	ClassDB::bind_method(D_METHOD("set_draw_spaces"), &TextEdit::set_draw_spaces);
 	ClassDB::bind_method(D_METHOD("is_drawing_spaces"), &TextEdit::is_drawing_spaces);
 	ClassDB::bind_method(D_METHOD("is_drawing_spaces"), &TextEdit::is_drawing_spaces);
-	ClassDB::bind_method(D_METHOD("set_breakpoint_gutter_enabled", "enable"), &TextEdit::set_breakpoint_gutter_enabled);
-	ClassDB::bind_method(D_METHOD("is_breakpoint_gutter_enabled"), &TextEdit::is_breakpoint_gutter_enabled);
 	ClassDB::bind_method(D_METHOD("set_draw_fold_gutter"), &TextEdit::set_draw_fold_gutter);
 	ClassDB::bind_method(D_METHOD("set_draw_fold_gutter"), &TextEdit::set_draw_fold_gutter);
 	ClassDB::bind_method(D_METHOD("is_drawing_fold_gutter"), &TextEdit::is_drawing_fold_gutter);
 	ClassDB::bind_method(D_METHOD("is_drawing_fold_gutter"), &TextEdit::is_drawing_fold_gutter);
 
 
@@ -7145,9 +6922,6 @@ void TextEdit::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option);
 	ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option);
 	ClassDB::bind_method(D_METHOD("get_menu"), &TextEdit::get_menu);
 	ClassDB::bind_method(D_METHOD("get_menu"), &TextEdit::get_menu);
 
 
-	ClassDB::bind_method(D_METHOD("get_breakpoints"), &TextEdit::get_breakpoints_array);
-	ClassDB::bind_method(D_METHOD("remove_breakpoints"), &TextEdit::remove_breakpoints);
-
 	ClassDB::bind_method(D_METHOD("draw_minimap", "draw"), &TextEdit::set_draw_minimap);
 	ClassDB::bind_method(D_METHOD("draw_minimap", "draw"), &TextEdit::set_draw_minimap);
 	ClassDB::bind_method(D_METHOD("is_drawing_minimap"), &TextEdit::is_drawing_minimap);
 	ClassDB::bind_method(D_METHOD("is_drawing_minimap"), &TextEdit::is_drawing_minimap);
 	ClassDB::bind_method(D_METHOD("set_minimap_width", "width"), &TextEdit::set_minimap_width);
 	ClassDB::bind_method(D_METHOD("set_minimap_width", "width"), &TextEdit::set_minimap_width);
@@ -7158,7 +6932,6 @@ void TextEdit::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_tabs"), "set_draw_tabs", "is_drawing_tabs");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_tabs"), "set_draw_tabs", "is_drawing_tabs");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_spaces"), "set_draw_spaces", "is_drawing_spaces");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_spaces"), "set_draw_spaces", "is_drawing_spaces");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "breakpoint_gutter"), "set_breakpoint_gutter_enabled", "is_breakpoint_gutter_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fold_gutter"), "set_draw_fold_gutter", "is_drawing_fold_gutter");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fold_gutter"), "set_draw_fold_gutter", "is_drawing_fold_gutter");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color");
@@ -7192,7 +6965,6 @@ void TextEdit::_bind_methods() {
 	ADD_SIGNAL(MethodInfo("gutter_clicked", PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::INT, "gutter")));
 	ADD_SIGNAL(MethodInfo("gutter_clicked", PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::INT, "gutter")));
 	ADD_SIGNAL(MethodInfo("gutter_added"));
 	ADD_SIGNAL(MethodInfo("gutter_added"));
 	ADD_SIGNAL(MethodInfo("gutter_removed"));
 	ADD_SIGNAL(MethodInfo("gutter_removed"));
-	ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "row")));
 	ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "row"), PropertyInfo(Variant::INT, "column")));
 	ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "row"), PropertyInfo(Variant::INT, "column")));
 	ADD_SIGNAL(MethodInfo("info_clicked", PropertyInfo(Variant::INT, "row"), PropertyInfo(Variant::STRING, "info")));
 	ADD_SIGNAL(MethodInfo("info_clicked", PropertyInfo(Variant::INT, "row"), PropertyInfo(Variant::STRING, "info")));
 	ADD_SIGNAL(MethodInfo("symbol_validate", PropertyInfo(Variant::STRING, "symbol")));
 	ADD_SIGNAL(MethodInfo("symbol_validate", PropertyInfo(Variant::STRING, "symbol")));
@@ -7227,8 +6999,6 @@ TextEdit::TextEdit() {
 	_update_caches();
 	_update_caches();
 	cache.row_height = 1;
 	cache.row_height = 1;
 	cache.line_spacing = 1;
 	cache.line_spacing = 1;
-	cache.breakpoint_gutter_width = 0;
-	breakpoint_gutter_width = 0;
 	cache.fold_gutter_width = 0;
 	cache.fold_gutter_width = 0;
 	fold_gutter_width = 0;
 	fold_gutter_width = 0;
 	info_gutter_width = 0;
 	info_gutter_width = 0;
@@ -7299,8 +7069,6 @@ TextEdit::TextEdit() {
 	line_length_guidelines = false;
 	line_length_guidelines = false;
 	line_length_guideline_soft_col = 80;
 	line_length_guideline_soft_col = 80;
 	line_length_guideline_hard_col = 100;
 	line_length_guideline_hard_col = 100;
-	draw_bookmark_gutter = false;
-	draw_breakpoint_gutter = false;
 	draw_fold_gutter = false;
 	draw_fold_gutter = false;
 	draw_info_gutter = false;
 	draw_info_gutter = false;
 	hiding_enabled = false;
 	hiding_enabled = false;
@@ -7340,8 +7108,6 @@ TextEdit::TextEdit() {
 	set_readonly(false);
 	set_readonly(false);
 	menu->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
 	menu->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
 	first_draw = true;
 	first_draw = true;
-
-	executing_line = -1;
 }
 }
 
 
 TextEdit::~TextEdit() {
 TextEdit::~TextEdit() {

+ 0 - 40
scene/gui/text_edit.h

@@ -81,8 +81,6 @@ private:
 
 
 			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 safe : 1;
 			bool has_info : 1;
 			bool has_info : 1;
@@ -93,8 +91,6 @@ private:
 			Line() {
 			Line() {
 				width_cache = 0;
 				width_cache = 0;
 				marked = false;
 				marked = false;
-				breakpoint = false;
-				bookmark = false;
 				hidden = false;
 				hidden = false;
 				safe = false;
 				safe = false;
 				has_info = false;
 				has_info = false;
@@ -121,10 +117,6 @@ private:
 		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; }
 		void set_safe(int p_line, bool p_safe) { text.write[p_line].safe = p_safe; }
@@ -321,9 +313,6 @@ private:
 	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;
 	bool draw_fold_gutter;
 	int fold_gutter_width;
 	int fold_gutter_width;
 	bool hiding_enabled;
 	bool hiding_enabled;
@@ -383,11 +372,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;
@@ -484,7 +470,6 @@ protected:
 		Ref<Texture2D> can_fold_icon;
 		Ref<Texture2D> can_fold_icon;
 		Ref<Texture2D> folded_icon;
 		Ref<Texture2D> folded_icon;
 		Ref<Texture2D> folded_eol_icon;
 		Ref<Texture2D> folded_eol_icon;
-		Ref<Texture2D> executing_icon;
 		Ref<StyleBox> style_normal;
 		Ref<StyleBox> style_normal;
 		Ref<StyleBox> style_focus;
 		Ref<StyleBox> style_focus;
 		Ref<StyleBox> style_readonly;
 		Ref<StyleBox> style_readonly;
@@ -501,9 +486,6 @@ protected:
 		Color font_color_readonly;
 		Color font_color_readonly;
 		Color selection_color;
 		Color selection_color;
 		Color mark_color;
 		Color mark_color;
-		Color bookmark_color;
-		Color breakpoint_color;
-		Color executing_line_color;
 		Color code_folding_color;
 		Color code_folding_color;
 		Color current_line_color;
 		Color current_line_color;
 		Color line_length_guideline_color;
 		Color line_length_guideline_color;
@@ -515,14 +497,12 @@ protected:
 
 
 		int row_height;
 		int row_height;
 		int line_spacing;
 		int line_spacing;
-		int breakpoint_gutter_width;
 		int fold_gutter_width;
 		int fold_gutter_width;
 		int info_gutter_width;
 		int info_gutter_width;
 		int minimap_width;
 		int minimap_width;
 		Cache() {
 		Cache() {
 			row_height = 0;
 			row_height = 0;
 			line_spacing = 0;
 			line_spacing = 0;
-			breakpoint_gutter_width = 0;
 			fold_gutter_width = 0;
 			fold_gutter_width = 0;
 			info_gutter_width = 0;
 			info_gutter_width = 0;
 			minimap_width = 0;
 			minimap_width = 0;
@@ -625,19 +605,8 @@ 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);
 	void set_line_as_safe(int p_line, bool p_safe);
 	bool is_line_set_as_safe(int p_line) const;
 	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 set_line_info_icon(int p_line, Ref<Texture2D> p_icon, String p_info = "");
 	void clear_info_icons();
 	void clear_info_icons();
@@ -788,15 +757,6 @@ public:
 	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);
 	void set_draw_fold_gutter(bool p_draw);
 	bool is_drawing_fold_gutter() const;
 	bool is_drawing_fold_gutter() const;
 
 

二進制
scene/resources/default_theme/bookmark.png


+ 6 - 4
scene/resources/default_theme/default_theme.cpp

@@ -419,9 +419,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
 
 
 	theme->set_icon("tab", "CodeEdit", make_icon(tab_png));
 	theme->set_icon("tab", "CodeEdit", make_icon(tab_png));
 	theme->set_icon("space", "CodeEdit", make_icon(space_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("folded", "CodeEdit", make_icon(arrow_right_png));
 	theme->set_icon("folded", "CodeEdit", make_icon(arrow_right_png));
 	theme->set_icon("fold", "CodeEdit", make_icon(arrow_down_png));
 	theme->set_icon("fold", "CodeEdit", make_icon(arrow_down_png));
-
 	theme->set_font("font", "CodeEdit", Ref<Font>());
 	theme->set_font("font", "CodeEdit", Ref<Font>());
 
 
 	theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0));
 	theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0));
@@ -435,9 +437,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
 	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("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("selection_color", "CodeEdit", font_color_selection);
 	theme->set_color("mark_color", "CodeEdit", Color(1.0, 0.4, 0.4, 0.4));
 	theme->set_color("mark_color", "CodeEdit", Color(1.0, 0.4, 0.4, 0.4));
-	theme->set_color("bookmark_color", "CodeEdit", Color(0.08, 0.49, 0.98));
-	theme->set_color("breakpoint_color", "CodeEdit", Color(0.8, 0.8, 0.4, 0.2));
-	theme->set_color("executing_line_color", "CodeEdit", Color(0.2, 0.8, 0.2, 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("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("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_color", "CodeEdit", control_font_color);

+ 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
 };
 };