diff --git a/doc/classes/ScriptEditorBase.xml b/doc/classes/ScriptEditorBase.xml index 50ee8110c0..48e6a0ab1d 100644 --- a/doc/classes/ScriptEditorBase.xml +++ b/doc/classes/ScriptEditorBase.xml @@ -68,13 +68,13 @@ - Emitted when the user contextual goto and the item is in the same script. + Emitted when the editor requests to save a new history navigation point. - Emitted when the user changes current script or moves caret by 10 or more columns within the same script. + Emitted when the editor requests an update to its navigation point. diff --git a/editor/doc/editor_help.cpp b/editor/doc/editor_help.cpp index a469a50955..6d7c317409 100644 --- a/editor/doc/editor_help.cpp +++ b/editor/doc/editor_help.cpp @@ -54,6 +54,7 @@ #include "editor/file_system/editor_paths.h" #include "editor/gui/editor_toaster.h" #include "editor/inspector/editor_property_name_processor.h" +#include "editor/script/script_editor_navigation_marker.h" #include "editor/script/script_editor_plugin.h" #include "editor/script/syntax_highlighters.h" #include "editor/settings/editor_settings.h" @@ -270,13 +271,14 @@ void EditorHelp::_search(bool p_search_previous) { void EditorHelp::_class_desc_finished() { if (scroll_to >= 0) { - class_desc->connect(SceneStringName(draw), callable_mp(class_desc, &RichTextLabel::scroll_to_paragraph).bind(scroll_to), CONNECT_ONE_SHOT | CONNECT_DEFERRED); + class_desc->connect(SceneStringName(draw), callable_mp(this, &EditorHelp::_class_desc_scroll_to_paragraph).bind(scroll_to, need_save_new_history), CONNECT_ONE_SHOT | CONNECT_DEFERRED); } scroll_to = -1; + need_save_new_history = false; } void EditorHelp::_class_list_select(const String &p_select) { - _goto_desc(p_select); + _goto_desc(p_select, true); } void EditorHelp::_class_desc_select(const String &p_select) { @@ -344,12 +346,14 @@ void EditorHelp::_class_desc_select(const String &p_select) { // Case order is important here to correctly handle edge cases like `Variant.Type` in `@GlobalScope`. if (table->has(link)) { // Found in the current page. + ScriptEditorNavigationMarker::get_singleton()->locate_begin(); if (class_desc->is_finished()) { - emit_signal(SNAME("request_save_history")); - class_desc->scroll_to_paragraph((*table)[link]); + _class_desc_scroll_to_paragraph((*table)[link], _need_save_new_history()); } else { scroll_to = (*table)[link]; + need_save_new_history = _need_save_new_history(); } + ScriptEditorNavigationMarker::get_singleton()->locate_end(); } else { // Look for link in `@GlobalScope`. if (topic == "class_enum") { @@ -726,7 +730,7 @@ void EditorHelp::_pop_code_font() { class_desc->pop(); // font } -Error EditorHelp::_goto_desc(const String &p_class) { +Error EditorHelp::_goto_desc(const String &p_class, bool p_can_trigger_save_history) { if (!doc->class_list.has(p_class)) { return ERR_DOES_NOT_EXIST; } @@ -738,11 +742,17 @@ Error EditorHelp::_goto_desc(const String &p_class) { description_line = 0; if (p_class == edited_class) { + if (p_can_trigger_save_history) { + trigger_history_save_on_navigate(); + } return OK; // Already there. } edited_class = p_class; _update_doc(); + if (p_can_trigger_save_history) { + trigger_history_save_on_navigate(); + } return OK; } @@ -2344,7 +2354,7 @@ void EditorHelp::_update_doc() { } void EditorHelp::_request_help(const String &p_string) { - Error err = _goto_desc(p_string); + Error err = _goto_desc(p_string, false); if (err == OK) { EditorNode::get_singleton()->get_editor_main_screen()->select(EditorMainScreen::EDITOR_SCRIPT); } @@ -2432,12 +2442,36 @@ void EditorHelp::_help_callback(const String &p_topic) { } if (class_desc->is_finished()) { - class_desc->scroll_to_paragraph(line); + _class_desc_scroll_to_paragraph(line, _need_save_new_history()); } else { scroll_to = line; + need_save_new_history = _need_save_new_history(); } } +void EditorHelp::_class_desc_scroll_to_paragraph(int p_line, bool p_save_history) { + // Save history before scrolling. + if (p_save_history) { + Dictionary state = get_state(); + // Row 0 is not a state worth saving as a previous state to history. + if (int(state["row"]) > 0) { + emit_signal(SNAME("_request_save_new_history"), state); + } + } + class_desc->scroll_to_paragraph(p_line); + // Save history after scrolling. + if (p_save_history) { + emit_signal(SNAME("_request_save_new_history"), get_state()); + if (ScriptEditorNavigationMarker::get_singleton()->is_locating()) { + ScriptEditorNavigationMarker::get_singleton()->locate_end(); + } + } +} + +bool EditorHelp::_need_save_new_history() const { + return !ScriptEditorNavigationMarker::get_singleton()->is_initializing() && ScriptEditorNavigationMarker::get_singleton()->is_locating(); +} + static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, const Control *p_owner_node, const String &p_class) { bool is_native = false; { @@ -3352,7 +3386,7 @@ void EditorHelp::go_to_help(const String &p_help) { void EditorHelp::go_to_class(const String &p_class) { _wait_for_thread(); - _goto_desc(p_class); + _goto_desc(p_class, true); } void EditorHelp::update_doc() { @@ -3362,6 +3396,21 @@ void EditorHelp::update_doc() { _update_doc(); } +void EditorHelp::trigger_history_save_on_navigate() { + if (_need_save_new_history()) { + emit_signal(SNAME("_request_save_new_history"), get_state()); + if (ScriptEditorNavigationMarker::get_singleton()->is_locating()) { + ScriptEditorNavigationMarker::get_singleton()->locate_end(); + } + } +} + +Dictionary EditorHelp::get_state() { + Dictionary state; + state["row"] = get_scroll(); // Use "row" to simplify the logic when processing history list. + return state; +} + void EditorHelp::cleanup_doc() { _wait_for_thread(); memdelete(doc); @@ -3380,12 +3429,15 @@ Vector> EditorHelp::get_sections() { void EditorHelp::scroll_to_section(int p_section_index) { _wait_for_thread(); + ScriptEditorNavigationMarker::get_singleton()->locate_begin(); int line = section_line[p_section_index].second; if (class_desc->is_finished()) { - class_desc->scroll_to_paragraph(line); + _class_desc_scroll_to_paragraph(line, _need_save_new_history()); } else { scroll_to = line; + need_save_new_history = _need_save_new_history(); } + ScriptEditorNavigationMarker::get_singleton()->locate_end(); } void EditorHelp::popup_search() { @@ -3425,7 +3477,7 @@ void EditorHelp::_bind_methods() { ClassDB::bind_method("_help_callback", &EditorHelp::_help_callback); ADD_SIGNAL(MethodInfo("go_to_help")); - ADD_SIGNAL(MethodInfo("request_save_history")); + ADD_SIGNAL(MethodInfo("_request_save_new_history", PropertyInfo(Variant::DICTIONARY, "state"))); } void EditorHelp::init_gdext_pointers() { diff --git a/editor/doc/editor_help.h b/editor/doc/editor_help.h index 8b5786a6b5..4848b728dd 100644 --- a/editor/doc/editor_help.h +++ b/editor/doc/editor_help.h @@ -148,8 +148,11 @@ class EditorHelp : public VBoxContainer { } theme_cache; int scroll_to = -1; + bool need_save_new_history = false; void _help_callback(const String &p_topic); + void _class_desc_scroll_to_paragraph(int p_line, bool p_save_history); + bool _need_save_new_history() const; void _add_text(const String &p_bbcode); bool scroll_locked = false; @@ -175,7 +178,7 @@ class EditorHelp : public VBoxContainer { void _class_desc_resized(bool p_force_update_theme); int display_margin = 0; - Error _goto_desc(const String &p_class); + Error _goto_desc(const String &p_class, bool p_can_trigger_save_history); //void _update_history_buttons(); void _update_method_list(MethodType p_method_type, const Vector &p_methods); void _update_method_descriptions(const DocData::ClassDoc &p_classdoc, MethodType p_method_type, const Vector &p_methods); @@ -249,6 +252,8 @@ public: void go_to_help(const String &p_help); void go_to_class(const String &p_class); void update_doc(); + void trigger_history_save_on_navigate(); + Dictionary get_state(); Vector> get_sections(); void scroll_to_section(int p_section_index); diff --git a/editor/gui/code_editor.cpp b/editor/gui/code_editor.cpp index 8f80bcc6bd..cec3ffbe17 100644 --- a/editor/gui/code_editor.cpp +++ b/editor/gui/code_editor.cpp @@ -37,6 +37,7 @@ #include "core/string/string_builder.h" #include "editor/editor_node.h" #include "editor/editor_string_names.h" +#include "editor/script/script_editor_navigation_marker.h" #include "editor/script/syntax_highlighters.h" #include "editor/settings/editor_settings.h" #include "editor/themes/editor_scale.h" @@ -88,7 +89,9 @@ void GotoLinePopup::_goto_line() { } void GotoLinePopup::_submit() { + ScriptEditorNavigationMarker::get_singleton()->locate_begin(); _goto_line(); + ScriptEditorNavigationMarker::get_singleton()->locate_end(); hide(); } @@ -1387,12 +1390,21 @@ void CodeTextEditor::center_viewport_to_caret_if_line_invisible(int p_line) { text_editor->call_on_all_layout_pending_finished(callable_mp(this, &CodeTextEditor::center_viewport_to_caret_if_line_invisible).bind(0)); return; } - if (!text_editor->is_line_in_viewport(p_line)) { + if (!text_editor->is_line_in_viewport(CLAMP(p_line, 0, text_editor->get_line_count() - 1))) { text_editor->center_viewport_to_caret(); } } -void CodeTextEditor::goto_line(int p_line, int p_column) { +void CodeTextEditor::trigger_history_save_on_navigate() { + if (!ScriptEditorNavigationMarker::get_singleton()->is_initializing() && ScriptEditorNavigationMarker::get_singleton()->is_locating()) { + call_on_all_layout_pending_finished(callable_mp(this, &CodeTextEditor::_emit_request_save_new_history)); + if (ScriptEditorNavigationMarker::get_singleton()->is_locating()) { + ScriptEditorNavigationMarker::get_singleton()->locate_end(); + } + } +} + +void CodeTextEditor::goto_line_without_history(int p_line, int p_column) { text_editor->remove_secondary_carets(); text_editor->deselect(); text_editor->unfold_line(CLAMP(p_line, 0, text_editor->get_line_count() - 1)); @@ -1403,6 +1415,11 @@ void CodeTextEditor::goto_line(int p_line, int p_column) { adjust_viewport_to_caret(); } +void CodeTextEditor::goto_line(int p_line, int p_column) { + goto_line_without_history(p_line, p_column); + trigger_history_save_on_navigate(); +} + void CodeTextEditor::goto_line_selection(int p_line, int p_begin, int p_end) { text_editor->remove_secondary_carets(); text_editor->unfold_line(CLAMP(p_line, 0, text_editor->get_line_count() - 1)); @@ -1410,6 +1427,7 @@ void CodeTextEditor::goto_line_selection(int p_line, int p_begin, int p_end) { text_editor->set_code_hint(""); text_editor->cancel_code_completion(); adjust_viewport_to_caret(); + trigger_history_save_on_navigate(); } void CodeTextEditor::goto_line_centered(int p_line, int p_column) { @@ -1421,6 +1439,15 @@ void CodeTextEditor::goto_line_centered(int p_line, int p_column) { text_editor->set_code_hint(""); text_editor->cancel_code_completion(); center_viewport_to_caret(); + trigger_history_save_on_navigate(); +} + +void CodeTextEditor::goto_line_and_center_if_necessary(int p_line, int p_column) { + if (!text_editor->is_line_in_viewport(CLAMP(p_line, 0, text_editor->get_line_count() - 1))) { + goto_line_centered(p_line, p_column); + } else { + goto_line(p_line, p_column); + } } void CodeTextEditor::set_executing_line(int p_line) { @@ -1431,7 +1458,7 @@ void CodeTextEditor::clear_executing_line() { text_editor->clear_executing_lines(); } -Variant CodeTextEditor::get_edit_state() { +Dictionary CodeTextEditor::get_edit_state() { Dictionary state; state.merge(get_navigation_state()); @@ -1445,7 +1472,7 @@ Variant CodeTextEditor::get_edit_state() { return state; } -Variant CodeTextEditor::get_previous_state() { +Dictionary CodeTextEditor::get_previous_state() { return previous_state; } @@ -1467,7 +1494,7 @@ void CodeTextEditor::set_preview_navigation_change(bool p_preview) { } } -void CodeTextEditor::set_edit_state(const Variant &p_state) { +void CodeTextEditor::set_edit_state(const Dictionary &p_state) { Dictionary state = p_state; /* update the row first as it sets the column to 0 */ @@ -1478,17 +1505,17 @@ void CodeTextEditor::set_edit_state(const Variant &p_state) { } else { text_editor->set_caret_line(state["row"]); text_editor->set_caret_column(state["column"]); - if (int(state["scroll_position"]) == -1) { - // Special case for previous state. - center_viewport_to_caret(); - } else { - text_editor->set_v_scroll(state["scroll_position"]); - } + text_editor->set_v_scroll(state["scroll_position"]); text_editor->set_h_scroll(state["h_scroll_position"]); } if (state.get("selection", false)) { - text_editor->select(state["selection_from_line"], state["selection_from_column"], state["selection_to_line"], state["selection_to_column"]); + // Selection can be set in two ways, from->to or to->from, so we need to check the order to set it correctly. + if (state["row"] < state["selection_to_line"] || state["column"] < state["selection_to_column"]) { + text_editor->select(state["selection_to_line"], state["selection_to_column"], state["selection_from_line"], state["selection_from_column"]); + } else { + text_editor->select(state["selection_from_line"], state["selection_from_column"], state["selection_to_line"], state["selection_to_column"]); + } } else { text_editor->deselect(); } @@ -1525,7 +1552,7 @@ void CodeTextEditor::set_edit_state(const Variant &p_state) { } } -Variant CodeTextEditor::get_navigation_state() { +Dictionary CodeTextEditor::get_navigation_state() { Dictionary state; state["scroll_position"] = text_editor->get_v_scroll(); @@ -1915,6 +1942,10 @@ void CodeTextEditor::_show_goto_popup_request() { emit_signal("show_goto_popup"); } +void CodeTextEditor::_emit_request_save_new_history() { + emit_signal(SNAME("_request_save_new_history")); +} + void CodeTextEditor::_bind_methods() { ADD_SIGNAL(MethodInfo("validate_script")); ADD_SIGNAL(MethodInfo("load_theme_settings")); @@ -1923,6 +1954,7 @@ void CodeTextEditor::_bind_methods() { ADD_SIGNAL(MethodInfo("show_goto_popup")); ADD_SIGNAL(MethodInfo("navigation_preview_ended")); ADD_SIGNAL(MethodInfo("zoomed", PropertyInfo(Variant::FLOAT, "zoom_factor"))); + ADD_SIGNAL(MethodInfo("_request_save_new_history", PropertyInfo(Variant::DICTIONARY, "state"))); } void CodeTextEditor::set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func, void *p_ud) { diff --git a/editor/gui/code_editor.h b/editor/gui/code_editor.h index d6240990a1..c147764ad8 100644 --- a/editor/gui/code_editor.h +++ b/editor/gui/code_editor.h @@ -211,6 +211,7 @@ class CodeTextEditor : public VBoxContainer { void _zoom_to(float p_zoom_factor); void _show_goto_popup_request(); + void _emit_request_save_new_history(); void _update_error_content_height(); @@ -260,17 +261,20 @@ public: void adjust_viewport_to_caret(); void center_viewport_to_caret(); void center_viewport_to_caret_if_line_invisible(int p_line); + void trigger_history_save_on_navigate(); + void goto_line_without_history(int p_line, int p_column = 0); void goto_line(int p_line, int p_column = 0); void goto_line_selection(int p_line, int p_begin, int p_end); void goto_line_centered(int p_line, int p_column = 0); + void goto_line_and_center_if_necessary(int p_line, int p_column = 0); void set_executing_line(int p_line); void clear_executing_line(); - Variant get_edit_state(); - void set_edit_state(const Variant &p_state); - Variant get_navigation_state(); - Variant get_previous_state(); + Dictionary get_edit_state(); + void set_edit_state(const Dictionary &p_state); + Dictionary get_navigation_state(); + Dictionary get_previous_state(); void store_previous_state(); bool is_previewing_navigation_change() const; diff --git a/editor/script/script_editor_base.cpp b/editor/script/script_editor_base.cpp index 01da19977b..77d8988e46 100644 --- a/editor/script/script_editor_base.cpp +++ b/editor/script/script_editor_base.cpp @@ -34,6 +34,7 @@ #include "core/object/callable_mp.h" #include "core/object/class_db.h" #include "editor/editor_node.h" +#include "editor/script/script_editor_navigation_marker.h" #include "editor/script/script_editor_plugin.h" #include "editor/script/syntax_highlighters.h" #include "editor/settings/editor_settings.h" @@ -53,10 +54,11 @@ void ScriptEditorBase::_bind_methods() { // First use in ScriptTextEditor. ADD_SIGNAL(MethodInfo("request_save_history")); + ADD_SIGNAL(MethodInfo("_request_save_new_history", PropertyInfo(Variant::DICTIONARY, "state"))); + ADD_SIGNAL(MethodInfo("request_save_previous_state", PropertyInfo(Variant::DICTIONARY, "state"))); ADD_SIGNAL(MethodInfo("request_help", PropertyInfo(Variant::STRING, "topic"))); ADD_SIGNAL(MethodInfo("request_open_script_at_line", PropertyInfo(Variant::OBJECT, "script"), PropertyInfo(Variant::INT, "line"))); ADD_SIGNAL(MethodInfo("go_to_help", PropertyInfo(Variant::STRING, "what"))); - ADD_SIGNAL(MethodInfo("request_save_previous_state", PropertyInfo(Variant::DICTIONARY, "state"))); ADD_SIGNAL(MethodInfo("replace_in_files_requested", PropertyInfo(Variant::STRING, "text"))); ADD_SIGNAL(MethodInfo("go_to_method", PropertyInfo(Variant::OBJECT, "script"), PropertyInfo(Variant::STRING, "method"))); } @@ -174,7 +176,9 @@ void TextEditorBase::EditMenus::_bookmark_item_pressed(int p_idx) { if (p_idx < 4) { // Any item before the separator. script_text_editor->_edit_option(bookmarks_menu->get_item_id(p_idx)); } else { + ScriptEditorNavigationMarker::get_singleton()->locate_begin(); script_text_editor->code_editor->goto_line_centered(bookmarks_menu->get_item_metadata(p_idx)); + ScriptEditorNavigationMarker::get_singleton()->locate_end(); } } @@ -488,10 +492,14 @@ bool TextEditorBase::_edit_option(int p_op) { code_editor->toggle_bookmark(); } break; case BOOKMARK_GOTO_NEXT: { + ScriptEditorNavigationMarker::get_singleton()->locate_begin(); code_editor->goto_next_bookmark(); + ScriptEditorNavigationMarker::get_singleton()->locate_end(); } break; case BOOKMARK_GOTO_PREV: { + ScriptEditorNavigationMarker::get_singleton()->locate_begin(); code_editor->goto_prev_bookmark(); + ScriptEditorNavigationMarker::get_singleton()->locate_end(); } break; case BOOKMARK_REMOVE_ALL: { code_editor->remove_all_bookmarks(); @@ -524,6 +532,20 @@ void TextEditorBase::_validate_script() { emit_signal(SNAME("edited_script_changed")); } +void TextEditorBase::_emit_request_save_new_history() { + Dictionary state = get_edit_state(); + state["ensure_caret_visible"] = true; + previous_history_line = state["row"]; + emit_signal(SNAME("_request_save_new_history"), state); +} + +void TextEditorBase::_emit_request_save_previous_state() { + Dictionary state = get_edit_state(); + state["ensure_caret_visible"] = true; + previous_history_line = state["row"]; + emit_signal(SNAME("request_save_previous_state"), state); +} + void TextEditorBase::add_syntax_highlighter(Ref p_highlighter) { ERR_FAIL_COND(p_highlighter.is_null()); @@ -631,6 +653,9 @@ void TextEditorBase::set_edit_state(const Variant &p_state) { code_editor->set_edit_state(p_state); Dictionary state = p_state; + if (state.has("row")) { + previous_history_line = state["row"]; + } if (state.has("syntax_highlighter")) { for (const Ref &highlighter : highlighters) { if (highlighter->_get_name() == String(state["syntax_highlighter"])) { @@ -653,6 +678,7 @@ TextEditorBase::TextEditorBase() { code_editor->connect("validate_script", callable_mp(this, &TextEditorBase::_validate_script)); code_editor->connect("load_theme_settings", callable_mp(this, &TextEditorBase::_load_theme_settings)); code_editor->connect("show_goto_popup", callable_mp(this, &TextEditorBase::_edit_option).bind(SEARCH_GOTO_LINE)); + code_editor->connect("_request_save_new_history", callable_mp(this, &TextEditorBase::_emit_request_save_new_history)); context_menu = memnew(PopupMenu); context_menu->connect(SceneStringName(id_pressed), callable_mp(this, &TextEditorBase::_edit_option)); diff --git a/editor/script/script_editor_base.h b/editor/script/script_editor_base.h index 7ecf5b8c85..f0dc6ec846 100644 --- a/editor/script/script_editor_base.h +++ b/editor/script/script_editor_base.h @@ -182,6 +182,10 @@ protected: void _convert_case(CodeTextEditor::CaseStyle p_case) { code_editor->convert_case(p_case); } + int previous_history_line = -1; + void _emit_request_save_new_history(); + void _emit_request_save_previous_state(); + public: virtual void add_syntax_highlighter(Ref p_highlighter) override; virtual void set_syntax_highlighter(Ref p_highlighter); @@ -208,9 +212,12 @@ public: virtual void trim_final_newlines() { code_editor->trim_final_newlines(); } virtual void insert_final_newline() { code_editor->insert_final_newline(); } + virtual void goto_line_without_history(int p_line, int p_column = 0) { code_editor->goto_line_without_history(p_line, p_column); } virtual void goto_line(int p_line, int p_column = 0) { code_editor->goto_line(p_line, p_column); } virtual void goto_line_selection(int p_line, int p_begin, int p_end) { code_editor->goto_line_selection(p_line, p_begin, p_end); } virtual void goto_line_centered(int p_line, int p_column = 0) { code_editor->goto_line_centered(p_line, p_column); } + virtual void goto_line_and_center_if_necessary(int p_line, int p_column = 0) { code_editor->goto_line_and_center_if_necessary(p_line, p_column); } + virtual void trigger_history_save_on_navigate() { code_editor->trigger_history_save_on_navigate(); } virtual void set_executing_line(int p_line) { code_editor->set_executing_line(p_line); } virtual void clear_executing_line() { code_editor->clear_executing_line(); } diff --git a/editor/script/script_editor_navigation_marker.cpp b/editor/script/script_editor_navigation_marker.cpp new file mode 100644 index 0000000000..292ea767fc --- /dev/null +++ b/editor/script/script_editor_navigation_marker.cpp @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* script_editor_navigation_marker.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "script_editor_navigation_marker.h" + +#include "core/config/engine.h" +#include "core/os/memory.h" + +ScriptEditorNavigationMarker *ScriptEditorNavigationMarker::get_singleton() { + if (!singleton) { + singleton = memnew(ScriptEditorNavigationMarker); + } + return singleton; +} + +void ScriptEditorNavigationMarker::release_singleton() { + if (!singleton) { + return; + } + memdelete(singleton); + singleton = nullptr; +} + +void ScriptEditorNavigationMarker::init_begin() { + init_in_progress = true; +} + +void ScriptEditorNavigationMarker::init_end() { + init_in_progress = false; +} + +void ScriptEditorNavigationMarker::locate_begin() { + locate_in_progress = true; +} + +void ScriptEditorNavigationMarker::locate_end() { + locate_in_progress = false; + locate_end_physics_frame = Engine::get_singleton()->get_physics_frames(); + locate_end_process_frame = Engine::get_singleton()->get_process_frames(); +} + +void ScriptEditorNavigationMarker::traverse_begin() { + traverse_in_progress = true; +} + +void ScriptEditorNavigationMarker::traverse_end() { + traverse_in_progress = false; + traverse_end_physics_frame = Engine::get_singleton()->get_physics_frames(); + traverse_end_process_frame = Engine::get_singleton()->get_process_frames(); +} + +bool ScriptEditorNavigationMarker::is_initializing() const { + return init_in_progress; +} + +bool ScriptEditorNavigationMarker::is_locating() const { + return locate_in_progress; +} + +bool ScriptEditorNavigationMarker::is_traversing() const { + return traverse_in_progress; +} + +bool ScriptEditorNavigationMarker::is_locate_just_occured() const { + if (Engine::get_singleton()->is_in_physics_frame()) { + return locate_end_physics_frame == Engine::get_singleton()->get_physics_frames() || locate_end_physics_frame == Engine::get_singleton()->get_physics_frames() - 1; + } else { + return locate_end_process_frame == Engine::get_singleton()->get_process_frames(); + } +} + +bool ScriptEditorNavigationMarker::is_traverse_just_occured() const { + if (Engine::get_singleton()->is_in_physics_frame()) { + return traverse_end_physics_frame == Engine::get_singleton()->get_physics_frames() || traverse_end_physics_frame == Engine::get_singleton()->get_physics_frames() - 1; + } else { + return traverse_end_process_frame == Engine::get_singleton()->get_process_frames(); + } +} diff --git a/editor/script/script_editor_navigation_marker.h b/editor/script/script_editor_navigation_marker.h new file mode 100644 index 0000000000..dab689d272 --- /dev/null +++ b/editor/script/script_editor_navigation_marker.h @@ -0,0 +1,66 @@ +/**************************************************************************/ +/* script_editor_navigation_marker.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +#include + +class ScriptEditorNavigationMarker { + static inline ScriptEditorNavigationMarker *singleton = nullptr; + +private: + bool init_in_progress = false; + + bool locate_in_progress = false; + uint64_t locate_end_physics_frame = 0; + uint64_t locate_end_process_frame = 0; + + bool traverse_in_progress = false; + uint64_t traverse_end_physics_frame = 0; + uint64_t traverse_end_process_frame = 0; + +public: + static ScriptEditorNavigationMarker *get_singleton(); + static void release_singleton(); + + void init_begin(); + void init_end(); + void locate_begin(); + void locate_end(); + void traverse_begin(); + void traverse_end(); + + bool is_initializing() const; + bool is_locating() const; + bool is_traversing() const; + + bool is_locate_just_occured() const; + bool is_traverse_just_occured() const; +}; diff --git a/editor/script/script_editor_plugin.cpp b/editor/script/script_editor_plugin.cpp index 036e6a6860..05fa3494f0 100644 --- a/editor/script/script_editor_plugin.cpp +++ b/editor/script/script_editor_plugin.cpp @@ -65,6 +65,7 @@ #include "editor/run/editor_run_bar.h" #include "editor/scene/editor_scene_tabs.h" #include "editor/script/find_in_files.h" +#include "editor/script/script_editor_navigation_marker.h" #include "editor/script/script_text_editor.h" #include "editor/script/syntax_highlighters.h" #include "editor/script/text_editor.h" @@ -196,7 +197,9 @@ void ScriptEditor::_script_created(Ref