diff options
-rw-r--r-- | core/config/project_settings.cpp | 12 | ||||
-rw-r--r-- | core/config/project_settings.h | 1 | ||||
-rw-r--r-- | doc/classes/ScriptEditorBase.xml | 6 | ||||
-rw-r--r-- | editor/code_editor.cpp | 19 | ||||
-rw-r--r-- | editor/code_editor.h | 4 | ||||
-rw-r--r-- | editor/editor_help.cpp | 2 | ||||
-rw-r--r-- | editor/filesystem_dock.cpp | 1 | ||||
-rw-r--r-- | editor/plugin_config_dialog.cpp | 1 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.cpp | 81 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.h | 2 | ||||
-rw-r--r-- | editor/plugins/editor_preview_plugins.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/editor_resource_tooltip_plugins.cpp | 27 | ||||
-rw-r--r-- | editor/plugins/editor_resource_tooltip_plugins.h | 11 | ||||
-rw-r--r-- | editor/plugins/script_editor_plugin.cpp | 50 | ||||
-rw-r--r-- | editor/plugins/script_editor_plugin.h | 2 | ||||
-rw-r--r-- | editor/plugins/script_text_editor.cpp | 27 | ||||
-rw-r--r-- | editor/plugins/script_text_editor.h | 6 | ||||
-rw-r--r-- | editor/project_manager.cpp | 14 |
18 files changed, 234 insertions, 34 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 104b17961d..869fef23a5 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -1017,7 +1017,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust } } // Check for the existence of a csproj file. - if (_csproj_exists(get_resource_path())) { + if (_csproj_exists(p_path.get_base_dir())) { // If there is a csproj file, add the C# feature if it doesn't already exist. if (!project_features.has("C#")) { project_features.append("C#"); @@ -1568,6 +1568,14 @@ ProjectSettings::ProjectSettings() { ProjectSettings::get_singleton()->add_hidden_prefix("input/"); } +ProjectSettings::ProjectSettings(const String &p_path) { + if (load_custom(p_path) == OK) { + project_loaded = true; + } +} + ProjectSettings::~ProjectSettings() { - singleton = nullptr; + if (singleton == this) { + singleton = nullptr; + } } diff --git a/core/config/project_settings.h b/core/config/project_settings.h index 1bad76acb1..922c88c151 100644 --- a/core/config/project_settings.h +++ b/core/config/project_settings.h @@ -224,6 +224,7 @@ public: #endif ProjectSettings(); + ProjectSettings(const String &p_path); ~ProjectSettings(); }; diff --git a/doc/classes/ScriptEditorBase.xml b/doc/classes/ScriptEditorBase.xml index dca4fe9276..403608355a 100644 --- a/doc/classes/ScriptEditorBase.xml +++ b/doc/classes/ScriptEditorBase.xml @@ -71,6 +71,12 @@ Emitted when the user contextual goto and the item is in the same script. </description> </signal> + <signal name="request_save_previous_state"> + <param index="0" name="line" type="int" /> + <description> + Emitted when the user changes current script or moves caret by 10 or more columns within the same script. + </description> + </signal> <signal name="search_in_files_requested"> <param index="0" name="text" type="String" /> <description> diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 779080786a..49896d66d8 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1613,13 +1613,26 @@ Variant CodeTextEditor::get_edit_state() { return state; } +Variant CodeTextEditor::get_previous_state() { + return previous_state; +} + +void CodeTextEditor::store_previous_state() { + previous_state = get_navigation_state(); +} + void CodeTextEditor::set_edit_state(const Variant &p_state) { Dictionary state = p_state; /* update the row first as it sets the column to 0 */ text_editor->set_caret_line(state["row"]); text_editor->set_caret_column(state["column"]); - text_editor->set_v_scroll(state["scroll_position"]); + if (int(state["scroll_position"]) == -1) { + // Special case for previous state. + text_editor->center_viewport_to_caret(); + } else { + text_editor->set_v_scroll(state["scroll_position"]); + } text_editor->set_h_scroll(state["h_scroll_position"]); if (state.get("selection", false)) { @@ -1648,6 +1661,10 @@ void CodeTextEditor::set_edit_state(const Variant &p_state) { text_editor->set_line_as_bookmarked(bookmarks[i], true); } } + + if (previous_state.is_empty()) { + previous_state = p_state; + } } Variant CodeTextEditor::get_navigation_state() { diff --git a/editor/code_editor.h b/editor/code_editor.h index 64b13b9006..c36eedb580 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -174,6 +174,8 @@ class CodeTextEditor : public VBoxContainer { int error_line; int error_column; + Dictionary previous_state; + void _update_text_editor_theme(); void _update_font_ligatures(); void _complete_request(); @@ -254,6 +256,8 @@ public: Variant get_edit_state(); void set_edit_state(const Variant &p_state); Variant get_navigation_state(); + Variant get_previous_state(); + void store_previous_state(); void set_error_count(int p_error_count); void set_warning_count(int p_warning_count); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 5cc09b7104..63c2ebe3d9 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -287,6 +287,7 @@ void EditorHelp::_class_desc_select(const String &p_select) { if (table->has(link)) { // Found in the current page. if (class_desc->is_ready()) { + emit_signal(SNAME("request_save_history")); class_desc->scroll_to_paragraph((*table)[link]); } else { scroll_to = (*table)[link]; @@ -3077,6 +3078,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")); } void EditorHelp::init_gdext_pointers() { diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 12c2408d0f..3f96d934a8 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -4184,6 +4184,7 @@ FileSystemDock::FileSystemDock() { ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &FileSystemDock::_project_settings_changed)); add_resource_tooltip_plugin(memnew(EditorTextureTooltipPlugin)); + add_resource_tooltip_plugin(memnew(EditorAudioStreamTooltipPlugin)); } FileSystemDock::~FileSystemDock() { diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index 6f54a1c57a..184a9233a8 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -72,6 +72,7 @@ void PluginConfigDialog::_on_confirmed() { String script_path = path.path_join(script_name); Ref<ConfigFile> cf = memnew(ConfigFile); + cf->load(path.path_join("plugin.cfg")); cf->set_value("plugin", "name", name_edit->get_text()); cf->set_value("plugin", "description", desc_edit->get_text()); cf->set_value("plugin", "author", author_edit->get_text()); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 8a9118a03e..5ac5dd6ee6 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1344,22 +1344,33 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { // Drag the pivot (in pivot mode / with V key) if (drag_type == DRAG_NONE) { + bool move_temp_pivot = ((b.is_valid() && b->is_shift_pressed()) || (k.is_valid() && k->is_shift_pressed())); + if ((b.is_valid() && b->is_pressed() && b->get_button_index() == MouseButton::LEFT && tool == TOOL_EDIT_PIVOT) || - (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == Key::V && tool == TOOL_SELECT && k->get_modifiers_mask().is_empty())) { + (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == Key::V && tool == TOOL_SELECT && (k->get_modifiers_mask().is_empty() || move_temp_pivot))) { List<CanvasItem *> selection = _get_edited_canvas_items(); // Filters the selection with nodes that allow setting the pivot drag_selection = List<CanvasItem *>(); for (CanvasItem *ci : selection) { - if (ci->_edit_use_pivot()) { + if (ci->_edit_use_pivot() || move_temp_pivot) { drag_selection.push_back(ci); } } // Start dragging if we still have nodes if (drag_selection.size() > 0) { + Vector2 event_pos = (b.is_valid()) ? b->get_position() : viewport->get_local_mouse_position(); + + if (move_temp_pivot) { + drag_type = DRAG_TEMP_PIVOT; + temp_pivot = transform.affine_inverse().xform(event_pos); + viewport->queue_redraw(); + return true; + } + _save_canvas_item_state(drag_selection); - drag_from = transform.affine_inverse().xform((b.is_valid()) ? b->get_position() : viewport->get_local_mouse_position()); + drag_from = transform.affine_inverse().xform(event_pos); Vector2 new_pos; if (drag_selection.size() == 1) { new_pos = snap_point(drag_from, SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, drag_selection[0]); @@ -1416,6 +1427,20 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { return true; } } + + if (drag_type == DRAG_TEMP_PIVOT) { + if (m.is_valid()) { + temp_pivot = transform.affine_inverse().xform(m->get_position()); + viewport->queue_redraw(); + return true; + } + + if ((b.is_valid() && !b->is_pressed() && b->get_button_index() == MouseButton::LEFT && tool == TOOL_EDIT_PIVOT) || + (k.is_valid() && !k->is_pressed() && k->get_keycode() == Key::V)) { + drag_type = DRAG_NONE; + return true; + } + } return false; } @@ -1441,7 +1466,9 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { drag_type = DRAG_ROTATE; drag_from = transform.affine_inverse().xform(b->get_position()); CanvasItem *ci = drag_selection[0]; - if (ci->_edit_use_pivot()) { + if (!Math::is_inf(temp_pivot.x) || !Math::is_inf(temp_pivot.y)) { + drag_rotation_center = temp_pivot; + } else if (ci->_edit_use_pivot()) { drag_rotation_center = ci->get_global_transform_with_canvas().xform(ci->_edit_get_pivot()); } else { drag_rotation_center = ci->get_global_transform_with_canvas().get_origin(); @@ -1461,7 +1488,16 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { drag_to = transform.affine_inverse().xform(m->get_position()); //Rotate the opposite way if the canvas item's compounded scale has an uneven number of negative elements bool opposite = (ci->get_global_transform().get_scale().sign().dot(ci->get_transform().get_scale().sign()) == 0); - ci->_edit_set_rotation(snap_angle(ci->_edit_get_rotation() + (opposite ? -1 : 1) * (drag_from - drag_rotation_center).angle_to(drag_to - drag_rotation_center), ci->_edit_get_rotation())); + real_t prev_rotation = ci->_edit_get_rotation(); + real_t new_rotation = snap_angle(ci->_edit_get_rotation() + (opposite ? -1 : 1) * (drag_from - drag_rotation_center).angle_to(drag_to - drag_rotation_center), prev_rotation); + + ci->_edit_set_rotation(new_rotation); + if (!Math::is_inf(temp_pivot.x) || !Math::is_inf(temp_pivot.y)) { + Transform2D xform = ci->get_global_transform_with_canvas() * ci->get_transform().affine_inverse(); + Vector2 radius = xform.xform(ci->_edit_get_position()) - temp_pivot; + radius = radius.rotated(new_rotation - prev_rotation); + ci->_edit_set_position(xform.affine_inverse().xform(temp_pivot + radius)); + } viewport->queue_redraw(); } return true; @@ -3161,7 +3197,7 @@ void CanvasItemEditor::_draw_ruler_tool() { } else { if (grid_snap_active) { Ref<Texture2D> position_icon = get_editor_theme_icon(SNAME("EditorPosition")); - viewport->draw_texture(get_editor_theme_icon(SNAME("EditorPosition")), (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2); + viewport->draw_texture(position_icon, (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2); } } } @@ -3583,6 +3619,10 @@ void CanvasItemEditor::_draw_selection() { get_theme_color(SNAME("accent_color"), EditorStringName(Editor)) * Color(1, 1, 1, 0.6), Math::round(2 * EDSCALE)); } + + if (!Math::is_inf(temp_pivot.x) || !Math::is_inf(temp_pivot.y)) { + viewport->draw_texture(pivot_icon, (temp_pivot - view_offset) * zoom - (pivot_icon->get_size() / 2).floor(), get_theme_color(SNAME("accent_color"), SNAME("Editor"))); + } } void CanvasItemEditor::_draw_straight_line(Point2 p_from, Point2 p_to, Color p_color) { @@ -3931,8 +3971,6 @@ void CanvasItemEditor::_notification(int p_what) { } break; case NOTIFICATION_PROCESS: { - int nb_having_pivot = 0; - // Update the viewport if the canvas_item changes List<CanvasItem *> selection = _get_edited_canvas_items(true); for (CanvasItem *ci : selection) { @@ -3972,14 +4010,10 @@ void CanvasItemEditor::_notification(int p_what) { viewport->queue_redraw(); } } - - if (ci->_edit_use_pivot()) { - nb_having_pivot++; - } } - // Activate / Deactivate the pivot tool - pivot_button->set_disabled(nb_having_pivot == 0); + // Activate / Deactivate the pivot tool. + pivot_button->set_disabled(selection.is_empty()); // Update the viewport if bones changes for (KeyValue<BoneKey, BoneList> &E : bone_list) { @@ -4048,6 +4082,11 @@ void CanvasItemEditor::_selection_changed() { _reset_drag(); } selected_from_canvas = false; + + if (temp_pivot != Vector2(INFINITY, INFINITY)) { + temp_pivot = Vector2(INFINITY, INFINITY); + viewport->queue_redraw(); + } } void CanvasItemEditor::edit(CanvasItem *p_canvas_item) { @@ -4202,6 +4241,18 @@ void CanvasItemEditor::_button_tool_select(int p_index) { tool = (Tool)p_index; + if (p_index == TOOL_EDIT_PIVOT && Input::get_singleton()->is_key_pressed(Key::SHIFT)) { + // Special action that places temporary rotation pivot in the middle of the selection. + List<CanvasItem *> selection = _get_edited_canvas_items(); + if (!selection.is_empty()) { + Vector2 center; + for (const CanvasItem *ci : selection) { + center += ci->_edit_get_position(); + } + temp_pivot = center / selection.size(); + } + } + viewport->queue_redraw(); _update_cursor(); } @@ -5279,7 +5330,7 @@ CanvasItemEditor::CanvasItemEditor() { main_menu_hbox->add_child(pivot_button); pivot_button->set_toggle_mode(true); pivot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_EDIT_PIVOT)); - pivot_button->set_tooltip_text(TTR("Click to change object's rotation pivot.")); + pivot_button->set_tooltip_text(TTR("Click to change object's rotation pivot.") + "\n" + TTR("Shift: Set temporary rotation pivot.") + "\n" + TTR("Click this button while holding Shift to put the rotation pivot in the center of the selected nodes.")); pan_button = memnew(Button); pan_button->set_theme_type_variation("FlatButton"); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index c4b995b048..f52ad3dc4f 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -174,6 +174,7 @@ private: DRAG_SCALE_BOTH, DRAG_ROTATE, DRAG_PIVOT, + DRAG_TEMP_PIVOT, DRAG_V_GUIDE, DRAG_H_GUIDE, DRAG_DOUBLE_GUIDE, @@ -251,6 +252,7 @@ private: bool key_scale = false; bool pan_pressed = false; + Vector2 temp_pivot = Vector2(INFINITY, INFINITY); bool ruler_tool_active = false; Point2 ruler_tool_origin; diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 70213b280c..9fb4d86fa2 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -678,6 +678,8 @@ Ref<Texture2D> EditorAudioStreamPreviewPlugin::generate(const Ref<Resource> &p_f } } + p_metadata["length"] = stream->get_length(); + //post_process_preview(img); Ref<Image> image = Image::create_from_data(w, h, false, Image::FORMAT_RGB8, img); diff --git a/editor/plugins/editor_resource_tooltip_plugins.cpp b/editor/plugins/editor_resource_tooltip_plugins.cpp index fab8ee9f59..dfeb59214c 100644 --- a/editor/plugins/editor_resource_tooltip_plugins.cpp +++ b/editor/plugins/editor_resource_tooltip_plugins.cpp @@ -103,6 +103,7 @@ bool EditorTextureTooltipPlugin::handles(const String &p_resource_type) const { Control *EditorTextureTooltipPlugin::make_tooltip_for_path(const String &p_resource_path, const Dictionary &p_metadata, Control *p_base) const { HBoxContainer *hb = memnew(HBoxContainer); VBoxContainer *vb = Object::cast_to<VBoxContainer>(p_base); + DEV_ASSERT(vb); vb->set_alignment(BoxContainer::ALIGNMENT_CENTER); Vector2 dimensions = p_metadata.get("dimensions", Vector2()); @@ -117,3 +118,29 @@ Control *EditorTextureTooltipPlugin::make_tooltip_for_path(const String &p_resou hb->add_child(vb); return hb; } + +// EditorAudioStreamTooltipPlugin + +bool EditorAudioStreamTooltipPlugin::handles(const String &p_resource_type) const { + return ClassDB::is_parent_class(p_resource_type, "AudioStream"); +} + +Control *EditorAudioStreamTooltipPlugin::make_tooltip_for_path(const String &p_resource_path, const Dictionary &p_metadata, Control *p_base) const { + VBoxContainer *vb = Object::cast_to<VBoxContainer>(p_base); + DEV_ASSERT(vb); + + double length = p_metadata.get("length", 0.0); + if (length >= 60.0) { + vb->add_child(memnew(Label(vformat(TTR("Length: %0dm %0ds"), int(length / 60.0), int(fmod(length, 60)))))); + } else if (length >= 1.0) { + vb->add_child(memnew(Label(vformat(TTR("Length: %0.1fs"), length)))); + } else { + vb->add_child(memnew(Label(vformat(TTR("Length: %0.3fs"), length)))); + } + + TextureRect *tr = memnew(TextureRect); + vb->add_child(tr); + request_thumbnail(p_resource_path, tr); + + return vb; +} diff --git a/editor/plugins/editor_resource_tooltip_plugins.h b/editor/plugins/editor_resource_tooltip_plugins.h index e3a27de0bb..43be8fd8e8 100644 --- a/editor/plugins/editor_resource_tooltip_plugins.h +++ b/editor/plugins/editor_resource_tooltip_plugins.h @@ -33,9 +33,8 @@ #include "core/object/gdvirtual.gen.inc" #include "core/object/ref_counted.h" -#include <scene/gui/control.h> +#include "scene/gui/control.h" -class Control; class Texture2D; class TextureRect; class VBoxContainer; @@ -67,4 +66,12 @@ public: virtual Control *make_tooltip_for_path(const String &p_resource_path, const Dictionary &p_metadata, Control *p_base) const override; }; +class EditorAudioStreamTooltipPlugin : public EditorResourceTooltipPlugin { + GDCLASS(EditorAudioStreamTooltipPlugin, EditorResourceTooltipPlugin); + +public: + virtual bool handles(const String &p_resource_type) const override; + virtual Control *make_tooltip_for_path(const String &p_resource_path, const Dictionary &p_metadata, Control *p_base) const override; +}; + #endif // EDITOR_RESOURCE_TOOLTIP_PLUGINS_H diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index cc9e887448..c48af90622 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -273,6 +273,7 @@ void ScriptEditorBase::_bind_methods() { 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("request_save_history")); + ADD_SIGNAL(MethodInfo("request_save_previous_state", PropertyInfo(Variant::INT, "line"))); ADD_SIGNAL(MethodInfo("go_to_help", PropertyInfo(Variant::STRING, "what"))); ADD_SIGNAL(MethodInfo("search_in_files_requested", PropertyInfo(Variant::STRING, "text"))); ADD_SIGNAL(MethodInfo("replace_in_files_requested", PropertyInfo(Variant::STRING, "text"))); @@ -639,6 +640,32 @@ void ScriptEditor::_save_history() { _update_history_arrows(); } +void ScriptEditor::_save_previous_state(Dictionary p_state) { + if (lock_history) { + // Done as a result of a deferred call triggered by set_edit_state(). + lock_history = false; + return; + } + + if (history_pos >= 0 && history_pos < history.size() && history[history_pos].control == tab_container->get_current_tab_control()) { + Node *n = tab_container->get_current_tab_control(); + + if (Object::cast_to<ScriptTextEditor>(n)) { + history.write[history_pos].state = p_state; + } + } + + history.resize(history_pos + 1); + ScriptHistory sh; + sh.control = tab_container->get_current_tab_control(); + sh.state = Variant(); + + history.push_back(sh); + history_pos++; + + _update_history_arrows(); +} + void ScriptEditor::_go_to_tab(int p_idx) { ScriptEditorBase *current = _get_current_editor(); if (current) { @@ -668,8 +695,10 @@ void ScriptEditor::_go_to_tab(int p_idx) { sh.control = c; sh.state = Variant(); - history.push_back(sh); - history_pos++; + if (!lock_history && (history.is_empty() || history[history.size() - 1].control != sh.control)) { + history.push_back(sh); + history_pos++; + } tab_container->set_current_tab(p_idx); @@ -2185,8 +2214,11 @@ void ScriptEditor::_update_script_names() { sd.index = i; sedata.set(i, sd); } + + lock_history = true; _go_to_tab(new_prev_tab); _go_to_tab(new_cur_tab); + lock_history = false; _sort_list_on_update = false; } @@ -2474,6 +2506,10 @@ bool ScriptEditor::edit(const Ref<Resource> &p_resource, int p_line, int p_col, if (script_editor_cache->has_section(p_resource->get_path())) { se->set_edit_state(script_editor_cache->get_value(p_resource->get_path(), "state")); + ScriptTextEditor *ste = Object::cast_to<ScriptTextEditor>(se); + if (ste) { + ste->store_previous_state(); + } } _sort_list_on_update = true; @@ -2485,6 +2521,7 @@ bool ScriptEditor::edit(const Ref<Resource> &p_resource, int p_line, int p_col, se->connect("request_open_script_at_line", callable_mp(this, &ScriptEditor::_goto_script_line)); se->connect("go_to_help", callable_mp(this, &ScriptEditor::_help_class_goto)); se->connect("request_save_history", callable_mp(this, &ScriptEditor::_save_history)); + se->connect("request_save_previous_state", callable_mp(this, &ScriptEditor::_save_previous_state)); se->connect("search_in_files_requested", callable_mp(this, &ScriptEditor::_on_find_in_files_requested)); se->connect("replace_in_files_requested", callable_mp(this, &ScriptEditor::_on_replace_in_files_requested)); se->connect("go_to_method", callable_mp(this, &ScriptEditor::script_goto_method)); @@ -3421,6 +3458,7 @@ void ScriptEditor::_help_class_open(const String &p_class) { _go_to_tab(tab_container->get_tab_count() - 1); eh->go_to_class(p_class); eh->connect("go_to_help", callable_mp(this, &ScriptEditor::_help_class_goto)); + eh->connect("request_save_history", callable_mp(this, &ScriptEditor::_save_history)); _add_recent_script(p_class); _sort_list_on_update = true; _update_script_names(); @@ -3549,6 +3587,7 @@ void ScriptEditor::_update_history_pos(int p_new_pos) { ScriptEditorBase *seb = Object::cast_to<ScriptEditorBase>(n); if (seb) { + lock_history = true; seb->set_edit_state(history[history_pos].state); seb->ensure_focus(); @@ -3558,9 +3597,10 @@ void ScriptEditor::_update_history_pos(int p_new_pos) { } } - if (Object::cast_to<EditorHelp>(n)) { - Object::cast_to<EditorHelp>(n)->set_scroll(history[history_pos].state); - Object::cast_to<EditorHelp>(n)->set_focused(); + EditorHelp *eh = Object::cast_to<EditorHelp>(n); + if (eh) { + eh->set_scroll(history[history_pos].state); + eh->set_focused(); } n->set_meta("__editor_pass", ++edit_pass); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index f87cb0958c..de3ab3fd5a 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -472,12 +472,14 @@ class ScriptEditor : public PanelContainer { void _history_back(); bool waiting_update_names; + bool lock_history = false; void _help_class_open(const String &p_class); void _help_class_goto(const String &p_desc); bool _help_tab_goto(const String &p_name, const String &p_desc); void _update_history_arrows(); void _save_history(); + void _save_previous_state(Dictionary p_state); void _go_to_tab(int p_idx); void _update_history_pos(int p_new_pos); void _update_script_colors(); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 0a6eacf11d..a642f35d6f 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -412,6 +412,14 @@ Variant ScriptTextEditor::get_navigation_state() { return code_editor->get_navigation_state(); } +Variant ScriptTextEditor::get_previous_state() { + return code_editor->get_previous_state(); +} + +void ScriptTextEditor::store_previous_state() { + return code_editor->store_previous_state(); +} + void ScriptTextEditor::_convert_case(CodeTextEditor::CaseStyle p_case) { code_editor->convert_case(p_case); } @@ -904,6 +912,18 @@ 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_breakpointed(p_row)); } +void ScriptTextEditor::_on_caret_moved() { + int current_line = code_editor->get_text_editor()->get_caret_line(); + if (ABS(current_line - previous_line) >= 10) { + Dictionary nav_state = get_navigation_state(); + nav_state["row"] = previous_line; + nav_state["scroll_position"] = -1; + emit_signal(SNAME("request_save_previous_state"), nav_state); + store_previous_state(); + } + previous_line = current_line; +} + void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_column) { Node *base = get_tree()->get_edited_scene_root(); if (base) { @@ -1344,12 +1364,12 @@ void ScriptTextEditor::_edit_option(int p_op) { code_editor->get_text_editor()->duplicate_lines(); } break; case EDIT_TOGGLE_FOLD_LINE: { - int previous_line = -1; + int prev_line = -1; for (int caret_idx : tx->get_caret_index_edit_order()) { int line_idx = tx->get_caret_line(caret_idx); - if (line_idx != previous_line) { + if (line_idx != prev_line) { tx->toggle_foldable_line(line_idx); - previous_line = line_idx; + prev_line = line_idx; } } tx->queue_redraw(); @@ -2352,6 +2372,7 @@ ScriptTextEditor::ScriptTextEditor() { code_editor->get_text_editor()->set_draw_breakpoints_gutter(true); code_editor->get_text_editor()->set_draw_executing_lines_gutter(true); code_editor->get_text_editor()->connect("breakpoint_toggled", callable_mp(this, &ScriptTextEditor::_breakpoint_toggled)); + code_editor->get_text_editor()->connect("caret_changed", callable_mp(this, &ScriptTextEditor::_on_caret_moved)); connection_gutter = 1; code_editor->get_text_editor()->add_gutter(connection_gutter); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index 2ea73d4c73..de89fe458c 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -99,6 +99,7 @@ class ScriptTextEditor : public ScriptEditorBase { Color marked_line_color = Color(1, 1, 1); Color folded_code_region_color = Color(1, 1, 1); + int previous_line = 0; PopupPanel *color_panel = nullptr; ColorPicker *color_picker = nullptr; @@ -164,6 +165,8 @@ protected: void _breakpoint_item_pressed(int p_idx); void _breakpoint_toggled(int p_row); + void _on_caret_moved(); + void _validate_script(); // No longer virtual. void _update_warnings(); void _update_errors(); @@ -260,6 +263,9 @@ public: virtual void validate() override; + Variant get_previous_state(); + void store_previous_state(); + ScriptTextEditor(); ~ScriptTextEditor(); }; diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 70cef0e345..4fe91d1cc5 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -802,18 +802,20 @@ void ProjectManager::_apply_project_tags() { } } - ConfigFile cfg; const String project_godot = project_list->get_selected_projects()[0].path.path_join("project.godot"); - Error err = cfg.load(project_godot); - if (err != OK) { - tag_edit_error->set_text(vformat(TTR("Couldn't load project at '%s' (error %d). It may be missing or corrupted."), project_godot, err)); + ProjectSettings *cfg = memnew(ProjectSettings(project_godot)); + if (!cfg->is_project_loaded()) { + memdelete(cfg); + tag_edit_error->set_text(vformat(TTR("Couldn't load project at '%s'. It may be missing or corrupted."), project_godot)); tag_edit_error->show(); callable_mp((Window *)tag_manage_dialog, &Window::show).call_deferred(); // Make sure the dialog does not disappear. return; } else { tags.sort(); - cfg.set_value("application", "config/tags", tags); - err = cfg.save(project_godot); + cfg->set("application/config/tags", tags); + Error err = cfg->save_custom(project_godot); + memdelete(cfg); + if (err != OK) { tag_edit_error->set_text(vformat(TTR("Couldn't save project at '%s' (error %d)."), project_godot, err)); tag_edit_error->show(); |