diff options
Diffstat (limited to 'editor')
71 files changed, 856 insertions, 324 deletions
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index de7f5c8b88..ed2044c117 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -684,6 +684,7 @@ void ConnectionsDock::_connect(ConnectDialog::ConnectionData p_cd) { } Callable callable = p_cd.get_callable(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(vformat(TTR("Connect '%s' to '%s'"), String(p_cd.signal), String(p_cd.method))); undo_redo->add_do_method(source, "connect", p_cd.signal, callable, p_cd.flags); undo_redo->add_undo_method(source, "disconnect", p_cd.signal, callable); @@ -704,6 +705,7 @@ void ConnectionsDock::_disconnect(TreeItem &p_item) { ERR_FAIL_COND(cd.source != selected_node); // Shouldn't happen but... Bugcheck. + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(vformat(TTR("Disconnect '%s' from '%s'"), cd.signal, cd.method)); Callable callable = cd.get_callable(); @@ -730,6 +732,7 @@ void ConnectionsDock::_disconnect_all() { TreeItem *child = item->get_first_child(); String signal_name = item->get_metadata(0).operator Dictionary()["name"]; + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(vformat(TTR("Disconnect all from signal: '%s'"), signal_name)); while (child) { @@ -991,10 +994,6 @@ void ConnectionsDock::_bind_methods() { ClassDB::bind_method("update_tree", &ConnectionsDock::update_tree); } -void ConnectionsDock::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) { - undo_redo = p_undo_redo; -} - void ConnectionsDock::set_node(Node *p_node) { selected_node = p_node; update_tree(); diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h index 126a0ca828..fcfc501386 100644 --- a/editor/connections_dialog.h +++ b/editor/connections_dialog.h @@ -47,7 +47,6 @@ #include "scene/gui/tree.h" class ConnectDialogBinds; -class EditorUndoRedoManager; class ConnectDialog : public ConfirmationDialog { GDCLASS(ConnectDialog, ConfirmationDialog); @@ -197,7 +196,6 @@ class ConnectionsDock : public VBoxContainer { Button *connect_button = nullptr; PopupMenu *signal_menu = nullptr; PopupMenu *slot_menu = nullptr; - Ref<EditorUndoRedoManager> undo_redo; LineEdit *search_box = nullptr; HashMap<StringName, HashMap<StringName, String>> descr_cache; @@ -231,7 +229,6 @@ protected: static void _bind_methods(); public: - void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo); void set_node(Node *p_node); void update_tree(); diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index edcbcaf963..68aff328ed 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -229,6 +229,12 @@ void EditorDebuggerNode::stop() { if (server.is_valid()) { server->stop(); EditorNode::get_log()->add_message("--- Debugging process stopped ---", EditorLog::MSG_TYPE_EDITOR); + + if (EditorNode::get_singleton()->is_movie_maker_enabled()) { + // Request attention in case the user was doing something else when movie recording is finished. + DisplayServer::get_singleton()->window_request_attention(); + } + server.unref(); } // Also close all debugging sessions. diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 46df618d57..24116a8053 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -338,7 +338,7 @@ float EditorAudioBus::_normalized_volume_to_scaled_db(float normalized) { * values to relative decibal values. * One formula is an exponential graph which intends to counteract * the logarithmic nature of human hearing. This is an approximation - * of the behaviour of a 'logarithmic potentiometer' found on most + * of the behavior of a 'logarithmic potentiometer' found on most * musical instruments and also emulated in popular software. * The other two equations are hand-tuned linear tapers that intend to * try to ease the exponential equation in areas where it makes sense.*/ diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index 90310bb43c..598bcdc639 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -194,7 +194,7 @@ void EditorAutoloadSettings::_autoload_edited() { TreeItem *ti = tree->get_edited(); int column = tree->get_edited_column(); - Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); if (column == 0) { String name = ti->get_text(0); @@ -289,7 +289,7 @@ void EditorAutoloadSettings::_autoload_button_pressed(Object *p_item, int p_colu String name = "autoload/" + ti->get_text(0); - Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); switch (p_button) { case BUTTON_OPEN: { @@ -714,7 +714,7 @@ void EditorAutoloadSettings::drop_data_fw(const Point2 &p_point, const Variant & orders.sort(); - Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Rearrange Autoloads")); @@ -757,7 +757,7 @@ bool EditorAutoloadSettings::autoload_add(const String &p_name, const String &p_ name = "autoload/" + name; - Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Add Autoload")); // Singleton autoloads are represented with a leading "*" in their path. @@ -783,7 +783,7 @@ bool EditorAutoloadSettings::autoload_add(const String &p_name, const String &p_ void EditorAutoloadSettings::autoload_remove(const String &p_name) { String name = "autoload/" + p_name; - Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); int order = ProjectSettings::get_singleton()->get_order(name); diff --git a/editor/editor_build_profile.cpp b/editor/editor_build_profile.cpp index 7fd27692b0..96c69c0bd1 100644 --- a/editor/editor_build_profile.cpp +++ b/editor/editor_build_profile.cpp @@ -875,7 +875,7 @@ EditorBuildProfileManager::EditorBuildProfileManager() { import_profile = memnew(EditorFileDialog); add_child(import_profile); import_profile->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); - import_profile->add_filter("*.build", TTR("Egine Build Profile")); + import_profile->add_filter("*.build", TTR("Engine Build Profile")); import_profile->connect("files_selected", callable_mp(this, &EditorBuildProfileManager::_import_profile)); import_profile->set_title(TTR("Load Profile")); import_profile->set_access(EditorFileDialog::ACCESS_FILESYSTEM); @@ -883,7 +883,7 @@ EditorBuildProfileManager::EditorBuildProfileManager() { export_profile = memnew(EditorFileDialog); add_child(export_profile); export_profile->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); - export_profile->add_filter("*.build", TTR("Egine Build Profile")); + export_profile->add_filter("*.build", TTR("Engine Build Profile")); export_profile->connect("file_selected", callable_mp(this, &EditorBuildProfileManager::_export_profile)); export_profile->set_title(TTR("Export Profile")); export_profile->set_access(EditorFileDialog::ACCESS_FILESYSTEM); diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 6d8f0df452..a3dd19bb67 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -457,12 +457,10 @@ Callable EditorData::get_move_array_element_function(const StringName &p_class) } void EditorData::remove_editor_plugin(EditorPlugin *p_plugin) { - p_plugin->undo_redo = Ref<EditorUndoRedoManager>(); editor_plugins.erase(p_plugin); } void EditorData::add_editor_plugin(EditorPlugin *p_plugin) { - p_plugin->undo_redo = undo_redo_manager; editor_plugins.push_back(p_plugin); } diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index 90f3f8d2f5..51ebc31df3 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -57,6 +57,24 @@ Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hin return font; } +Ref<SystemFont> load_system_font(const PackedStringArray &p_names, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { + Ref<SystemFont> font; + font.instantiate(); + + font->set_font_names(p_names); + font->set_multichannel_signed_distance_field(p_msdf); + font->set_antialiasing(p_aa); + font->set_hinting(p_hinting); + font->set_force_autohinter(p_autohint); + font->set_subpixel_positioning(p_font_subpixel_positioning); + + if (r_fallbacks != nullptr) { + r_fallbacks->push_back(font); + } + + return font; +} + Ref<FontFile> load_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { Ref<FontFile> font; font.instantiate(); @@ -166,6 +184,20 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontFile> thai_font_bold = load_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontVariation> fallback_font_bold = make_bold_font(fallback_font, embolden_strength, &fallbacks_bold); Ref<FontVariation> japanese_font_bold = make_bold_font(japanese_font, embolden_strength, &fallbacks_bold); + + if (OS::get_singleton()->has_feature("system_fonts")) { + PackedStringArray emoji_font_names; + emoji_font_names.push_back("Apple Color Emoji"); + emoji_font_names.push_back("Segoe UI Emoji"); + emoji_font_names.push_back("Noto Color Emoji"); + emoji_font_names.push_back("Twitter Color Emoji"); + emoji_font_names.push_back("OpenMoji"); + emoji_font_names.push_back("EmojiOne Color"); + Ref<SystemFont> emoji_font = load_system_font(emoji_font_names, font_hinting, font_antialiasing, true, font_subpixel_positioning, false); + fallbacks.push_back(emoji_font); + fallbacks_bold.push_back(emoji_font); + } + default_font_bold->set_fallbacks(fallbacks_bold); default_font_bold_msdf->set_fallbacks(fallbacks_bold); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index ddb9bb30f1..89398409a2 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -375,7 +375,7 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview if (qualifier == "vararg") { hint = TTR("This method supports a variable number of arguments."); } else if (qualifier == "virtual") { - hint = TTR("This method is called by the engine.\nIt can be overriden to customise built-in behavior."); + hint = TTR("This method is called by the engine.\nIt can be overridden to customize built-in behavior."); } else if (qualifier == "const") { hint = TTR("This method has no side effects.\nIt does not modify the object in any way."); } else if (qualifier == "static") { diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 94dd4d0606..6e18bde303 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -39,6 +39,7 @@ #include "editor/editor_property_name_processor.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_undo_redo_manager.h" #include "editor/plugins/script_editor_plugin.h" #include "multi_node_edit.h" #include "scene/gui/center_container.h" @@ -1698,6 +1699,7 @@ void EditorInspectorArray::_move_element(int p_element_index, int p_to_pos) { } else { action_name = vformat("Move element %d to position %d in property array with prefix %s.", p_element_index, p_to_pos, array_element_prefix); } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(action_name); if (mode == MODE_USE_MOVE_ARRAY_ELEMENT_FUNCTION) { // Call the function. @@ -1841,6 +1843,7 @@ void EditorInspectorArray::_move_element(int p_element_index, int p_to_pos) { } void EditorInspectorArray::_clear_array() { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(vformat("Clear property array with prefix %s.", array_element_prefix)); if (mode == MODE_USE_MOVE_ARRAY_ELEMENT_FUNCTION) { for (int i = count - 1; i >= 0; i--) { @@ -1893,6 +1896,7 @@ void EditorInspectorArray::_resize_array(int p_size) { return; } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(vformat("Resize property array with prefix %s.", array_element_prefix)); if (p_size > count) { if (mode == MODE_USE_MOVE_ARRAY_ELEMENT_FUNCTION) { @@ -2242,10 +2246,6 @@ void EditorInspectorArray::_bind_methods() { ADD_SIGNAL(MethodInfo("page_change_request")); } -void EditorInspectorArray::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) { - undo_redo = p_undo_redo; -} - void EditorInspectorArray::setup_with_move_element_function(Object *p_object, String p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable, bool p_numbered, int p_page_length, const String &p_add_item_text) { count_property = ""; mode = MODE_USE_MOVE_ARRAY_ELEMENT_FUNCTION; @@ -2508,10 +2508,6 @@ Button *EditorInspector::create_inspector_action_button(const String &p_text) { return button; } -void EditorInspector::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) { - undo_redo = p_undo_redo; -} - String EditorInspector::get_selected_path() const { return property_selected; } @@ -3077,7 +3073,6 @@ void EditorInspector::update_tree() { int page = per_array_page.has(array_element_prefix) ? per_array_page[array_element_prefix] : 0; editor_inspector_array->setup_with_move_element_function(object, array_label, array_element_prefix, page, c, use_folding); editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request).bind(array_element_prefix)); - editor_inspector_array->set_undo_redo(undo_redo); } else if (p.type == Variant::INT) { // Setup the array to use the count property and built-in functions to create/move/delete elements. if (class_name_components.size() >= 2) { @@ -3087,8 +3082,6 @@ void EditorInspector::update_tree() { editor_inspector_array->setup_with_count_property(object, class_name_components[0], p.name, array_element_prefix, page, c, foldable, movable, numbered, page_size, add_button_text, swap_method); editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request).bind(array_element_prefix)); - - editor_inspector_array->set_undo_redo(undo_redo); } } @@ -3565,6 +3558,7 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo } } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); if (!undo_redo.is_valid() || bool(object->call("_dont_undo_redo"))) { object->set(p_name, p_value); if (p_refresh_all) { @@ -3685,6 +3679,7 @@ void EditorInspector::_multiple_properties_changed(Vector<String> p_paths, Array } names += p_paths[i]; } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Set Multiple:") + " " + names, UndoRedo::MERGE_ENDS); for (int i = 0; i < p_paths.size(); i++) { _edit_set(p_paths[i], p_values[i], false, ""); @@ -3719,6 +3714,7 @@ void EditorInspector::_property_deleted(const String &p_path) { if (p_path.begins_with("metadata/")) { String name = p_path.replace_first("metadata/", ""); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(vformat(TTR("Remove metadata %s"), name)); undo_redo->add_do_method(object, "remove_meta", name); undo_redo->add_undo_method(object, "set_meta", name, object->get_meta(name)); @@ -3784,6 +3780,7 @@ void EditorInspector::_property_pinned(const String &p_path, bool p_pinned) { Node *node = Object::cast_to<Node>(object); ERR_FAIL_COND(!node); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); if (undo_redo.is_valid()) { undo_redo->create_action(vformat(p_pinned ? TTR("Pinned %s") : TTR("Unpinned %s"), p_path)); undo_redo->add_do_method(node, "_set_property_pinned", p_path, p_pinned); @@ -3981,6 +3978,7 @@ void EditorInspector::_add_meta_confirm() { Variant defval; Callable::CallError ce; Variant::construct(Variant::Type(add_meta_type->get_selected_id()), defval, nullptr, 0, ce); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(vformat(TTR("Add metadata %s"), name)); undo_redo->add_do_method(object, "set_meta", name, defval); undo_redo->add_undo_method(object, "remove_meta", name); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index bada02e254..1b93b19845 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -31,7 +31,6 @@ #ifndef EDITOR_INSPECTOR_H #define EDITOR_INSPECTOR_H -#include "editor/editor_undo_redo_manager.h" #include "editor_property_name_processor.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" @@ -305,8 +304,6 @@ public: class EditorInspectorArray : public EditorInspectorSection { GDCLASS(EditorInspectorArray, EditorInspectorSection); - Ref<EditorUndoRedoManager> undo_redo; - enum Mode { MODE_NONE, MODE_USE_COUNT_PROPERTY, @@ -401,8 +398,6 @@ protected: static void _bind_methods(); public: - void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo); - void setup_with_move_element_function(Object *p_object, String p_label, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable = true, bool p_numbered = false, int p_page_length = 5, const String &p_add_item_text = ""); void setup_with_count_property(Object *p_object, String p_label, const StringName &p_count_property, const StringName &p_array_element_prefix, int p_page, const Color &p_bg_color, bool p_foldable, bool p_movable = true, bool p_numbered = false, int p_page_length = 5, const String &p_add_item_text = "", const String &p_swap_method = ""); VBoxContainer *get_vbox(int p_index); @@ -441,7 +436,6 @@ public: class EditorInspector : public ScrollContainer { GDCLASS(EditorInspector, ScrollContainer); - Ref<EditorUndoRedoManager> undo_redo; enum { MAX_PLUGINS = 1024 }; @@ -555,8 +549,6 @@ public: static EditorProperty *instantiate_property_editor(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false); - void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo); - String get_selected_path() const; void update_tree(); diff --git a/editor/editor_locale_dialog.cpp b/editor/editor_locale_dialog.cpp index 106cc61947..a913fb2fd9 100644 --- a/editor/editor_locale_dialog.cpp +++ b/editor/editor_locale_dialog.cpp @@ -141,6 +141,7 @@ void EditorLocaleDialog::_filter_lang_option_changed() { f_lang_all.sort(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Changed Locale Language Filter")); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/language_filter", f_lang_all); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/language_filter", prev); @@ -174,6 +175,7 @@ void EditorLocaleDialog::_filter_script_option_changed() { f_script_all.sort(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Changed Locale Script Filter")); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/script_filter", f_script_all); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/script_filter", prev); @@ -207,6 +209,7 @@ void EditorLocaleDialog::_filter_cnt_option_changed() { f_cnt_all.sort(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Changed Locale Country Filter")); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/country_filter", f_cnt_all); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/country_filter", prev); @@ -221,6 +224,7 @@ void EditorLocaleDialog::_filter_mode_changed(int p_mode) { prev = GLOBAL_GET("internationalization/locale/locale_filter_mode"); } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Changed Locale Filter Mode")); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter_mode", f_mode); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter_mode", prev); @@ -385,8 +389,6 @@ void EditorLocaleDialog::popup_locale_dialog() { } EditorLocaleDialog::EditorLocaleDialog() { - undo_redo = EditorNode::get_undo_redo(); - set_title(TTR("Select a Locale")); VBoxContainer *vb = memnew(VBoxContainer); diff --git a/editor/editor_locale_dialog.h b/editor/editor_locale_dialog.h index 8ac642a038..48f9edd4b0 100644 --- a/editor/editor_locale_dialog.h +++ b/editor/editor_locale_dialog.h @@ -40,7 +40,6 @@ class VBoxContainer; class LineEdit; class Tree; class OptionButton; -class EditorUndoRedoManager; class EditorLocaleDialog : public ConfirmationDialog { GDCLASS(EditorLocaleDialog, ConfirmationDialog); @@ -63,8 +62,6 @@ class EditorLocaleDialog : public ConfirmationDialog { Tree *script_list = nullptr; Tree *cnt_list = nullptr; - Ref<EditorUndoRedoManager> undo_redo; - bool locale_set = false; bool updating_lists = false; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 0f2543f708..84284a7f31 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -30,6 +30,7 @@ #include "editor_log.h" +#include "core/object/undo_redo.h" #include "core/os/keyboard.h" #include "core/version.h" #include "editor/editor_node.h" @@ -226,7 +227,7 @@ void EditorLog::add_message(const String &p_msg, MessageType p_type) { // Make text split by new lines their own message. // See #41321 for reasoning. At time of writing, multiple print()'s in running projects // get grouped together and sent to the editor log as one message. This can mess with the - // search functionality (see the comments on the PR above for more details). This behaviour + // search functionality (see the comments on the PR above for more details). This behavior // also matches that of other IDE's. Vector<String> lines = p_msg.split("\n", true); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index bbb7fb384a..716e0b454f 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -110,6 +110,7 @@ #include "editor/export/export_template_manager.h" #include "editor/export/project_export.h" #include "editor/filesystem_dock.h" +#include "editor/history_dock.h" #include "editor/import/audio_stream_import_settings.h" #include "editor/import/dynamic_font_import_settings.h" #include "editor/import/editor_import_collada.h" @@ -3560,6 +3561,14 @@ bool EditorNode::is_addon_plugin_enabled(const String &p_addon) const { return addon_name_to_plugin.has("res://addons/" + p_addon + "/plugin.cfg"); } +void EditorNode::set_movie_maker_enabled(bool p_enabled) { + write_movie_button->set_pressed(p_enabled); +} + +bool EditorNode::is_movie_maker_enabled() const { + return write_movie_button->is_pressed(); +} + void EditorNode::_remove_edited_scene(bool p_change_tab) { int new_index = editor_data.get_edited_scene(); int old_index = new_index; @@ -3689,6 +3698,7 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { EditorDebuggerNode::get_singleton()->update_live_edit_root(); ScriptEditor::get_singleton()->set_scene_root_script(editor_data.get_scene_root_script(editor_data.get_edited_scene())); editor_data.notify_edited_scene_changed(); + emit_signal(SNAME("scene_changed")); } bool EditorNode::is_changing_scene() const { @@ -4075,7 +4085,7 @@ void EditorNode::_quick_opened() { List<String> scene_extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions); - if (open_scene_dialog || scene_extensions.find(files[i].get_extension())) { + if (open_scene_dialog || scene_extensions.find(files[i].get_extension().to_lower())) { open_request(res_path); } else { load_resource(res_path); @@ -6032,6 +6042,7 @@ void EditorNode::_bind_methods() { ADD_SIGNAL(MethodInfo("resource_saved", PropertyInfo(Variant::OBJECT, "obj"))); ADD_SIGNAL(MethodInfo("scene_saved", PropertyInfo(Variant::STRING, "path"))); ADD_SIGNAL(MethodInfo("project_settings_changed")); + ADD_SIGNAL(MethodInfo("scene_changed")); } static Node *_resource_get_edited_scene() { @@ -7097,6 +7108,8 @@ EditorNode::EditorNode() { filesystem_dock->connect("display_mode_changed", callable_mp(this, &EditorNode::_save_docks)); get_project_settings()->connect_filesystem_dock_signals(filesystem_dock); + HistoryDock *hd = memnew(HistoryDock); + // Scene: Top left. dock_slot[DOCK_SLOT_LEFT_UR]->add_child(SceneTreeDock::get_singleton()); dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_UR]->get_tab_idx_from_control(SceneTreeDock::get_singleton()), TTR("Scene")); @@ -7117,6 +7130,10 @@ EditorNode::EditorNode() { dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(NodeDock::get_singleton()); dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(NodeDock::get_singleton()), TTR("Node")); + // History: Full height right, behind Node. + dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(hd); + dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(hd), TTR("History")); + // Hide unused dock slots and vsplits. dock_slot[DOCK_SLOT_LEFT_UL]->hide(); dock_slot[DOCK_SLOT_LEFT_BL]->hide(); diff --git a/editor/editor_node.h b/editor/editor_node.h index b5d844558e..9c8d564057 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -770,6 +770,9 @@ public: void set_addon_plugin_enabled(const String &p_addon, bool p_enabled, bool p_config_changed = false); bool is_addon_plugin_enabled(const String &p_addon) const; + void set_movie_maker_enabled(bool p_enabled); + bool is_movie_maker_enabled() const; + void edit_node(Node *p_node); void edit_resource(const Ref<Resource> &p_resource) { InspectorDock::get_singleton()->edit_resource(p_resource); }; diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index e852100555..8fca21ae7b 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -289,6 +289,14 @@ bool EditorInterface::is_plugin_enabled(const String &p_plugin) const { return EditorNode::get_singleton()->is_addon_plugin_enabled(p_plugin); } +void EditorInterface::set_movie_maker_enabled(bool p_enabled) { + EditorNode::get_singleton()->set_movie_maker_enabled(p_enabled); +} + +bool EditorInterface::is_movie_maker_enabled() const { + return EditorNode::get_singleton()->is_movie_maker_enabled(); +} + EditorInspector *EditorInterface::get_inspector() const { return InspectorDock::get_inspector_singleton(); } @@ -364,6 +372,9 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("set_plugin_enabled", "plugin", "enabled"), &EditorInterface::set_plugin_enabled); ClassDB::bind_method(D_METHOD("is_plugin_enabled", "plugin"), &EditorInterface::is_plugin_enabled); + ClassDB::bind_method(D_METHOD("set_movie_maker_enabled", "enabled"), &EditorInterface::set_movie_maker_enabled); + ClassDB::bind_method(D_METHOD("is_movie_maker_enabled"), &EditorInterface::is_movie_maker_enabled); + ClassDB::bind_method(D_METHOD("get_inspector"), &EditorInterface::get_inspector); ClassDB::bind_method(D_METHOD("save_scene"), &EditorInterface::save_scene); @@ -956,7 +967,7 @@ void EditorPlugin::_bind_methods() { } Ref<EditorUndoRedoManager> EditorPlugin::get_undo_redo() { - return undo_redo; + return EditorNode::get_undo_redo(); } EditorPluginCreateFunc EditorPlugins::creation_funcs[MAX_CREATE_FUNCS]; diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 1211bcf53c..753ccedf70 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -32,7 +32,6 @@ #define EDITOR_PLUGIN_H #include "core/io/config_file.h" -#include "core/object/undo_redo.h" #include "editor/debugger/editor_debugger_node.h" #include "editor/editor_inspector.h" #include "editor/editor_translation_parser.h" @@ -113,6 +112,9 @@ public: void set_plugin_enabled(const String &p_plugin, bool p_enabled); bool is_plugin_enabled(const String &p_plugin) const; + void set_movie_maker_enabled(bool p_enabled); + bool is_movie_maker_enabled() const; + EditorInspector *get_inspector() const; Error save_scene(); @@ -131,7 +133,6 @@ public: class EditorPlugin : public Node { GDCLASS(EditorPlugin, Node); friend class EditorData; - Ref<EditorUndoRedoManager> undo_redo; bool input_event_forwarding_always_enabled = false; bool force_draw_over_forwarding_enabled = false; diff --git a/editor/editor_plugin_settings.h b/editor/editor_plugin_settings.h index 9c619066f2..829135b544 100644 --- a/editor/editor_plugin_settings.h +++ b/editor/editor_plugin_settings.h @@ -31,7 +31,6 @@ #ifndef EDITOR_PLUGIN_SETTINGS_H #define EDITOR_PLUGIN_SETTINGS_H -#include "core/object/undo_redo.h" #include "editor/editor_data.h" #include "editor/plugin_config_dialog.h" diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 84caed9db5..d76dce0c1d 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -2688,7 +2688,7 @@ void EditorPropertyQuaternion::_custom_value_changed(double val) { v.y = Math::deg_to_rad(edit_euler.y); v.z = Math::deg_to_rad(edit_euler.z); - Quaternion temp_q = Quaternion(v); + Quaternion temp_q = Quaternion::from_euler(v); spin[0]->set_value(temp_q.x); spin[1]->set_value(temp_q.y); spin[2]->set_value(temp_q.z); @@ -2725,7 +2725,7 @@ void EditorPropertyQuaternion::update_property() { spin[2]->set_value(val.z); spin[3]->set_value(val.w); if (!is_grabbing_euler()) { - Vector3 v = val.normalized().get_euler_yxz(); + Vector3 v = val.normalized().get_euler(); edit_euler.x = Math::rad_to_deg(v.x); edit_euler.y = Math::rad_to_deg(v.y); edit_euler.z = Math::rad_to_deg(v.z); @@ -4097,7 +4097,6 @@ void EditorPropertyResource::update_property() { sub_inspector->set_keying(is_keying()); sub_inspector->set_read_only(is_read_only()); sub_inspector->set_use_folding(is_using_folding()); - sub_inspector->set_undo_redo(EditorNode::get_undo_redo()); sub_inspector_vbox = memnew(VBoxContainer); add_child(sub_inspector_vbox); diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index bec05a0cd6..659221ee0b 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -466,7 +466,7 @@ void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_d Variant array = object->get_array(); - // Handle the case where array is not initialised yet. + // Handle the case where array is not initialized yet. if (!array.is_array()) { Callable::CallError ce; Variant::construct(array_type, array, nullptr, 0, ce); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 409ef95fb0..11b8f224f5 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -159,7 +159,7 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const { if (!sc->has_meta("original")) { // Getting the meta when it doesn't exist will return an empty array. If the 'shortcut_events' have been cleared, - // we still want save the shortcut in this case so that shortcuts that the user has customised are not reset, + // we still want save the shortcut in this case so that shortcuts that the user has customized are not reset, // even if the 'original' has not been populated yet. This can happen when calling save() from the Project Manager. save_array.push_back(dict); continue; diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp index db501aac03..a72c545b2f 100644 --- a/editor/editor_settings_dialog.cpp +++ b/editor/editor_settings_dialog.cpp @@ -132,6 +132,7 @@ void EditorSettingsDialog::_notification(int p_what) { } break; case NOTIFICATION_READY: { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->get_or_create_history(EditorUndoRedoManager::GLOBAL_HISTORY).undo_redo->set_method_notify_callback(EditorDebuggerNode::_method_changeds, nullptr); undo_redo->get_or_create_history(EditorUndoRedoManager::GLOBAL_HISTORY).undo_redo->set_property_notify_callback(EditorDebuggerNode::_property_changeds, nullptr); undo_redo->get_or_create_history(EditorUndoRedoManager::GLOBAL_HISTORY).undo_redo->set_commit_notify_callback(_undo_redo_callback, this); @@ -158,9 +159,9 @@ void EditorSettingsDialog::_notification(int p_what) { void EditorSettingsDialog::shortcut_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); const Ref<InputEventKey> k = p_event; - if (k.is_valid() && k->is_pressed()) { bool handled = false; @@ -229,6 +230,7 @@ void EditorSettingsDialog::_event_config_confirmed() { void EditorSettingsDialog::_update_builtin_action(const String &p_name, const Array &p_events) { Array old_input_array = EditorSettings::get_singleton()->get_builtin_action_overrides(p_name); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Edit Built-in Action") + " '" + p_name + "'"); undo_redo->add_do_method(EditorSettings::get_singleton(), "mark_setting_changed", "builtin_action_overrides"); undo_redo->add_undo_method(EditorSettings::get_singleton(), "mark_setting_changed", "builtin_action_overrides"); @@ -244,6 +246,7 @@ void EditorSettingsDialog::_update_builtin_action(const String &p_name, const Ar void EditorSettingsDialog::_update_shortcut_events(const String &p_path, const Array &p_events) { Ref<Shortcut> current_sc = EditorSettings::get_singleton()->get_shortcut(p_path); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Edit Shortcut") + " '" + p_path + "'"); undo_redo->add_do_method(current_sc.ptr(), "set_events", p_events); undo_redo->add_undo_method(current_sc.ptr(), "set_events", current_sc->get_events()); @@ -697,8 +700,6 @@ void EditorSettingsDialog::_bind_methods() { EditorSettingsDialog::EditorSettingsDialog() { set_title(TTR("Editor Settings")); - undo_redo = EditorNode::get_undo_redo(); - tabs = memnew(TabContainer); tabs->set_theme_type_variation("TabContainerOdd"); tabs->connect("tab_changed", callable_mp(this, &EditorSettingsDialog::_tabs_tab_changed)); @@ -723,7 +724,6 @@ EditorSettingsDialog::EditorSettingsDialog() { inspector->get_inspector()->set_use_filter(true); inspector->register_search_box(search_box); inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); - inspector->get_inspector()->set_undo_redo(undo_redo); tab_general->add_child(inspector); inspector->get_inspector()->connect("property_edited", callable_mp(this, &EditorSettingsDialog::_settings_property_edited)); inspector->get_inspector()->connect("restart_requested", callable_mp(this, &EditorSettingsDialog::_editor_restart_request)); diff --git a/editor/editor_settings_dialog.h b/editor/editor_settings_dialog.h index 05424a64ed..a330de1e2c 100644 --- a/editor/editor_settings_dialog.h +++ b/editor/editor_settings_dialog.h @@ -40,8 +40,6 @@ #include "scene/gui/tab_container.h" #include "scene/gui/texture_rect.h" -class EditorUndoRedoManager; - class EditorSettingsDialog : public AcceptDialog { GDCLASS(EditorSettingsDialog, AcceptDialog); @@ -75,8 +73,6 @@ class EditorSettingsDialog : public AcceptDialog { Timer *timer = nullptr; - Ref<EditorUndoRedoManager> undo_redo; - virtual void cancel_pressed() override; virtual void ok_pressed() override; diff --git a/editor/editor_undo_redo_manager.cpp b/editor/editor_undo_redo_manager.cpp index 064448fd96..09b567fc68 100644 --- a/editor/editor_undo_redo_manager.cpp +++ b/editor/editor_undo_redo_manager.cpp @@ -241,6 +241,7 @@ void EditorUndoRedoManager::commit_action(bool p_execute) { history.undo_stack.push_back(pending_action); pending_action = Action(); is_committing = false; + emit_signal(SNAME("history_changed")); } bool EditorUndoRedoManager::is_committing_action() const { @@ -252,14 +253,14 @@ bool EditorUndoRedoManager::undo() { return false; } - History *selected_history = nullptr; + int selected_history = INVALID_HISTORY; double global_timestamp = 0; // Pick the history with greatest last action timestamp (either global or current scene). { History &history = get_or_create_history(GLOBAL_HISTORY); if (!history.undo_stack.is_empty()) { - selected_history = &history; + selected_history = history.id; global_timestamp = history.undo_stack.back()->get().timestamp; } } @@ -267,32 +268,44 @@ bool EditorUndoRedoManager::undo() { { History &history = get_or_create_history(EditorNode::get_editor_data().get_current_edited_scene_history_id()); if (!history.undo_stack.is_empty() && history.undo_stack.back()->get().timestamp > global_timestamp) { - selected_history = &history; + selected_history = history.id; } } - if (selected_history) { - Action action = selected_history->undo_stack.back()->get(); - selected_history->undo_stack.pop_back(); - selected_history->redo_stack.push_back(action); - return selected_history->undo_redo->undo(); + if (selected_history != INVALID_HISTORY) { + return undo_history(selected_history); } return false; } +bool EditorUndoRedoManager::undo_history(int p_id) { + ERR_FAIL_COND_V(p_id == INVALID_HISTORY, false); + History &history = get_or_create_history(p_id); + + Action action = history.undo_stack.back()->get(); + history.undo_stack.pop_back(); + history.redo_stack.push_back(action); + + bool success = history.undo_redo->undo(); + if (success) { + emit_signal(SNAME("version_changed")); + } + return success; +} + bool EditorUndoRedoManager::redo() { if (!has_redo()) { return false; } - History *selected_history = nullptr; + int selected_history = INVALID_HISTORY; double global_timestamp = INFINITY; // Pick the history with lowest last action timestamp (either global or current scene). { History &history = get_or_create_history(GLOBAL_HISTORY); if (!history.redo_stack.is_empty()) { - selected_history = &history; + selected_history = history.id; global_timestamp = history.redo_stack.back()->get().timestamp; } } @@ -300,19 +313,31 @@ bool EditorUndoRedoManager::redo() { { History &history = get_or_create_history(EditorNode::get_editor_data().get_current_edited_scene_history_id()); if (!history.redo_stack.is_empty() && history.redo_stack.back()->get().timestamp < global_timestamp) { - selected_history = &history; + selected_history = history.id; } } - if (selected_history) { - Action action = selected_history->redo_stack.back()->get(); - selected_history->redo_stack.pop_back(); - selected_history->undo_stack.push_back(action); - return selected_history->undo_redo->redo(); + if (selected_history != INVALID_HISTORY) { + return redo_history(selected_history); } return false; } +bool EditorUndoRedoManager::redo_history(int p_id) { + ERR_FAIL_COND_V(p_id == INVALID_HISTORY, false); + History &history = get_or_create_history(p_id); + + Action action = history.redo_stack.back()->get(); + history.redo_stack.pop_back(); + history.undo_stack.push_back(action); + + bool success = history.undo_redo->redo(); + if (success) { + emit_signal(SNAME("version_changed")); + } + return success; +} + void EditorUndoRedoManager::set_history_as_saved(int p_id) { History &history = get_or_create_history(p_id); history.saved_version = history.undo_redo->get_version(); @@ -352,6 +377,7 @@ void EditorUndoRedoManager::clear_history(bool p_increase_version, int p_idx) { if (!p_increase_version) { set_history_as_saved(p_idx); } + emit_signal(SNAME("history_changed")); return; } @@ -359,6 +385,7 @@ void EditorUndoRedoManager::clear_history(bool p_increase_version, int p_idx) { E.value.undo_redo->clear_history(p_increase_version); set_history_as_saved(E.key); } + emit_signal(SNAME("history_changed")); } String EditorUndoRedoManager::get_current_action_name() { @@ -434,6 +461,9 @@ void EditorUndoRedoManager::_bind_methods() { ClassDB::bind_method(D_METHOD("get_object_history_id", "object"), &EditorUndoRedoManager::get_history_id_for_object); ClassDB::bind_method(D_METHOD("get_history_undo_redo", "id"), &EditorUndoRedoManager::get_history_undo_redo); + ADD_SIGNAL(MethodInfo("history_changed")); + ADD_SIGNAL(MethodInfo("version_changed")); + BIND_ENUM_CONSTANT(GLOBAL_HISTORY); BIND_ENUM_CONSTANT(INVALID_HISTORY); } diff --git a/editor/editor_undo_redo_manager.h b/editor/editor_undo_redo_manager.h index c4d85daa22..60bcd059df 100644 --- a/editor/editor_undo_redo_manager.h +++ b/editor/editor_undo_redo_manager.h @@ -44,7 +44,6 @@ public: INVALID_HISTORY = -99, }; -private: struct Action { int history_id = INVALID_HISTORY; double timestamp = 0; @@ -60,6 +59,7 @@ private: List<Action> redo_stack; }; +private: HashMap<int, History> history_map; Action pending_action; @@ -114,7 +114,9 @@ public: bool is_committing_action() const; bool undo(); + bool undo_history(int p_id); bool redo(); + bool redo_history(int p_id); void clear_history(bool p_increase_version = true, int p_idx = INVALID_HISTORY); void set_history_as_saved(int p_idx); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 608e7ce3cb..62bcf0b193 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1283,42 +1283,71 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin } Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES); - print_verbose("Duplicating " + old_path + " -> " + new_path); - Error err = p_item.is_file ? da->copy(old_path, new_path) : da->copy_dir(old_path, new_path); - if (err == OK) { - // Move/Rename any corresponding import settings too. - if (p_item.is_file && FileAccess::exists(old_path + ".import")) { - err = da->copy(old_path + ".import", new_path + ".import"); + + if (p_item.is_file) { + print_verbose("Duplicating " + old_path + " -> " + new_path); + + // Create the directory structure. + da->make_dir_recursive(new_path.get_base_dir()); + + if (FileAccess::exists(old_path + ".import")) { + Error err = da->copy(old_path, new_path); if (err != OK) { - EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + ".import\n"); + EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + ": " + error_names[err] + "\n"); + return; } // Remove uid from .import file to avoid conflict. Ref<ConfigFile> cfg; cfg.instantiate(); - cfg->load(new_path + ".import"); + cfg->load(old_path + ".import"); cfg->erase_section_key("remap", "uid"); - cfg->save(new_path + ".import"); - } else if (p_item.is_file && (old_path.get_extension() == "tscn" || old_path.get_extension() == "tres")) { - // FIXME: Quick hack to fix text resources. This should be fixed properly. - Ref<FileAccess> file = FileAccess::open(old_path, FileAccess::READ, &err); - if (err == OK) { - PackedStringArray lines = file->get_as_utf8_string().split("\n"); - String line = lines[0]; - - if (line.contains("uid")) { - line = line.substr(0, line.find(" uid")) + "]"; - lines.write[0] = line; + err = cfg->save(new_path + ".import"); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + ".import: " + error_names[err] + "\n"); + return; + } + } else { + // Files which do not use an uid can just be copied. + if (ResourceLoader::get_resource_uid(old_path) == ResourceUID::INVALID_ID) { + Error err = da->copy(old_path, new_path); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + ": " + error_names[err] + "\n"); + } + return; + } - Ref<FileAccess> file2 = FileAccess::open(new_path, FileAccess::WRITE, &err); - if (err == OK) { - file2->store_string(String("\n").join(lines)); - } + // Load the resource and save it again in the new location (this generates a new UID). + Error err; + Ref<Resource> res = ResourceLoader::load(old_path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err); + if (err == OK && res.is_valid()) { + err = ResourceSaver::save(res, new_path, ResourceSaver::FLAG_COMPRESS); + if (err != OK) { + EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + " " + vformat(TTR("Failed to save resource at %s: %s"), new_path, error_names[err])); } + } else if (err != OK) { + // When loading files like text files the error is OK but the resource is still null. + // We can ignore such files. + EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + " " + vformat(TTR("Failed to load resource at %s: %s"), new_path, error_names[err])); } } } else { - EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + "\n"); + // Recursively duplicate all files inside the folder. + Ref<DirAccess> old_dir = DirAccess::open(old_path); + Ref<FileAccess> file_access = FileAccess::create(FileAccess::ACCESS_RESOURCES); + old_dir->set_include_navigational(false); + old_dir->list_dir_begin(); + for (String f = old_dir->_get_next(); !f.is_empty(); f = old_dir->_get_next()) { + if (f.get_extension() == "import") { + continue; + } + if (file_access->file_exists(old_path + f)) { + _try_duplicate_item(FileOrFolder(old_path + f, true), new_path + f); + } else if (da->dir_exists(old_path + f)) { + _try_duplicate_item(FileOrFolder(old_path + f, false), new_path + f); + } + } + old_dir->list_dir_end(); } } diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index f11e328087..ab96caa88c 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -130,6 +130,7 @@ void GroupDialog::_add_pressed() { return; } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Add to Group")); while (selected) { @@ -159,6 +160,7 @@ void GroupDialog::_removed_pressed() { return; } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Remove from Group")); while (selected) { @@ -246,6 +248,7 @@ void GroupDialog::_group_renamed() { renamed_group->set_text(0, name); // Spaces trimmed. + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Rename Group")); List<Node *> nodes; @@ -322,6 +325,7 @@ void GroupDialog::_modify_group_pressed(Object *p_item, int p_column, int p_id, case DELETE_GROUP: { String name = ti->get_text(0); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Delete Group")); List<Node *> nodes; @@ -402,10 +406,6 @@ void GroupDialog::_notification(int p_what) { } } -void GroupDialog::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) { - undo_redo = p_undo_redo; -} - void GroupDialog::edit() { popup_centered(); @@ -597,6 +597,7 @@ void GroupsEditor::_add_group(const String &p_group) { return; } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Add to Group")); undo_redo->add_do_method(node, "add_to_group", name, true); @@ -651,6 +652,7 @@ void GroupsEditor::_group_renamed() { ti->set_text(0, name); // Spaces trimmed. + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Rename Group")); undo_redo->add_do_method(node, "remove_from_group", selected_group); @@ -686,6 +688,7 @@ void GroupsEditor::_modify_group(Object *p_item, int p_column, int p_id, MouseBu switch (p_id) { case DELETE_GROUP: { const String name = ti->get_text(0); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Remove from Group")); undo_redo->add_do_method(node, "remove_from_group", name); @@ -764,10 +767,6 @@ void GroupsEditor::update_tree() { } } -void GroupsEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) { - undo_redo = p_undo_redo; -} - void GroupsEditor::set_current(Node *p_node) { node = p_node; update_tree(); @@ -775,7 +774,6 @@ void GroupsEditor::set_current(Node *p_node) { void GroupsEditor::_show_group_dialog() { group_dialog->edit(); - group_dialog->set_undo_redo(undo_redo); } void GroupsEditor::_bind_methods() { diff --git a/editor/groups_editor.h b/editor/groups_editor.h index 5d012a3501..3900e0e28c 100644 --- a/editor/groups_editor.h +++ b/editor/groups_editor.h @@ -39,8 +39,6 @@ #include "scene/gui/popup.h" #include "scene/gui/tree.h" -class EditorUndoRedoManager; - class GroupDialog : public AcceptDialog { GDCLASS(GroupDialog, AcceptDialog); @@ -69,8 +67,6 @@ class GroupDialog : public AcceptDialog { String selected_group; - Ref<EditorUndoRedoManager> undo_redo; - void _group_selected(); void _remove_filter_changed(const String &p_filter); @@ -102,7 +98,6 @@ public: }; void edit(); - void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo); GroupDialog(); }; @@ -120,8 +115,6 @@ class GroupsEditor : public VBoxContainer { Button *add = nullptr; Tree *tree = nullptr; - Ref<EditorUndoRedoManager> undo_redo; - String selected_group; void update_tree(); @@ -143,7 +136,6 @@ public: COPY_GROUP, }; - void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo); void set_current(Node *p_node); GroupsEditor(); diff --git a/editor/history_dock.cpp b/editor/history_dock.cpp new file mode 100644 index 0000000000..57088a76cb --- /dev/null +++ b/editor/history_dock.cpp @@ -0,0 +1,251 @@ +/*************************************************************************/ +/* history_dock.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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 "history_dock.h" + +#include "editor/editor_node.h" +#include "editor/editor_undo_redo_manager.h" +#include "scene/gui/check_box.h" +#include "scene/gui/item_list.h" + +struct SortActionsByTimestamp { + bool operator()(const EditorUndoRedoManager::Action &l, const EditorUndoRedoManager::Action &r) const { + return l.timestamp > r.timestamp; + } +}; + +void HistoryDock::on_history_changed() { + if (is_visible_in_tree()) { + refresh_history(); + } else { + need_refresh = true; + } +} + +void HistoryDock::refresh_history() { + action_list->clear(); + bool include_scene = current_scene_checkbox->is_pressed(); + bool include_global = global_history_checkbox->is_pressed(); + + if (!include_scene && !include_global) { + action_list->add_item(TTR("The Beginning")); + return; + } + + const EditorUndoRedoManager::History ¤t_scene_history = ur_manager->get_or_create_history(EditorNode::get_editor_data().get_current_edited_scene_history_id()); + const EditorUndoRedoManager::History &global_history = ur_manager->get_or_create_history(EditorUndoRedoManager::GLOBAL_HISTORY); + + Vector<EditorUndoRedoManager::Action> full_history; + { + int full_size = 0; + if (include_scene) { + full_size += current_scene_history.redo_stack.size() + current_scene_history.undo_stack.size(); + } + if (include_global) { + full_size += global_history.redo_stack.size() + global_history.undo_stack.size(); + } + full_history.resize(full_size); + } + + int i = 0; + if (include_scene) { + for (const EditorUndoRedoManager::Action &E : current_scene_history.redo_stack) { + full_history.write[i] = E; + i++; + } + for (const EditorUndoRedoManager::Action &E : current_scene_history.undo_stack) { + full_history.write[i] = E; + i++; + } + } + if (include_global) { + for (const EditorUndoRedoManager::Action &E : global_history.redo_stack) { + full_history.write[i] = E; + i++; + } + for (const EditorUndoRedoManager::Action &E : global_history.undo_stack) { + full_history.write[i] = E; + i++; + } + } + + full_history.sort_custom<SortActionsByTimestamp>(); + for (const EditorUndoRedoManager::Action &E : full_history) { + action_list->add_item(E.action_name); + if (E.history_id == EditorUndoRedoManager::GLOBAL_HISTORY) { + action_list->set_item_custom_fg_color(-1, get_theme_color(SNAME("accent_color"), SNAME("Editor"))); + } + } + + action_list->add_item(TTR("The Beginning")); + refresh_version(); +} + +void HistoryDock::on_version_changed() { + if (is_visible_in_tree()) { + refresh_version(); + } else { + need_refresh = true; + } +} + +void HistoryDock::refresh_version() { + int idx = 0; + bool include_scene = current_scene_checkbox->is_pressed(); + bool include_global = global_history_checkbox->is_pressed(); + + if (!include_scene && !include_global) { + current_version = idx; + action_list->set_current(idx); + return; + } + + const EditorUndoRedoManager::History ¤t_scene_history = ur_manager->get_or_create_history(EditorNode::get_editor_data().get_current_edited_scene_history_id()); + const EditorUndoRedoManager::History &global_history = ur_manager->get_or_create_history(EditorUndoRedoManager::GLOBAL_HISTORY); + double newest_undo_timestamp = 0; + + if (include_scene && !current_scene_history.undo_stack.is_empty()) { + newest_undo_timestamp = current_scene_history.undo_stack.front()->get().timestamp; + } + + if (include_global && !global_history.undo_stack.is_empty()) { + double global_undo_timestamp = global_history.undo_stack.front()->get().timestamp; + if (global_undo_timestamp > newest_undo_timestamp) { + newest_undo_timestamp = global_undo_timestamp; + } + } + + if (include_scene) { + int skip = 0; + for (const EditorUndoRedoManager::Action &E : current_scene_history.redo_stack) { + if (E.timestamp < newest_undo_timestamp) { + skip++; + } else { + break; + } + } + idx += current_scene_history.redo_stack.size() - skip; + } + + if (include_global) { + int skip = 0; + for (const EditorUndoRedoManager::Action &E : global_history.redo_stack) { + if (E.timestamp < newest_undo_timestamp) { + skip++; + } else { + break; + } + } + idx += global_history.redo_stack.size() - skip; + } + + current_version = idx; + action_list->set_current(idx); +} + +void HistoryDock::seek_history(int p_index) { + bool include_scene = current_scene_checkbox->is_pressed(); + bool include_global = global_history_checkbox->is_pressed(); + + if (!include_scene && !include_global) { + return; + } + int current_scene_id = EditorNode::get_editor_data().get_current_edited_scene_history_id(); + + while (current_version < p_index) { + if (include_scene) { + if (include_global) { + ur_manager->undo(); + } else { + ur_manager->undo_history(current_scene_id); + } + } else { + ur_manager->undo_history(EditorUndoRedoManager::GLOBAL_HISTORY); + } + } + + while (current_version > p_index) { + if (include_scene) { + if (include_global) { + ur_manager->redo(); + } else { + ur_manager->redo_history(current_scene_id); + } + } else { + ur_manager->redo_history(EditorUndoRedoManager::GLOBAL_HISTORY); + } + } +} + +void HistoryDock::_notification(int p_notification) { + switch (p_notification) { + case NOTIFICATION_ENTER_TREE: { + EditorNode::get_singleton()->connect("scene_changed", callable_mp(this, &HistoryDock::on_history_changed)); + } break; + + case NOTIFICATION_VISIBILITY_CHANGED: { + if (is_visible_in_tree() && need_refresh) { + refresh_history(); + } + } break; + } +} + +HistoryDock::HistoryDock() { + ur_manager = EditorNode::get_undo_redo(); + ur_manager->connect("history_changed", callable_mp(this, &HistoryDock::on_history_changed)); + ur_manager->connect("version_changed", callable_mp(this, &HistoryDock::on_version_changed)); + + HBoxContainer *mode_hb = memnew(HBoxContainer); + add_child(mode_hb); + + current_scene_checkbox = memnew(CheckBox); + mode_hb->add_child(current_scene_checkbox); + current_scene_checkbox->set_flat(true); + current_scene_checkbox->set_pressed(true); + current_scene_checkbox->set_text(TTR("Scene")); + current_scene_checkbox->set_h_size_flags(SIZE_EXPAND_FILL); + current_scene_checkbox->set_clip_text(true); + current_scene_checkbox->connect("toggled", callable_mp(this, &HistoryDock::refresh_history).unbind(1)); + + global_history_checkbox = memnew(CheckBox); + mode_hb->add_child(global_history_checkbox); + global_history_checkbox->set_flat(true); + global_history_checkbox->set_pressed(true); + global_history_checkbox->set_text(TTR("Global")); + global_history_checkbox->set_h_size_flags(SIZE_EXPAND_FILL); + global_history_checkbox->set_clip_text(true); + global_history_checkbox->connect("toggled", callable_mp(this, &HistoryDock::refresh_history).unbind(1)); + + action_list = memnew(ItemList); + add_child(action_list); + action_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + action_list->connect("item_selected", callable_mp(this, &HistoryDock::seek_history)); +} diff --git a/editor/history_dock.h b/editor/history_dock.h new file mode 100644 index 0000000000..9dda8165e6 --- /dev/null +++ b/editor/history_dock.h @@ -0,0 +1,66 @@ +/*************************************************************************/ +/* history_dock.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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. */ +/*************************************************************************/ + +#ifndef HISTORY_DOCK_H +#define HISTORY_DOCK_H + +#include "scene/gui/box_container.h" + +class CheckBox; +class ItemList; +class EditorUndoRedoManager; + +class HistoryDock : public VBoxContainer { + GDCLASS(HistoryDock, VBoxContainer); + + Ref<EditorUndoRedoManager> ur_manager; + ItemList *action_list = nullptr; + + CheckBox *current_scene_checkbox = nullptr; + CheckBox *global_history_checkbox = nullptr; + + bool need_refresh = true; + int current_version = 0; + + void on_history_changed(); + void refresh_history(); + void on_version_changed(); + void refresh_version(); + +protected: + void _notification(int p_notification); + +public: + void seek_history(int p_index); + + HistoryDock(); +}; + +#endif // HISTORY_DOCK_H diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index ab15aa4fdc..9adabfb5d1 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -368,7 +368,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const for (int j = 0; j < hslices; j++) { int x = slice_w * j; int y = slice_h * i; - Ref<Image> slice = image->get_rect(Rect2i(x, y, slice_w, slice_h)); + Ref<Image> slice = image->get_region(Rect2i(x, y, slice_w, slice_h)); ERR_CONTINUE(slice.is_null() || slice->is_empty()); if (slice->get_width() != slice_w || slice->get_height() != slice_h) { slice->resize(slice_w, slice_h); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 27b261f320..bd2eb5fd9e 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -34,6 +34,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_undo_redo_manager.h" #include "editor/plugins/script_editor_plugin.h" InspectorDock *InspectorDock::singleton = nullptr; @@ -769,7 +770,6 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) { inspector->set_property_name_style(EditorPropertyNameProcessor::get_default_inspector_style()); inspector->set_use_folding(!bool(EDITOR_GET("interface/inspector/disable_folding"))); inspector->register_text_enter(search); - inspector->set_undo_redo(editor_data->get_undo_redo()); inspector->set_use_filter(true); // TODO: check me diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp index 7727ff31e4..4b8257969c 100644 --- a/editor/localization_editor.cpp +++ b/editor/localization_editor.cpp @@ -81,6 +81,7 @@ void LocalizationEditor::_translation_add(const PackedStringArray &p_paths) { } } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(vformat(TTR("Add %d Translations"), p_paths.size())); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translations", translations); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translations", GLOBAL_GET("internationalization/locale/translations")); @@ -111,6 +112,7 @@ void LocalizationEditor::_translation_delete(Object *p_item, int p_column, int p translations.remove_at(idx); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Remove Translation")); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translations", translations); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translations", GLOBAL_GET("internationalization/locale/translations")); @@ -141,6 +143,7 @@ void LocalizationEditor::_translation_res_add(const PackedStringArray &p_paths) } } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(vformat(TTR("Translation Resource Remap: Add %d Path(s)"), p_paths.size())); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", remaps); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", prev); @@ -172,6 +175,7 @@ void LocalizationEditor::_translation_res_option_add(const PackedStringArray &p_ } remaps[key] = r; + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(vformat(TTR("Translation Resource Remap: Add %d Remap(s)"), p_paths.size())); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", remaps); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", GLOBAL_GET("internationalization/locale/translation_remaps")); @@ -234,6 +238,8 @@ void LocalizationEditor::_translation_res_option_changed() { remaps[key] = r; updating_translations = true; + + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Change Resource Remap Language")); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", remaps); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", GLOBAL_GET("internationalization/locale/translation_remaps")); @@ -267,6 +273,7 @@ void LocalizationEditor::_translation_res_delete(Object *p_item, int p_column, i remaps.erase(key); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Remove Resource Remap")); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", remaps); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", GLOBAL_GET("internationalization/locale/translation_remaps")); @@ -306,6 +313,7 @@ void LocalizationEditor::_translation_res_option_delete(Object *p_item, int p_co r.remove_at(idx); remaps[key] = r; + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Remove Resource Remap Option")); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", remaps); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translation_remaps", GLOBAL_GET("internationalization/locale/translation_remaps")); @@ -324,6 +332,7 @@ void LocalizationEditor::_pot_add(const PackedStringArray &p_paths) { } } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(vformat(TTR("Add %d file(s) for POT generation"), p_paths.size())); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translations_pot_files", pot_translations); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translations_pot_files", GLOBAL_GET("internationalization/locale/translations_pot_files")); @@ -350,6 +359,7 @@ void LocalizationEditor::_pot_delete(Object *p_item, int p_column, int p_button, pot_translations.remove_at(idx); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Remove file from POT generation")); undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/translations_pot_files", pot_translations); undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/translations_pot_files", GLOBAL_GET("internationalization/locale/translations_pot_files")); @@ -592,7 +602,6 @@ void LocalizationEditor::_bind_methods() { } LocalizationEditor::LocalizationEditor() { - undo_redo = EditorNode::get_undo_redo(); localization_changed = "localization_changed"; TabContainer *translations = memnew(TabContainer); diff --git a/editor/localization_editor.h b/editor/localization_editor.h index ecac171fe3..5fa6d9519a 100644 --- a/editor/localization_editor.h +++ b/editor/localization_editor.h @@ -31,7 +31,6 @@ #ifndef LOCALIZATION_EDITOR_H #define LOCALIZATION_EDITOR_H -#include "core/object/undo_redo.h" #include "editor/editor_locale_dialog.h" #include "scene/gui/tree.h" @@ -56,7 +55,6 @@ class LocalizationEditor : public VBoxContainer { EditorFileDialog *pot_file_open_dialog = nullptr; EditorFileDialog *pot_generate_dialog = nullptr; - Ref<EditorUndoRedoManager> undo_redo; bool updating_translations = false; String localization_changed; diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp index 55fa2f22dd..266b265819 100644 --- a/editor/node_dock.cpp +++ b/editor/node_dock.cpp @@ -117,13 +117,11 @@ NodeDock::NodeDock() { groups_button->connect("pressed", callable_mp(this, &NodeDock::show_groups)); connections = memnew(ConnectionsDock); - connections->set_undo_redo(EditorNode::get_undo_redo()); add_child(connections); connections->set_v_size_flags(SIZE_EXPAND_FILL); connections->hide(); groups = memnew(GroupsEditor); - groups->set_undo_redo(EditorNode::get_undo_redo()); add_child(groups); groups->set_v_size_flags(SIZE_EXPAND_FILL); groups->hide(); diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index cb07d8cf01..ecb4837695 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -91,6 +91,7 @@ void AbstractPolygon2DEditor::_set_polygon(int p_idx, const Variant &p_polygon) void AbstractPolygon2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) { Node2D *node = _get_node(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->add_do_method(node, "set_polygon", p_polygon); undo_redo->add_undo_method(node, "set_polygon", p_previous); } @@ -100,6 +101,7 @@ Vector2 AbstractPolygon2DEditor::_get_offset(int p_idx) const { } void AbstractPolygon2DEditor::_commit_action() { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); undo_redo->commit_action(); @@ -203,6 +205,7 @@ void AbstractPolygon2DEditor::_wip_close() { if (_is_line()) { _set_polygon(0, wip); } else if (wip.size() >= (_is_line() ? 2 : 3)) { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Create Polygon")); _action_add_polygon(wip); if (_has_uv()) { @@ -254,6 +257,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) return false; } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); Ref<InputEventMouseButton> mb = p_event; if (!_has_resource()) { @@ -611,6 +615,7 @@ void AbstractPolygon2DEditor::_bind_methods() { } void AbstractPolygon2DEditor::remove_point(const Vertex &p_vertex) { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); Vector<Vector2> vertices = _get_polygon(p_vertex.polygon); if (vertices.size() > (_is_line() ? 2 : 3)) { @@ -706,8 +711,6 @@ AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_edge_point(c } AbstractPolygon2DEditor::AbstractPolygon2DEditor(bool p_wip_destructive) { - undo_redo = EditorNode::get_undo_redo(); - edited_point = PosVertex(); wip_destructive = p_wip_destructive; diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h index 1fbbe67c8d..8a3db9d837 100644 --- a/editor/plugins/abstract_polygon_2d_editor.h +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -36,7 +36,6 @@ #include "scene/gui/box_container.h" class CanvasItemEditor; -class EditorUndoRedoManager; class AbstractPolygon2DEditor : public HBoxContainer { GDCLASS(AbstractPolygon2DEditor, HBoxContainer); @@ -100,8 +99,6 @@ protected: int mode = MODE_EDIT; - Ref<EditorUndoRedoManager> undo_redo; - virtual void _menu_option(int p_option); void _wip_changed(); void _wip_close(); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index e45081fd67..6d00e77a4b 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -153,7 +153,8 @@ void AnimationNodeBlendTreeEditor::update_graph() { node->add_child(name); node->set_slot(0, false, 0, Color(), true, read_only ? -1 : 0, get_theme_color(SNAME("font_color"), SNAME("Label"))); name->connect("text_submitted", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed).bind(agnode), CONNECT_DEFERRED); - name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out).bind(name, agnode), CONNECT_DEFERRED); + name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out).bind(agnode), CONNECT_DEFERRED); + name->connect("text_changed", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_rename_lineedit_changed), CONNECT_DEFERRED); base = 1; node->set_show_close_button(true); node->connect("close_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_delete_request).bind(E), CONNECT_DEFERRED); @@ -993,13 +994,18 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima } update_graph(); // Needed to update the signal connections with the new name. + current_node_rename_text = String(); } -void AnimationNodeBlendTreeEditor::_node_renamed_focus_out(Node *le, Ref<AnimationNode> p_node) { - if (le == nullptr) { +void AnimationNodeBlendTreeEditor::_node_renamed_focus_out(Ref<AnimationNode> p_node) { + if (current_node_rename_text.is_empty()) { return; // The text_submitted signal triggered the graph update and freed the LineEdit. } - _node_renamed(le->call("get_text"), p_node); + _node_renamed(current_node_rename_text, p_node); +} + +void AnimationNodeBlendTreeEditor::_node_rename_lineedit_changed(const String &p_text) { + current_node_rename_text = p_text; } bool AnimationNodeBlendTreeEditor::can_edit(const Ref<AnimationNode> &p_node) { diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h index 46e0d18c69..b55fc3b617 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.h +++ b/editor/plugins/animation_blend_tree_editor_plugin.h @@ -92,9 +92,11 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { void _node_dragged(const Vector2 &p_from, const Vector2 &p_to, const StringName &p_which); void _node_renamed(const String &p_text, Ref<AnimationNode> p_node); - void _node_renamed_focus_out(Node *le, Ref<AnimationNode> p_node); + void _node_renamed_focus_out(Ref<AnimationNode> p_node); + void _node_rename_lineedit_changed(const String &p_text); void _node_changed(const StringName &p_node_name); + String current_node_rename_text; bool updating; void _connection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index b4737976d8..1ebe81c4b0 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -39,6 +39,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_undo_redo_manager.h" #include "editor/plugins/canvas_item_editor_plugin.h" // For onion skinning. #include "editor/plugins/node_3d_editor_plugin.h" // For onion skinning. #include "editor/scene_tree_dock.h" @@ -167,6 +168,7 @@ void AnimationPlayerEditor::_autoplay_pressed() { return; } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); String current = animation->get_item_text(animation->get_selected()); if (player->get_autoplay() == current) { //unset @@ -383,6 +385,7 @@ void AnimationPlayerEditor::_animation_remove_confirmed() { if (current.contains("/")) { current = current.get_slice("/", 1); } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Remove Animation")); if (player->get_autoplay() == current) { undo_redo->add_do_method(player, "set_autoplay", ""); @@ -458,6 +461,7 @@ void AnimationPlayerEditor::_animation_name_edited() { return; } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); switch (name_dialog_op) { case TOOL_RENAME_ANIM: { String current = animation->get_item_text(animation->get_selected()); @@ -592,6 +596,7 @@ void AnimationPlayerEditor::_blend_editor_next_changed(const int p_idx) { String current = animation->get_item_text(animation->get_selected()); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Blend Next Changed")); undo_redo->add_do_method(player, "animation_set_next", current, blend_editor.next->get_item_text(p_idx)); undo_redo->add_undo_method(player, "animation_set_next", current, player->animation_get_next(current)); @@ -678,6 +683,7 @@ void AnimationPlayerEditor::_blend_edited() { float blend_time = selected->get_range(1); float prev_blend_time = player->get_blend_time(current, to); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Change Blend Time")); undo_redo->add_do_method(player, "set_blend_time", current, to, blend_time); undo_redo->add_undo_method(player, "set_blend_time", current, to, prev_blend_time); @@ -984,10 +990,6 @@ void AnimationPlayerEditor::_update_name_dialog_library_dropdown() { } } -void AnimationPlayerEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) { - undo_redo = p_undo_redo; -} - void AnimationPlayerEditor::edit(AnimationPlayer *p_player) { if (player && pin->is_pressed()) { return; // Ignore, pinned. @@ -1894,7 +1896,6 @@ void AnimationPlayerEditorPlugin::_update_keying() { } void AnimationPlayerEditorPlugin::edit(Object *p_object) { - anim_editor->set_undo_redo(get_undo_redo()); if (!p_object) { return; } @@ -1915,7 +1916,6 @@ void AnimationPlayerEditorPlugin::make_visible(bool p_visible) { AnimationPlayerEditorPlugin::AnimationPlayerEditorPlugin() { anim_editor = memnew(AnimationPlayerEditor(this)); - anim_editor->set_undo_redo(EditorNode::get_undo_redo()); EditorNode::get_singleton()->add_bottom_panel_item(TTR("Animation"), anim_editor); } diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h index ae570e53f3..6370b00ea8 100644 --- a/editor/plugins/animation_player_editor_plugin.h +++ b/editor/plugins/animation_player_editor_plugin.h @@ -41,7 +41,6 @@ #include "scene/gui/texture_button.h" #include "scene/gui/tree.h" -class EditorUndoRedoManager; class AnimationPlayerEditorPlugin; class AnimationPlayerEditor : public VBoxContainer { @@ -101,7 +100,6 @@ class AnimationPlayerEditor : public VBoxContainer { LineEdit *name = nullptr; OptionButton *library = nullptr; Label *name_title = nullptr; - Ref<EditorUndoRedoManager> undo_redo; Ref<Texture2D> autoplay_icon; Ref<Texture2D> reset_icon; @@ -237,7 +235,6 @@ public: void ensure_visibility(); - void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo); void edit(AnimationPlayer *p_player); void forward_force_draw_over_viewport(Control *p_overlay); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 291b939fe9..1d6f41d4c4 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -868,6 +868,7 @@ void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_ite return; } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(action_name); for (CanvasItem *ci : modified_canvas_items) { CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(ci); @@ -934,6 +935,7 @@ void CanvasItemEditor::_add_node_pressed(int p_result) { return; } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Move Node(s) to Position")); for (Node *node : nodes_to_move) { CanvasItem *ci = Object::cast_to<CanvasItem>(node); @@ -1022,6 +1024,7 @@ void CanvasItemEditor::_on_grid_menu_id_pressed(int p_id) { } bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_event) { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); Ref<InputEventMouseButton> b = p_event; Ref<InputEventMouseMotion> m = p_event; @@ -4000,10 +4003,6 @@ void CanvasItemEditor::_selection_changed() { selected_from_canvas = false; } -void CanvasItemEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) { - undo_redo = p_undo_redo; -} - void CanvasItemEditor::edit(CanvasItem *p_canvas_item) { Array selection = editor_selection->get_selected_nodes(); if (selection.size() != 1 || Object::cast_to<Node>(selection[0]) != p_canvas_item) { @@ -4278,6 +4277,7 @@ void CanvasItemEditor::_update_override_camera_button(bool p_game_running) { } void CanvasItemEditor::_popup_callback(int p_op) { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); last_option = MenuOption(p_op); switch (p_op) { case SHOW_ORIGIN: { @@ -4983,7 +4983,6 @@ CanvasItemEditor::CanvasItemEditor() { snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; - undo_redo = EditorNode::get_singleton()->get_undo_redo(); editor_selection = EditorNode::get_singleton()->get_editor_selection(); editor_selection->add_editor_plugin(this); editor_selection->connect("selection_changed", callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw)); @@ -5434,7 +5433,6 @@ CanvasItemEditor::CanvasItemEditor() { CanvasItemEditor *CanvasItemEditor::singleton = nullptr; void CanvasItemEditorPlugin::edit(Object *p_object) { - canvas_item_editor->set_undo_redo(EditorNode::get_undo_redo()); canvas_item_editor->edit(Object::cast_to<CanvasItem>(p_object)); } @@ -5581,37 +5579,38 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & String name = path.get_file().get_basename(); child->set_name(Node::adjust_name_casing(name)); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); Ref<Texture2D> texture = ResourceCache::get_ref(path); if (parent) { - editor_data->get_undo_redo()->add_do_method(parent, "add_child", child, true); - editor_data->get_undo_redo()->add_do_method(child, "set_owner", EditorNode::get_singleton()->get_edited_scene()); - editor_data->get_undo_redo()->add_do_reference(child); - editor_data->get_undo_redo()->add_undo_method(parent, "remove_child", child); + undo_redo->add_do_method(parent, "add_child", child, true); + undo_redo->add_do_method(child, "set_owner", EditorNode::get_singleton()->get_edited_scene()); + undo_redo->add_do_reference(child); + undo_redo->add_undo_method(parent, "remove_child", child); } else { // If no parent is selected, set as root node of the scene. - editor_data->get_undo_redo()->add_do_method(EditorNode::get_singleton(), "set_edited_scene", child); - editor_data->get_undo_redo()->add_do_method(child, "set_owner", EditorNode::get_singleton()->get_edited_scene()); - editor_data->get_undo_redo()->add_do_reference(child); - editor_data->get_undo_redo()->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr); + undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", child); + undo_redo->add_do_method(child, "set_owner", EditorNode::get_singleton()->get_edited_scene()); + undo_redo->add_do_reference(child); + undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr); } if (parent) { String new_name = parent->validate_child_name(child); EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton(); - editor_data->get_undo_redo()->add_do_method(ed, "live_debug_create_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent), child->get_class(), new_name); - editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent)) + "/" + new_name)); + undo_redo->add_do_method(ed, "live_debug_create_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent), child->get_class(), new_name); + undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent)) + "/" + new_name)); } if (Object::cast_to<TouchScreenButton>(child) || Object::cast_to<TextureButton>(child)) { - editor_data->get_undo_redo()->add_do_property(child, "texture_normal", texture); + undo_redo->add_do_property(child, "texture_normal", texture); } else { - editor_data->get_undo_redo()->add_do_property(child, "texture", texture); + undo_redo->add_do_property(child, "texture", texture); } // make visible for certain node type if (Object::cast_to<Control>(child)) { Size2 texture_size = texture->get_size(); - editor_data->get_undo_redo()->add_do_property(child, "rect_size", texture_size); + undo_redo->add_do_property(child, "rect_size", texture_size); } else if (Object::cast_to<Polygon2D>(child)) { Size2 texture_size = texture->get_size(); Vector<Vector2> list = { @@ -5620,7 +5619,7 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & Vector2(texture_size.width, texture_size.height), Vector2(0, texture_size.height) }; - editor_data->get_undo_redo()->add_do_property(child, "polygon", list); + undo_redo->add_do_property(child, "polygon", list); } // Compute the global position @@ -5629,7 +5628,7 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & // there's nothing to be used as source position so snapping will work as absolute if enabled target_position = canvas_item_editor->snap_point(target_position); - editor_data->get_undo_redo()->add_do_method(child, "set_global_position", target_position); + undo_redo->add_do_method(child, "set_global_position", target_position); } bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) { @@ -5654,15 +5653,16 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons instantiated_scene->set_scene_file_path(ProjectSettings::get_singleton()->localize_path(path)); - editor_data->get_undo_redo()->add_do_method(parent, "add_child", instantiated_scene, true); - editor_data->get_undo_redo()->add_do_method(instantiated_scene, "set_owner", edited_scene); - editor_data->get_undo_redo()->add_do_reference(instantiated_scene); - editor_data->get_undo_redo()->add_undo_method(parent, "remove_child", instantiated_scene); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); + undo_redo->add_do_method(parent, "add_child", instantiated_scene, true); + undo_redo->add_do_method(instantiated_scene, "set_owner", edited_scene); + undo_redo->add_do_reference(instantiated_scene); + undo_redo->add_undo_method(parent, "remove_child", instantiated_scene); String new_name = parent->validate_child_name(instantiated_scene); EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton(); - editor_data->get_undo_redo()->add_do_method(ed, "live_debug_instance_node", edited_scene->get_path_to(parent), path, new_name); - editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)) + "/" + new_name)); + undo_redo->add_do_method(ed, "live_debug_instance_node", edited_scene->get_path_to(parent), path, new_name); + undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)) + "/" + new_name)); CanvasItem *instance_ci = Object::cast_to<CanvasItem>(instantiated_scene); if (instance_ci) { @@ -5676,7 +5676,7 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons // Preserve instance position of the original scene. target_pos += instance_ci->_edit_get_position(); - editor_data->get_undo_redo()->add_do_method(instantiated_scene, "set_position", target_pos); + undo_redo->add_do_method(instantiated_scene, "set_position", target_pos); } return true; @@ -5694,7 +5694,8 @@ void CanvasItemEditorViewport::_perform_drop_data() { Vector<String> error_files; - editor_data->get_undo_redo()->create_action(TTR("Create Node")); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); + undo_redo->create_action(TTR("Create Node")); for (int i = 0; i < selected_files.size(); i++) { String path = selected_files[i]; @@ -5725,7 +5726,7 @@ void CanvasItemEditorViewport::_perform_drop_data() { } } - editor_data->get_undo_redo()->commit_action(); + undo_redo->commit_action(); if (error_files.size() > 0) { String files_str; @@ -5751,8 +5752,10 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian ResourceLoader::get_recognized_extensions_for_type("Texture2D", &texture_extensions); for (int i = 0; i < files.size(); i++) { + String extension = files[i].get_extension().to_lower(); + // Check if dragged files with texture or scene extension can be created at least once. - if (texture_extensions.find(files[i].get_extension()) || scene_extensions.find(files[i].get_extension())) { + if (texture_extensions.find(extension) || scene_extensions.find(extension)) { Ref<Resource> res = ResourceLoader::load(files[i]); if (res.is_null()) { continue; @@ -5916,7 +5919,6 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(CanvasItemEditor *p_canvas_it texture_node_types.push_back("NinePatchRect"); target_node = nullptr; - editor_data = SceneTreeDock::get_singleton()->get_editor_data(); canvas_item_editor = p_canvas_item_editor; preview_node = memnew(Control); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 3ade048e4b..ba193a67b8 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -45,7 +45,6 @@ class EditorData; class CanvasItemEditorViewport; class ViewPanner; -class EditorUndoRedoManager; class CanvasItemEditorSelectedItem : public Object { GDCLASS(CanvasItemEditorSelectedItem, Object); @@ -401,8 +400,6 @@ private: void _prepare_grid_menu(); void _on_grid_menu_id_pressed(int p_id); - Ref<EditorUndoRedoManager> undo_redo; - List<CanvasItem *> _get_edited_canvas_items(bool retrieve_locked = false, bool remove_canvas_item_if_parent_in_selection = true); Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list); void _expand_encompassing_rect_using_children(Rect2 &r_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D(), bool include_locked_nodes = true); @@ -548,7 +545,6 @@ public: Tool get_current_tool() { return tool; } void set_current_tool(Tool p_tool); - void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo); void edit(CanvasItem *p_canvas_item); void focus_selection(); @@ -593,7 +589,6 @@ class CanvasItemEditorViewport : public Control { Node *target_node = nullptr; Point2 drop_pos; - EditorData *editor_data = nullptr; CanvasItemEditor *canvas_item_editor = nullptr; Control *preview_node = nullptr; AcceptDialog *accept = nullptr; diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 4aee9b879e..c7bb6b79ef 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -37,6 +37,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_undo_redo_manager.h" CurveEditor::CurveEditor() { _selected_point = -1; @@ -139,14 +140,13 @@ void CurveEditor::gui_input(const Ref<InputEvent> &p_event) { if (!mb.is_pressed() && _dragging && mb.get_button_index() == MouseButton::LEFT) { _dragging = false; if (_has_undo_data) { - Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo(); - - ur->create_action(_selected_tangent == TANGENT_NONE ? TTR("Modify Curve Point") : TTR("Modify Curve Tangent")); - ur->add_do_method(*_curve_ref, "_set_data", _curve_ref->get_data()); - ur->add_undo_method(*_curve_ref, "_set_data", _undo_data); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); + undo_redo->create_action(_selected_tangent == TANGENT_NONE ? TTR("Modify Curve Point") : TTR("Modify Curve Tangent")); + undo_redo->add_do_method(*_curve_ref, "_set_data", _curve_ref->get_data()); + undo_redo->add_undo_method(*_curve_ref, "_set_data", _undo_data); // Note: this will trigger one more "changed" signal even if nothing changes, // but it's ok since it would have fired every frame during the drag anyways - ur->commit_action(); + undo_redo->commit_action(); _has_undo_data = false; } @@ -301,13 +301,11 @@ void CurveEditor::on_preset_item_selected(int preset_id) { break; } - Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo(); - ur->create_action(TTR("Load Curve Preset")); - - ur->add_do_method(&curve, "_set_data", curve.get_data()); - ur->add_undo_method(&curve, "_set_data", previous_data); - - ur->commit_action(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); + undo_redo->create_action(TTR("Load Curve Preset")); + undo_redo->add_do_method(&curve, "_set_data", curve.get_data()); + undo_redo->add_undo_method(&curve, "_set_data", previous_data); + undo_redo->commit_action(); } void CurveEditor::_curve_changed() { @@ -435,8 +433,8 @@ CurveEditor::TangentIndex CurveEditor::get_tangent_at(Vector2 pos) const { void CurveEditor::add_point(Vector2 pos) { ERR_FAIL_COND(_curve_ref.is_null()); - Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo(); - ur->create_action(TTR("Remove Curve Point")); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); + undo_redo->create_action(TTR("Remove Curve Point")); Vector2 point_pos = get_world_pos(pos); if (point_pos.y < 0.0) { @@ -449,22 +447,21 @@ void CurveEditor::add_point(Vector2 pos) { int i = _curve_ref->add_point(point_pos); _curve_ref->remove_point(i); - ur->add_do_method(*_curve_ref, "add_point", point_pos); - ur->add_undo_method(*_curve_ref, "remove_point", i); - - ur->commit_action(); + undo_redo->add_do_method(*_curve_ref, "add_point", point_pos); + undo_redo->add_undo_method(*_curve_ref, "remove_point", i); + undo_redo->commit_action(); } void CurveEditor::remove_point(int index) { ERR_FAIL_COND(_curve_ref.is_null()); - Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo(); - ur->create_action(TTR("Remove Curve Point")); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); + undo_redo->create_action(TTR("Remove Curve Point")); Curve::Point p = _curve_ref->get_point(index); - ur->add_do_method(*_curve_ref, "remove_point", index); - ur->add_undo_method(*_curve_ref, "add_point", p.position, p.left_tangent, p.right_tangent, p.left_mode, p.right_mode); + undo_redo->add_do_method(*_curve_ref, "remove_point", index); + undo_redo->add_undo_method(*_curve_ref, "add_point", p.position, p.left_tangent, p.right_tangent, p.left_mode, p.right_mode); if (index == _selected_point) { set_selected_point(-1); @@ -474,14 +471,14 @@ void CurveEditor::remove_point(int index) { set_hover_point_index(-1); } - ur->commit_action(); + undo_redo->commit_action(); } void CurveEditor::toggle_linear(TangentIndex tangent) { ERR_FAIL_COND(_curve_ref.is_null()); - Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo(); - ur->create_action(TTR("Toggle Curve Linear Tangent")); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); + undo_redo->create_action(TTR("Toggle Curve Linear Tangent")); if (tangent == TANGENT_NONE) { tangent = _selected_tangent; @@ -493,8 +490,8 @@ void CurveEditor::toggle_linear(TangentIndex tangent) { Curve::TangentMode prev_mode = _curve_ref->get_point_left_mode(_selected_point); Curve::TangentMode mode = is_linear ? Curve::TANGENT_FREE : Curve::TANGENT_LINEAR; - ur->add_do_method(*_curve_ref, "set_point_left_mode", _selected_point, mode); - ur->add_undo_method(*_curve_ref, "set_point_left_mode", _selected_point, prev_mode); + undo_redo->add_do_method(*_curve_ref, "set_point_left_mode", _selected_point, mode); + undo_redo->add_undo_method(*_curve_ref, "set_point_left_mode", _selected_point, prev_mode); } else { bool is_linear = _curve_ref->get_point_right_mode(_selected_point) == Curve::TANGENT_LINEAR; @@ -502,11 +499,11 @@ void CurveEditor::toggle_linear(TangentIndex tangent) { Curve::TangentMode prev_mode = _curve_ref->get_point_right_mode(_selected_point); Curve::TangentMode mode = is_linear ? Curve::TANGENT_FREE : Curve::TANGENT_LINEAR; - ur->add_do_method(*_curve_ref, "set_point_right_mode", _selected_point, mode); - ur->add_undo_method(*_curve_ref, "set_point_right_mode", _selected_point, prev_mode); + undo_redo->add_do_method(*_curve_ref, "set_point_right_mode", _selected_point, mode); + undo_redo->add_undo_method(*_curve_ref, "set_point_right_mode", _selected_point, prev_mode); } - ur->commit_action(); + undo_redo->commit_action(); } void CurveEditor::set_selected_point(int index) { @@ -755,10 +752,10 @@ void CurveEditor::_draw() { float width = view_size.x - 60 * EDSCALE; if (_selected_point > 0 && _selected_point + 1 < curve.get_point_count()) { text_color.a *= 0.4; - draw_multiline_string(font, Vector2(50 * EDSCALE, font_height), TTR("Hold Shift to edit tangents individually"), HORIZONTAL_ALIGNMENT_LEFT, width, -1, font_size, text_color); + draw_multiline_string(font, Vector2(50 * EDSCALE, font_height), TTR("Hold Shift to edit tangents individually"), HORIZONTAL_ALIGNMENT_LEFT, width, font_size, -1, text_color); } else if (curve.get_point_count() == 0) { text_color.a *= 0.4; - draw_multiline_string(font, Vector2(50 * EDSCALE, font_height), TTR("Right click to add point"), HORIZONTAL_ALIGNMENT_LEFT, width, -1, font_size, text_color); + draw_multiline_string(font, Vector2(50 * EDSCALE, font_height), TTR("Right click to add point"), HORIZONTAL_ALIGNMENT_LEFT, width, font_size, -1, text_color); } } diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 997dc0b2b5..5f9446c3b1 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -93,7 +93,7 @@ Ref<Texture2D> EditorTexturePreviewPlugin::generate(const Ref<Resource> &p_from, return Ref<Texture2D>(); } - img = atlas->get_rect(atex->get_region()); + img = atlas->get_region(atex->get_region()); } else { Ref<Texture2D> tex = p_from; if (tex.is_valid()) { diff --git a/editor/plugins/gradient_editor.cpp b/editor/plugins/gradient_editor.cpp index 822f303d93..7039ada10a 100644 --- a/editor/plugins/gradient_editor.cpp +++ b/editor/plugins/gradient_editor.cpp @@ -99,7 +99,7 @@ void GradientEditor::_gradient_changed() { void GradientEditor::_ramp_changed() { editing = true; - Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Gradient Edited"), UndoRedo::MERGE_ENDS); undo_redo->add_do_method(gradient.ptr(), "set_offsets", get_offsets()); undo_redo->add_do_method(gradient.ptr(), "set_colors", get_colors()); diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp index e7ef65c32b..f2c46cc9e8 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.cpp +++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -30,6 +30,9 @@ #include "light_occluder_2d_editor_plugin.h" +#include "editor/editor_node.h" +#include "editor/editor_undo_redo_manager.h" + Ref<OccluderPolygon2D> LightOccluder2DEditor::_ensure_occluder() const { Ref<OccluderPolygon2D> occluder = node->get_occluder_polygon(); if (!occluder.is_valid()) { @@ -81,6 +84,7 @@ void LightOccluder2DEditor::_set_polygon(int p_idx, const Variant &p_polygon) co void LightOccluder2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) { Ref<OccluderPolygon2D> occluder = _ensure_occluder(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->add_do_method(occluder.ptr(), "set_polygon", p_polygon); undo_redo->add_undo_method(occluder.ptr(), "set_polygon", p_previous); } @@ -94,6 +98,7 @@ void LightOccluder2DEditor::_create_resource() { return; } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Create Occluder Polygon")); undo_redo->add_do_method(node, "set_occluder_polygon", Ref<OccluderPolygon2D>(memnew(OccluderPolygon2D))); undo_redo->add_undo_method(node, "set_occluder_polygon", Variant(Ref<RefCounted>())); diff --git a/editor/plugins/line_2d_editor_plugin.cpp b/editor/plugins/line_2d_editor_plugin.cpp index d73761d770..9182b23867 100644 --- a/editor/plugins/line_2d_editor_plugin.cpp +++ b/editor/plugins/line_2d_editor_plugin.cpp @@ -30,6 +30,9 @@ #include "line_2d_editor_plugin.h" +#include "editor/editor_node.h" +#include "editor/editor_undo_redo_manager.h" + Node2D *Line2DEditor::_get_node() const { return node; } @@ -52,6 +55,7 @@ void Line2DEditor::_set_polygon(int p_idx, const Variant &p_polygon) const { void Line2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) { Node2D *_node = _get_node(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->add_do_method(_node, "set_points", p_polygon); undo_redo->add_undo_method(_node, "set_points", p_previous); } diff --git a/editor/plugins/navigation_polygon_editor_plugin.cpp b/editor/plugins/navigation_polygon_editor_plugin.cpp index 8f3553b8cf..664e18f555 100644 --- a/editor/plugins/navigation_polygon_editor_plugin.cpp +++ b/editor/plugins/navigation_polygon_editor_plugin.cpp @@ -30,6 +30,9 @@ #include "navigation_polygon_editor_plugin.h" +#include "editor/editor_node.h" +#include "editor/editor_undo_redo_manager.h" + Ref<NavigationPolygon> NavigationPolygonEditor::_ensure_navpoly() const { Ref<NavigationPolygon> navpoly = node->get_navigation_polygon(); if (!navpoly.is_valid()) { @@ -73,6 +76,7 @@ void NavigationPolygonEditor::_set_polygon(int p_idx, const Variant &p_polygon) void NavigationPolygonEditor::_action_add_polygon(const Variant &p_polygon) { Ref<NavigationPolygon> navpoly = _ensure_navpoly(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->add_do_method(navpoly.ptr(), "add_outline", p_polygon); undo_redo->add_undo_method(navpoly.ptr(), "remove_outline", navpoly->get_outline_count()); undo_redo->add_do_method(navpoly.ptr(), "make_polygons_from_outlines"); @@ -81,6 +85,7 @@ void NavigationPolygonEditor::_action_add_polygon(const Variant &p_polygon) { void NavigationPolygonEditor::_action_remove_polygon(int p_idx) { Ref<NavigationPolygon> navpoly = _ensure_navpoly(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->add_do_method(navpoly.ptr(), "remove_outline", p_idx); undo_redo->add_undo_method(navpoly.ptr(), "add_outline_at_index", navpoly->get_outline(p_idx), p_idx); undo_redo->add_do_method(navpoly.ptr(), "make_polygons_from_outlines"); @@ -89,6 +94,7 @@ void NavigationPolygonEditor::_action_remove_polygon(int p_idx) { void NavigationPolygonEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) { Ref<NavigationPolygon> navpoly = _ensure_navpoly(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->add_do_method(navpoly.ptr(), "set_outline", p_idx, p_polygon); undo_redo->add_undo_method(navpoly.ptr(), "set_outline", p_idx, p_previous); undo_redo->add_do_method(navpoly.ptr(), "make_polygons_from_outlines"); @@ -104,6 +110,7 @@ void NavigationPolygonEditor::_create_resource() { return; } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Create Navigation Polygon")); undo_redo->add_do_method(node, "set_navigation_polygon", Ref<NavigationPolygon>(memnew(NavigationPolygon))); undo_redo->add_undo_method(node, "set_navigation_polygon", Variant(Ref<RefCounted>())); diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index 508e485a86..0af2a13df2 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -110,7 +110,9 @@ void EditorNode3DGizmo::clear() { collision_mesh = Ref<TriangleMesh>(); instances.clear(); handles.clear(); + handle_ids.clear(); secondary_handles.clear(); + secondary_handle_ids.clear(); } void EditorNode3DGizmo::redraw() { @@ -406,12 +408,15 @@ void EditorNode3DGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref< return; } - ERR_FAIL_COND(!spatial_node); + ERR_FAIL_NULL(spatial_node); + + Vector<Vector3> &handle_list = p_secondary ? secondary_handles : handles; + Vector<int> &id_list = p_secondary ? secondary_handle_ids : handle_ids; if (p_ids.is_empty()) { - ERR_FAIL_COND_MSG((!handles.is_empty() && !handle_ids.is_empty()) || (!secondary_handles.is_empty() && !secondary_handle_ids.is_empty()), "Fail"); + ERR_FAIL_COND_MSG(!id_list.is_empty(), "IDs must be provided for all handles, as handles with IDs already exist."); } else { - ERR_FAIL_COND_MSG(handles.size() != handle_ids.size() || secondary_handles.size() != secondary_handle_ids.size(), "Fail"); + ERR_FAIL_COND_MSG(p_handles.size() != p_ids.size(), "The number of IDs should be the same as the number of handles."); } bool is_current_hover_gizmo = Node3DEditor::get_singleton()->get_current_hover_gizmo() == this; @@ -464,19 +469,17 @@ void EditorNode3DGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref< } instances.push_back(ins); - Vector<Vector3> &h = p_secondary ? secondary_handles : handles; - int current_size = h.size(); - h.resize(current_size + p_handles.size()); + int current_size = handle_list.size(); + handle_list.resize(current_size + p_handles.size()); for (int i = 0; i < p_handles.size(); i++) { - h.write[current_size + i] = p_handles[i]; + handle_list.write[current_size + i] = p_handles[i]; } if (!p_ids.is_empty()) { - Vector<int> &ids = p_secondary ? secondary_handle_ids : handle_ids; - current_size = ids.size(); - ids.resize(current_size + p_ids.size()); + current_size = id_list.size(); + id_list.resize(current_size + p_ids.size()); for (int i = 0; i < p_ids.size(); i++) { - ids.write[current_size + i] = p_ids[i]; + id_list.write[current_size + i] = p_ids[i]; } } } @@ -1145,7 +1148,7 @@ int EditorNode3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_ } Vector<int> EditorNode3DGizmoPlugin::subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const { - TypedArray<Transform3D> frustum; + TypedArray<Plane> frustum; frustum.resize(p_frustum.size()); for (int i = 0; i < p_frustum.size(); i++) { frustum[i] = p_frustum[i]; diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 675f27f1f6..7febb50f5c 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -40,6 +40,7 @@ #include "editor/debugger/editor_debugger_node.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" +#include "editor/editor_undo_redo_manager.h" #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/node_3d_editor_gizmos.h" #include "editor/plugins/script_editor_plugin.h" @@ -1650,12 +1651,12 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } se->gizmo->commit_subgizmos(ids, restore, false); - spatial_editor->update_transform_gizmo(); } else { commit_transform(); } _edit.mode = TRANSFORM_NONE; set_message(""); + spatial_editor->update_transform_gizmo(); } surface->queue_redraw(); } @@ -2664,7 +2665,7 @@ void Node3DEditorViewport::_notification(int p_what) { return; } if (preview_node->is_inside_tree()) { - preview_node_pos = _get_instance_position(preview_node_viewport_pos); + preview_node_pos = spatial_editor->snap_point(_get_instance_position(preview_node_viewport_pos)); Transform3D preview_gl_transform = Transform3D(Basis(), preview_node_pos); preview_node->set_global_transform(preview_gl_transform); if (!preview_node->is_visible()) { @@ -2898,6 +2899,7 @@ void Node3DEditorViewport::_draw() { } void Node3DEditorViewport::_menu_option(int p_option) { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); switch (p_option) { case VIEW_TOP: { cursor.y_rot = 0; @@ -3748,24 +3750,45 @@ void Node3DEditorViewport::assign_pending_data_pointers(Node3D *p_preview_node, Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const { const float MAX_DISTANCE = 50.0; + const float FALLBACK_DISTANCE = 5.0; Vector3 world_ray = _get_ray(p_pos); Vector3 world_pos = _get_ray_pos(p_pos); - Vector3 point = world_pos + world_ray * MAX_DISTANCE; - PhysicsDirectSpaceState3D *ss = get_tree()->get_root()->get_world_3d()->get_direct_space_state(); PhysicsDirectSpaceState3D::RayParameters ray_params; ray_params.from = world_pos; - ray_params.to = world_pos + world_ray * MAX_DISTANCE; + ray_params.to = world_pos + world_ray * camera->get_far(); PhysicsDirectSpaceState3D::RayResult result; if (ss->intersect_ray(ray_params, result)) { - point = result.position; + return result.position; + } + + const bool is_orthogonal = camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL; + + // The XZ plane. + Vector3 intersection; + Plane plane(Vector3(0, 1, 0)); + if (plane.intersects_ray(world_pos, world_ray, &intersection)) { + if (is_orthogonal || world_pos.distance_to(intersection) <= MAX_DISTANCE) { + return intersection; + } + } + + // Plane facing the camera using fallback distance. + if (is_orthogonal) { + plane = Plane(world_ray, cursor.pos - world_ray * (cursor.distance - FALLBACK_DISTANCE)); + } else { + plane = Plane(world_ray, world_pos + world_ray * FALLBACK_DISTANCE); + } + if (plane.intersects_ray(world_pos, world_ray, &intersection)) { + return intersection; } - return point; + // Not likely, but just in case... + return world_pos + world_ray * FALLBACK_DISTANCE; } AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, bool p_exclude_top_level_transform) { @@ -4027,15 +4050,16 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po instantiated_scene->set_scene_file_path(ProjectSettings::get_singleton()->localize_path(path)); } - editor_data->get_undo_redo()->add_do_method(parent, "add_child", instantiated_scene, true); - editor_data->get_undo_redo()->add_do_method(instantiated_scene, "set_owner", EditorNode::get_singleton()->get_edited_scene()); - editor_data->get_undo_redo()->add_do_reference(instantiated_scene); - editor_data->get_undo_redo()->add_undo_method(parent, "remove_child", instantiated_scene); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); + undo_redo->add_do_method(parent, "add_child", instantiated_scene, true); + undo_redo->add_do_method(instantiated_scene, "set_owner", EditorNode::get_singleton()->get_edited_scene()); + undo_redo->add_do_reference(instantiated_scene); + undo_redo->add_undo_method(parent, "remove_child", instantiated_scene); String new_name = parent->validate_child_name(instantiated_scene); EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton(); - editor_data->get_undo_redo()->add_do_method(ed, "live_debug_instance_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent), path, new_name); - editor_data->get_undo_redo()->add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent)) + "/" + new_name)); + undo_redo->add_do_method(ed, "live_debug_instance_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent), path, new_name); + undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(parent)) + "/" + new_name)); Node3D *node3d = Object::cast_to<Node3D>(instantiated_scene); if (node3d) { @@ -4045,29 +4069,30 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po gl_transform = parent_node3d->get_global_gizmo_transform(); } - gl_transform.origin = spatial_editor->snap_point(preview_node_pos); + gl_transform.origin = preview_node_pos; gl_transform.basis *= node3d->get_transform().basis; - editor_data->get_undo_redo()->add_do_method(instantiated_scene, "set_global_transform", gl_transform); + undo_redo->add_do_method(instantiated_scene, "set_global_transform", gl_transform); } return true; } void Node3DEditorViewport::_perform_drop_data() { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); if (spatial_editor->get_preview_material_target().is_valid()) { GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(ObjectDB::get_instance(spatial_editor->get_preview_material_target())); MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(ObjectDB::get_instance(spatial_editor->get_preview_material_target())); if (mesh_instance && spatial_editor->get_preview_material_surface() != -1) { - editor_data->get_undo_redo()->create_action(vformat(TTR("Set Surface %d Override Material"), spatial_editor->get_preview_material_surface())); - editor_data->get_undo_redo()->add_do_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_material()); - editor_data->get_undo_redo()->add_undo_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material()); - editor_data->get_undo_redo()->commit_action(); + undo_redo->create_action(vformat(TTR("Set Surface %d Override Material"), spatial_editor->get_preview_material_surface())); + undo_redo->add_do_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_material()); + undo_redo->add_undo_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material()); + undo_redo->commit_action(); } else if (geometry_instance) { - editor_data->get_undo_redo()->create_action(TTR("Set Material Override")); - editor_data->get_undo_redo()->add_do_method(geometry_instance, "set_material_override", spatial_editor->get_preview_material()); - editor_data->get_undo_redo()->add_undo_method(geometry_instance, "set_material_override", spatial_editor->get_preview_reset_material()); - editor_data->get_undo_redo()->commit_action(); + undo_redo->create_action(TTR("Set Material Override")); + undo_redo->add_do_method(geometry_instance, "set_material_override", spatial_editor->get_preview_material()); + undo_redo->add_undo_method(geometry_instance, "set_material_override", spatial_editor->get_preview_reset_material()); + undo_redo->commit_action(); } _remove_preview_material(); @@ -4078,7 +4103,7 @@ void Node3DEditorViewport::_perform_drop_data() { Vector<String> error_files; - editor_data->get_undo_redo()->create_action(TTR("Create Node")); + undo_redo->create_action(TTR("Create Node")); for (int i = 0; i < selected_files.size(); i++) { String path = selected_files[i]; @@ -4096,7 +4121,7 @@ void Node3DEditorViewport::_perform_drop_data() { } } - editor_data->get_undo_redo()->commit_action(); + undo_redo->commit_action(); if (error_files.size() > 0) { String files_str; @@ -4129,11 +4154,13 @@ bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant ResourceLoader::get_recognized_extensions_for_type("Texture", &texture_extensions); for (int i = 0; i < files.size(); i++) { + String extension = files[i].get_extension().to_lower(); + // Check if dragged files with mesh or scene extension can be created at least once. - if (mesh_extensions.find(files[i].get_extension()) || - scene_extensions.find(files[i].get_extension()) || - material_extensions.find(files[i].get_extension()) || - texture_extensions.find(files[i].get_extension())) { + if (mesh_extensions.find(extension) || + scene_extensions.find(extension) || + material_extensions.find(extension) || + texture_extensions.find(extension)) { Ref<Resource> res = ResourceLoader::load(files[i]); if (res.is_null()) { continue; @@ -4262,6 +4289,7 @@ void Node3DEditorViewport::commit_transform() { TTRC("Translate"), TTRC("Scale"), }; + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(_transform_name[_edit.mode]); List<Node *> &selection = editor_selection->get_selected_node_list(); @@ -4667,9 +4695,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p _edit.gizmo_handle_secondary = false; index = p_index; - editor_data = SceneTreeDock::get_singleton()->get_editor_data(); editor_selection = EditorNode::get_singleton()->get_editor_selection(); - undo_redo = EditorNode::get_singleton()->get_undo_redo(); orthogonal = false; auto_orthogonal = false; @@ -5753,6 +5779,7 @@ void Node3DEditor::_xform_dialog_action() { t.basis.rotate(rotate); t.origin = translate; + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("XForm Dialog")); const List<Node *> &selection = editor_selection->get_selected_node_list(); @@ -5864,6 +5891,7 @@ void Node3DEditor::_update_camera_override_viewport(Object *p_viewport) { } void Node3DEditor::_menu_item_pressed(int p_option) { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); switch (p_option) { case MENU_TOOL_SELECT: case MENU_TOOL_MOVE: @@ -7049,6 +7077,7 @@ void Node3DEditor::_snap_selected_nodes_to_floor() { } if (snapped_to_floor) { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Snap Nodes to Floor")); // Perform snapping if at least one node can be snapped @@ -7118,6 +7147,7 @@ void Node3DEditor::_add_sun_to_scene(bool p_already_added_environment) { ERR_FAIL_COND(!base); Node *new_sun = preview_sun->duplicate(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Add Preview Sun to Scene")); undo_redo->add_do_method(base, "add_child", new_sun, true); // Move to the beginning of the scene tree since more "global" nodes @@ -7151,6 +7181,7 @@ void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) { new_env->set_camera_attributes(preview_environment->get_camera_attributes()->duplicate(true)); } + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Add Preview Environment to Scene")); undo_redo->add_do_method(base, "add_child", new_env, true); // Move to the beginning of the scene tree since more "global" nodes @@ -7290,14 +7321,6 @@ Vector<int> Node3DEditor::get_subgizmo_selection() { return ret; } -void Node3DEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) { - undo_redo = p_undo_redo; -} - -Ref<EditorUndoRedoManager> Node3DEditor::get_undo_redo() { - return undo_redo; -} - void Node3DEditor::add_control_to_menu_panel(Control *p_control) { context_menu_hbox->add_child(p_control); } @@ -7748,7 +7771,6 @@ Node3DEditor::Node3DEditor() { gizmo.scale = 1.0; viewport_environment = Ref<Environment>(memnew(Environment)); - undo_redo = EditorNode::get_singleton()->get_undo_redo(); VBoxContainer *vbc = this; custom_camera = nullptr; diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 7dbe153efd..5ea1bf6dc1 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -53,7 +53,6 @@ class Node3DEditorViewport; class SubViewportContainer; class DirectionalLight3D; class WorldEnvironment; -class EditorUndoRedoManager; class ViewportRotationControl : public Control { GDCLASS(ViewportRotationControl, Control); @@ -203,9 +202,7 @@ private: Node *target_node = nullptr; Point2 drop_pos; - EditorData *editor_data = nullptr; EditorSelection *editor_selection = nullptr; - Ref<EditorUndoRedoManager> undo_redo; CheckBox *preview_camera = nullptr; SubViewportContainer *subviewport_container = nullptr; @@ -686,7 +683,6 @@ private: HBoxContainer *context_menu_hbox = nullptr; void _generate_selection_boxes(); - Ref<EditorUndoRedoManager> undo_redo; int camera_override_viewport_id; @@ -835,9 +831,6 @@ public: Ref<Environment> get_viewport_environment() { return viewport_environment; } - void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo); - Ref<EditorUndoRedoManager> get_undo_redo(); - void add_control_to_menu_panel(Control *p_control); void remove_control_from_menu_panel(Control *p_control); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 3f8ca825c0..6218c887fb 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -32,8 +32,10 @@ #include "core/input/input_event.h" #include "core/math/geometry_2d.h" +#include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_undo_redo_manager.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "scene/2d/skeleton_2d.h" #include "scene/gui/menu_button.h" @@ -150,6 +152,7 @@ void Polygon2DEditor::_sync_bones() { Array new_bones = node->call("_get_bones"); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Sync Bones")); undo_redo->add_do_method(node, "_set_bones", new_bones); undo_redo->add_undo_method(node, "_set_bones", prev_bones); @@ -279,6 +282,7 @@ void Polygon2DEditor::_uv_edit_popup_hide() { } void Polygon2DEditor::_menu_option(int p_option) { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); switch (p_option) { case MODE_EDIT_UV: { if (node->get_texture().is_null()) { @@ -391,6 +395,7 @@ void Polygon2DEditor::_update_polygon_editing_state() { void Polygon2DEditor::_commit_action() { // Makes that undo/redoing actions made outside of the UV editor still affect its polygon. + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); undo_redo->add_do_method(CanvasItemEditor::get_singleton(), "update_viewport"); @@ -458,8 +463,9 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { mtx.columns[2] = -uv_draw_ofs; mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom)); - Ref<InputEventMouseButton> mb = p_input; + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); + Ref<InputEventMouseButton> mb = p_input; if (mb.is_valid()) { if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp index 21647d1b69..e35e794b24 100644 --- a/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/editor/plugins/resource_preloader_editor_plugin.cpp @@ -36,6 +36,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_undo_redo_manager.h" void ResourcePreloaderEditor::_notification(int p_what) { switch (p_what) { diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index e4f0192c64..4ff3919e9b 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -3892,7 +3892,7 @@ ScriptEditor::ScriptEditor() { vbc->add_child(disk_changed_list); disk_changed_list->set_v_size_flags(SIZE_EXPAND_FILL); - disk_changed->connect("confirmed", callable_mp(this, &ScriptEditor::reload_scripts)); + disk_changed->connect("confirmed", callable_mp(this, &ScriptEditor::reload_scripts).bind(false)); disk_changed->set_ok_button_text(TTR("Reload")); disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave"); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 456c28d887..2f80e41dd4 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -32,6 +32,7 @@ #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_undo_redo_manager.h" #include "editor/filesystem_dock.h" #include "editor/plugins/text_shader_editor.h" #include "editor/plugins/visual_shader_editor_plugin.h" @@ -225,7 +226,7 @@ void ShaderEditorPlugin::_close_shader(int p_index) { memdelete(c); edited_shaders.remove_at(p_index); _update_shader_list(); - EditorNode::get_singleton()->get_undo_redo()->clear_history(); // To prevent undo on deleted graphs. + EditorNode::get_undo_redo()->clear_history(); // To prevent undo on deleted graphs. } void ShaderEditorPlugin::_resource_saved(Object *obj) { diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index f0a08cb4f5..a7a8d526d0 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -86,8 +86,8 @@ void TextureRegionEditor::_region_draw() { mtx.scale_basis(Vector2(draw_zoom, draw_zoom)); RS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(), mtx); - edit_draw->draw_rect(Rect2(Point2(), base_tex->get_size()), Color(0.5, 0.5, 0.5, 0.5), false); - edit_draw->draw_texture(base_tex, Point2()); + edit_draw->draw_rect(Rect2(Point2(), preview_tex->get_size()), Color(0.5, 0.5, 0.5, 0.5), false); + edit_draw->draw_texture(preview_tex, Point2()); RS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(), Transform2D()); const Color color = get_theme_color(SNAME("mono_color"), SNAME("Editor")); @@ -905,6 +905,13 @@ void TextureRegionEditor::edit(Object *p_obj) { if (atlas_tex.is_valid()) { atlas_tex->disconnect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed)); } + + node_sprite_2d = nullptr; + node_sprite_3d = nullptr; + node_ninepatch = nullptr; + obj_styleBox = Ref<StyleBoxTexture>(nullptr); + atlas_tex = Ref<AtlasTexture>(nullptr); + if (p_obj) { node_sprite_2d = Object::cast_to<Sprite2D>(p_obj); node_sprite_3d = Object::cast_to<Sprite3D>(p_obj); @@ -926,13 +933,8 @@ void TextureRegionEditor::edit(Object *p_obj) { p_obj->connect("texture_changed", callable_mp(this, &TextureRegionEditor::_texture_changed)); } _edit_region(); - } else { - node_sprite_2d = nullptr; - node_sprite_3d = nullptr; - node_ninepatch = nullptr; - obj_styleBox = Ref<StyleBoxTexture>(nullptr); - atlas_tex = Ref<AtlasTexture>(nullptr); } + edit_draw->queue_redraw(); popup_centered_ratio(0.5); request_center = true; @@ -946,20 +948,80 @@ void TextureRegionEditor::_texture_changed() { } void TextureRegionEditor::_edit_region() { + CanvasItem::TextureFilter filter = CanvasItem::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS; + Ref<Texture2D> texture = nullptr; if (atlas_tex.is_valid()) { texture = atlas_tex->get_atlas(); } else if (node_sprite_2d) { texture = node_sprite_2d->get_texture(); + filter = node_sprite_2d->get_texture_filter_in_tree(); } else if (node_sprite_3d) { texture = node_sprite_3d->get_texture(); + + StandardMaterial3D::TextureFilter filter_3d = node_sprite_3d->get_texture_filter(); + + switch (filter_3d) { + case StandardMaterial3D::TEXTURE_FILTER_NEAREST: + filter = CanvasItem::TEXTURE_FILTER_NEAREST; + break; + case StandardMaterial3D::TEXTURE_FILTER_LINEAR: + filter = CanvasItem::TEXTURE_FILTER_LINEAR; + break; + case StandardMaterial3D::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: + filter = CanvasItem::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS; + break; + case StandardMaterial3D::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: + filter = CanvasItem::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS; + break; + case StandardMaterial3D::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: + filter = CanvasItem::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC; + break; + case StandardMaterial3D::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: + filter = CanvasItem::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC; + break; + default: + // fallback to project default + filter = CanvasItem::TEXTURE_FILTER_PARENT_NODE; + break; + } } else if (node_ninepatch) { texture = node_ninepatch->get_texture(); + filter = node_ninepatch->get_texture_filter_in_tree(); } else if (obj_styleBox.is_valid()) { texture = obj_styleBox->get_texture(); } + // occurs when get_texture_filter_in_tree reaches the scene root + if (filter == CanvasItem::TEXTURE_FILTER_PARENT_NODE) { + SubViewport *root = EditorNode::get_singleton()->get_scene_root(); + + if (root != nullptr) { + Viewport::DefaultCanvasItemTextureFilter filter_default = root->get_default_canvas_item_texture_filter(); + + // depending on default filter, set filter to match, otherwise fall back on nearest w/ mipmaps + switch (filter_default) { + case DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST: + filter = CanvasItem::TEXTURE_FILTER_NEAREST; + break; + case DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR: + filter = CanvasItem::TEXTURE_FILTER_LINEAR; + break; + case DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: + filter = CanvasItem::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS; + break; + case DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: + default: + filter = CanvasItem::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS; + break; + } + } else { + filter = CanvasItem::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS; + } + } + if (texture.is_null()) { + preview_tex->set_diffuse_texture(nullptr); _zoom_reset(); hscroll->hide(); vscroll->hide(); @@ -967,6 +1029,9 @@ void TextureRegionEditor::_edit_region() { return; } + preview_tex->set_texture_filter(filter); + preview_tex->set_diffuse_texture(texture); + if (cache_map.has(texture->get_rid())) { autoslice_cache = cache_map[texture->get_rid()]; autoslice_is_dirty = false; @@ -1002,6 +1067,8 @@ TextureRegionEditor::TextureRegionEditor() { atlas_tex = Ref<AtlasTexture>(nullptr); undo_redo = EditorNode::get_singleton()->get_undo_redo(); + preview_tex = Ref<CanvasTexture>(memnew(CanvasTexture)); + snap_step = Vector2(10, 10); snap_separation = Vector2(0, 0); snap_mode = SNAP_NONE; diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index e3bbaf49fc..7eda4f469f 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -86,6 +86,8 @@ class TextureRegionEditor : public AcceptDialog { Ref<StyleBoxTexture> obj_styleBox; Ref<AtlasTexture> atlas_tex; + Ref<CanvasTexture> preview_tex; + Rect2 rect; Rect2 rect_prev; float prev_margin = 0.0f; diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index f1dfba6f35..8bf99db43b 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -33,7 +33,9 @@ #include "tiles_editor_plugin.h" #include "editor/editor_inspector.h" +#include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_undo_redo_manager.h" #include "editor/progress_dialog.h" #include "editor/editor_node.h" @@ -1310,6 +1312,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven } void TileSetAtlasSourceEditor::_end_dragging() { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); switch (drag_type) { case DRAG_TYPE_CREATE_TILES: undo_redo->create_action(TTR("Create tiles")); @@ -1540,6 +1543,8 @@ HashMap<Vector2i, List<const PropertyInfo *>> TileSetAtlasSourceEditor::_group_p } void TileSetAtlasSourceEditor::_menu_option(int p_option) { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); + switch (p_option) { case TILE_DELETE: { List<PropertyInfo> list; @@ -2198,6 +2203,7 @@ void TileSetAtlasSourceEditor::_auto_create_tiles() { Vector2i separation = tile_set_atlas_source->get_separation(); Vector2i texture_region_size = tile_set_atlas_source->get_texture_region_size(); Size2i grid_size = tile_set_atlas_source->get_atlas_grid_size(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Create tiles in non-transparent texture regions")); for (int y = 0; y < grid_size.y; y++) { for (int x = 0; x < grid_size.x; x++) { @@ -2243,6 +2249,7 @@ void TileSetAtlasSourceEditor::_auto_remove_tiles() { Vector2i texture_region_size = tile_set_atlas_source->get_texture_region_size(); Vector2i grid_size = tile_set_atlas_source->get_atlas_grid_size(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Remove tiles in fully transparent texture regions")); List<PropertyInfo> list; @@ -2336,8 +2343,6 @@ void TileSetAtlasSourceEditor::_bind_methods() { } TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { - undo_redo = EditorNode::get_undo_redo(); - set_process_unhandled_key_input(true); set_process_internal(true); @@ -2366,7 +2371,6 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tile_proxy_object->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_proxy_object_changed)); tile_inspector = memnew(EditorInspector); - tile_inspector->set_undo_redo(undo_redo); tile_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); tile_inspector->edit(tile_proxy_object); tile_inspector->set_use_folding(true); @@ -2414,7 +2418,6 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { atlas_source_proxy_object->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_atlas_source_proxy_object_changed)); atlas_source_inspector = memnew(EditorInspector); - atlas_source_inspector->set_undo_redo(undo_redo); atlas_source_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); atlas_source_inspector->edit(atlas_source_proxy_object); middle_vbox_container->add_child(atlas_source_inspector); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h index badb702e29..8e217e359f 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.h +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h @@ -114,8 +114,6 @@ private: TileSetAtlasSource *tile_set_atlas_source = nullptr; int tile_set_atlas_source_id = TileSet::INVALID_SOURCE; - Ref<EditorUndoRedoManager> undo_redo; - bool tile_set_changed_needs_update = false; // -- Properties painting -- diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp index ef69326686..3b711a568e 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp @@ -35,6 +35,7 @@ #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_undo_redo_manager.h" #include "scene/gui/item_list.h" @@ -235,6 +236,7 @@ void TileSetScenesCollectionSourceEditor::_scenes_list_item_activated(int p_inde void TileSetScenesCollectionSourceEditor::_source_add_pressed() { int scene_id = tile_set_scenes_collection_source->get_next_scene_tile_id(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Add a Scene Tile")); undo_redo->add_do_method(tile_set_scenes_collection_source, "create_scene_tile", Ref<PackedScene>(), scene_id); undo_redo->add_undo_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id); @@ -249,6 +251,7 @@ void TileSetScenesCollectionSourceEditor::_source_delete_pressed() { ERR_FAIL_COND(selected_indices.size() <= 0); int scene_id = scene_tiles_list->get_item_metadata(selected_indices[0]); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Remove a Scene Tile")); undo_redo->add_do_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id); undo_redo->add_undo_method(tile_set_scenes_collection_source, "create_scene_tile", tile_set_scenes_collection_source->get_scene_tile_scene(scene_id), scene_id); @@ -400,6 +403,7 @@ void TileSetScenesCollectionSourceEditor::_drop_data_fw(const Point2 &p_point, c Ref<PackedScene> resource = ResourceLoader::load(files[i]); if (resource.is_valid()) { int scene_id = tile_set_scenes_collection_source->get_next_scene_tile_id(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Add a Scene Tile")); undo_redo->add_do_method(tile_set_scenes_collection_source, "create_scene_tile", resource, scene_id); undo_redo->add_undo_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id); @@ -453,8 +457,6 @@ void TileSetScenesCollectionSourceEditor::_bind_methods() { } TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() { - undo_redo = EditorNode::get_undo_redo(); - // -- Right side -- HSplitContainer *split_container_right_side = memnew(HSplitContainer); split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL); @@ -479,7 +481,6 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() { scenes_collection_source_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed)); scenes_collection_source_inspector = memnew(EditorInspector); - scenes_collection_source_inspector->set_undo_redo(undo_redo); scenes_collection_source_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); scenes_collection_source_inspector->edit(scenes_collection_source_proxy_object); middle_vbox_container->add_child(scenes_collection_source_inspector); @@ -495,7 +496,6 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() { tile_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1)); tile_inspector = memnew(EditorInspector); - tile_inspector->set_undo_redo(undo_redo); tile_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); tile_inspector->edit(tile_proxy_object); tile_inspector->set_use_folding(true); diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h index 0284b45c0f..7270cccbd8 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h @@ -37,8 +37,6 @@ #include "scene/gui/item_list.h" #include "scene/resources/tile_set.h" -class UndoRedo; - class TileSetScenesCollectionSourceEditor : public HBoxContainer { GDCLASS(TileSetScenesCollectionSourceEditor, HBoxContainer); @@ -97,8 +95,6 @@ private: TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr; int tile_set_source_id = -1; - Ref<EditorUndoRedoManager> undo_redo; - bool tile_set_scenes_collection_source_changed_needs_update = false; // Source inspector. diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index 336ce9e4c8..4fdfaed50e 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -430,7 +430,7 @@ void VersionControlEditorPlugin::_discard_file(String p_file_path, EditorVCSInte CHECK_PLUGIN_INITIALIZED(); EditorVCSInterface::get_singleton()->discard_file(p_file_path); } - // FIXIT: The project.godot file shows weird behaviour + // FIXIT: The project.godot file shows weird behavior EditorFileSystem::get_singleton()->update_file(p_file_path); } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 9b6ff894b9..c8f6a2431d 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -4062,7 +4062,7 @@ void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> p_input, bool type_changed = next_input_type != prev_input_type; - Ref<EditorUndoRedoManager> undo_redo_man = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo_man = EditorNode::get_undo_redo(); undo_redo_man->create_action(TTR("Visual Shader Input Type Changed")); undo_redo_man->add_do_method(p_input.ptr(), "set_input_name", p_name); @@ -4131,7 +4131,7 @@ void VisualShaderEditor::_parameter_ref_select_item(Ref<VisualShaderNodeParamete bool type_changed = p_parameter_ref->get_parameter_type_by_name(p_name) != p_parameter_ref->get_parameter_type_by_name(prev_name); - Ref<EditorUndoRedoManager> undo_redo_man = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo_man = EditorNode::get_undo_redo(); undo_redo_man->create_action(TTR("ParameterRef Name Changed")); undo_redo_man->add_do_method(p_parameter_ref.ptr(), "set_parameter_name", p_name); @@ -4175,7 +4175,7 @@ void VisualShaderEditor::_varying_select_item(Ref<VisualShaderNodeVarying> p_var bool is_getter = Ref<VisualShaderNodeVaryingGetter>(p_varying.ptr()).is_valid(); - Ref<EditorUndoRedoManager> undo_redo_man = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo_man = EditorNode::get_undo_redo(); undo_redo_man->create_action(TTR("Varying Name Changed")); undo_redo_man->add_do_method(p_varying.ptr(), "set_varying_name", p_name); @@ -5892,7 +5892,7 @@ public: return; } - Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); updating = true; undo_redo->create_action(TTR("Edit Visual Property:") + " " + p_property, UndoRedo::MERGE_ENDS); @@ -6094,7 +6094,7 @@ void EditorPropertyVisualShaderMode::_option_selected(int p_which) { return; } - Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Visual Shader Mode Changed")); //do is easy undo_redo->add_do_method(visual_shader.ptr(), "set_mode", p_which); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index f23b08409e..28111bed58 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -114,6 +114,7 @@ void ProjectSettingsEditor::_add_setting() { Variant value; Variant::construct(Variant::Type(type_box->get_selected_id()), value, nullptr, 0, ce); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Add Project Setting")); undo_redo->add_do_property(ps, setting, value); undo_redo->add_undo_property(ps, setting, ps->has_setting(setting) ? ps->get(setting) : Variant()); @@ -133,6 +134,7 @@ void ProjectSettingsEditor::_delete_setting() { Variant value = ps->get(setting); int order = ps->get_order(setting); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Delete Item")); undo_redo->add_do_method(ps, "clear", setting); @@ -221,9 +223,9 @@ void ProjectSettingsEditor::_select_type(Variant::Type p_type) { void ProjectSettingsEditor::shortcut_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); const Ref<InputEventKey> k = p_event; - if (k.is_valid() && k->is_pressed()) { bool handled = false; @@ -339,6 +341,7 @@ void ProjectSettingsEditor::_action_added(const String &p_name) { action["events"] = Array(); action["deadzone"] = 0.5f; + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Add Input Action")); undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name); @@ -354,6 +357,7 @@ void ProjectSettingsEditor::_action_edited(const String &p_name, const Dictionar const String property_name = "input/" + p_name; Dictionary old_val = GLOBAL_GET(property_name); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); if (old_val["deadzone"] != p_action["deadzone"]) { // Deadzone Changed undo_redo->create_action(TTR("Change Action deadzone")); @@ -390,6 +394,7 @@ void ProjectSettingsEditor::_action_removed(const String &p_name) { Dictionary old_val = GLOBAL_GET(property_name); int order = ProjectSettings::get_singleton()->get_order(property_name); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Erase Input Action")); undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", property_name); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", property_name, old_val); @@ -412,6 +417,7 @@ void ProjectSettingsEditor::_action_renamed(const String &p_old_name, const Stri int order = ProjectSettings::get_singleton()->get_order(old_property_name); Dictionary action = GLOBAL_GET(old_property_name); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Rename Input Action Event")); // Do: clear old, set new undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", old_property_name); @@ -441,6 +447,7 @@ void ProjectSettingsEditor::_action_reordered(const String &p_action_name, const HashMap<String, Variant> action_values; ProjectSettings::get_singleton()->get_property_list(&props); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Update Input Action Order")); for (const PropertyInfo &prop : props) { @@ -573,7 +580,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { set_title(TTR("Project Settings (project.godot)")); ps = ProjectSettings::get_singleton(); - undo_redo = p_data->get_undo_redo(); data = p_data; tab_container = memnew(TabContainer); @@ -632,7 +638,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { custom_properties->add_child(del_button); general_settings_inspector = memnew(SectionedInspector); - general_settings_inspector->get_inspector()->set_undo_redo(EditorNode::get_undo_redo()); general_settings_inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); general_settings_inspector->register_search_box(search_box); general_settings_inspector->get_inspector()->set_use_filter(true); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index ec10c76cb7..7f6dd1b692 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -42,7 +42,6 @@ #include "editor/shader_globals_editor.h" #include "scene/gui/tab_container.h" -class EditorUndoRedoManager; class FileSystemDock; class ProjectSettingsEditor : public AcceptDialog { @@ -78,7 +77,6 @@ class ProjectSettingsEditor : public AcceptDialog { ImportDefaultsEditor *import_defaults_editor = nullptr; EditorData *data = nullptr; - Ref<EditorUndoRedoManager> undo_redo; void _advanced_toggled(bool p_button_pressed); void _update_advanced(bool p_is_advanced); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 6a935b4f7b..64ac38aaa5 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -42,6 +42,7 @@ #include "editor/editor_paths.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_undo_redo_manager.h" #include "editor/multi_node_edit.h" #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/canvas_item_editor_plugin.h" @@ -267,7 +268,7 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base) return; } - Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Replace with Branch Scene")); Node *parent = base->get_parent(); @@ -3568,7 +3569,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec editor_selection->connect("selection_changed", callable_mp(this, &SceneTreeDock::_selection_changed)); - scene_tree->set_undo_redo(editor_data->get_undo_redo()); + scene_tree->set_as_scene_tree_dock(); scene_tree->set_editor_selection(editor_selection); create_dialog = memnew(CreateDialog); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index c8bc189106..46d3502a24 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -68,6 +68,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i Node *n = get_node(np); ERR_FAIL_COND(!n); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); if (p_id == BUTTON_SUBSCENE) { if (n == get_scene_node()) { if (n && n->get_scene_inherited_state().is_valid()) { @@ -167,6 +168,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i void SceneTreeEditor::_toggle_visible(Node *p_node) { if (p_node->has_method("is_visible") && p_node->has_method("set_visible")) { bool v = bool(p_node->call("is_visible")); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->add_do_method(p_node, "set_visible", !v); undo_redo->add_undo_method(p_node, "set_visible", v); } @@ -379,8 +381,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { item->set_tooltip_text(0, tooltip); } - if (can_open_instance && undo_redo.is_valid()) { //Show buttons only when necessary(SceneTreeDock) to avoid crashes - + if (can_open_instance && is_scene_tree_dock) { // Show buttons only when necessary (SceneTreeDock) to avoid crashes. if (!p_node->is_connected("script_changed", callable_mp(this, &SceneTreeEditor::_node_script_changed))) { p_node->connect("script_changed", callable_mp(this, &SceneTreeEditor::_node_script_changed).bind(p_node)); } @@ -997,11 +998,12 @@ void SceneTreeEditor::_renamed() { return; } - if (!undo_redo.is_valid()) { + if (!is_scene_tree_dock) { n->set_name(new_name); which->set_metadata(0, n->get_path()); emit_signal(SNAME("node_renamed")); } else { + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Rename Node")); emit_signal(SNAME("node_prerename"), n, new_name); undo_redo->add_do_method(this, "_rename_node", n->get_instance_id(), new_name); @@ -1045,8 +1047,8 @@ String SceneTreeEditor::get_filter_term_warning() { return filter_term_warning; } -void SceneTreeEditor::set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo) { - undo_redo = p_undo_redo; +void SceneTreeEditor::set_as_scene_tree_dock() { + is_scene_tree_dock = true; } void SceneTreeEditor::set_display_foreign_nodes(bool p_display) { diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h index dcdfead885..33ef5dbcb3 100644 --- a/editor/scene_tree_editor.h +++ b/editor/scene_tree_editor.h @@ -37,8 +37,6 @@ #include "scene/gui/dialogs.h" #include "scene/gui/tree.h" -class EditorUndoRedoManager; - class SceneTreeEditor : public Control { GDCLASS(SceneTreeEditor, Control); @@ -98,9 +96,9 @@ class SceneTreeEditor : public Control { bool can_open_instance; bool updating_tree = false; bool show_enabled_subscene = false; + bool is_scene_tree_dock = false; void _renamed(); - Ref<EditorUndoRedoManager> undo_redo; HashSet<Node *> marked; bool marked_selectable = false; @@ -145,7 +143,7 @@ public: String get_filter() const; String get_filter_term_warning(); - void set_undo_redo(Ref<EditorUndoRedoManager> p_undo_redo); + void set_as_scene_tree_dock(); void set_display_foreign_nodes(bool p_display); void set_marked(const HashSet<Node *> &p_marked, bool p_selectable = false, bool p_children_selectable = true); diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp index 6967536692..596b3eefba 100644 --- a/editor/shader_globals_editor.cpp +++ b/editor/shader_globals_editor.cpp @@ -86,7 +86,7 @@ protected: return false; } - Ref<EditorUndoRedoManager> undo_redo = EditorNode::get_undo_redo(); + Ref<EditorUndoRedoManager> &undo_redo = EditorNode::get_undo_redo(); undo_redo->create_action(TTR("Set Shader Global Variable")); undo_redo->add_do_method(RS::get_singleton(), "global_shader_parameter_set", p_name, p_value); |