summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/config/project_settings.cpp12
-rw-r--r--core/config/project_settings.h1
-rw-r--r--doc/classes/ScriptEditorBase.xml6
-rw-r--r--editor/code_editor.cpp19
-rw-r--r--editor/code_editor.h4
-rw-r--r--editor/editor_help.cpp2
-rw-r--r--editor/filesystem_dock.cpp1
-rw-r--r--editor/plugin_config_dialog.cpp1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp81
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h2
-rw-r--r--editor/plugins/editor_preview_plugins.cpp2
-rw-r--r--editor/plugins/editor_resource_tooltip_plugins.cpp27
-rw-r--r--editor/plugins/editor_resource_tooltip_plugins.h11
-rw-r--r--editor/plugins/script_editor_plugin.cpp50
-rw-r--r--editor/plugins/script_editor_plugin.h2
-rw-r--r--editor/plugins/script_text_editor.cpp27
-rw-r--r--editor/plugins/script_text_editor.h6
-rw-r--r--editor/project_manager.cpp14
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();