summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/classes/EditorUndoRedoManager.xml7
-rw-r--r--editor/editor_inspector.cpp4
-rw-r--r--editor/editor_node.cpp20
-rw-r--r--editor/editor_node.h2
-rw-r--r--editor/editor_properties_array_dict.cpp4
-rw-r--r--editor/editor_undo_redo_manager.cpp16
-rw-r--r--editor/editor_undo_redo_manager.h2
-rw-r--r--editor/plugins/cast_2d_editor_plugin.cpp1
-rw-r--r--editor/plugins/script_editor_plugin.cpp9
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp4
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp6
-rw-r--r--modules/gridmap/editor/grid_map_editor_plugin.cpp21
12 files changed, 63 insertions, 33 deletions
diff --git a/doc/classes/EditorUndoRedoManager.xml b/doc/classes/EditorUndoRedoManager.xml
index 26580bbf06..5ac0d790a2 100644
--- a/doc/classes/EditorUndoRedoManager.xml
+++ b/doc/classes/EditorUndoRedoManager.xml
@@ -88,6 +88,13 @@
The way undo operation are ordered in actions is dictated by [param backward_undo_ops]. When [param backward_undo_ops] is [code]false[/code] undo option are ordered in the same order they were added. Which means the first operation to be added will be the first to be undone.
</description>
</method>
+ <method name="force_fixed_history">
+ <return type="void" />
+ <description>
+ Forces the next operation (e.g. [method add_do_method]) to use the action's history rather than guessing it from the object. This is sometimes needed when a history can't be correctly determined, like for a nested resource that doesn't have a path yet.
+ This method should only be used when absolutely necessary, otherwise it might cause invalid history state. For most of complex cases, the [code]custom_context[/code] parameter of [method create_action] is sufficient.
+ </description>
+ </method>
<method name="get_history_undo_redo" qualifiers="const">
<return type="UndoRedo" />
<param index="0" name="id" type="int" />
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 6c26231a4b..81d9510033 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -2598,6 +2598,10 @@ int EditorInspector::inspector_plugin_count = 0;
EditorProperty *EditorInspector::instantiate_property_editor(Object *p_object, const Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
for (int i = inspector_plugin_count - 1; i >= 0; i--) {
+ if (!inspector_plugins[i]->can_handle(p_object)) {
+ continue;
+ }
+
inspector_plugins[i]->parse_property(p_object, p_type, p_path, p_hint, p_hint_text, p_usage, p_wide);
if (inspector_plugins[i]->added_editors.size()) {
for (List<EditorInspectorPlugin::AddedEditor>::Element *E = inspector_plugins[i]->added_editors.front()->next(); E; E = E->next()) { //only keep first one
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 55487f7896..ae7066fea9 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -1737,7 +1737,7 @@ bool EditorNode::_validate_scene_recursive(const String &p_filename, Node *p_nod
return false;
}
-int EditorNode::_save_external_resources() {
+int EditorNode::_save_external_resources(bool p_also_save_external_data) {
// Save external resources and its subresources if any was modified.
int flg = 0;
@@ -1783,6 +1783,16 @@ int EditorNode::_save_external_resources() {
saved++;
}
+ if (p_also_save_external_data) {
+ for (int i = 0; i < editor_data.get_editor_plugin_count(); i++) {
+ EditorPlugin *plugin = editor_data.get_editor_plugin(i);
+ if (!plugin->get_unsaved_status().is_empty()) {
+ plugin->save_external_data();
+ saved++;
+ }
+ }
+ }
+
EditorUndoRedoManager::get_singleton()->set_history_as_saved(EditorUndoRedoManager::GLOBAL_HISTORY);
return saved;
@@ -1812,9 +1822,7 @@ static void _reset_animation_mixers(Node *p_node, List<Pair<AnimationMixer *, Re
}
void EditorNode::_save_scene(String p_file, int idx) {
- if (!saving_scene.is_empty() && saving_scene == p_file) {
- return;
- }
+ ERR_FAIL_COND_MSG(!saving_scene.is_empty() && saving_scene == p_file, "Scene saved while already being saved!");
Node *scene = editor_data.get_edited_scene_root(idx);
@@ -2728,10 +2736,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
ScriptEditor::get_singleton()->save_current_script();
}
- const int saved = _save_external_resources();
+ const int saved = _save_external_resources(true);
if (saved > 0) {
show_accept(
- vformat(TTR("The current scene has no root node, but %d modified external resource(s) were saved anyway."), saved),
+ vformat(TTR("The current scene has no root node, but %d modified external resource(s) and/or plugin data were saved anyway."), saved),
TTR("OK"));
} else if (p_option == FILE_SAVE_AS_SCENE) {
// Don't show this dialog when pressing Ctrl + S to avoid interfering with script saving.
diff --git a/editor/editor_node.h b/editor/editor_node.h
index b7b4dff74e..49674dd1c1 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -573,7 +573,7 @@ private:
void _update_undo_redo_allowed();
- int _save_external_resources();
+ int _save_external_resources(bool p_also_save_external_data = false);
void _set_current_scene(int p_idx);
void _set_current_scene_nocheck(int p_idx);
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index 127bca9bbf..633f6abad9 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -435,7 +435,7 @@ void EditorPropertyArray::update_property() {
editor->setup("Object");
new_prop = editor;
} else {
- new_prop = EditorInspector::instantiate_property_editor(nullptr, value_type, "", subtype_hint, subtype_hint_string, PROPERTY_USAGE_NONE);
+ new_prop = EditorInspector::instantiate_property_editor(this, value_type, "", subtype_hint, subtype_hint_string, PROPERTY_USAGE_NONE);
}
new_prop->set_selectable(false);
new_prop->set_use_folding(is_using_folding());
@@ -1064,7 +1064,7 @@ void EditorPropertyDictionary::update_property() {
editor->setup("Object");
new_prop = editor;
} else {
- new_prop = EditorInspector::instantiate_property_editor(nullptr, value_type, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE);
+ new_prop = EditorInspector::instantiate_property_editor(this, value_type, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE);
}
new_prop->set_selectable(false);
new_prop->set_use_folding(is_using_folding());
diff --git a/editor/editor_undo_redo_manager.cpp b/editor/editor_undo_redo_manager.cpp
index 94f76dbc41..55bc198dfb 100644
--- a/editor/editor_undo_redo_manager.cpp
+++ b/editor/editor_undo_redo_manager.cpp
@@ -104,8 +104,13 @@ int EditorUndoRedoManager::get_history_id_for_object(Object *p_object) const {
}
EditorUndoRedoManager::History &EditorUndoRedoManager::get_history_for_object(Object *p_object) {
- int history_id = get_history_id_for_object(p_object);
- ERR_FAIL_COND_V_MSG(pending_action.history_id != INVALID_HISTORY && history_id != pending_action.history_id, get_or_create_history(pending_action.history_id), vformat("UndoRedo history mismatch: expected %d, got %d.", pending_action.history_id, history_id));
+ int history_id;
+ if (!forced_history) {
+ history_id = get_history_id_for_object(p_object);
+ ERR_FAIL_COND_V_MSG(pending_action.history_id != INVALID_HISTORY && history_id != pending_action.history_id, get_or_create_history(pending_action.history_id), vformat("UndoRedo history mismatch: expected %d, got %d.", pending_action.history_id, history_id));
+ } else {
+ history_id = pending_action.history_id;
+ }
History &history = get_or_create_history(history_id);
if (pending_action.history_id == INVALID_HISTORY) {
@@ -116,6 +121,11 @@ EditorUndoRedoManager::History &EditorUndoRedoManager::get_history_for_object(Ob
return history;
}
+void EditorUndoRedoManager::force_fixed_history() {
+ ERR_FAIL_COND_MSG(pending_action.history_id == INVALID_HISTORY, "The current action has no valid history assigned.");
+ forced_history = true;
+}
+
void EditorUndoRedoManager::create_action_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode, bool p_backward_undo_ops) {
if (pending_action.history_id != INVALID_HISTORY) {
// Nested action.
@@ -236,6 +246,7 @@ void EditorUndoRedoManager::commit_action(bool p_execute) {
return; // Empty action, do nothing.
}
+ forced_history = false;
is_committing = true;
History &history = get_or_create_history(pending_action.history_id);
@@ -469,6 +480,7 @@ void EditorUndoRedoManager::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_action", "name", "merge_mode", "custom_context", "backward_undo_ops"), &EditorUndoRedoManager::create_action, DEFVAL(UndoRedo::MERGE_DISABLE), DEFVAL((Object *)nullptr), DEFVAL(false));
ClassDB::bind_method(D_METHOD("commit_action", "execute"), &EditorUndoRedoManager::commit_action, DEFVAL(true));
ClassDB::bind_method(D_METHOD("is_committing_action"), &EditorUndoRedoManager::is_committing_action);
+ ClassDB::bind_method(D_METHOD("force_fixed_history"), &EditorUndoRedoManager::force_fixed_history);
{
MethodInfo mi;
diff --git a/editor/editor_undo_redo_manager.h b/editor/editor_undo_redo_manager.h
index e8c782871c..219d5e0702 100644
--- a/editor/editor_undo_redo_manager.h
+++ b/editor/editor_undo_redo_manager.h
@@ -67,6 +67,7 @@ private:
HashMap<int, History> history_map;
Action pending_action;
+ bool forced_history = false;
bool is_committing = false;
History *_get_newest_undo();
@@ -79,6 +80,7 @@ public:
UndoRedo *get_history_undo_redo(int p_idx) const;
int get_history_id_for_object(Object *p_object) const;
History &get_history_for_object(Object *p_object);
+ void force_fixed_history();
void create_action_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode = UndoRedo::MERGE_DISABLE, bool p_backward_undo_ops = false);
void create_action(const String &p_name = "", UndoRedo::MergeMode p_mode = UndoRedo::MERGE_DISABLE, Object *p_custom_context = nullptr, bool p_backward_undo_ops = false);
diff --git a/editor/plugins/cast_2d_editor_plugin.cpp b/editor/plugins/cast_2d_editor_plugin.cpp
index c9d7ff8e08..3da7d4a7dc 100644
--- a/editor/plugins/cast_2d_editor_plugin.cpp
+++ b/editor/plugins/cast_2d_editor_plugin.cpp
@@ -102,7 +102,6 @@ bool Cast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
node->set("target_position", point);
canvas_item_editor->update_viewport();
- node->notify_property_list_changed();
return true;
}
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 3d043909b2..9d5dbb4a4f 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1012,8 +1012,6 @@ void ScriptEditor::_resave_scripts(const String &p_str) {
se->trim_final_newlines();
}
- se->insert_final_newline();
-
if (convert_indent_on_save) {
se->convert_indent();
}
@@ -1410,8 +1408,6 @@ void ScriptEditor::_menu_option(int p_option) {
current->trim_final_newlines();
}
- current->insert_final_newline();
-
if (convert_indent_on_save) {
current->convert_indent();
}
@@ -2614,8 +2610,6 @@ void ScriptEditor::save_current_script() {
current->trim_final_newlines();
}
- current->insert_final_newline();
-
if (convert_indent_on_save) {
current->convert_indent();
}
@@ -2662,8 +2656,6 @@ void ScriptEditor::save_all_scripts() {
se->trim_final_newlines();
}
- se->insert_final_newline();
-
if (!se->is_unsaved()) {
continue;
}
@@ -2713,6 +2705,7 @@ void ScriptEditor::apply_scripts() const {
if (!se) {
continue;
}
+ se->insert_final_newline();
se->apply_code();
}
}
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index b33250bcb5..27056a6cc4 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -1056,10 +1056,12 @@ void SpriteFramesEditor::_rename_node_animation(EditorUndoRedoManager *undo_redo
for (Node *E : nodes) {
String current_name = E->call("get_animation");
if (current_name == p_filter) {
+ undo_redo->force_fixed_history(); // Fixes corner-case when editing SpriteFrames stored as separate file.
undo_redo->add_undo_method(E, "set_animation", p_new_animation);
}
String autoplay_name = E->call("get_autoplay");
if (autoplay_name == p_filter) {
+ undo_redo->force_fixed_history();
undo_redo->add_undo_method(E, "set_autoplay", p_new_autoplay);
}
}
@@ -1067,10 +1069,12 @@ void SpriteFramesEditor::_rename_node_animation(EditorUndoRedoManager *undo_redo
for (Node *E : nodes) {
String current_name = E->call("get_animation");
if (current_name == p_filter) {
+ undo_redo->force_fixed_history();
undo_redo->add_do_method(E, "set_animation", p_new_animation);
}
String autoplay_name = E->call("get_autoplay");
if (autoplay_name == p_filter) {
+ undo_redo->force_fixed_history();
undo_redo->add_do_method(E, "set_autoplay", p_new_autoplay);
}
}
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 3f6927c02a..607c446e1b 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -3649,12 +3649,15 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, cons
if (output_port_type == VisualShaderNode::PORT_TYPE_SAMPLER) {
if (is_texture2d) {
+ undo_redo->force_fixed_history(); // vsnode is freshly created and has no path, so history can't be correctly determined.
undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeTexture::SOURCE_PORT);
}
if (is_texture3d || is_texture2d_array) {
+ undo_redo->force_fixed_history();
undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeSample3D::SOURCE_PORT);
}
if (is_cubemap) {
+ undo_redo->force_fixed_history();
undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeCubemap::SOURCE_PORT);
}
}
@@ -3754,16 +3757,19 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, cons
//post-initialization
if (is_texture2d || is_texture3d || is_curve || is_curve_xyz) {
+ undo_redo->force_fixed_history();
undo_redo->add_do_method(vsnode.ptr(), "set_texture", ResourceLoader::load(p_resource_path));
return;
}
if (is_cubemap) {
+ undo_redo->force_fixed_history();
undo_redo->add_do_method(vsnode.ptr(), "set_cube_map", ResourceLoader::load(p_resource_path));
return;
}
if (is_texture2d_array) {
+ undo_redo->force_fixed_history();
undo_redo->add_do_method(vsnode.ptr(), "set_texture_array", ResourceLoader::load(p_resource_path));
}
}
diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp
index b93b7c1a8c..f402e2a583 100644
--- a/modules/gridmap/editor/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp
@@ -59,10 +59,18 @@ void GridMapEditor::_menu_option(int p_option) {
switch (p_option) {
case MENU_OPTION_PREV_LEVEL: {
floor->set_value(floor->get_value() - 1);
+ if (selection.active && input_action == INPUT_SELECT) {
+ selection.current[edit_axis]--;
+ _validate_selection();
+ }
} break;
case MENU_OPTION_NEXT_LEVEL: {
floor->set_value(floor->get_value() + 1);
+ if (selection.active && input_action == INPUT_SELECT) {
+ selection.current[edit_axis]++;
+ _validate_selection();
+ }
} break;
case MENU_OPTION_X_AXIS:
@@ -754,19 +762,6 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D
}
}
}
-
- if (k->is_shift_pressed() && selection.active && input_action != INPUT_PASTE) {
- if (k->get_keycode() == (Key)options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL))) {
- selection.click[edit_axis]--;
- _validate_selection();
- return EditorPlugin::AFTER_GUI_INPUT_STOP;
- }
- if (k->get_keycode() == (Key)options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_NEXT_LEVEL))) {
- selection.click[edit_axis]++;
- _validate_selection();
- return EditorPlugin::AFTER_GUI_INPUT_STOP;
- }
- }
}
}