diff options
Diffstat (limited to 'editor')
156 files changed, 1605 insertions, 992 deletions
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index 9b1ff78727..3b9d6c18eb 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "editor/action_map_editor.h" + #include "editor/editor_scale.h" #include "editor/event_listener_line_edit.h" #include "editor/input_event_configuration_dialog.h" @@ -395,15 +396,9 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info action_tree->clear(); TreeItem *root = action_tree->create_item(); - int uneditable_count = 0; - for (int i = 0; i < actions_cache.size(); i++) { ActionInfo action_info = actions_cache[i]; - if (!action_info.editable) { - uneditable_count++; - } - const Array events = action_info.action["events"]; if (!_should_display_action(action_info.name, events)) { continue; diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h index d56ee6f9eb..ad9980c4ef 100644 --- a/editor/action_map_editor.h +++ b/editor/action_map_editor.h @@ -47,8 +47,8 @@ class ActionMapEditor : public Control { public: struct ActionInfo { - String name = String(); - Dictionary action = Dictionary(); + String name; + Dictionary action; Ref<Texture2D> icon = Ref<Texture2D>(); bool editable = true; @@ -67,8 +67,8 @@ private: // Storing which action/event is currently being edited in the InputEventConfigurationDialog. - Dictionary current_action = Dictionary(); - String current_action_name = String(); + Dictionary current_action; + String current_action_name; int current_action_event_index = -1; // Popups diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 44ecda103e..0c8176a44b 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -3613,7 +3613,7 @@ void AnimationTrackEditor::_animation_track_remove_request(int p_track, Ref<Anim } int idx = p_track; if (idx >= 0 && idx < p_from_animation->get_track_count()) { - undo_redo->create_action(TTR("Remove Anim Track")); + undo_redo->create_action(TTR("Remove Anim Track"), UndoRedo::MERGE_DISABLE, p_from_animation.ptr()); // Remove corresponding reset tracks if they are no longer needed. AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player(); diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp index b9e52ad7ad..b84e58125e 100644 --- a/editor/audio_stream_preview.cpp +++ b/editor/audio_stream_preview.cpp @@ -42,6 +42,10 @@ float AudioStreamPreview::get_max(float p_time, float p_time_next) const { } int max = preview.size() / 2; + if (max == 0) { + return 0; + } + int time_from = p_time / length * max; int time_to = p_time_next / length * max; time_from = CLAMP(time_from, 0, max - 1); @@ -69,6 +73,10 @@ float AudioStreamPreview::get_min(float p_time, float p_time_next) const { } int max = preview.size() / 2; + if (max == 0) { + return 0; + } + int time_from = p_time / length * max; int time_to = p_time_next / length * max; time_from = CLAMP(time_from, 0, max - 1); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 212a46cb62..510dc345bf 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1872,7 +1872,7 @@ void CodeTextEditor::_apply_settings_change() { } fc->set_opentype_features(ftrs); } break; - default: { // Default. + default: { // Enabled. Dictionary ftrs; ftrs[TS->name_to_tag("calt")] = 1; fc->set_opentype_features(ftrs); @@ -2106,7 +2106,7 @@ CodeTextEditor::CodeTextEditor() { } fc->set_opentype_features(ftrs); } break; - default: { // Default. + default: { // Enabled. Dictionary ftrs; ftrs[TS->name_to_tag("calt")] = 1; fc->set_opentype_features(ftrs); 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/create_dialog.cpp b/editor/create_dialog.cpp index 6142856f75..cdc3e220fb 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -284,12 +284,12 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String bool can_instantiate = (p_type_category == TypeCategory::CPP_TYPE && ClassDB::can_instantiate(p_type)) || p_type_category == TypeCategory::OTHER_TYPE; - if (!can_instantiate) { - r_item->set_custom_color(0, search_options->get_theme_color(SNAME("disabled_font_color"), SNAME("Editor"))); + if (can_instantiate && !ClassDB::is_virtual(p_type)) { + r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, icon_fallback)); + } else { r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, "NodeDisabled")); + r_item->set_custom_color(0, search_options->get_theme_color(SNAME("disabled_font_color"), SNAME("Editor"))); r_item->set_selectable(0, false); - } else { - r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type, icon_fallback)); } bool is_deprecated = EditorHelp::get_doc_data()->class_list[p_type].is_deprecated; @@ -752,8 +752,7 @@ CreateDialog::CreateDialog() { favorites->connect("cell_selected", callable_mp(this, &CreateDialog::_favorite_selected)); favorites->connect("item_activated", callable_mp(this, &CreateDialog::_favorite_activated)); favorites->add_theme_constant_override("draw_guides", 1); - // Cannot forward drag data to a non control, must be fixed. - //favorites->set_drag_forwarding(this); + favorites->set_drag_forwarding(this); fav_vb->add_margin_child(TTR("Favorites:"), favorites, true); VBoxContainer *rec_vb = memnew(VBoxContainer); diff --git a/editor/debugger/editor_debugger_inspector.cpp b/editor/debugger/editor_debugger_inspector.cpp index 371aaf8617..c64f23aba0 100644 --- a/editor/debugger/editor_debugger_inspector.cpp +++ b/editor/debugger/editor_debugger_inspector.cpp @@ -230,7 +230,7 @@ void EditorDebuggerInspector::add_stack_variable(const Array &p_array) { Variant v = var.value; PropertyHint h = PROPERTY_HINT_NONE; - String hs = String(); + String hs; if (v.get_type() == Variant::OBJECT) { v = Object::cast_to<EncodedObjectAsID>(v)->get_object_id(); diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index 68aff328ed..49fbaa81bc 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -119,8 +119,8 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() { } if (!debugger_plugins.is_empty()) { - for (const Ref<Script> &i : debugger_plugins) { - node->add_debugger_plugin(i); + for (Ref<EditorDebuggerPlugin> plugin : debugger_plugins) { + plugin->create_session(node); } } @@ -723,22 +723,36 @@ EditorDebuggerNode::CameraOverride EditorDebuggerNode::get_camera_override() { return camera_override; } -void EditorDebuggerNode::add_debugger_plugin(const Ref<Script> &p_script) { - ERR_FAIL_COND_MSG(debugger_plugins.has(p_script), "Debugger plugin already exists."); - ERR_FAIL_COND_MSG(p_script.is_null(), "Debugger plugin script is null"); - ERR_FAIL_COND_MSG(p_script->get_instance_base_type() == StringName(), "Debugger plugin script has error."); - ERR_FAIL_COND_MSG(String(p_script->get_instance_base_type()) != "EditorDebuggerPlugin", "Base type of debugger plugin is not 'EditorDebuggerPlugin'."); - ERR_FAIL_COND_MSG(!p_script->is_tool(), "Debugger plugin script is not in tool mode."); - debugger_plugins.insert(p_script); +void EditorDebuggerNode::add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin) { + ERR_FAIL_COND_MSG(p_plugin.is_null(), "Debugger plugin is null."); + ERR_FAIL_COND_MSG(debugger_plugins.has(p_plugin), "Debugger plugin already exists."); + debugger_plugins.insert(p_plugin); + + Ref<EditorDebuggerPlugin> plugin = p_plugin; for (int i = 0; get_debugger(i); i++) { - get_debugger(i)->add_debugger_plugin(p_script); + plugin->create_session(get_debugger(i)); } } -void EditorDebuggerNode::remove_debugger_plugin(const Ref<Script> &p_script) { - ERR_FAIL_COND_MSG(!debugger_plugins.has(p_script), "Debugger plugin doesn't exists."); - debugger_plugins.erase(p_script); - for (int i = 0; get_debugger(i); i++) { - get_debugger(i)->remove_debugger_plugin(p_script); +void EditorDebuggerNode::remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin) { + ERR_FAIL_COND_MSG(p_plugin.is_null(), "Debugger plugin is null."); + ERR_FAIL_COND_MSG(!debugger_plugins.has(p_plugin), "Debugger plugin doesn't exists."); + debugger_plugins.erase(p_plugin); + Ref<EditorDebuggerPlugin>(p_plugin)->clear(); +} + +bool EditorDebuggerNode::plugins_capture(ScriptEditorDebugger *p_debugger, const String &p_message, const Array &p_data) { + int session_index = tabs->get_tab_idx_from_control(p_debugger); + ERR_FAIL_COND_V(session_index < 0, false); + int colon_index = p_message.find_char(':'); + ERR_FAIL_COND_V_MSG(colon_index < 1, false, "Invalid message received."); + + const String cap = p_message.substr(0, colon_index); + bool parsed = false; + for (Ref<EditorDebuggerPlugin> plugin : debugger_plugins) { + if (plugin->has_capture(cap)) { + parsed |= plugin->capture(p_message, p_data, session_index); + } } + return parsed; } diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h index 305f18a652..259efeb47b 100644 --- a/editor/debugger/editor_debugger_node.h +++ b/editor/debugger/editor_debugger_node.h @@ -36,6 +36,7 @@ class Button; class DebugAdapterParser; +class EditorDebuggerPlugin; class EditorDebuggerTree; class EditorDebuggerRemoteObject; class MenuButton; @@ -113,7 +114,7 @@ private: CameraOverride camera_override = OVERRIDE_NONE; HashMap<Breakpoint, bool, Breakpoint> breakpoints; - HashSet<Ref<Script>> debugger_plugins; + HashSet<Ref<EditorDebuggerPlugin>> debugger_plugins; ScriptEditorDebugger *_add_debugger(); EditorDebuggerRemoteObject *get_inspected_remote_object(); @@ -205,8 +206,9 @@ public: Error start(const String &p_uri = "tcp://"); void stop(); - void add_debugger_plugin(const Ref<Script> &p_script); - void remove_debugger_plugin(const Ref<Script> &p_script); + bool plugins_capture(ScriptEditorDebugger *p_debugger, const String &p_message, const Array &p_data); + void add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin); + void remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin); }; #endif // EDITOR_DEBUGGER_NODE_H diff --git a/editor/debugger/editor_network_profiler.cpp b/editor/debugger/editor_network_profiler.cpp deleted file mode 100644 index 8c18eba71d..0000000000 --- a/editor/debugger/editor_network_profiler.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/*************************************************************************/ -/* editor_network_profiler.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 "editor_network_profiler.h" - -#include "core/os/os.h" -#include "editor/editor_scale.h" -#include "editor/editor_settings.h" - -void EditorNetworkProfiler::_bind_methods() { - ADD_SIGNAL(MethodInfo("enable_profiling", PropertyInfo(Variant::BOOL, "enable"))); -} - -void EditorNetworkProfiler::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: - case NOTIFICATION_THEME_CHANGED: { - activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons"))); - clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons"))); - incoming_bandwidth_text->set_right_icon(get_theme_icon(SNAME("ArrowDown"), SNAME("EditorIcons"))); - outgoing_bandwidth_text->set_right_icon(get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons"))); - - // This needs to be done here to set the faded color when the profiler is first opened - incoming_bandwidth_text->add_theme_color_override("font_uneditable_color", get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, 0.5)); - outgoing_bandwidth_text->add_theme_color_override("font_uneditable_color", get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, 0.5)); - } break; - } -} - -void EditorNetworkProfiler::_update_frame() { - counters_display->clear(); - - TreeItem *root = counters_display->create_item(); - - for (const KeyValue<ObjectID, SceneDebugger::RPCNodeInfo> &E : nodes_data) { - TreeItem *node = counters_display->create_item(root); - - for (int j = 0; j < counters_display->get_columns(); ++j) { - node->set_text_alignment(j, j > 0 ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT); - } - - node->set_text(0, E.value.node_path); - node->set_text(1, E.value.incoming_rpc == 0 ? "-" : itos(E.value.incoming_rpc)); - node->set_text(2, E.value.outgoing_rpc == 0 ? "-" : itos(E.value.outgoing_rpc)); - } -} - -void EditorNetworkProfiler::_activate_pressed() { - if (activate->is_pressed()) { - activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"))); - activate->set_text(TTR("Stop")); - } else { - activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons"))); - activate->set_text(TTR("Start")); - } - emit_signal(SNAME("enable_profiling"), activate->is_pressed()); -} - -void EditorNetworkProfiler::_clear_pressed() { - nodes_data.clear(); - set_bandwidth(0, 0); - if (frame_delay->is_stopped()) { - frame_delay->set_wait_time(0.1); - frame_delay->start(); - } -} - -void EditorNetworkProfiler::add_node_frame_data(const SceneDebugger::RPCNodeInfo p_frame) { - if (!nodes_data.has(p_frame.node)) { - nodes_data.insert(p_frame.node, p_frame); - } else { - nodes_data[p_frame.node].incoming_rpc += p_frame.incoming_rpc; - nodes_data[p_frame.node].outgoing_rpc += p_frame.outgoing_rpc; - } - - if (frame_delay->is_stopped()) { - frame_delay->set_wait_time(0.1); - frame_delay->start(); - } -} - -void EditorNetworkProfiler::set_bandwidth(int p_incoming, int p_outgoing) { - incoming_bandwidth_text->set_text(vformat(TTR("%s/s"), String::humanize_size(p_incoming))); - outgoing_bandwidth_text->set_text(vformat(TTR("%s/s"), String::humanize_size(p_outgoing))); - - // Make labels more prominent when the bandwidth is greater than 0 to attract user attention - incoming_bandwidth_text->add_theme_color_override( - "font_uneditable_color", - get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, p_incoming > 0 ? 1 : 0.5)); - outgoing_bandwidth_text->add_theme_color_override( - "font_uneditable_color", - get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, p_outgoing > 0 ? 1 : 0.5)); -} - -bool EditorNetworkProfiler::is_profiling() { - return activate->is_pressed(); -} - -EditorNetworkProfiler::EditorNetworkProfiler() { - HBoxContainer *hb = memnew(HBoxContainer); - hb->add_theme_constant_override("separation", 8 * EDSCALE); - add_child(hb); - - activate = memnew(Button); - activate->set_toggle_mode(true); - activate->set_text(TTR("Start")); - activate->connect("pressed", callable_mp(this, &EditorNetworkProfiler::_activate_pressed)); - hb->add_child(activate); - - clear_button = memnew(Button); - clear_button->set_text(TTR("Clear")); - clear_button->connect("pressed", callable_mp(this, &EditorNetworkProfiler::_clear_pressed)); - hb->add_child(clear_button); - - hb->add_spacer(); - - Label *lb = memnew(Label); - lb->set_text(TTR("Down")); - hb->add_child(lb); - - incoming_bandwidth_text = memnew(LineEdit); - incoming_bandwidth_text->set_editable(false); - incoming_bandwidth_text->set_custom_minimum_size(Size2(120, 0) * EDSCALE); - incoming_bandwidth_text->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); - hb->add_child(incoming_bandwidth_text); - - Control *down_up_spacer = memnew(Control); - down_up_spacer->set_custom_minimum_size(Size2(30, 0) * EDSCALE); - hb->add_child(down_up_spacer); - - lb = memnew(Label); - lb->set_text(TTR("Up")); - hb->add_child(lb); - - outgoing_bandwidth_text = memnew(LineEdit); - outgoing_bandwidth_text->set_editable(false); - outgoing_bandwidth_text->set_custom_minimum_size(Size2(120, 0) * EDSCALE); - outgoing_bandwidth_text->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); - hb->add_child(outgoing_bandwidth_text); - - // Set initial texts in the incoming/outgoing bandwidth labels - set_bandwidth(0, 0); - - counters_display = memnew(Tree); - counters_display->set_custom_minimum_size(Size2(300, 0) * EDSCALE); - counters_display->set_v_size_flags(SIZE_EXPAND_FILL); - counters_display->set_hide_folding(true); - counters_display->set_hide_root(true); - counters_display->set_columns(3); - counters_display->set_column_titles_visible(true); - counters_display->set_column_title(0, TTR("Node")); - counters_display->set_column_expand(0, true); - counters_display->set_column_clip_content(0, true); - counters_display->set_column_custom_minimum_width(0, 60 * EDSCALE); - counters_display->set_column_title(1, TTR("Incoming RPC")); - counters_display->set_column_expand(1, false); - counters_display->set_column_clip_content(1, true); - counters_display->set_column_custom_minimum_width(1, 120 * EDSCALE); - counters_display->set_column_title(2, TTR("Outgoing RPC")); - counters_display->set_column_expand(2, false); - counters_display->set_column_clip_content(2, true); - counters_display->set_column_custom_minimum_width(2, 120 * EDSCALE); - add_child(counters_display); - - frame_delay = memnew(Timer); - frame_delay->set_wait_time(0.1); - frame_delay->set_one_shot(true); - add_child(frame_delay); - frame_delay->connect("timeout", callable_mp(this, &EditorNetworkProfiler::_update_frame)); -} diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp index e2fd462f3a..071eb583c0 100644 --- a/editor/debugger/editor_performance_profiler.cpp +++ b/editor/debugger/editor_performance_profiler.cpp @@ -234,6 +234,7 @@ TreeItem *EditorPerformanceProfiler::_get_monitor_base(const StringName &p_base_ base->set_editable(0, false); base->set_selectable(0, false); base->set_expand_right(0, true); + base->set_custom_font(0, get_theme_font(SNAME("bold"), SNAME("EditorFonts"))); base_map.insert(p_base_name, base); return base; } diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index f1f34b8ebb..fd77ad784a 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -37,7 +37,6 @@ #include "core/string/ustring.h" #include "core/version.h" #include "editor/debugger/debug_adapter/debug_adapter_protocol.h" -#include "editor/debugger/editor_network_profiler.h" #include "editor/debugger/editor_performance_profiler.h" #include "editor/debugger/editor_profiler.h" #include "editor/debugger/editor_visual_profiler.h" @@ -52,6 +51,7 @@ #include "editor/plugins/node_3d_editor_plugin.h" #include "main/performance.h" #include "scene/3d/camera_3d.h" +#include "scene/debugger/scene_debugger.h" #include "scene/gui/dialogs.h" #include "scene/gui/label.h" #include "scene/gui/line_edit.h" @@ -713,17 +713,6 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da profiler->add_frame_metric(metric, true); } - } else if (p_msg == "multiplayer:rpc") { - SceneDebugger::RPCProfilerFrame frame; - frame.deserialize(p_data); - for (int i = 0; i < frame.infos.size(); i++) { - network_profiler->add_node_frame_data(frame.infos[i]); - } - - } else if (p_msg == "multiplayer:bandwidth") { - ERR_FAIL_COND(p_data.size() < 2); - network_profiler->set_bandwidth(p_data[0], p_data[1]); - } else if (p_msg == "request_quit") { emit_signal(SNAME("stop_requested")); _stop_and_notify(); @@ -741,22 +730,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da int colon_index = p_msg.find_char(':'); ERR_FAIL_COND_MSG(colon_index < 1, "Invalid message received"); - bool parsed = false; - const String cap = p_msg.substr(0, colon_index); - HashMap<StringName, Callable>::Iterator element = captures.find(cap); - if (element) { - Callable &c = element->value; - ERR_FAIL_COND_MSG(c.is_null(), "Invalid callable registered: " + cap); - Variant cmd = p_msg.substr(colon_index + 1), cmd_data = p_data; - const Variant *args[2] = { &cmd, &cmd_data }; - Variant retval; - Callable::CallError err; - c.callp(args, 2, retval, err); - ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'capture' to callable: " + Variant::get_callable_error_text(c, args, 2, err)); - ERR_FAIL_COND_MSG(retval.get_type() != Variant::BOOL, "Error calling 'capture' to callable: " + String(c) + ". Return type is not bool."); - parsed = retval; - } - + bool parsed = EditorDebuggerNode::get_singleton()->plugins_capture(this, p_msg, p_data); if (!parsed) { WARN_PRINT("unknown message " + p_msg); } @@ -982,10 +956,6 @@ void ScriptEditorDebugger::_profiler_activate(bool p_enable, int p_type) { Array msg_data; msg_data.push_back(p_enable); switch (p_type) { - case PROFILER_NETWORK: - _put_msg("profiler:multiplayer", msg_data); - _put_msg("profiler:rpc", msg_data); - break; case PROFILER_VISUAL: _put_msg("profiler:visual", msg_data); break; @@ -1658,41 +1628,25 @@ void ScriptEditorDebugger::_bind_methods() { ADD_SIGNAL(MethodInfo("errors_cleared")); } -void ScriptEditorDebugger::add_debugger_plugin(const Ref<Script> &p_script) { - if (!debugger_plugins.has(p_script)) { - EditorDebuggerPlugin *plugin = memnew(EditorDebuggerPlugin()); - plugin->attach_debugger(this); - plugin->set_script(p_script); - tabs->add_child(plugin); - debugger_plugins.insert(p_script, plugin); - } +void ScriptEditorDebugger::add_debugger_tab(Control *p_control) { + tabs->add_child(p_control); } -void ScriptEditorDebugger::remove_debugger_plugin(const Ref<Script> &p_script) { - if (debugger_plugins.has(p_script)) { - tabs->remove_child(debugger_plugins[p_script]); - debugger_plugins[p_script]->detach_debugger(false); - memdelete(debugger_plugins[p_script]); - debugger_plugins.erase(p_script); - } +void ScriptEditorDebugger::remove_debugger_tab(Control *p_control) { + int idx = tabs->get_tab_idx_from_control(p_control); + ERR_FAIL_COND(idx < 0); + p_control->queue_free(); } void ScriptEditorDebugger::send_message(const String &p_message, const Array &p_args) { _put_msg(p_message, p_args); } -void ScriptEditorDebugger::register_message_capture(const StringName &p_name, const Callable &p_callable) { - ERR_FAIL_COND_MSG(has_capture(p_name), "Capture already registered: " + p_name); - captures.insert(p_name, p_callable); -} - -void ScriptEditorDebugger::unregister_message_capture(const StringName &p_name) { - ERR_FAIL_COND_MSG(!has_capture(p_name), "Capture not registered: " + p_name); - captures.erase(p_name); -} - -bool ScriptEditorDebugger::has_capture(const StringName &p_name) { - return captures.has(p_name); +void ScriptEditorDebugger::toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data) { + Array msg_data; + msg_data.push_back(p_enable); + msg_data.append_array(p_data); + _put_msg("profiler:" + p_profiler, msg_data); } ScriptEditorDebugger::ScriptEditorDebugger() { @@ -1904,13 +1858,6 @@ ScriptEditorDebugger::ScriptEditorDebugger() { visual_profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate).bind(PROFILER_VISUAL)); } - { //network profiler - network_profiler = memnew(EditorNetworkProfiler); - network_profiler->set_name(TTR("Network Profiler")); - tabs->add_child(network_profiler); - network_profiler->connect("enable_profiling", callable_mp(this, &ScriptEditorDebugger::_profiler_activate).bind(PROFILER_NETWORK)); - } - { //monitors performance_profiler = memnew(EditorPerformanceProfiler); tabs->add_child(performance_profiler); diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h index aa0a50ff03..22d6e48294 100644 --- a/editor/debugger/script_editor_debugger.h +++ b/editor/debugger/script_editor_debugger.h @@ -50,7 +50,6 @@ class ItemList; class EditorProfiler; class EditorFileDialog; class EditorVisualProfiler; -class EditorNetworkProfiler; class EditorPerformanceProfiler; class SceneDebuggerTree; class EditorDebuggerPlugin; @@ -72,7 +71,6 @@ private: }; enum ProfilerType { - PROFILER_NETWORK, PROFILER_VISUAL, PROFILER_SCRIPTS_SERVERS }; @@ -151,7 +149,6 @@ private: EditorProfiler *profiler = nullptr; EditorVisualProfiler *visual_profiler = nullptr; - EditorNetworkProfiler *network_profiler = nullptr; EditorPerformanceProfiler *performance_profiler = nullptr; OS::ProcessID remote_pid = 0; @@ -163,10 +160,6 @@ private: EditorDebuggerNode::CameraOverride camera_override; - HashMap<Ref<Script>, EditorDebuggerPlugin *> debugger_plugins; - - HashMap<StringName, Callable> captures; - void _stack_dump_frame_selected(); void _file_selected(const String &p_file); @@ -286,14 +279,11 @@ public: virtual Size2 get_minimum_size() const override; - void add_debugger_plugin(const Ref<Script> &p_script); - void remove_debugger_plugin(const Ref<Script> &p_script); + void add_debugger_tab(Control *p_control); + void remove_debugger_tab(Control *p_control); void send_message(const String &p_message, const Array &p_args); - - void register_message_capture(const StringName &p_name, const Callable &p_callable); - void unregister_message_capture(const StringName &p_name); - bool has_capture(const StringName &p_name); + void toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data); ScriptEditorDebugger(); ~ScriptEditorDebugger(); diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index 7d6eb186dc..14a2640e63 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -335,7 +335,7 @@ static Variant get_documentation_default_value(const StringName &p_class_name, c Variant default_value = Variant(); r_default_value_valid = false; - if (ClassDB::can_instantiate(p_class_name)) { + if (ClassDB::can_instantiate(p_class_name) && !ClassDB::is_virtual(p_class_name)) { // Keep this condition in sync with ClassDB::class_get_default_property_value. default_value = ClassDB::class_get_default_property_value(p_class_name, p_property_name, &r_default_value_valid); } else { // Cannot get default value of classes that can't be instantiated 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_audio_buses.h b/editor/editor_audio_buses.h index 436b391ccd..97e94089cc 100644 --- a/editor/editor_audio_buses.h +++ b/editor/editor_audio_buses.h @@ -47,6 +47,7 @@ #include "scene/gui/tree.h" class EditorAudioBuses; +class EditorFileDialog; class EditorAudioBus : public PanelContainer { GDCLASS(EditorAudioBus, PanelContainer); 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_build_profile.h b/editor/editor_build_profile.h index 606c415429..9624f7e44b 100644 --- a/editor/editor_build_profile.h +++ b/editor/editor_build_profile.h @@ -117,6 +117,7 @@ public: VARIANT_ENUM_CAST(EditorBuildProfile::BuildOption) VARIANT_ENUM_CAST(EditorBuildProfile::BuildOptionCategory) +class EditorFileDialog; class EditorFileSystemDirectory; class EditorBuildProfileManager : public AcceptDialog { diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp index a0913265eb..3f93fa1f41 100644 --- a/editor/editor_command_palette.cpp +++ b/editor/editor_command_palette.cpp @@ -226,7 +226,7 @@ void EditorCommandPalette::_add_command(String p_command_name, String p_key_name void EditorCommandPalette::execute_command(String &p_command_key) { ERR_FAIL_COND_MSG(!commands.has(p_command_key), p_command_key + " not found."); commands[p_command_key].last_used = OS::get_singleton()->get_unix_time(); - commands[p_command_key].callable.call_deferredp(nullptr, 0); + commands[p_command_key].callable.call_deferred(); _save_history(); } 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_feature_profile.cpp b/editor/editor_feature_profile.cpp index 9549ffb09b..49fb16a095 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -47,6 +47,7 @@ const char *EditorFeatureProfile::feature_names[FEATURE_MAX] = { TTRC("Node Dock"), TTRC("FileSystem Dock"), TTRC("Import Dock"), + TTRC("History Dock"), }; const char *EditorFeatureProfile::feature_descriptions[FEATURE_MAX] = { @@ -57,6 +58,7 @@ const char *EditorFeatureProfile::feature_descriptions[FEATURE_MAX] = { TTRC("Allows to work with signals and groups of the node selected in the Scene dock."), TTRC("Allows to browse the local file system via a dedicated dock."), TTRC("Allows to configure import settings for individual assets. Requires the FileSystem dock to function."), + TTRC("Provides an overview of the editor's and each scene's undo history."), }; const char *EditorFeatureProfile::feature_identifiers[FEATURE_MAX] = { @@ -67,6 +69,7 @@ const char *EditorFeatureProfile::feature_identifiers[FEATURE_MAX] = { "node_dock", "filesystem_dock", "import_dock", + "history_dock", }; void EditorFeatureProfile::set_disable_class(const StringName &p_class, bool p_disabled) { @@ -302,6 +305,7 @@ void EditorFeatureProfile::_bind_methods() { BIND_ENUM_CONSTANT(FEATURE_NODE_DOCK); BIND_ENUM_CONSTANT(FEATURE_FILESYSTEM_DOCK); BIND_ENUM_CONSTANT(FEATURE_IMPORT_DOCK); + BIND_ENUM_CONSTANT(FEATURE_HISTORY_DOCK); BIND_ENUM_CONSTANT(FEATURE_MAX); } diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h index dab6c951e4..1d79844913 100644 --- a/editor/editor_feature_profile.h +++ b/editor/editor_feature_profile.h @@ -40,6 +40,8 @@ #include "scene/gui/split_container.h" #include "scene/gui/tree.h" +class EditorFileDialog; + class EditorFeatureProfile : public RefCounted { GDCLASS(EditorFeatureProfile, RefCounted); @@ -52,6 +54,7 @@ public: FEATURE_NODE_DOCK, FEATURE_FILESYSTEM_DOCK, FEATURE_IMPORT_DOCK, + FEATURE_HISTORY_DOCK, FEATURE_MAX }; diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index 90f3f8d2f5..e7d4636ad9 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); @@ -303,7 +335,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { } mono_fc->set_opentype_features(ftrs); } break; - default: { // Default. + default: { // Enabled. Dictionary ftrs; ftrs[TS->name_to_tag("calt")] = 1; mono_fc->set_opentype_features(ftrs); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 7f2b34b6f3..efa85dadee 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -54,10 +54,14 @@ void EditorHelp::_update_theme() { qualifier_color = get_theme_color(SNAME("qualifier_color"), SNAME("EditorHelp")); type_color = get_theme_color(SNAME("type_color"), SNAME("EditorHelp")); + class_desc->add_theme_style_override("normal", get_theme_stylebox(SNAME("background"), SNAME("EditorHelp"))); + class_desc->add_theme_style_override("focus", get_theme_stylebox(SNAME("background"), SNAME("EditorHelp"))); class_desc->add_theme_color_override("selection_color", get_theme_color(SNAME("selection_color"), SNAME("EditorHelp"))); class_desc->add_theme_constant_override("line_separation", get_theme_constant(SNAME("line_separation"), SNAME("EditorHelp"))); class_desc->add_theme_constant_override("table_h_separation", get_theme_constant(SNAME("table_h_separation"), SNAME("EditorHelp"))); class_desc->add_theme_constant_override("table_v_separation", get_theme_constant(SNAME("table_v_separation"), SNAME("EditorHelp"))); + class_desc->add_theme_constant_override("text_highlight_h_padding", get_theme_constant(SNAME("text_highlight_h_padding"), SNAME("EditorHelp"))); + class_desc->add_theme_constant_override("text_highlight_v_padding", get_theme_constant(SNAME("text_highlight_v_padding"), SNAME("EditorHelp"))); doc_font = get_theme_font(SNAME("doc"), SNAME("EditorFonts")); doc_bold_font = get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts")); @@ -385,7 +389,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") { @@ -1796,9 +1800,19 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control Ref<Font> doc_code_font = p_owner_node->get_theme_font(SNAME("doc_source"), SNAME("EditorFonts")); Ref<Font> doc_kbd_font = p_owner_node->get_theme_font(SNAME("doc_keyboard"), SNAME("EditorFonts")); - Color link_color = p_owner_node->get_theme_color(SNAME("link_color"), SNAME("EditorHelp")); - Color code_color = p_owner_node->get_theme_color(SNAME("code_color"), SNAME("EditorHelp")); - Color kbd_color = p_owner_node->get_theme_color(SNAME("kbd_color"), SNAME("EditorHelp")); + const Color type_color = p_owner_node->get_theme_color(SNAME("type_color"), SNAME("EditorHelp")); + const Color code_color = p_owner_node->get_theme_color(SNAME("code_color"), SNAME("EditorHelp")); + const Color kbd_color = p_owner_node->get_theme_color(SNAME("kbd_color"), SNAME("EditorHelp")); + const Color code_dark_color = Color(code_color, 0.8); + + const Color link_color = p_owner_node->get_theme_color(SNAME("link_color"), SNAME("EditorHelp")); + const Color link_method_color = p_owner_node->get_theme_color(SNAME("accent_color"), SNAME("Editor")); + const Color link_property_color = link_color.lerp(p_owner_node->get_theme_color(SNAME("accent_color"), SNAME("Editor")), 0.25); + const Color link_annotation_color = link_color.lerp(p_owner_node->get_theme_color(SNAME("accent_color"), SNAME("Editor")), 0.5); + + const Color code_bg_color = p_owner_node->get_theme_color(SNAME("code_bg_color"), SNAME("EditorHelp")); + const Color kbd_bg_color = p_owner_node->get_theme_color(SNAME("kbd_bg_color"), SNAME("EditorHelp")); + const Color param_bg_color = p_owner_node->get_theme_color(SNAME("param_bg_color"), SNAME("EditorHelp")); String bbcode = p_bbcode.dedent().replace("\t", "").replace("\r", "").strip_edges(); @@ -1931,14 +1945,21 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control const String link_tag = tag.substr(0, tag_end); const String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" "); - // Use monospace font with translucent colored background color to make clickable references + // Use monospace font to make clickable references // easier to distinguish from inline code and other text. p_rt->push_font(doc_code_font); - p_rt->push_color(link_color); - p_rt->push_bgcolor(code_color * Color(1, 1, 1, 0.15)); + + Color target_color = link_color; + if (link_tag == "method") { + target_color = link_method_color; + } else if (link_tag == "member" || link_tag == "signal" || link_tag == "theme property") { + target_color = link_property_color; + } else if (link_tag == "annotation") { + target_color = link_annotation_color; + } + p_rt->push_color(target_color); p_rt->push_meta("@" + link_tag + " " + link_target); - p_rt->add_text(link_target + (tag.begins_with("method ") ? "()" : "")); - p_rt->pop(); + p_rt->add_text(link_target + (link_tag == "method" ? "()" : "")); p_rt->pop(); p_rt->pop(); p_rt->pop(); @@ -1950,7 +1971,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control // Use monospace font with translucent background color to make code easier to distinguish from other text. p_rt->push_font(doc_code_font); - p_rt->push_bgcolor(Color(0.5, 0.5, 0.5, 0.15)); + p_rt->push_bgcolor(param_bg_color); p_rt->push_color(code_color); p_rt->add_text(param_name); p_rt->pop(); @@ -1961,17 +1982,15 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control } else if (doc->class_list.has(tag)) { // Class reference tag such as [Node2D] or [SceneTree]. - // Use monospace font with translucent colored background color to make clickable references + // Use monospace font to make clickable references // easier to distinguish from inline code and other text. p_rt->push_font(doc_code_font); - p_rt->push_color(link_color); - p_rt->push_bgcolor(code_color * Color(1, 1, 1, 0.15)); + p_rt->push_color(type_color); p_rt->push_meta("#" + tag); p_rt->add_text(tag); p_rt->pop(); p_rt->pop(); p_rt->pop(); - p_rt->pop(); pos = brk_end + 1; } else if (tag == "b") { @@ -1985,30 +2004,30 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "code") { - // Use monospace font with translucent background color to make code easier to distinguish from other text. + // Use monospace font with darkened background color to make code easier to distinguish from other text. p_rt->push_font(doc_code_font); - p_rt->push_bgcolor(Color(0.5, 0.5, 0.5, 0.15)); - p_rt->push_color(code_color); + p_rt->push_bgcolor(code_bg_color); + p_rt->push_color(code_color.lerp(p_owner_node->get_theme_color(SNAME("error_color"), SNAME("Editor")), 0.6)); code_tag = true; pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "codeblock") { - // Use monospace font with translucent background color to make code easier to distinguish from other text. + // Use monospace font with darkened background color to make code easier to distinguish from other text. // Use a single-column table with cell row background color instead of `[bgcolor]`. // This makes the background color highlight cover the entire block, rather than individual lines. p_rt->push_font(doc_code_font); p_rt->push_table(1); p_rt->push_cell(); - p_rt->set_cell_row_background_color(Color(0.5, 0.5, 0.5, 0.15), Color(0.5, 0.5, 0.5, 0.15)); + p_rt->set_cell_row_background_color(code_bg_color, Color(code_bg_color, 0.99)); p_rt->set_cell_padding(Rect2(10 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE)); - p_rt->push_color(code_color); + p_rt->push_color(code_dark_color); codeblock_tag = true; pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "kbd") { // Use keyboard font with custom color and background color. p_rt->push_font(doc_kbd_font); - p_rt->push_bgcolor(Color(0.5, 0.5, 0.5, 0.15)); + p_rt->push_bgcolor(kbd_bg_color); p_rt->push_color(kbd_color); code_tag = true; // Though not strictly a code tag, logic is similar. pos = brk_end + 1; 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 c8a6f43dbb..cbad9aa737 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -110,9 +110,11 @@ #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" +#include "editor/import/editor_import_plugin.h" #include "editor/import/resource_importer_bitmask.h" #include "editor/import/resource_importer_bmfont.h" #include "editor/import/resource_importer_csv_translation.h" @@ -243,15 +245,11 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto String full_path = p_full_paths[set_idx]; // Get rid of file extensions and res:// prefixes. - if (scene_name.rfind(".") >= 0) { - scene_name = scene_name.substr(0, scene_name.rfind(".")); - } + scene_name = scene_name.get_basename(); if (full_path.begins_with("res://")) { full_path = full_path.substr(6); } - if (full_path.rfind(".") >= 0) { - full_path = full_path.substr(0, full_path.rfind(".")); - } + full_path = full_path.get_basename(); // Normalize trailing slashes when normalizing directory names. scene_name = scene_name.trim_suffix("/"); @@ -269,7 +267,7 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto String parent = full_path.substr(0, difference); int slash_idx = parent.rfind("/"); slash_idx = parent.rfind("/", slash_idx - 1); - parent = slash_idx >= 0 ? parent.substr(slash_idx + 1) : parent; + parent = (slash_idx >= 0 && parent.length() > 1) ? parent.substr(slash_idx + 1) : parent; r_filenames.write[set_idx] = parent + r_filenames[set_idx]; } } @@ -301,15 +299,11 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto String path = p_full_paths[E->get()]; // Get rid of file extensions and res:// prefixes. - if (scene_name.rfind(".") >= 0) { - scene_name = scene_name.substr(0, scene_name.rfind(".")); - } + scene_name = scene_name.get_basename(); if (path.begins_with("res://")) { path = path.substr(6); } - if (path.rfind(".") >= 0) { - path = path.substr(0, path.rfind(".")); - } + path = path.get_basename(); // Normalize trailing slashes when normalizing directory names. scene_name = scene_name.trim_suffix("/"); @@ -543,7 +537,7 @@ void EditorNode::_update_from_settings() { RS::get_singleton()->environment_set_volumetric_fog_filter_active(bool(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter"))); RS::get_singleton()->canvas_set_shadow_texture_size(GLOBAL_GET("rendering/2d/shadow_atlas/size")); - bool use_half_res_gi = GLOBAL_DEF("rendering/global_illumination/gi/use_half_resolution", false); + bool use_half_res_gi = GLOBAL_GET("rendering/global_illumination/gi/use_half_resolution"); RS::get_singleton()->gi_set_use_half_resolution(use_half_res_gi); bool snap_2d_transforms = GLOBAL_GET("rendering/2d/snap/snap_2d_transforms_to_pixel"); @@ -3697,6 +3691,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 { @@ -4083,7 +4078,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); @@ -4179,6 +4174,7 @@ void EditorNode::register_editor_types() { GDREGISTER_CLASS(EditorScenePostImport); GDREGISTER_CLASS(EditorCommandPalette); GDREGISTER_CLASS(EditorDebuggerPlugin); + GDREGISTER_ABSTRACT_CLASS(EditorDebuggerSession); } void EditorNode::unregister_editor_types() { @@ -5140,7 +5136,7 @@ bool EditorNode::has_scenes_in_session() { bool EditorNode::ensure_main_scene(bool p_from_native) { pick_main_scene->set_meta("from_native", p_from_native); // Whether from play button or native run. - String main_scene = GLOBAL_DEF_BASIC("application/run/main_scene", ""); + String main_scene = GLOBAL_GET("application/run/main_scene"); if (main_scene.is_empty()) { current_menu_option = -1; @@ -5207,7 +5203,7 @@ bool EditorNode::is_run_playing() const { String EditorNode::get_run_playing_scene() const { String run_filename = editor_run.get_running_scene(); if (run_filename.is_empty() && is_run_playing()) { - run_filename = GLOBAL_DEF_BASIC("application/run/main_scene", ""); // Must be the main scene then. + run_filename = GLOBAL_GET("application/run/main_scene"); // Must be the main scene then. } return run_filename; @@ -5767,7 +5763,7 @@ void EditorNode::_global_menu_new_window(const Variant &p_tag) { } void EditorNode::_dropped_files(const Vector<String> &p_files) { - String to_path = ProjectSettings::get_singleton()->globalize_path(FileSystemDock::get_singleton()->get_selected_path()); + String to_path = ProjectSettings::get_singleton()->globalize_path(FileSystemDock::get_singleton()->get_current_directory()); _add_dropped_files_recursive(p_files, to_path); @@ -5974,12 +5970,14 @@ void EditorNode::_feature_profile_changed() { TabContainer *import_tabs = cast_to<TabContainer>(ImportDock::get_singleton()->get_parent()); TabContainer *node_tabs = cast_to<TabContainer>(NodeDock::get_singleton()->get_parent()); TabContainer *fs_tabs = cast_to<TabContainer>(FileSystemDock::get_singleton()->get_parent()); + TabContainer *history_tabs = cast_to<TabContainer>(history_dock->get_parent()); if (profile.is_valid()) { node_tabs->set_tab_hidden(node_tabs->get_tab_idx_from_control(NodeDock::get_singleton()), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_NODE_DOCK)); // The Import dock is useless without the FileSystem dock. Ensure the configuration is valid. bool fs_dock_disabled = profile->is_feature_disabled(EditorFeatureProfile::FEATURE_FILESYSTEM_DOCK); fs_tabs->set_tab_hidden(fs_tabs->get_tab_idx_from_control(FileSystemDock::get_singleton()), fs_dock_disabled); import_tabs->set_tab_hidden(import_tabs->get_tab_idx_from_control(ImportDock::get_singleton()), fs_dock_disabled || profile->is_feature_disabled(EditorFeatureProfile::FEATURE_IMPORT_DOCK)); + history_tabs->set_tab_hidden(history_tabs->get_tab_idx_from_control(history_dock), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_HISTORY_DOCK)); main_editor_buttons[EDITOR_3D]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D)); main_editor_buttons[EDITOR_SCRIPT]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT)); @@ -5995,6 +5993,8 @@ void EditorNode::_feature_profile_changed() { import_tabs->set_tab_hidden(import_tabs->get_tab_idx_from_control(ImportDock::get_singleton()), false); node_tabs->set_tab_hidden(node_tabs->get_tab_idx_from_control(NodeDock::get_singleton()), false); fs_tabs->set_tab_hidden(fs_tabs->get_tab_idx_from_control(FileSystemDock::get_singleton()), false); + history_tabs->set_tab_hidden(history_tabs->get_tab_idx_from_control(history_dock), false); + history_dock->set_visible(true); ImportDock::get_singleton()->set_visible(true); NodeDock::get_singleton()->set_visible(true); FileSystemDock::get_singleton()->set_visible(true); @@ -6040,6 +6040,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() { @@ -7105,6 +7106,8 @@ EditorNode::EditorNode() { filesystem_dock->connect("display_mode_changed", callable_mp(this, &EditorNode::_save_docks)); get_project_settings()->connect_filesystem_dock_signals(filesystem_dock); + history_dock = 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")); @@ -7125,6 +7128,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(history_dock); + dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(history_dock), 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 9c8d564057..f27fe429b9 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -77,6 +77,7 @@ class EditorUndoRedoManager; class ExportTemplateManager; class FileDialog; class FileSystemDock; +class HistoryDock; class HSplitContainer; class ImportDock; class LinkButton; @@ -274,6 +275,7 @@ private: EditorRunNative *run_native = nullptr; EditorSelection *editor_selection = nullptr; EditorSettingsDialog *editor_settings_dialog = nullptr; + HistoryDock *history_dock = nullptr; ProjectExportDialog *project_export = nullptr; ProjectSettingsEditor *project_settings_editor = nullptr; diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index d83dc32e90..e11bc3c252 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -30,15 +30,20 @@ #include "editor_plugin.h" +#include "editor/debugger/editor_debugger_node.h" #include "editor/editor_command_palette.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_resource_preview.h" #include "editor/editor_settings.h" +#include "editor/editor_translation_parser.h" #include "editor/editor_undo_redo_manager.h" #include "editor/export/editor_export.h" #include "editor/filesystem_dock.h" +#include "editor/import/editor_import_plugin.h" +#include "editor/import/resource_importer_scene.h" #include "editor/plugins/canvas_item_editor_plugin.h" +#include "editor/plugins/editor_debugger_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/project_settings_editor.h" @@ -238,14 +243,18 @@ void EditorInterface::select_file(const String &p_file) { FileSystemDock::get_singleton()->select_file(p_file); } -String EditorInterface::get_selected_path() const { - return FileSystemDock::get_singleton()->get_selected_path(); +Vector<String> EditorInterface::get_selected_paths() const { + return FileSystemDock::get_singleton()->get_selected_paths(); } String EditorInterface::get_current_path() const { return FileSystemDock::get_singleton()->get_current_path(); } +String EditorInterface::get_current_directory() const { + return FileSystemDock::get_singleton()->get_current_directory(); +} + void EditorInterface::inspect_object(Object *p_obj, const String &p_for_property, bool p_inspector_only) { EditorNode::get_singleton()->push_item(p_obj, p_for_property, p_inspector_only); } @@ -363,8 +372,9 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("get_editor_main_screen"), &EditorInterface::get_editor_main_screen); ClassDB::bind_method(D_METHOD("make_mesh_previews", "meshes", "preview_size"), &EditorInterface::_make_mesh_previews); ClassDB::bind_method(D_METHOD("select_file", "file"), &EditorInterface::select_file); - ClassDB::bind_method(D_METHOD("get_selected_path"), &EditorInterface::get_selected_path); + ClassDB::bind_method(D_METHOD("get_selected_paths"), &EditorInterface::get_selected_paths); ClassDB::bind_method(D_METHOD("get_current_path"), &EditorInterface::get_current_path); + ClassDB::bind_method(D_METHOD("get_current_directory"), &EditorInterface::get_current_directory); ClassDB::bind_method(D_METHOD("get_file_system_dock"), &EditorInterface::get_file_system_dock); ClassDB::bind_method(D_METHOD("get_editor_paths"), &EditorInterface::get_editor_paths); ClassDB::bind_method(D_METHOD("get_command_palette"), &EditorInterface::get_command_palette); @@ -837,12 +847,12 @@ ScriptCreateDialog *EditorPlugin::get_script_create_dialog() { return SceneTreeDock::get_singleton()->get_script_create_dialog(); } -void EditorPlugin::add_debugger_plugin(const Ref<Script> &p_script) { - EditorDebuggerNode::get_singleton()->add_debugger_plugin(p_script); +void EditorPlugin::add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin) { + EditorDebuggerNode::get_singleton()->add_debugger_plugin(p_plugin); } -void EditorPlugin::remove_debugger_plugin(const Ref<Script> &p_script) { - EditorDebuggerNode::get_singleton()->remove_debugger_plugin(p_script); +void EditorPlugin::remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin) { + EditorDebuggerNode::get_singleton()->remove_debugger_plugin(p_plugin); } void EditorPlugin::_editor_project_settings_changed() { @@ -967,7 +977,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 d8c3cc7330..9c639164f2 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -32,33 +32,34 @@ #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" -#include "editor/import/editor_import_plugin.h" -#include "editor/import/resource_importer_scene.h" -#include "editor/script_create_dialog.h" #include "scene/3d/camera_3d.h" -#include "scene/main/node.h" -#include "scene/resources/texture.h" +#include "scene/gui/control.h" class Node3D; -class Camera3D; +class Button; +class PopupMenu; class EditorCommandPalette; -class EditorSelection; +class EditorDebuggerPlugin; class EditorExport; -class EditorSettings; -class EditorImportPlugin; class EditorExportPlugin; +class EditorFileSystem; +class EditorImportPlugin; +class EditorInspector; +class EditorInspectorPlugin; class EditorNode3DGizmoPlugin; +class EditorPaths; class EditorResourcePreview; -class EditorUndoRedoManager; -class EditorFileSystem; +class EditorSceneFormatImporter; +class EditorScenePostImportPlugin; +class EditorSelection; +class EditorSettings; class EditorToolAddons; -class EditorPaths; +class EditorTranslationParserPlugin; +class EditorUndoRedoManager; class FileSystemDock; +class ScriptCreateDialog; class ScriptEditor; +class VBoxContainer; class EditorInterface : public Node { GDCLASS(EditorInterface, Node); @@ -93,8 +94,9 @@ public: EditorCommandPalette *get_command_palette() const; void select_file(const String &p_file); - String get_selected_path() const; + Vector<String> get_selected_paths() const; String get_current_path() const; + String get_current_directory() const; void inspect_object(Object *p_obj, const String &p_for_property = String(), bool p_inspector_only = false); @@ -134,7 +136,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; @@ -303,8 +304,8 @@ public: void add_autoload_singleton(const String &p_name, const String &p_path); void remove_autoload_singleton(const String &p_name); - void add_debugger_plugin(const Ref<Script> &p_script); - void remove_debugger_plugin(const Ref<Script> &p_script); + void add_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin); + void remove_debugger_plugin(const Ref<EditorDebuggerPlugin> &p_plugin); void enable_plugin(); void disable_plugin(); 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..d71976a1af 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -1045,7 +1045,6 @@ void EditorPropertyLayersGrid::_notification(int p_what) { const int vofs = (grid_size.height - h) / 2; int layer_index = 0; - int block_index = 0; Point2 arrow_pos; @@ -1112,8 +1111,6 @@ void EditorPropertyLayersGrid::_notification(int p_what) { break; } } - - ++block_index; } if ((expansion_rows != prev_expansion_rows) && expanded) { @@ -2688,7 +2685,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 +2722,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 +4094,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.h b/editor/editor_properties.h index 20b130f57f..ad36e01544 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -639,7 +639,7 @@ class EditorPropertyQuaternion : public EditorProperty { EditorSpinSlider *euler[3]; Button *edit_button = nullptr; - Vector3 edit_euler = Vector3(); + Vector3 edit_euler; void _value_changed(double p_val, const String &p_name); void _edit_custom_value(); 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_resource_picker.cpp b/editor/editor_resource_picker.cpp index 7c1e3e63ef..20a9826edb 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -256,7 +256,7 @@ void EditorResourcePicker::_update_menu_items() { paste_valid = ClassDB::is_parent_class(res_type, base) || EditorNode::get_editor_data().script_class_is_parent(res_type, base); - if (!paste_valid) { + if (paste_valid) { break; } } @@ -570,13 +570,17 @@ void EditorResourcePicker::_get_allowed_types(bool p_with_convert, HashSet<Strin for (int i = 0; i < size; i++) { String base = allowed_types[i].strip_edges(); - p_vector->insert(base); + if (!ClassDB::is_virtual(base)) { + p_vector->insert(base); + } // If we hit a familiar base type, take all the data from cache. if (allowed_types_cache.has(base)) { List<StringName> allowed_subtypes = allowed_types_cache[base]; for (const StringName &subtype_name : allowed_subtypes) { - p_vector->insert(subtype_name); + if (!ClassDB::is_virtual(subtype_name)) { + p_vector->insert(subtype_name); + } } } else { List<StringName> allowed_subtypes; @@ -586,13 +590,17 @@ void EditorResourcePicker::_get_allowed_types(bool p_with_convert, HashSet<Strin ClassDB::get_inheriters_from_class(base, &inheriters); } for (const StringName &subtype_name : inheriters) { - p_vector->insert(subtype_name); + if (!ClassDB::is_virtual(subtype_name)) { + p_vector->insert(subtype_name); + } allowed_subtypes.push_back(subtype_name); } for (const StringName &subtype_name : global_classes) { if (EditorNode::get_editor_data().script_class_is_parent(subtype_name, base)) { - p_vector->insert(subtype_name); + if (!ClassDB::is_virtual(subtype_name)) { + p_vector->insert(subtype_name); + } allowed_subtypes.push_back(subtype_name); } } diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index 599df12bd3..913a0ba104 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -31,6 +31,7 @@ #include "editor_run.h" #include "core/config/project_settings.h" +#include "editor/debugger/editor_debugger_node.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "main/main.h" @@ -57,8 +58,11 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) { args.push_back(resource_path.replace(" ", "%20")); } - args.push_back("--remote-debug"); - args.push_back(EditorDebuggerNode::get_singleton()->get_server_uri()); + const String debug_uri = EditorDebuggerNode::get_singleton()->get_server_uri(); + if (debug_uri.size()) { + args.push_back("--remote-debug"); + args.push_back(debug_uri); + } args.push_back("--editor-pid"); args.push_back(itos(OS::get_singleton()->get_process_id())); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 409ef95fb0..bc186c7a16 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; @@ -412,16 +412,16 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { EDITOR_SETTING_USAGE(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/editor/custom_display_scale", 1.0, "0.5,3,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/editor/main_font_size", 14, "8,48,1") EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/editor/code_font_size", 14, "8,48,1") - EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/code_font_contextual_ligatures", 0, "Default,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/code_font_contextual_ligatures", 1, "Enabled,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set") _initial_set("interface/editor/code_font_custom_opentype_features", ""); _initial_set("interface/editor/code_font_custom_variations", ""); - EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_antialiasing", 1, "None,Grayscale,LCD sub-pixel") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_antialiasing", 1, "None,Grayscale,LCD Subpixel") #ifdef MACOS_ENABLED EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (None),None,Light,Normal") #else EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (Light),None,Light,Normal") #endif - EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_subpixel_positioning", 1, "Disabled,Auto,One half of a pixel,One quarter of a pixel") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_subpixel_positioning", 1, "Disabled,Auto,One Half of a Pixel,One Quarter of a Pixel") EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/main_font", "", "*.ttf,*.otf,*.woff,*.woff2,*.pfb,*.pfm") EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/main_font_bold", "", "*.ttf,*.otf,*.woff,*.woff2,*.pfb,*.pfm") diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp index db501aac03..77a0d9f85c 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()); @@ -484,6 +487,7 @@ void EditorSettingsDialog::_update_shortcuts() { TreeItem *section = E.value; if (section->get_first_child() == nullptr) { root->remove_child(section); + memdelete(section); } } } @@ -697,8 +701,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 +725,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_spin_slider.cpp b/editor/editor_spin_slider.cpp index 1cdfceebc8..11a8fce9c3 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -619,11 +619,9 @@ bool EditorSpinSlider::is_grabbing() const { void EditorSpinSlider::_focus_entered() { _ensure_input_popup(); - Rect2 gr = get_screen_rect(); value_input->set_text(get_text_value()); - value_input_popup->set_position(gr.position); - value_input_popup->set_size(gr.size); - value_input_popup->call_deferred(SNAME("popup")); + value_input_popup->set_size(get_size()); + value_input_popup->call_deferred(SNAME("show")); value_input->call_deferred(SNAME("grab_focus")); value_input->call_deferred(SNAME("select_all")); value_input->set_focus_next(find_next_valid_focus()->get_path()); @@ -658,14 +656,13 @@ void EditorSpinSlider::_ensure_input_popup() { return; } - value_input_popup = memnew(Popup); + value_input_popup = memnew(Control); add_child(value_input_popup); value_input = memnew(LineEdit); value_input_popup->add_child(value_input); - value_input_popup->set_wrap_controls(true); value_input->set_anchors_and_offsets_preset(PRESET_FULL_RECT); - value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed)); + value_input_popup->connect("hidden", callable_mp(this, &EditorSpinSlider::_value_input_closed)); value_input->connect("text_submitted", callable_mp(this, &EditorSpinSlider::_value_input_submitted)); value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited)); value_input->connect("gui_input", callable_mp(this, &EditorSpinSlider::_value_input_gui_input)); diff --git a/editor/editor_spin_slider.h b/editor/editor_spin_slider.h index afcaa3e4b6..fd5c3dc5df 100644 --- a/editor/editor_spin_slider.h +++ b/editor/editor_spin_slider.h @@ -63,7 +63,7 @@ class EditorSpinSlider : public Range { Vector2 grabbing_spinner_mouse_pos; double pre_grab_value = 0.0; - Popup *value_input_popup = nullptr; + Control *value_input_popup = nullptr; LineEdit *value_input = nullptr; bool value_input_just_closed = false; bool value_input_dirty = false; diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 17b5eb3314..692deb3beb 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -1491,6 +1491,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("normal", "RichTextLabel", style_tree_bg); // Editor help. + Ref<StyleBoxFlat> style_editor_help = style_default->duplicate(); + style_editor_help->set_bg_color(dark_color_2); + style_editor_help->set_border_color(dark_color_3); + theme->set_stylebox("background", "EditorHelp", style_editor_help); + theme->set_color("title_color", "EditorHelp", accent_color); theme->set_color("headline_color", "EditorHelp", mono_color); theme->set_color("text_color", "EditorHelp", font_color); @@ -1503,9 +1508,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("link_color", "EditorHelp", accent_color.lerp(mono_color, 0.8)); theme->set_color("code_color", "EditorHelp", accent_color.lerp(mono_color, 0.6)); theme->set_color("kbd_color", "EditorHelp", accent_color.lerp(property_color, 0.6)); + theme->set_color("code_bg_color", "EditorHelp", dark_color_3); + theme->set_color("kbd_bg_color", "EditorHelp", dark_color_1); + theme->set_color("param_bg_color", "EditorHelp", dark_color_1); theme->set_constant("line_separation", "EditorHelp", Math::round(6 * EDSCALE)); theme->set_constant("table_h_separation", "EditorHelp", 16 * EDSCALE); theme->set_constant("table_v_separation", "EditorHelp", 6 * EDSCALE); + theme->set_constant("text_highlight_h_padding", "EditorHelp", 1 * EDSCALE); + theme->set_constant("text_highlight_v_padding", "EditorHelp", 2 * EDSCALE); // Panel theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4, corner_width)); diff --git a/editor/editor_undo_redo_manager.cpp b/editor/editor_undo_redo_manager.cpp index 064448fd96..4bfa9b686c 100644 --- a/editor/editor_undo_redo_manager.cpp +++ b/editor/editor_undo_redo_manager.cpp @@ -33,6 +33,7 @@ #include "core/io/resource.h" #include "core/os/os.h" #include "core/templates/local_vector.h" +#include "editor/debugger/editor_debugger_node.h" #include "editor/editor_log.h" #include "editor/editor_node.h" #include "scene/main/node.h" @@ -109,9 +110,14 @@ EditorUndoRedoManager::History &EditorUndoRedoManager::get_history_for_object(Ob } void EditorUndoRedoManager::create_action_for_history(const String &p_name, int p_history_id, UndoRedo::MergeMode p_mode) { - pending_action.action_name = p_name; - pending_action.timestamp = OS::get_singleton()->get_unix_time(); - pending_action.merge_mode = p_mode; + if (pending_action.history_id != INVALID_HISTORY) { + // Nested action. + p_history_id = pending_action.history_id; + } else { + pending_action.action_name = p_name; + pending_action.timestamp = OS::get_singleton()->get_unix_time(); + pending_action.merge_mode = p_mode; + } if (p_history_id != INVALID_HISTORY) { pending_action.history_id = p_history_id; @@ -228,6 +234,12 @@ void EditorUndoRedoManager::commit_action(bool p_execute) { history.undo_redo->commit_action(p_execute); history.redo_stack.clear(); + if (history.undo_redo->get_action_level() > 0) { + // Nested action. + is_committing = false; + return; + } + if (!history.undo_stack.is_empty()) { const Action &prev_action = history.undo_stack.back()->get(); if (pending_action.merge_mode != UndoRedo::MERGE_DISABLE && pending_action.merge_mode == prev_action.merge_mode && pending_action.action_name == prev_action.action_name) { @@ -241,6 +253,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 +265,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 +280,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 +325,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 +389,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 +397,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 +473,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/export/editor_export_platform_pc.cpp b/editor/export/editor_export_platform_pc.cpp index c5b61e9b03..9de2f94900 100644 --- a/editor/export/editor_export_platform_pc.cpp +++ b/editor/export/editor_export_platform_pc.cpp @@ -146,9 +146,16 @@ Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_ return ERR_FILE_NOT_FOUND; } + String wrapper_template_path = template_path.get_basename() + "_console.exe"; + int con_wrapper_mode = p_preset->get("debug/export_console_script"); + bool copy_wrapper = (con_wrapper_mode == 1 && p_debug) || (con_wrapper_mode == 2); + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); da->make_dir_recursive(p_path.get_base_dir()); Error err = da->copy(template_path, p_path, get_chmod_flags()); + if (err == OK && copy_wrapper && FileAccess::exists(wrapper_template_path)) { + err = da->copy(wrapper_template_path, p_path.get_basename() + ".console.exe", get_chmod_flags()); + } if (err != OK) { add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("Failed to copy export template.")); } diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 608e7ce3cb..bda5dd68c4 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -42,6 +42,7 @@ #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/import/resource_importer_scene.h" #include "editor/import_dock.h" #include "editor/scene_create_dialog.h" #include "editor/scene_tree_dock.h" @@ -511,7 +512,15 @@ void FileSystemDock::_tree_multi_selected(Object *p_item, int p_column, bool p_s } } -String FileSystemDock::get_selected_path() const { +Vector<String> FileSystemDock::get_selected_paths() const { + return _tree_get_selected(false); +} + +String FileSystemDock::get_current_path() const { + return path; +} + +String FileSystemDock::get_current_directory() const { if (path.ends_with("/")) { return path; } else { @@ -519,10 +528,6 @@ String FileSystemDock::get_selected_path() const { } } -String FileSystemDock::get_current_path() const { - return path; -} - void FileSystemDock::_set_current_path_text(const String &p_path) { if (p_path == "Favorites") { current_path->set_text(TTR("Favorites")); @@ -1283,42 +1288,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(); } } @@ -1697,7 +1731,7 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_ove } } -Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) { +Vector<String> FileSystemDock::_tree_get_selected(bool remove_self_inclusion) const { // Build a list of selected items with the active one at the first position. Vector<String> selected_strings; diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index f39ca9e74d..ebb6f1e2a0 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -297,12 +297,12 @@ private: void _update_display_mode(bool p_force = false); - Vector<String> _tree_get_selected(bool remove_self_inclusion = true); + Vector<String> _tree_get_selected(bool remove_self_inclusion = true) const; bool _is_file_type_disabled_by_feature_profile(const StringName &p_class); void _feature_profile_changed(); - Vector<String> _remove_self_included_paths(Vector<String> selected_strings); + static Vector<String> _remove_self_included_paths(Vector<String> selected_strings); private: static FileSystemDock *singleton; @@ -315,9 +315,11 @@ protected: static void _bind_methods(); public: - String get_selected_path() const; + Vector<String> get_selected_paths() const; String get_current_path() const; + String get_current_directory() const; + void navigate_to_path(const String &p_path); void focus_on_filter(); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index a2bd1223a9..b7605d8e2b 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -422,8 +422,7 @@ void FindInFilesDialog::set_find_in_files_mode(FindInFilesMode p_mode) { } String FindInFilesDialog::get_search_text() const { - String text = _search_text_line_edit->get_text(); - return text.strip_edges(); + return _search_text_line_edit->get_text(); } String FindInFilesDialog::get_replace_text() const { 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/debugger/editor_network_profiler.h b/editor/history_dock.h index aea7ce3eec..9dda8165e6 100644 --- a/editor/debugger/editor_network_profiler.h +++ b/editor/history_dock.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* editor_network_profiler.h */ +/* history_dock.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,45 +28,39 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EDITOR_NETWORK_PROFILER_H -#define EDITOR_NETWORK_PROFILER_H +#ifndef HISTORY_DOCK_H +#define HISTORY_DOCK_H -#include "scene/debugger/scene_debugger.h" #include "scene/gui/box_container.h" -#include "scene/gui/button.h" -#include "scene/gui/label.h" -#include "scene/gui/split_container.h" -#include "scene/gui/tree.h" -class EditorNetworkProfiler : public VBoxContainer { - GDCLASS(EditorNetworkProfiler, VBoxContainer) +class CheckBox; +class ItemList; +class EditorUndoRedoManager; -private: - Button *activate = nullptr; - Button *clear_button = nullptr; - Tree *counters_display = nullptr; - LineEdit *incoming_bandwidth_text = nullptr; - LineEdit *outgoing_bandwidth_text = nullptr; +class HistoryDock : public VBoxContainer { + GDCLASS(HistoryDock, VBoxContainer); - Timer *frame_delay = nullptr; + Ref<EditorUndoRedoManager> ur_manager; + ItemList *action_list = nullptr; - HashMap<ObjectID, SceneDebugger::RPCNodeInfo> nodes_data; + CheckBox *current_scene_checkbox = nullptr; + CheckBox *global_history_checkbox = nullptr; - void _update_frame(); + bool need_refresh = true; + int current_version = 0; - void _activate_pressed(); - void _clear_pressed(); + void on_history_changed(); + void refresh_history(); + void on_version_changed(); + void refresh_version(); protected: - void _notification(int p_what); - static void _bind_methods(); + void _notification(int p_notification); public: - void add_node_frame_data(const SceneDebugger::RPCNodeInfo p_frame); - void set_bandwidth(int p_incoming, int p_outgoing); - bool is_profiling(); + void seek_history(int p_index); - EditorNetworkProfiler(); + HistoryDock(); }; -#endif // EDITOR_NETWORK_PROFILER_H +#endif // HISTORY_DOCK_H diff --git a/editor/import/audio_stream_import_settings.cpp b/editor/import/audio_stream_import_settings.cpp index d94b517003..a8cd4c3e49 100644 --- a/editor/import/audio_stream_import_settings.cpp +++ b/editor/import/audio_stream_import_settings.cpp @@ -32,6 +32,7 @@ #include "editor/audio_stream_preview.h" #include "editor/editor_file_system.h" #include "editor/editor_scale.h" +#include "scene/gui/check_box.h" AudioStreamImportSettings *AudioStreamImportSettings::singleton = nullptr; diff --git a/editor/import/audio_stream_import_settings.h b/editor/import/audio_stream_import_settings.h index 5e399237ca..fc756c6524 100644 --- a/editor/import/audio_stream_import_settings.h +++ b/editor/import/audio_stream_import_settings.h @@ -34,9 +34,12 @@ #include "editor/editor_plugin.h" #include "scene/audio/audio_stream_player.h" #include "scene/gui/color_rect.h" +#include "scene/gui/dialogs.h" #include "scene/gui/spin_box.h" #include "scene/resources/texture.h" +class CheckBox; + class AudioStreamImportSettings : public ConfirmationDialog { GDCLASS(AudioStreamImportSettings, ConfirmationDialog); diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index 5585c8edd2..8f15becd95 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -30,6 +30,7 @@ #include "dynamic_font_import_settings.h" +#include "core/config/project_settings.h" #include "editor/editor_file_dialog.h" #include "editor/editor_file_system.h" #include "editor/editor_inspector.h" @@ -492,9 +493,9 @@ void DynamicFontImportSettings::_variation_add() { TreeItem *vars_item = vars_list->create_item(vars_list_root); ERR_FAIL_NULL(vars_item); - vars_item->set_text(0, TTR("New configuration")); + vars_item->set_text(0, TTR("New Configuration")); vars_item->set_editable(0, true); - vars_item->add_button(1, vars_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove Variation")); + vars_item->add_button(1, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove Variation")); vars_item->set_button_color(1, 0, Color(1, 1, 1, 0.75)); Ref<DynamicFontImportSettingsData> import_variation_data; @@ -528,6 +529,12 @@ void DynamicFontImportSettings::_variation_selected() { label_glyphs->set_text(TTR("Preloaded glyphs: ") + itos(import_variation_data->selected_glyphs.size())); _range_selected(); _change_text_opts(); + + btn_fill->set_disabled(false); + btn_fill_locales->set_disabled(false); + } else { + btn_fill->set_disabled(true); + btn_fill_locales->set_disabled(true); } } @@ -551,6 +558,15 @@ void DynamicFontImportSettings::_variation_remove(Object *p_item, int p_column, } _variations_validate(); + + vars_item = vars_list->get_selected(); + if (vars_item) { + btn_fill->set_disabled(false); + btn_fill_locales->set_disabled(false); + } else { + btn_fill->set_disabled(true); + btn_fill_locales->set_disabled(true); + } } void DynamicFontImportSettings::_variation_changed(const String &p_edited_property) { @@ -582,10 +598,10 @@ void DynamicFontImportSettings::_variations_validate() { } } if ((TextServer::FontAntialiasing)(int)import_settings_data->get("antialiasing") == TextServer::FONT_ANTIALIASING_LCD) { - warn += "\n" + TTR("Note: LCD sub-pixel anti-aliasing is selected, each of the glyphs will be pre-rendered for all supported sub-pixel layouts (5x)."); + warn += "\n" + TTR("Note: LCD Subpixel antialiasing is selected, each of the glyphs will be pre-rendered for all supported subpixel layouts (5x)."); } if ((TextServer::SubpixelPositioning)(int)import_settings_data->get("subpixel_positioning") != TextServer::SUBPIXEL_POSITIONING_DISABLED) { - warn += "\n" + TTR("Note: Sub-pixel positioning is selected, each of the glyphs might be pre-rendered for multiple sub-pixel offsets (up to 4x)."); + warn += "\n" + TTR("Note: Subpixel positioning is selected, each of the glyphs might be pre-rendered for multiple subpixel offsets (up to 4x)."); } if (warn.is_empty()) { label_warn->set_text(""); @@ -623,6 +639,27 @@ void DynamicFontImportSettings::_change_text_opts() { text_edit->add_theme_font_override("font", font_main_text); } +void DynamicFontImportSettings::_glyph_update_lbl() { + Ref<DynamicFontImportSettingsData> import_variation_data; + + TreeItem *vars_item = vars_list->get_selected(); + if (vars_item) { + import_variation_data = vars_item->get_metadata(0); + } + if (import_variation_data.is_null()) { + return; + } + + int linked_glyphs = 0; + for (const char32_t &c : import_variation_data->selected_chars) { + if (import_variation_data->selected_glyphs.has(font_main->get_glyph_index(16, c))) { + linked_glyphs++; + } + } + int unlinked_glyphs = import_variation_data->selected_glyphs.size() - linked_glyphs; + label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(unlinked_glyphs + import_variation_data->selected_chars.size())); +} + void DynamicFontImportSettings::_glyph_clear() { Ref<DynamicFontImportSettingsData> import_variation_data; @@ -635,7 +672,7 @@ void DynamicFontImportSettings::_glyph_clear() { } import_variation_data->selected_glyphs.clear(); - label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size())); + _glyph_update_lbl(); _range_selected(); } @@ -662,7 +699,7 @@ void DynamicFontImportSettings::_glyph_text_selected() { } } TS->free_rid(text_rid); - label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size())); + _glyph_update_lbl(); } _range_selected(); } @@ -699,7 +736,7 @@ void DynamicFontImportSettings::_glyph_selected() { item->clear_custom_bg_color(glyph_table->get_selected_column()); } } - label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size())); + _glyph_update_lbl(); item = glyph_tree->get_selected(); ERR_FAIL_NULL(item); @@ -800,7 +837,7 @@ void DynamicFontImportSettings::_edit_range(int32_t p_start, int32_t p_end) { col = 0; } } - label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size())); + _glyph_update_lbl(); } bool DynamicFontImportSettings::_char_update(int32_t p_char) { @@ -885,7 +922,7 @@ void DynamicFontImportSettings::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - add_var->set_icon(add_var->get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + add_var->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); } break; } } @@ -947,10 +984,73 @@ void DynamicFontImportSettings::_re_import() { EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(base_path, "font_data_dynamic", main_settings); } +void DynamicFontImportSettings::_locale_edited() { + TreeItem *item = locale_tree->get_selected(); + ERR_FAIL_NULL(item); + item->set_checked(0, !item->is_checked(0)); +} + +void DynamicFontImportSettings::_process_locales() { + Ref<DynamicFontImportSettingsData> import_variation_data; + + TreeItem *vars_item = vars_list->get_selected(); + if (vars_item) { + import_variation_data = vars_item->get_metadata(0); + } + if (import_variation_data.is_null()) { + return; + } + + for (int i = 0; i < locale_root->get_child_count(); i++) { + TreeItem *item = locale_root->get_child(i); + if (item) { + if (item->is_checked(0)) { + String locale = item->get_text(0); + Ref<Translation> tr = ResourceLoader::load(locale); + if (tr.is_valid()) { + Vector<String> messages = tr->get_translated_message_list(); + for (const String &E : messages) { + RID text_rid = TS->create_shaped_text(); + if (text_rid.is_valid()) { + TS->shaped_text_add_string(text_rid, E, font_main->get_rids(), 16, Dictionary(), tr->get_locale()); + TS->shaped_text_shape(text_rid); + const Glyph *gl = TS->shaped_text_get_glyphs(text_rid); + const int gl_size = TS->shaped_text_get_glyph_count(text_rid); + + for (int j = 0; j < gl_size; j++) { + if (gl[j].font_rid.is_valid() && gl[j].index != 0) { + import_variation_data->selected_glyphs.insert(gl[j].index); + } + } + TS->free_rid(text_rid); + } + } + } + } + } + } + + _glyph_update_lbl(); + _range_selected(); +} + void DynamicFontImportSettings::open_settings(const String &p_path) { // Load base font data. Vector<uint8_t> font_data = FileAccess::get_file_as_array(p_path); + // Load project locale list. + locale_tree->clear(); + locale_root = locale_tree->create_item(); + ERR_FAIL_NULL(locale_root); + + Vector<String> translations = GLOBAL_GET("internationalization/locale/translations"); + for (const String &E : translations) { + TreeItem *item = locale_tree->create_item(locale_root); + ERR_FAIL_NULL(item); + item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + item->set_text(0, E); + } + // Load font for preview. font_preview.instantiate(); font_preview->set_data(font_data); @@ -1003,10 +1103,11 @@ void DynamicFontImportSettings::open_settings(const String &p_path) { int gww = get_theme_font(SNAME("font"))->get_string_size("00000").x + 50; glyph_table->set_column_custom_minimum_width(0, gww); - glyph_table->clear(); vars_list->clear(); + glyph_tree->set_selected(glyph_root->get_child(0)); + vars_list_root = vars_list->create_item(); import_settings_data->settings.clear(); @@ -1044,7 +1145,7 @@ void DynamicFontImportSettings::open_settings(const String &p_path) { vars_item->set_text(0, cfg_name); vars_item->set_editable(0, true); - vars_item->add_button(1, vars_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove Variation")); + vars_item->add_button(1, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove Variation")); vars_item->set_button_color(1, 0, Color(1, 1, 1, 0.75)); Ref<DynamicFontImportSettingsData> import_variation_data_custom; @@ -1080,6 +1181,10 @@ void DynamicFontImportSettings::open_settings(const String &p_path) { import_variation_data_custom->selected_glyphs.insert(c); } } + if (preload_configurations.is_empty()) { + _variation_add(); // Add default variation. + } + vars_list->set_selected(vars_list_root->get_child(0)); } else { Variant value = config->get_value("params", key); import_settings_data->defaults[key] = value; @@ -1122,14 +1227,14 @@ DynamicFontImportSettings::DynamicFontImportSettings() { options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant())); - options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel"), 1)); + options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD Subpixel"), 1)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_RANGE, "1,250,1"), 48)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1)); - options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1)); + options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One Half of a Pixel,One Quarter of a Pixel"), 1)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::NIL, "Metadata Overrides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant())); @@ -1219,7 +1324,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { // Page 2 layout: Configurations VBoxContainer *page2_vb = memnew(VBoxContainer); - page2_vb->set_name(TTR("Pre-render configurations")); + page2_vb->set_name(TTR("Pre-render Configurations")); main_pages->add_child(page2_vb); page2_description = memnew(Label); @@ -1248,7 +1353,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { add_var = memnew(Button); page2_hb_vars->add_child(add_var); add_var->set_tooltip_text(TTR("Add configuration")); - add_var->set_icon(add_var->get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + add_var->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); add_var->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_variation_add)); vars_list = memnew(Tree); @@ -1269,11 +1374,57 @@ DynamicFontImportSettings::DynamicFontImportSettings() { inspector_vars->connect("property_edited", callable_mp(this, &DynamicFontImportSettings::_variation_changed)); page2_side_vb->add_child(inspector_vars); + VBoxContainer *preload_pages_vb = memnew(VBoxContainer); + page2_hb->add_child(preload_pages_vb); + preload_pages = memnew(TabContainer); preload_pages->set_tab_alignment(TabBar::ALIGNMENT_CENTER); preload_pages->set_v_size_flags(Control::SIZE_EXPAND_FILL); preload_pages->set_h_size_flags(Control::SIZE_EXPAND_FILL); - page2_hb->add_child(preload_pages); + preload_pages_vb->add_child(preload_pages); + + HBoxContainer *gl_hb = memnew(HBoxContainer); + preload_pages_vb->add_child(gl_hb); + gl_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + + label_glyphs = memnew(Label); + gl_hb->add_child(label_glyphs); + label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(0)); + label_glyphs->set_custom_minimum_size(Size2(50 * EDSCALE, 0)); + + Button *btn_clear = memnew(Button); + gl_hb->add_child(btn_clear); + btn_clear->set_text(TTR("Clear Glyph List")); + btn_clear->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_glyph_clear)); + + VBoxContainer *page2_0_vb = memnew(VBoxContainer); + page2_0_vb->set_name(TTR("Glyphs from the Translations")); + preload_pages->add_child(page2_0_vb); + + page2_0_description = memnew(Label); + page2_0_description->set_text(TTR("Select translations to add all required glyphs to pre-render list:")); + page2_0_description->set_h_size_flags(Control::SIZE_EXPAND_FILL); + page2_0_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); + page2_0_vb->add_child(page2_0_description); + + locale_tree = memnew(Tree); + page2_0_vb->add_child(locale_tree); + locale_tree->set_columns(1); + locale_tree->set_hide_root(true); + locale_tree->set_column_expand(0, true); + locale_tree->connect("item_activated", callable_mp(this, &DynamicFontImportSettings::_locale_edited)); + locale_tree->set_column_custom_minimum_width(0, 120 * EDSCALE); + locale_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); + locale_root = locale_tree->create_item(); + + HBoxContainer *locale_hb = memnew(HBoxContainer); + page2_0_vb->add_child(locale_hb); + locale_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + + btn_fill_locales = memnew(Button); + locale_hb->add_child(btn_fill_locales); + btn_fill_locales->set_text(TTR("Shape all Strings in the Translations and Add Glyphs")); + btn_fill_locales->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_process_locales)); // Page 2.1 layout: Text to select glyphs VBoxContainer *page2_1_vb = memnew(VBoxContainer); @@ -1281,7 +1432,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { preload_pages->add_child(page2_1_vb); page2_1_description = memnew(Label); - page2_1_description->set_text(TTR("Enter a text to shape and add all required glyphs to pre-render list:")); + page2_1_description->set_text(TTR("Enter a text and select OpenType features to shape and add all required glyphs to pre-render list:")); page2_1_description->set_h_size_flags(Control::SIZE_EXPAND_FILL); page2_1_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); page2_1_vb->add_child(page2_1_description); @@ -1307,21 +1458,11 @@ DynamicFontImportSettings::DynamicFontImportSettings() { page2_1_vb->add_child(text_hb); text_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); - label_glyphs = memnew(Label); - text_hb->add_child(label_glyphs); - label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(0)); - label_glyphs->set_custom_minimum_size(Size2(50 * EDSCALE, 0)); - - Button *btn_fill = memnew(Button); + btn_fill = memnew(Button); text_hb->add_child(btn_fill); - btn_fill->set_text(TTR("Shape text and add glyphs")); + btn_fill->set_text(TTR("Shape Text and Add Glyphs")); btn_fill->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_glyph_text_selected)); - Button *btn_clear = memnew(Button); - text_hb->add_child(btn_clear); - btn_clear->set_text(TTR("Clear glyph list")); - btn_clear->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_glyph_clear)); - // Page 2.2 layout: Character map VBoxContainer *page2_2_vb = memnew(VBoxContainer); page2_2_vb->set_name(TTR("Glyphs from the Character Map")); diff --git a/editor/import/dynamic_font_import_settings.h b/editor/import/dynamic_font_import_settings.h index a1f763b445..386e9896dc 100644 --- a/editor/import/dynamic_font_import_settings.h +++ b/editor/import/dynamic_font_import_settings.h @@ -118,18 +118,30 @@ class DynamicFontImportSettings : public ConfirmationDialog { TabContainer *preload_pages = nullptr; + Label *label_glyphs = nullptr; + void _glyph_clear(); + void _glyph_update_lbl(); + + // Page 2.0 layout: Translations + Label *page2_0_description = nullptr; + Tree *locale_tree = nullptr; + TreeItem *locale_root = nullptr; + Button *btn_fill_locales = nullptr; + + void _locale_edited(); + void _process_locales(); + // Page 2.1 layout: Text to select glyphs Label *page2_1_description = nullptr; - Label *label_glyphs = nullptr; TextEdit *text_edit = nullptr; EditorInspector *inspector_text = nullptr; + Button *btn_fill = nullptr; List<ResourceImporter::ImportOption> options_text; Ref<DynamicFontImportSettingsData> text_settings_data; void _change_text_opts(); void _glyph_text_selected(); - void _glyph_clear(); // Page 2.2 layout: Character map Label *page2_2_description = nullptr; diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp index c822cd0fec..a6ae832479 100644 --- a/editor/import/resource_importer_dynamic_font.cpp +++ b/editor/import/resource_importer_dynamic_font.cpp @@ -76,6 +76,9 @@ bool ResourceImporterDynamicFont::get_option_visibility(const String &p_path, co if (p_option == "msdf_size" && !bool(p_options["multichannel_signed_distance_field"])) { return false; } + if (p_option == "antialiasing" && bool(p_options["multichannel_signed_distance_field"])) { + return false; + } if (p_option == "oversampling" && bool(p_options["multichannel_signed_distance_field"])) { return false; } @@ -105,7 +108,7 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List< r_options->push_back(ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant())); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel"), 1)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD Subpixel"), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), (msdf) ? true : false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8)); @@ -113,7 +116,7 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List< r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One Half of a Pixel,One Quarter of a Pixel"), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0)); r_options->push_back(ImportOption(PropertyInfo(Variant::NIL, "Fallbacks", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant())); diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp index 58c2061051..9d15854707 100644 --- a/editor/import/resource_importer_imagefont.cpp +++ b/editor/import/resource_importer_imagefont.cpp @@ -63,7 +63,8 @@ void ResourceImporterImageFont::get_import_options(const String &p_path, List<Im r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "character_ranges"), Vector<String>())); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "columns"), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "rows"), 1)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "font_size"), 14)); + r_options->push_back(ImportOption(PropertyInfo(Variant::RECT2I, "image_margin"), Rect2i())); + r_options->push_back(ImportOption(PropertyInfo(Variant::RECT2I, "character_margin"), Rect2i())); r_options->push_back(ImportOption(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), Array())); @@ -93,33 +94,39 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin int columns = p_options["columns"]; int rows = p_options["rows"]; - int base_size = p_options["font_size"]; Vector<String> ranges = p_options["character_ranges"]; Array fallbacks = p_options["fallbacks"]; + Rect2i img_margin = p_options["image_margin"]; + Rect2i char_margin = p_options["character_margin"]; + + Ref<Image> img; + img.instantiate(); + Error err = ImageLoader::load_image(p_source_file, img); + ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_READ, TTR("Can't load font texture:") + " \"" + p_source_file + "\"."); + + int count = columns * rows; + int chr_cell_width = (img->get_width() - img_margin.position.x - img_margin.size.x) / columns; + int chr_cell_height = (img->get_height() - img_margin.position.y - img_margin.size.y) / rows; + ERR_FAIL_COND_V_MSG(chr_cell_width <= 0 || chr_cell_height <= 0, ERR_FILE_CANT_READ, TTR("Image margin too big.")); + + int chr_width = chr_cell_width - char_margin.position.x - char_margin.size.x; + int chr_height = chr_cell_height - char_margin.position.y - char_margin.size.y; + ERR_FAIL_COND_V_MSG(chr_width <= 0 || chr_height <= 0, ERR_FILE_CANT_READ, TTR("Character margin too bit.")); Ref<FontFile> font; font.instantiate(); font->set_antialiasing(TextServer::FONT_ANTIALIASING_NONE); font->set_generate_mipmaps(false); font->set_multichannel_signed_distance_field(false); - font->set_fixed_size(base_size); + font->set_fixed_size(chr_height); font->set_subpixel_positioning(TextServer::SUBPIXEL_POSITIONING_DISABLED); font->set_force_autohinter(false); font->set_hinting(TextServer::HINTING_NONE); font->set_oversampling(1.0f); font->set_fallbacks(fallbacks); + font->set_texture_image(0, Vector2i(chr_height, 0), 0, img); - Ref<Image> img; - img.instantiate(); - Error err = ImageLoader::load_image(p_source_file, img); - ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_READ, TTR("Can't load font texture:") + " \"" + p_source_file + "\"."); - font->set_texture_image(0, Vector2i(base_size, 0), 0, img); - - int count = columns * rows; - int chr_width = img->get_width() / columns; - int chr_height = img->get_height() / rows; int pos = 0; - for (int i = 0; i < ranges.size(); i++) { int32_t start, end; Vector<String> tokens = ranges[i].split("-"); @@ -141,17 +148,17 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin for (int32_t idx = start; idx <= end; idx++) { int x = pos % columns; int y = pos / columns; - font->set_glyph_advance(0, base_size, idx, Vector2(chr_width, 0)); - font->set_glyph_offset(0, Vector2i(base_size, 0), idx, Vector2(0, -0.5 * chr_height)); - font->set_glyph_size(0, Vector2i(base_size, 0), idx, Vector2(chr_width, chr_height)); - font->set_glyph_uv_rect(0, Vector2i(base_size, 0), idx, Rect2(chr_width * x, chr_height * y, chr_width, chr_height)); - font->set_glyph_texture_idx(0, Vector2i(base_size, 0), idx, 0); + font->set_glyph_advance(0, chr_height, idx, Vector2(chr_width, 0)); + font->set_glyph_offset(0, Vector2i(chr_height, 0), idx, Vector2(0, -0.5 * chr_height)); + font->set_glyph_size(0, Vector2i(chr_height, 0), idx, Vector2(chr_width, chr_height)); + font->set_glyph_uv_rect(0, Vector2i(chr_height, 0), idx, Rect2(img_margin.position.x + chr_cell_width * x + char_margin.position.x, img_margin.position.y + chr_cell_height * y + char_margin.position.y, chr_width, chr_height)); + font->set_glyph_texture_idx(0, Vector2i(chr_height, 0), idx, 0); pos++; - ERR_FAIL_COND_V_MSG(pos >= count, ERR_CANT_CREATE, "Too many characters in range."); + ERR_FAIL_COND_V_MSG(pos >= count, ERR_CANT_CREATE, "Too many characters in range, should be " + itos(columns * rows)); } } - font->set_cache_ascent(0, base_size, 0.5 * chr_height); - font->set_cache_descent(0, base_size, 0.5 * chr_height); + font->set_cache_ascent(0, chr_height, 0.5 * chr_height); + font->set_cache_descent(0, chr_height, 0.5 * chr_height); int flg = 0; if ((bool)p_options["compress"]) { 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/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 8ede88a888..f7a3ce2679 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -402,7 +402,7 @@ void _rescale_importer_mesh(Vector3 p_scale, Ref<ImporterMesh> p_mesh, bool is_s const int fmt_compress_flags = p_mesh->get_surface_format(surf_idx); Array arr = p_mesh->get_surface_arrays(surf_idx); String name = p_mesh->get_surface_name(surf_idx); - Dictionary lods = Dictionary(); + Dictionary lods; Ref<Material> mat = p_mesh->get_surface_material(surf_idx); { Vector<Vector3> vertex_array = arr[ArrayMesh::ARRAY_VERTEX]; @@ -1276,14 +1276,12 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< } break; } - int idx = 0; for (const Ref<Shape3D> &E : shapes) { CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E); base->add_child(cshape, true); cshape->set_owner(base->get_owner()); - idx++; } } } diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index 1dcae2841b..f5a0f0abcf 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -107,7 +107,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s file->get_buffer((uint8_t *)&riff, 4); //RIFF if (riff[0] != 'R' || riff[1] != 'I' || riff[2] != 'F' || riff[3] != 'F') { - ERR_FAIL_V(ERR_FILE_UNRECOGNIZED); + ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, vformat("Not a WAV file. File should start with 'RIFF', but found '%s', in file of size %d bytes", riff, file->get_length())); } /* GET FILESIZE */ @@ -115,12 +115,12 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s /* CHECK WAVE */ - char wave[4]; - - file->get_buffer((uint8_t *)&wave, 4); //RIFF + char wave[5]; + wave[4] = 0; + file->get_buffer((uint8_t *)&wave, 4); //WAVE if (wave[0] != 'W' || wave[1] != 'A' || wave[2] != 'V' || wave[3] != 'E') { - ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Not a WAV file (no WAVE RIFF header)."); + ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, vformat("Not a WAV file. Header should contain 'WAVE', but found '%s', in file of size %d bytes", wave, file->get_length())); } // Let users override potential loop points from the WAV. 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/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index a7ebf21cd2..affb31945d 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -36,6 +36,7 @@ #include "editor/editor_plugin.h" #include "editor/editor_scale.h" #include "editor/project_settings_editor.h" +#include "scene/gui/grid_container.h" void PluginConfigDialog::_clear_fields() { name_edit->set_text(""); 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..8414945223 100644 --- a/editor/plugins/abstract_polygon_2d_editor.h +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -36,7 +36,7 @@ #include "scene/gui/box_container.h" class CanvasItemEditor; -class EditorUndoRedoManager; +class ConfirmationDialog; class AbstractPolygon2DEditor : public HBoxContainer { GDCLASS(AbstractPolygon2DEditor, HBoxContainer); @@ -100,8 +100,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_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h index c8b01cb54b..54aa227c96 100644 --- a/editor/plugins/animation_blend_space_1d_editor.h +++ b/editor/plugins/animation_blend_space_1d_editor.h @@ -40,7 +40,8 @@ #include "scene/gui/separator.h" #include "scene/gui/tree.h" -class EditorUndoRedoManager; +class CheckBox; +class PanelContainer; class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin { GDCLASS(AnimationNodeBlendSpace1DEditor, AnimationTreeNodeEditorPlugin); diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index 6f206ff445..3ec8324e1d 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -42,6 +42,7 @@ #include "editor/editor_undo_redo_manager.h" #include "scene/animation/animation_blend_tree.h" #include "scene/animation/animation_player.h" +#include "scene/gui/grid_container.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" #include "scene/main/window.h" diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h index 1f015a1804..e4512b78a3 100644 --- a/editor/plugins/animation_blend_space_2d_editor.h +++ b/editor/plugins/animation_blend_space_2d_editor.h @@ -40,6 +40,10 @@ #include "scene/gui/separator.h" #include "scene/gui/tree.h" +class CheckBox; +class OptionButton; +class PanelContainer; + class EditorUndoRedoManager; class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin { diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h index b55fc3b617..112c824d8e 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.h +++ b/editor/plugins/animation_blend_tree_editor_plugin.h @@ -31,17 +31,22 @@ #ifndef ANIMATION_BLEND_TREE_EDITOR_PLUGIN_H #define ANIMATION_BLEND_TREE_EDITOR_PLUGIN_H -#include "editor/editor_plugin.h" #include "editor/plugins/animation_tree_editor_plugin.h" #include "scene/animation/animation_blend_tree.h" #include "scene/gui/button.h" #include "scene/gui/graph_edit.h" +#include "scene/gui/panel_container.h" #include "scene/gui/popup.h" #include "scene/gui/tree.h" +class AcceptDialog; +class CheckBox; class ProgressBar; class EditorFileDialog; +class EditorProperty; class EditorUndoRedoManager; +class MenuButton; +class PanelContainer; class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { GDCLASS(AnimationNodeBlendTreeEditor, AnimationTreeNodeEditorPlugin); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index b4737976d8..85739d0d8f 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); @@ -944,7 +950,7 @@ void AnimationPlayerEditor::_update_animation_list_icons() { } void AnimationPlayerEditor::_update_name_dialog_library_dropdown() { - StringName current_library_name = StringName(); + StringName current_library_name; if (animation->has_selectable_items()) { String current_animation_name = animation->get_item_text(animation->get_selected()); Ref<Animation> current_animation = player->get_animation(current_animation_name); @@ -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/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index c32f9b1775..cc709182a8 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -420,7 +420,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv if (mm.is_valid()) { state_machine_draw->grab_focus(); - String new_over_node = StringName(); + String new_over_node; int new_over_node_what = -1; if (tool_select->is_pressed()) { for (int i = node_rects.size() - 1; i >= 0; i--) { // Inverse to draw order. diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index d0828a5f52..180f238834 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -31,16 +31,17 @@ #ifndef ANIMATION_STATE_MACHINE_EDITOR_H #define ANIMATION_STATE_MACHINE_EDITOR_H -#include "editor/editor_plugin.h" #include "editor/plugins/animation_tree_editor_plugin.h" #include "scene/animation/animation_node_state_machine.h" -#include "scene/gui/button.h" #include "scene/gui/graph_edit.h" #include "scene/gui/popup.h" #include "scene/gui/tree.h" +class ConfirmationDialog; class EditorFileDialog; class EditorUndoRedoManager; +class OptionButton; +class PanelContainer; class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { GDCLASS(AnimationNodeStateMachineEditor, AnimationTreeNodeEditorPlugin); diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index 070d25e29f..2795892c2e 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -50,6 +50,9 @@ #include "scene/gui/texture_button.h" #include "scene/main/http_request.h" +class EditorFileDialog; +class MenuButton; + class EditorAssetLibraryItem : public PanelContainer { GDCLASS(EditorAssetLibraryItem, PanelContainer); diff --git a/editor/plugins/bit_map_editor_plugin.h b/editor/plugins/bit_map_editor_plugin.h index b045f8c751..8c65b1b6f1 100644 --- a/editor/plugins/bit_map_editor_plugin.h +++ b/editor/plugins/bit_map_editor_plugin.h @@ -31,9 +31,12 @@ #ifndef BIT_MAP_EDITOR_PLUGIN_H #define BIT_MAP_EDITOR_PLUGIN_H +#include "editor/editor_inspector.h" #include "editor/editor_plugin.h" #include "scene/resources/bit_map.h" +class TextureRect; + class BitMapEditor : public VBoxContainer { GDCLASS(BitMapEditor, VBoxContainer); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 291b939fe9..5584b0299c 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -412,7 +412,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig // Other nodes sides if ((is_snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) { - Transform2D to_snap_transform = Transform2D(); + Transform2D to_snap_transform; List<const CanvasItem *> exceptions = List<const CanvasItem *>(); for (const CanvasItem *E : p_other_nodes_exceptions) { exceptions.push_back(E); @@ -813,7 +813,7 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2 Rect2 parent_rect = p_control->get_parent_anchorable_rect(); - Vector2 output = Vector2(); + Vector2 output; if (p_control->is_layout_rtl()) { output.x = (parent_rect.size.x == 0) ? 0.0 : (parent_rect.size.x - p_control->get_transform().xform(position).x - parent_rect.position.x) / parent_rect.size.x; } else { @@ -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); @@ -927,13 +928,12 @@ void CanvasItemEditor::_add_node_pressed(int p_result) { [[fallthrough]]; } case ADD_MOVE: { - if (p_result == ADD_MOVE) { - nodes_to_move = EditorNode::get_singleton()->get_editor_selection()->get_selected_node_list(); - } + nodes_to_move = EditorNode::get_singleton()->get_editor_selection()->get_selected_node_list(); if (nodes_to_move.is_empty()) { 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 +1022,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; @@ -1728,22 +1729,16 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { drag_to = transform.affine_inverse().xform(m->get_position()); - Transform2D xform = ci->get_global_transform_with_canvas().affine_inverse(); + Transform2D xform = ci->get_global_transform_with_canvas(); Point2 drag_to_snapped_begin; Point2 drag_to_snapped_end; - // last call decides which snapping lines are drawn - if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP || drag_type == DRAG_TOP_LEFT) { - drag_to_snapped_end = snap_point(xform.affine_inverse().xform(current_end) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, ci); - drag_to_snapped_begin = snap_point(xform.affine_inverse().xform(current_begin) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, ci); - } else { - drag_to_snapped_begin = snap_point(xform.affine_inverse().xform(current_begin) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, ci); - drag_to_snapped_end = snap_point(xform.affine_inverse().xform(current_end) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, ci); - } + drag_to_snapped_end = snap_point(xform.xform(current_end) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, ci); + drag_to_snapped_begin = snap_point(xform.xform(current_begin) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, ci); - Point2 drag_begin = xform.xform(drag_to_snapped_begin); - Point2 drag_end = xform.xform(drag_to_snapped_end); + Point2 drag_begin = xform.affine_inverse().xform(drag_to_snapped_begin); + Point2 drag_end = xform.affine_inverse().xform(drag_to_snapped_end); // Horizontal resize if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) { @@ -2065,12 +2060,9 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } } - int index = 0; for (CanvasItem *ci : drag_selection) { Transform2D xform = ci->get_global_transform_with_canvas().affine_inverse() * ci->get_transform(); - ci->_edit_set_position(ci->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); - index++; } return true; } @@ -2188,12 +2180,9 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { new_pos = previous_pos + (drag_to - drag_from); } - int index = 0; for (CanvasItem *ci : drag_selection) { Transform2D xform = ci->get_global_transform_with_canvas().affine_inverse() * ci->get_transform(); - ci->_edit_set_position(ci->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); - index++; } } return true; @@ -2279,7 +2268,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } } - String suffix = String(); + String suffix; if (locked == 1) { suffix = " (" + TTR("Locked") + ")"; } else if (locked == 2) { @@ -2801,7 +2790,7 @@ void CanvasItemEditor::_draw_rulers() { int font_size = get_theme_font_size(SNAME("rulers_size"), SNAME("EditorFonts")); // The rule transform - Transform2D ruler_transform = Transform2D(); + Transform2D ruler_transform; if (grid_snap_active || _is_grid_visible()) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (snap_relative && selection.size() > 0) { @@ -2827,11 +2816,11 @@ void CanvasItemEditor::_draw_rulers() { // Subdivisions int major_subdivision = 2; - Transform2D major_subdivide = Transform2D(); + Transform2D major_subdivide; major_subdivide.scale(Size2(1.0 / major_subdivision, 1.0 / major_subdivision)); int minor_subdivision = 5; - Transform2D minor_subdivide = Transform2D(); + Transform2D minor_subdivide; minor_subdivide.scale(Size2(1.0 / minor_subdivision, 1.0 / minor_subdivision)); // First and last graduations to draw (in the ruler space) @@ -3043,7 +3032,7 @@ void CanvasItemEditor::_draw_ruler_tool() { viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); - Point2 v_angle_text_pos = Point2(); + Point2 v_angle_text_pos; v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width); v_angle_text_pos.y = begin.y < end.y ? MIN(text_pos2.y - 2 * text_height, begin.y - text_height * 0.5) : MAX(text_pos2.y + text_height * 3, begin.y + text_height * 1.5); viewport->draw_string_outline(font, v_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); @@ -3054,7 +3043,7 @@ void CanvasItemEditor::_draw_ruler_tool() { viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); - Point2 h_angle_text_pos = Point2(); + Point2 h_angle_text_pos; h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width); if (begin.y < end.y) { h_angle_text_pos.y = end.y + text_height * 1.5; @@ -4000,10 +3989,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 +4263,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 +4969,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 +5419,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 +5565,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 +5605,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 +5614,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 +5639,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 +5662,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 +5680,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 +5712,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 +5738,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 +5905,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..cc98aa8c51 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -42,10 +42,12 @@ #include "scene/gui/texture_rect.h" #include "scene/main/canvas_item.h" +class AcceptDialog; +class ConfirmationDialog; class EditorData; class CanvasItemEditorViewport; +class MenuButton; class ViewPanner; -class EditorUndoRedoManager; class CanvasItemEditorSelectedItem : public Object { GDCLASS(CanvasItemEditorSelectedItem, Object); @@ -337,12 +339,12 @@ private: Point2 drag_start_origin; DragType drag_type = DRAG_NONE; - Point2 drag_from = Vector2(); - Point2 drag_to = Vector2(); + Point2 drag_from; + Point2 drag_to; Point2 drag_rotation_center; List<CanvasItem *> drag_selection; int dragged_guide_index = -1; - Point2 dragged_guide_pos = Point2(); + Point2 dragged_guide_pos; bool is_hovering_h_guide = false; bool is_hovering_v_guide = false; @@ -401,8 +403,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 +548,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 +592,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/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp index bb6092755e..00b7845cee 100644 --- a/editor/plugins/control_editor_plugin.cpp +++ b/editor/plugins/control_editor_plugin.cpp @@ -35,6 +35,7 @@ #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" #include "editor/plugins/canvas_item_editor_plugin.h" +#include "scene/gui/grid_container.h" #include "scene/gui/separator.h" // Inspector controls. @@ -810,25 +811,12 @@ void ControlEditorToolbar::_container_flags_selected(int p_flags, bool p_vertica undo_redo->commit_action(); } -Vector2 ControlEditorToolbar::_anchor_to_position(const Control *p_control, Vector2 anchor) { - ERR_FAIL_COND_V(!p_control, Vector2()); - - Transform2D parent_transform = p_control->get_transform().affine_inverse(); - Rect2 parent_rect = p_control->get_parent_anchorable_rect(); - - if (p_control->is_layout_rtl()) { - return parent_transform.xform(parent_rect.position + Vector2(parent_rect.size.x - parent_rect.size.x * anchor.x, parent_rect.size.y * anchor.y)); - } else { - return parent_transform.xform(parent_rect.position + Vector2(parent_rect.size.x * anchor.x, parent_rect.size.y * anchor.y)); - } -} - Vector2 ControlEditorToolbar::_position_to_anchor(const Control *p_control, Vector2 position) { ERR_FAIL_COND_V(!p_control, Vector2()); Rect2 parent_rect = p_control->get_parent_anchorable_rect(); - Vector2 output = Vector2(); + Vector2 output; if (p_control->is_layout_rtl()) { output.x = (parent_rect.size.x == 0) ? 0.0 : (parent_rect.size.x - p_control->get_transform().xform(position).x - parent_rect.position.x) / parent_rect.size.x; } else { diff --git a/editor/plugins/control_editor_plugin.h b/editor/plugins/control_editor_plugin.h index 22267cbc04..14886e77a4 100644 --- a/editor/plugins/control_editor_plugin.h +++ b/editor/plugins/control_editor_plugin.h @@ -31,6 +31,7 @@ #ifndef CONTROL_EDITOR_PLUGIN_H #define CONTROL_EDITOR_PLUGIN_H +#include "editor/editor_inspector.h" #include "editor/editor_plugin.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" @@ -45,6 +46,7 @@ #include "scene/gui/texture_rect.h" class EditorUndoRedoManager; +class GridContainer; // Inspector controls. class ControlPositioningWarning : public MarginContainer { @@ -222,7 +224,6 @@ class ControlEditorToolbar : public HBoxContainer { void _anchor_mode_toggled(bool p_status); void _container_flags_selected(int p_flags, bool p_vertical); - Vector2 _anchor_to_position(const Control *p_control, Vector2 anchor); Vector2 _position_to_anchor(const Control *p_control, Vector2 position); bool _is_node_locked(const Node *p_node); List<Control *> _get_edited_controls(); diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.h b/editor/plugins/cpu_particles_2d_editor_plugin.h index 06ca208463..694162588b 100644 --- a/editor/plugins/cpu_particles_2d_editor_plugin.h +++ b/editor/plugins/cpu_particles_2d_editor_plugin.h @@ -36,10 +36,13 @@ #include "scene/2d/cpu_particles_2d.h" #include "scene/gui/box_container.h" -class EditorPlugin; +class CheckBox; +class ConfirmationDialog; class SpinBox; class EditorFileDialog; class EditorUndoRedoManager; +class MenuButton; +class OptionButton; class CPUParticles2DEditorPlugin : public EditorPlugin { GDCLASS(CPUParticles2DEditorPlugin, EditorPlugin); 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/curve_editor_plugin.h b/editor/plugins/curve_editor_plugin.h index 5cf3b16a06..5503ce96ff 100644 --- a/editor/plugins/curve_editor_plugin.h +++ b/editor/plugins/curve_editor_plugin.h @@ -31,6 +31,7 @@ #ifndef CURVE_EDITOR_PLUGIN_H #define CURVE_EDITOR_PLUGIN_H +#include "editor/editor_inspector.h" #include "editor/editor_plugin.h" #include "editor/editor_resource_preview.h" #include "scene/resources/curve.h" diff --git a/editor/plugins/editor_debugger_plugin.cpp b/editor/plugins/editor_debugger_plugin.cpp index 4ce3d7cfd5..5dd3038c0e 100644 --- a/editor/plugins/editor_debugger_plugin.cpp +++ b/editor/plugins/editor_debugger_plugin.cpp @@ -32,7 +32,7 @@ #include "editor/debugger/script_editor_debugger.h" -void EditorDebuggerPlugin::_breaked(bool p_really_did, bool p_can_debug, String p_message, bool p_has_stackdump) { +void EditorDebuggerSession::_breaked(bool p_really_did, bool p_can_debug, String p_message, bool p_has_stackdump) { if (p_really_did) { emit_signal(SNAME("breaked"), p_can_debug); } else { @@ -40,22 +40,22 @@ void EditorDebuggerPlugin::_breaked(bool p_really_did, bool p_can_debug, String } } -void EditorDebuggerPlugin::_started() { +void EditorDebuggerSession::_started() { emit_signal(SNAME("started")); } -void EditorDebuggerPlugin::_stopped() { +void EditorDebuggerSession::_stopped() { emit_signal(SNAME("stopped")); } -void EditorDebuggerPlugin::_bind_methods() { - ClassDB::bind_method(D_METHOD("send_message", "message", "data"), &EditorDebuggerPlugin::send_message); - ClassDB::bind_method(D_METHOD("register_message_capture", "name", "callable"), &EditorDebuggerPlugin::register_message_capture); - ClassDB::bind_method(D_METHOD("unregister_message_capture", "name"), &EditorDebuggerPlugin::unregister_message_capture); - ClassDB::bind_method(D_METHOD("has_capture", "name"), &EditorDebuggerPlugin::has_capture); - ClassDB::bind_method(D_METHOD("is_breaked"), &EditorDebuggerPlugin::is_breaked); - ClassDB::bind_method(D_METHOD("is_debuggable"), &EditorDebuggerPlugin::is_debuggable); - ClassDB::bind_method(D_METHOD("is_session_active"), &EditorDebuggerPlugin::is_session_active); +void EditorDebuggerSession::_bind_methods() { + ClassDB::bind_method(D_METHOD("send_message", "message", "data"), &EditorDebuggerSession::send_message, DEFVAL(Array())); + ClassDB::bind_method(D_METHOD("toggle_profiler", "profiler", "enable", "data"), &EditorDebuggerSession::toggle_profiler, DEFVAL(Array())); + ClassDB::bind_method(D_METHOD("is_breaked"), &EditorDebuggerSession::is_breaked); + ClassDB::bind_method(D_METHOD("is_debuggable"), &EditorDebuggerSession::is_debuggable); + ClassDB::bind_method(D_METHOD("is_active"), &EditorDebuggerSession::is_active); + ClassDB::bind_method(D_METHOD("add_session_tab", "control"), &EditorDebuggerSession::add_session_tab); + ClassDB::bind_method(D_METHOD("remove_session_tab", "control"), &EditorDebuggerSession::remove_session_tab); ADD_SIGNAL(MethodInfo("started")); ADD_SIGNAL(MethodInfo("stopped")); @@ -63,62 +63,131 @@ void EditorDebuggerPlugin::_bind_methods() { ADD_SIGNAL(MethodInfo("continued")); } -void EditorDebuggerPlugin::attach_debugger(ScriptEditorDebugger *p_debugger) { - debugger = p_debugger; - if (debugger) { - debugger->connect("started", callable_mp(this, &EditorDebuggerPlugin::_started)); - debugger->connect("stopped", callable_mp(this, &EditorDebuggerPlugin::_stopped)); - debugger->connect("breaked", callable_mp(this, &EditorDebuggerPlugin::_breaked)); - } +void EditorDebuggerSession::add_session_tab(Control *p_tab) { + ERR_FAIL_COND(!p_tab || !debugger); + debugger->add_debugger_tab(p_tab); + tabs.insert(p_tab); } -void EditorDebuggerPlugin::detach_debugger(bool p_call_debugger) { - if (debugger) { - debugger->disconnect("started", callable_mp(this, &EditorDebuggerPlugin::_started)); - debugger->disconnect("stopped", callable_mp(this, &EditorDebuggerPlugin::_stopped)); - debugger->disconnect("breaked", callable_mp(this, &EditorDebuggerPlugin::_breaked)); - if (p_call_debugger && get_script_instance()) { - debugger->remove_debugger_plugin(get_script_instance()->get_script()); - } - debugger = nullptr; - } +void EditorDebuggerSession::remove_session_tab(Control *p_tab) { + ERR_FAIL_COND(!p_tab || !debugger); + debugger->remove_debugger_tab(p_tab); + tabs.erase(p_tab); } -void EditorDebuggerPlugin::send_message(const String &p_message, const Array &p_args) { +void EditorDebuggerSession::send_message(const String &p_message, const Array &p_args) { ERR_FAIL_COND_MSG(!debugger, "Plugin is not attached to debugger"); debugger->send_message(p_message, p_args); } -void EditorDebuggerPlugin::register_message_capture(const StringName &p_name, const Callable &p_callable) { +void EditorDebuggerSession::toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data) { ERR_FAIL_COND_MSG(!debugger, "Plugin is not attached to debugger"); - debugger->register_message_capture(p_name, p_callable); + debugger->toggle_profiler(p_profiler, p_enable, p_data); } -void EditorDebuggerPlugin::unregister_message_capture(const StringName &p_name) { - ERR_FAIL_COND_MSG(!debugger, "Plugin is not attached to debugger"); - debugger->unregister_message_capture(p_name); -} - -bool EditorDebuggerPlugin::has_capture(const StringName &p_name) { - ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger"); - return debugger->has_capture(p_name); -} - -bool EditorDebuggerPlugin::is_breaked() { +bool EditorDebuggerSession::is_breaked() { ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger"); return debugger->is_breaked(); } -bool EditorDebuggerPlugin::is_debuggable() { +bool EditorDebuggerSession::is_debuggable() { ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger"); return debugger->is_debuggable(); } -bool EditorDebuggerPlugin::is_session_active() { +bool EditorDebuggerSession::is_active() { ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger"); return debugger->is_session_active(); } +void EditorDebuggerSession::detach_debugger() { + if (!debugger) { + return; + } + debugger->disconnect("started", callable_mp(this, &EditorDebuggerSession::_started)); + debugger->disconnect("stopped", callable_mp(this, &EditorDebuggerSession::_stopped)); + debugger->disconnect("breaked", callable_mp(this, &EditorDebuggerSession::_breaked)); + debugger->disconnect("tree_exited", callable_mp(this, &EditorDebuggerSession::_debugger_gone_away)); + for (Control *tab : tabs) { + debugger->remove_debugger_tab(tab); + } + tabs.clear(); + debugger = nullptr; +} + +void EditorDebuggerSession::_debugger_gone_away() { + debugger = nullptr; + tabs.clear(); +} + +EditorDebuggerSession::EditorDebuggerSession(ScriptEditorDebugger *p_debugger) { + ERR_FAIL_COND(!p_debugger); + debugger = p_debugger; + debugger->connect("started", callable_mp(this, &EditorDebuggerSession::_started)); + debugger->connect("stopped", callable_mp(this, &EditorDebuggerSession::_stopped)); + debugger->connect("breaked", callable_mp(this, &EditorDebuggerSession::_breaked)); + debugger->connect("tree_exited", callable_mp(this, &EditorDebuggerSession::_debugger_gone_away), CONNECT_ONE_SHOT); +} + +EditorDebuggerSession::~EditorDebuggerSession() { + detach_debugger(); +} + +/// EditorDebuggerPlugin + EditorDebuggerPlugin::~EditorDebuggerPlugin() { - detach_debugger(true); + clear(); +} + +void EditorDebuggerPlugin::clear() { + for (int i = 0; i < sessions.size(); i++) { + sessions[i]->detach_debugger(); + } + sessions.clear(); +} + +void EditorDebuggerPlugin::create_session(ScriptEditorDebugger *p_debugger) { + sessions.push_back(Ref<EditorDebuggerSession>(memnew(EditorDebuggerSession(p_debugger)))); + setup_session(sessions.size() - 1); +} + +void EditorDebuggerPlugin::setup_session(int p_idx) { + GDVIRTUAL_CALL(_setup_session, p_idx); +} + +Ref<EditorDebuggerSession> EditorDebuggerPlugin::get_session(int p_idx) { + ERR_FAIL_INDEX_V(p_idx, sessions.size(), nullptr); + return sessions[p_idx]; +} + +Array EditorDebuggerPlugin::get_sessions() { + Array ret; + for (int i = 0; i < sessions.size(); i++) { + ret.push_back(sessions[i]); + } + return ret; +} + +bool EditorDebuggerPlugin::has_capture(const String &p_message) const { + bool ret = false; + if (GDVIRTUAL_CALL(_has_capture, p_message, ret)) { + return ret; + } + return false; +} + +bool EditorDebuggerPlugin::capture(const String &p_message, const Array &p_data, int p_session_id) { + bool ret = false; + if (GDVIRTUAL_CALL(_capture, p_message, p_data, p_session_id, ret)) { + return ret; + } + return false; +} + +void EditorDebuggerPlugin::_bind_methods() { + GDVIRTUAL_BIND(_setup_session, "session_id"); + GDVIRTUAL_BIND(_has_capture, "capture"); + GDVIRTUAL_BIND(_capture, "message", "data", "session_id"); + ClassDB::bind_method(D_METHOD("get_session", "id"), &EditorDebuggerPlugin::get_session); + ClassDB::bind_method(D_METHOD("get_sessions"), &EditorDebuggerPlugin::get_sessions); } diff --git a/editor/plugins/editor_debugger_plugin.h b/editor/plugins/editor_debugger_plugin.h index b602c36912..46f8f17cc2 100644 --- a/editor/plugins/editor_debugger_plugin.h +++ b/editor/plugins/editor_debugger_plugin.h @@ -35,29 +35,62 @@ class ScriptEditorDebugger; -class EditorDebuggerPlugin : public Control { - GDCLASS(EditorDebuggerPlugin, Control); +class EditorDebuggerSession : public RefCounted { + GDCLASS(EditorDebuggerSession, RefCounted); private: + HashSet<Control *> tabs; + ScriptEditorDebugger *debugger = nullptr; void _breaked(bool p_really_did, bool p_can_debug, String p_message, bool p_has_stackdump); void _started(); void _stopped(); + void _debugger_gone_away(); protected: static void _bind_methods(); public: - void attach_debugger(ScriptEditorDebugger *p_debugger); - void detach_debugger(bool p_call_debugger); - void send_message(const String &p_message, const Array &p_args); - void register_message_capture(const StringName &p_name, const Callable &p_callable); - void unregister_message_capture(const StringName &p_name); - bool has_capture(const StringName &p_name); + void detach_debugger(); + + void add_session_tab(Control *p_tab); + void remove_session_tab(Control *p_tab); + void send_message(const String &p_message, const Array &p_args = Array()); + void toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data = Array()); bool is_breaked(); bool is_debuggable(); - bool is_session_active(); + bool is_active(); + + EditorDebuggerSession(ScriptEditorDebugger *p_debugger); + ~EditorDebuggerSession(); +}; + +class EditorDebuggerPlugin : public RefCounted { + GDCLASS(EditorDebuggerPlugin, RefCounted); + +private: + List<Ref<EditorDebuggerSession>> sessions; + +protected: + static void _bind_methods(); + +public: + void create_session(ScriptEditorDebugger *p_debugger); + void clear(); + + virtual void setup_session(int p_idx); + virtual bool capture(const String &p_message, const Array &p_data, int p_session); + virtual bool has_capture(const String &p_capture) const; + + Ref<EditorDebuggerSession> get_session(int p_session_id); + Array get_sessions(); + + GDVIRTUAL3R(bool, _capture, const String &, const Array &, int); + GDVIRTUAL1RC(bool, _has_capture, const String &); + GDVIRTUAL1(_setup_session, int); + + EditorDebuggerPlugin() {} ~EditorDebuggerPlugin(); }; 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/gdextension_export_plugin.h b/editor/plugins/gdextension_export_plugin.h index e1d68d97b5..c5f7d2a047 100644 --- a/editor/plugins/gdextension_export_plugin.h +++ b/editor/plugins/gdextension_export_plugin.h @@ -107,7 +107,7 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p for (const String &E : p_features) { tags.append(E); } - ERR_FAIL_MSG(vformat("Couldn't export extension: %s. No suitable library found for export flags: %s", p_path, String(", ").join(tags))); + ERR_FAIL_MSG(vformat("No suitable library found. The libraries' tags referred to an invalid feature flag. Possible feature flags for your platform: %s", p_path, String(", ").join(tags))); } List<String> dependencies; diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.h b/editor/plugins/gpu_particles_2d_editor_plugin.h index 0229b57c10..0a0ea21c1f 100644 --- a/editor/plugins/gpu_particles_2d_editor_plugin.h +++ b/editor/plugins/gpu_particles_2d_editor_plugin.h @@ -37,8 +37,12 @@ #include "scene/gui/box_container.h" #include "scene/gui/spin_box.h" +class CheckBox; +class ConfirmationDialog; class EditorFileDialog; class EditorUndoRedoManager; +class MenuButton; +class OptionButton; class GPUParticles2DEditorPlugin : public EditorPlugin { GDCLASS(GPUParticles2DEditorPlugin, EditorPlugin); diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.h b/editor/plugins/gpu_particles_3d_editor_plugin.h index 17bdfa6e3f..e5b264cfe4 100644 --- a/editor/plugins/gpu_particles_3d_editor_plugin.h +++ b/editor/plugins/gpu_particles_3d_editor_plugin.h @@ -35,6 +35,10 @@ #include "scene/3d/gpu_particles_3d.h" #include "scene/gui/spin_box.h" +class ConfirmationDialog; +class HBoxContainer; +class MenuButton; +class OptionButton; class SceneTreeDialog; class GPUParticles3DEditorBase : public Control { diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h index 684279039a..2c1f49df29 100644 --- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h +++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h @@ -37,6 +37,7 @@ struct EditorProgress; class EditorFileDialog; +class HBoxContainer; class GPUParticlesCollisionSDF3DEditorPlugin : public EditorPlugin { GDCLASS(GPUParticlesCollisionSDF3DEditorPlugin, EditorPlugin); diff --git a/editor/plugins/gradient_editor.cpp b/editor/plugins/gradient_editor.cpp index 822f303d93..f6d5adcd68 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()); @@ -203,6 +203,7 @@ void GradientEditor::gui_input(const Ref<InputEvent> &p_event) { grabbed = _get_point_from_pos(mb->get_position().x); _show_color_picker(); accept_event(); + return; } // Delete point on right click. diff --git a/editor/plugins/gradient_editor_plugin.h b/editor/plugins/gradient_editor_plugin.h index ab191d83e2..f3859e74d3 100644 --- a/editor/plugins/gradient_editor_plugin.h +++ b/editor/plugins/gradient_editor_plugin.h @@ -31,6 +31,7 @@ #ifndef GRADIENT_EDITOR_PLUGIN_H #define GRADIENT_EDITOR_PLUGIN_H +#include "editor/editor_inspector.h" #include "editor/editor_plugin.h" #include "gradient_editor.h" diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.cpp b/editor/plugins/gradient_texture_2d_editor_plugin.cpp index dc01a52bb3..561dca4fc6 100644 --- a/editor/plugins/gradient_texture_2d_editor_plugin.cpp +++ b/editor/plugins/gradient_texture_2d_editor_plugin.cpp @@ -121,13 +121,12 @@ void GradientTexture2DEditorRect::_notification(int p_what) { Size2 rect_size = get_size(); // Get the size and position to draw the texture and handles at. - size = Size2(texture->get_width() * rect_size.height / texture->get_height(), rect_size.height); - if (size.width > rect_size.width) { - size.width = rect_size.width; - size.height = texture->get_height() * size.width / texture->get_width(); - } - offset = ((rect_size - size + handle_size) / 2).round(); - size -= handle_size; + // Subtract handle sizes so they stay inside the preview, but keep the texture's aspect ratio. + Size2 available_size = rect_size - handle_size; + Size2 ratio = available_size / texture->get_size(); + size = MIN(ratio.x, ratio.y) * texture->get_size(); + offset = ((rect_size - size) / 2).round(); + checkerboard->set_rect(Rect2(offset, size)); draw_set_transform(offset); @@ -180,8 +179,9 @@ GradientTexture2DEditorRect::GradientTexture2DEditorRect() { checkerboard = memnew(TextureRect); checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE); + checkerboard->set_ignore_texture_size(true); checkerboard->set_draw_behind_parent(true); - add_child(checkerboard); + add_child(checkerboard, false, INTERNAL_MODE_FRONT); set_custom_minimum_size(Size2(0, 250 * EDSCALE)); } diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.h b/editor/plugins/gradient_texture_2d_editor_plugin.h index 9faf33152a..0737300498 100644 --- a/editor/plugins/gradient_texture_2d_editor_plugin.h +++ b/editor/plugins/gradient_texture_2d_editor_plugin.h @@ -31,6 +31,7 @@ #ifndef GRADIENT_TEXTURE_2D_EDITOR_PLUGIN_H #define GRADIENT_TEXTURE_2D_EDITOR_PLUGIN_H +#include "editor/editor_inspector.h" #include "editor/editor_plugin.h" #include "editor/editor_spin_slider.h" 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/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h index 8e64434d8b..076fd5e537 100644 --- a/editor/plugins/material_editor_plugin.h +++ b/editor/plugins/material_editor_plugin.h @@ -31,6 +31,7 @@ #ifndef MATERIAL_EDITOR_PLUGIN_H #define MATERIAL_EDITOR_PLUGIN_H +#include "editor/editor_inspector.h" #include "editor/editor_plugin.h" #include "editor/plugins/editor_resource_conversion_plugin.h" #include "scene/3d/camera_3d.h" @@ -45,7 +46,7 @@ class SubViewportContainer; class MaterialEditor : public Control { GDCLASS(MaterialEditor, Control); - Vector2 rot = Vector2(); + Vector2 rot; HBoxContainer *layout_2d = nullptr; ColorRect *rect_instance = nullptr; diff --git a/editor/plugins/mesh_editor_plugin.h b/editor/plugins/mesh_editor_plugin.h index 6394cb1171..b8d6562c5c 100644 --- a/editor/plugins/mesh_editor_plugin.h +++ b/editor/plugins/mesh_editor_plugin.h @@ -31,6 +31,7 @@ #ifndef MESH_EDITOR_PLUGIN_H #define MESH_EDITOR_PLUGIN_H +#include "editor/editor_inspector.h" #include "editor/editor_plugin.h" #include "scene/3d/camera_3d.h" #include "scene/3d/light_3d.h" diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h index 88800227d1..81ba263be0 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.h +++ b/editor/plugins/mesh_instance_3d_editor_plugin.h @@ -35,6 +35,10 @@ #include "scene/3d/mesh_instance_3d.h" #include "scene/gui/spin_box.h" +class AcceptDialog; +class ConfirmationDialog; +class MenuButton; + class MeshInstance3DEditor : public Control { GDCLASS(MeshInstance3DEditor, Control); diff --git a/editor/plugins/multimesh_editor_plugin.h b/editor/plugins/multimesh_editor_plugin.h index 5773989d0d..76f86cfa5d 100644 --- a/editor/plugins/multimesh_editor_plugin.h +++ b/editor/plugins/multimesh_editor_plugin.h @@ -36,6 +36,10 @@ #include "scene/gui/slider.h" #include "scene/gui/spin_box.h" +class AcceptDialog; +class ConfirmationDialog; +class MenuButton; +class OptionButton; class SceneTreeDialog; class MultiMeshEditor : public Control { 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 0f0d60c171..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]; } } } diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 5309a028a9..5929807f98 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" @@ -1328,7 +1329,7 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) { } } - String suffix = String(); + String suffix; if (locked == 1) { suffix = " (" + TTR("Locked") + ")"; } else if (locked == 2) { @@ -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; @@ -3490,7 +3492,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() { } for (int i = 0; i < 3; i++) { - Transform3D axis_angle = Transform3D(); + Transform3D axis_angle; if (xform.basis.get_column(i).normalized().dot(xform.basis.get_column((i + 1) % 3).normalized()) < 1.0) { axis_angle = axis_angle.looking_at(xform.basis.get_column(i).normalized(), xform.basis.get_column((i + 1) % 3).normalized()); } @@ -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: @@ -6775,8 +6803,8 @@ void Node3DEditor::_init_grid() { // Don't draw lines over the origin if it's enabled. if (!(origin_enabled && Math::is_zero_approx(position_a))) { - Vector3 line_bgn = Vector3(); - Vector3 line_end = Vector3(); + Vector3 line_bgn; + Vector3 line_end; line_bgn[a] = position_a; line_end[a] = position_a; line_bgn[b] = bgn_b; @@ -6791,8 +6819,8 @@ void Node3DEditor::_init_grid() { } if (!(origin_enabled && Math::is_zero_approx(position_b))) { - Vector3 line_bgn = Vector3(); - Vector3 line_end = Vector3(); + Vector3 line_bgn; + Vector3 line_end; line_bgn[b] = position_b; line_end[b] = position_b; line_bgn[a] = bgn_a; @@ -6960,8 +6988,8 @@ void Node3DEditor::_snap_selected_nodes_to_floor() { for (Node *E : selection) { Node3D *sp = Object::cast_to<Node3D>(E); if (sp) { - Vector3 from = Vector3(); - Vector3 position_offset = Vector3(); + Vector3 from; + Vector3 position_offset; // Priorities for snapping to floor are CollisionShapes, VisualInstances and then origin HashSet<VisualInstance3D *> vi = _get_child_nodes<VisualInstance3D>(sp); @@ -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..a8d3bfb70c 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -39,6 +39,7 @@ #include "scene/3d/light_3d.h" #include "scene/3d/visual_instance_3d.h" #include "scene/3d/world_environment.h" +#include "scene/gui/box_container.h" #include "scene/gui/color_picker.h" #include "scene/gui/panel_container.h" #include "scene/gui/spin_box.h" @@ -47,13 +48,17 @@ #include "scene/resources/fog_material.h" #include "scene/resources/sky_material.h" +class AcceptDialog; +class CheckBox; +class ConfirmationDialog; class EditorData; +class MenuButton; class Node3DEditor; class Node3DEditorViewport; +class OptionButton; class SubViewportContainer; class DirectionalLight3D; class WorldEnvironment; -class EditorUndoRedoManager; class ViewportRotationControl : public Control { GDCLASS(ViewportRotationControl, Control); @@ -203,9 +208,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; @@ -572,7 +575,7 @@ private: bool grid_enabled = false; bool grid_init_draw = false; Camera3D::ProjectionType grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE; - Vector3 grid_camera_last_update_position = Vector3(); + Vector3 grid_camera_last_update_position; Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[4], scale_gizmo[3], scale_plane_gizmo[3], axis_gizmo[3]; Ref<StandardMaterial3D> gizmo_color[3]; @@ -686,7 +689,6 @@ private: HBoxContainer *context_menu_hbox = nullptr; void _generate_selection_boxes(); - Ref<EditorUndoRedoManager> undo_redo; int camera_override_viewport_id; @@ -835,9 +837,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/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h index 13eca79010..d2015b2bb8 100644 --- a/editor/plugins/path_2d_editor_plugin.h +++ b/editor/plugins/path_2d_editor_plugin.h @@ -33,10 +33,12 @@ #include "editor/editor_plugin.h" #include "scene/2d/path_2d.h" +#include "scene/gui/box_container.h" #include "scene/gui/separator.h" class CanvasItemEditor; class EditorUndoRedoManager; +class MenuButton; class Path2DEditor : public HBoxContainer { GDCLASS(Path2DEditor, HBoxContainer); diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h index 11a640b79f..a2816c89ae 100644 --- a/editor/plugins/path_3d_editor_plugin.h +++ b/editor/plugins/path_3d_editor_plugin.h @@ -37,6 +37,8 @@ #include "scene/3d/path_3d.h" #include "scene/gui/separator.h" +class MenuButton; + class Path3DGizmo : public EditorNode3DGizmo { GDCLASS(Path3DGizmo, EditorNode3DGizmo); 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/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index d878d3f9af..6021401e4f 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -33,11 +33,17 @@ #include "editor/plugins/abstract_polygon_2d_editor.h" +class AcceptDialog; +class ButtonGroup; +class HScrollBar; class HSlider; +class MenuButton; class Panel; class ScrollContainer; class SpinBox; +class TextureRect; class ViewPanner; +class VScrollBar; class Polygon2DEditor : public AbstractPolygon2DEditor { GDCLASS(Polygon2DEditor, AbstractPolygon2DEditor); diff --git a/editor/plugins/polygon_3d_editor_plugin.h b/editor/plugins/polygon_3d_editor_plugin.h index 918072b429..fe8e2ce36d 100644 --- a/editor/plugins/polygon_3d_editor_plugin.h +++ b/editor/plugins/polygon_3d_editor_plugin.h @@ -34,10 +34,12 @@ #include "editor/editor_plugin.h" #include "scene/3d/collision_polygon_3d.h" #include "scene/3d/mesh_instance_3d.h" +#include "scene/gui/box_container.h" #include "scene/resources/immediate_mesh.h" class CanvasItemEditor; class EditorUndoRedoManager; +class MenuButton; class Polygon3DEditor : public HBoxContainer { GDCLASS(Polygon3DEditor, HBoxContainer); 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/resource_preloader_editor_plugin.h b/editor/plugins/resource_preloader_editor_plugin.h index ef80283dae..59641e2561 100644 --- a/editor/plugins/resource_preloader_editor_plugin.h +++ b/editor/plugins/resource_preloader_editor_plugin.h @@ -33,6 +33,7 @@ #include "editor/editor_plugin.h" #include "scene/gui/dialogs.h" +#include "scene/gui/panel_container.h" #include "scene/gui/tree.h" #include "scene/main/resource_preloader.h" diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp index de30c4100d..a38a040814 100644 --- a/editor/plugins/root_motion_editor_plugin.cpp +++ b/editor/plugins/root_motion_editor_plugin.cpp @@ -30,6 +30,8 @@ #include "root_motion_editor_plugin.h" #include "editor/editor_node.h" +#include "scene/animation/animation_player.h" +#include "scene/animation/animation_tree.h" #include "scene/main/window.h" void EditorPropertyRootMotion::_confirmed() { diff --git a/editor/plugins/root_motion_editor_plugin.h b/editor/plugins/root_motion_editor_plugin.h index 5b8c1d77b3..7134b48c36 100644 --- a/editor/plugins/root_motion_editor_plugin.h +++ b/editor/plugins/root_motion_editor_plugin.h @@ -32,9 +32,8 @@ #define ROOT_MOTION_EDITOR_PLUGIN_H #include "editor/editor_inspector.h" -#include "editor/editor_spin_slider.h" -#include "editor/property_selector.h" -#include "scene/animation/animation_tree.h" + +class Tree; class EditorPropertyRootMotion : public EditorProperty { GDCLASS(EditorPropertyRootMotion, EditorProperty); 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/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index a45ce4cc22..3f84ded0a2 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -48,6 +48,7 @@ #include "scene/resources/text_file.h" class EditorFileDialog; +class TextureRect; class EditorSyntaxHighlighter : public SyntaxHighlighter { GDCLASS(EditorSyntaxHighlighter, SyntaxHighlighter) 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/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index 7638778af7..1ae419053e 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -35,6 +35,7 @@ class HSplitContainer; class ItemList; +class MenuButton; class ShaderCreateDialog; class TabContainer; class TextShaderEditor; diff --git a/editor/plugins/skeleton_2d_editor_plugin.h b/editor/plugins/skeleton_2d_editor_plugin.h index 295725b751..6794f72955 100644 --- a/editor/plugins/skeleton_2d_editor_plugin.h +++ b/editor/plugins/skeleton_2d_editor_plugin.h @@ -35,6 +35,9 @@ #include "scene/2d/skeleton_2d.h" #include "scene/gui/spin_box.h" +class AcceptDialog; +class MenuButton; + class Skeleton2DEditor : public Control { GDCLASS(Skeleton2DEditor, Control); diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 7922a768ec..58c25c1a5d 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -1288,7 +1288,7 @@ void Skeleton3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gi ERR_FAIL_COND(!skeleton); // Prepare for global to local. - Transform3D original_to_local = Transform3D(); + Transform3D original_to_local; int parent_idx = skeleton->get_bone_parent(p_id); if (parent_idx >= 0) { original_to_local = original_to_local * skeleton->get_bone_global_pose(parent_idx); @@ -1296,7 +1296,7 @@ void Skeleton3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gi Basis to_local = original_to_local.get_basis().inverse(); // Prepare transform. - Transform3D t = Transform3D(); + Transform3D t; // Basis. t.basis = to_local * p_transform.get_basis(); diff --git a/editor/plugins/sprite_2d_editor_plugin.h b/editor/plugins/sprite_2d_editor_plugin.h index b87f108bd2..ae1083ed41 100644 --- a/editor/plugins/sprite_2d_editor_plugin.h +++ b/editor/plugins/sprite_2d_editor_plugin.h @@ -35,6 +35,10 @@ #include "scene/2d/sprite_2d.h" #include "scene/gui/spin_box.h" +class AcceptDialog; +class ConfirmationDialog; +class MenuButton; + class Sprite2DEditor : public Control { GDCLASS(Sprite2DEditor, Control); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index d3ab5b6f77..cf8cc71db7 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -1525,7 +1525,7 @@ SpriteFramesEditor::SpriteFramesEditor() { _zoom_reset(); // Ensure the anim search box is wide enough by default. - // Not by setting its minimum size so it can still be shrinked if desired. + // Not by setting its minimum size so it can still be shrunk if desired. set_split_offset(56 * EDSCALE); } diff --git a/editor/plugins/texture_3d_editor_plugin.h b/editor/plugins/texture_3d_editor_plugin.h index 7795c83c8a..6790f6f2d5 100644 --- a/editor/plugins/texture_3d_editor_plugin.h +++ b/editor/plugins/texture_3d_editor_plugin.h @@ -31,6 +31,7 @@ #ifndef TEXTURE_3D_EDITOR_PLUGIN_H #define TEXTURE_3D_EDITOR_PLUGIN_H +#include "editor/editor_inspector.h" #include "editor/editor_plugin.h" #include "scene/gui/spin_box.h" #include "scene/resources/shader.h" diff --git a/editor/plugins/texture_editor_plugin.h b/editor/plugins/texture_editor_plugin.h index 9beada556c..d7312bfcb4 100644 --- a/editor/plugins/texture_editor_plugin.h +++ b/editor/plugins/texture_editor_plugin.h @@ -31,9 +31,13 @@ #ifndef TEXTURE_EDITOR_PLUGIN_H #define TEXTURE_EDITOR_PLUGIN_H +#include "editor/editor_inspector.h" #include "editor/editor_plugin.h" +#include "scene/gui/margin_container.h" #include "scene/resources/texture.h" +class TextureRect; + class TexturePreview : public MarginContainer { GDCLASS(TexturePreview, MarginContainer); diff --git a/editor/plugins/texture_layered_editor_plugin.h b/editor/plugins/texture_layered_editor_plugin.h index f4dbc104c8..16a2f65386 100644 --- a/editor/plugins/texture_layered_editor_plugin.h +++ b/editor/plugins/texture_layered_editor_plugin.h @@ -31,6 +31,7 @@ #ifndef TEXTURE_LAYERED_EDITOR_PLUGIN_H #define TEXTURE_LAYERED_EDITOR_PLUGIN_H +#include "editor/editor_inspector.h" #include "editor/editor_plugin.h" #include "scene/gui/spin_box.h" #include "scene/resources/shader.h" diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index f0a08cb4f5..b0c8597adf 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")); @@ -242,7 +242,7 @@ void TextureRegionEditor::_region_draw() { hscroll->set_value((hscroll->get_min() + hscroll->get_max() - hscroll->get_page()) / 2); vscroll->set_value((vscroll->get_min() + vscroll->get_max() - vscroll->get_page()) / 2); // This ensures that the view is updated correctly. - callable_mp(this, &TextureRegionEditor::_pan_callback).bind(Vector2(1, 0)).call_deferredp(nullptr, 0); + callable_mp(this, &TextureRegionEditor::_pan_callback).bind(Vector2(1, 0)).call_deferred(); request_center = false; } @@ -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..48cbb6b70e 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -32,6 +32,7 @@ #define TEXTURE_REGION_EDITOR_PLUGIN_H #include "canvas_item_editor_plugin.h" +#include "editor/editor_inspector.h" #include "editor/editor_plugin.h" #include "scene/2d/sprite_2d.h" #include "scene/3d/sprite_3d.h" @@ -41,6 +42,7 @@ class ViewPanner; class EditorUndoRedoManager; +class OptionButton; class TextureRegionEditor : public AcceptDialog { GDCLASS(TextureRegionEditor, AcceptDialog); @@ -86,6 +88,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/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h index 9f89a047cb..b54aa5de6c 100644 --- a/editor/plugins/theme_editor_plugin.h +++ b/editor/plugins/theme_editor_plugin.h @@ -45,6 +45,8 @@ #include "scene/resources/theme.h" class EditorFileDialog; +class PanelContainer; +class TabContainer; class ThemeItemImportTree : public VBoxContainer { GDCLASS(ThemeItemImportTree, VBoxContainer); diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 69104cadec..4fe7178e7e 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -192,6 +192,19 @@ void TileAtlasView::_draw_base_tiles() { rect = rect.intersection(Rect2i(Vector2(), texture->get_size())); if (rect.size.x > 0 && rect.size.y > 0) { base_tiles_draw->draw_texture_rect_region(texture, rect, rect); + } + } + } + } + + // Draw dark overlay after for performance reasons. + for (int x = 0; x < grid_size.x; x++) { + for (int y = 0; y < grid_size.y; y++) { + Vector2i coords = Vector2i(x, y); + if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) { + Rect2i rect = Rect2i((texture_region_size + separation) * coords + margins, texture_region_size + separation); + rect = rect.intersection(Rect2i(Vector2(), texture->get_size())); + if (rect.size.x > 0 && rect.size.y > 0) { base_tiles_draw->draw_rect(rect, Color(0.0, 0.0, 0.0, 0.5)); } } @@ -242,23 +255,34 @@ void TileAtlasView::_draw_base_tiles() { // Draw the tile. TileMap::draw_tile(base_tiles_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, 0, frame); + } + } - // Draw, the texture in the separation areas - if (separation.x > 0) { - Rect2i right_sep_rect = Rect2i(base_frame_rect.get_position() + Vector2i(base_frame_rect.size.x, 0), Vector2i(separation.x, base_frame_rect.size.y)); - right_sep_rect = right_sep_rect.intersection(Rect2i(Vector2(), texture->get_size())); - if (right_sep_rect.size.x > 0 && right_sep_rect.size.y > 0) { - base_tiles_draw->draw_texture_rect_region(texture, right_sep_rect, right_sep_rect); - base_tiles_draw->draw_rect(right_sep_rect, Color(0.0, 0.0, 0.0, 0.5)); + // Draw Dark overlay on separation in its own pass. + if (separation.x > 0 || separation.y > 0) { + for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) { + Vector2i atlas_coords = tile_set_atlas_source->get_tile_id(i); + + for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(atlas_coords); frame++) { + // Update the y to max value. + Rect2i base_frame_rect = tile_set_atlas_source->get_tile_texture_region(atlas_coords, frame); + + if (separation.x > 0) { + Rect2i right_sep_rect = Rect2i(base_frame_rect.get_position() + Vector2i(base_frame_rect.size.x, 0), Vector2i(separation.x, base_frame_rect.size.y)); + right_sep_rect = right_sep_rect.intersection(Rect2i(Vector2(), texture->get_size())); + if (right_sep_rect.size.x > 0 && right_sep_rect.size.y > 0) { + //base_tiles_draw->draw_texture_rect_region(texture, right_sep_rect, right_sep_rect); + base_tiles_draw->draw_rect(right_sep_rect, Color(0.0, 0.0, 0.0, 0.5)); + } } - } - if (separation.y > 0) { - Rect2i bottom_sep_rect = Rect2i(base_frame_rect.get_position() + Vector2i(0, base_frame_rect.size.y), Vector2i(base_frame_rect.size.x + separation.x, separation.y)); - bottom_sep_rect = bottom_sep_rect.intersection(Rect2i(Vector2(), texture->get_size())); - if (bottom_sep_rect.size.x > 0 && bottom_sep_rect.size.y > 0) { - base_tiles_draw->draw_texture_rect_region(texture, bottom_sep_rect, bottom_sep_rect); - base_tiles_draw->draw_rect(bottom_sep_rect, Color(0.0, 0.0, 0.0, 0.5)); + if (separation.y > 0) { + Rect2i bottom_sep_rect = Rect2i(base_frame_rect.get_position() + Vector2i(0, base_frame_rect.size.y), Vector2i(base_frame_rect.size.x + separation.x, separation.y)); + bottom_sep_rect = bottom_sep_rect.intersection(Rect2i(Vector2(), texture->get_size())); + if (bottom_sep_rect.size.x > 0 && bottom_sep_rect.size.y > 0) { + //base_tiles_draw->draw_texture_rect_region(texture, bottom_sep_rect, bottom_sep_rect); + base_tiles_draw->draw_rect(bottom_sep_rect, Color(0.0, 0.0, 0.0, 0.5)); + } } } } diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index f1dfba6f35..ab54a093f2 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; @@ -1997,7 +2002,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() { continue; } Rect2i rect = tile_atlas_view->get_alternative_tile_rect(coords, alternative_tile); - Vector2 position = rect.get_center(); + Vector2 position = rect.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative_tile); Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform(); xform.translate_local(position); @@ -2021,7 +2026,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_unscaled_draw() { continue; } Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E.tile, E.alternative); - Vector2 position = rect.get_center(); + Vector2 position = rect.get_center() + tile_set_atlas_source->get_tile_effective_texture_offset(E.tile, E.alternative); Transform2D xform = alternative_tiles_control->get_parent_control()->get_transform(); xform.translate_local(position); @@ -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/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp index 5b54062632..4239e2c981 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.cpp +++ b/editor/plugins/tiles/tiles_editor_plugin.cpp @@ -92,7 +92,7 @@ void TilesEditorPlugin::_thread() { TypedArray<Vector2i> used_cells = tile_map->get_used_cells(0); - Rect2 encompassing_rect = Rect2(); + Rect2 encompassing_rect; encompassing_rect.set_position(tile_map->map_to_local(used_cells[0])); for (int i = 0; i < used_cells.size(); i++) { Vector2i cell = used_cells[i]; diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h index bdada9ec90..fe0d8179bc 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.h +++ b/editor/plugins/tiles/tiles_editor_plugin.h @@ -71,7 +71,7 @@ private: // For synchronization. int atlas_sources_lists_current = 0; float atlas_view_zoom = 1.0; - Vector2 atlas_view_scroll = Vector2(); + Vector2 atlas_view_scroll; void _tile_map_changed(); 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/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index f7e033d753..5e21215738 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -32,20 +32,13 @@ #define VISUAL_SHADER_EDITOR_PLUGIN_H #include "editor/editor_plugin.h" +#include "editor/editor_properties.h" #include "editor/plugins/editor_resource_conversion_plugin.h" #include "scene/resources/visual_shader.h" -class Button; -class CodeEdit; -class CodeHighlighter; class CurveEditor; class GraphEdit; class GraphNode; -class PopupMenu; -class PopupPanel; -class RichTextLabel; -class TextEdit; -class Tree; class VisualShaderEditor; class EditorUndoRedoManager; diff --git a/editor/plugins/voxel_gi_editor_plugin.h b/editor/plugins/voxel_gi_editor_plugin.h index 43d6f71e26..feff3b4f35 100644 --- a/editor/plugins/voxel_gi_editor_plugin.h +++ b/editor/plugins/voxel_gi_editor_plugin.h @@ -37,6 +37,7 @@ class EditorFileDialog; struct EditorProgress; +class HBoxContainer; class VoxelGIEditorPlugin : public EditorPlugin { GDCLASS(VoxelGIEditorPlugin, EditorPlugin); diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index 78f3b4de0e..8de2833240 100644 --- a/editor/project_converter_3_to_4.cpp +++ b/editor/project_converter_3_to_4.cpp @@ -366,6 +366,7 @@ static const char *gdscript_function_renames[][2] = { { "get_scancode", "get_keycode" }, // InputEventKey { "get_scancode_string", "get_keycode_string" }, // OS { "get_scancode_with_modifiers", "get_keycode_with_modifiers" }, // InputEventKey + { "get_selected_path", "get_current_directory" }, // EditorInterface { "get_shift", "is_shift_pressed" }, // InputEventWithModifiers { "get_size_override", "get_size_2d_override" }, // SubViewport { "get_slide_count", "get_slide_collision_count" }, // CharacterBody2D, CharacterBody3D diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 588746bf64..b2a2566ad4 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -546,7 +546,6 @@ private: Vector<String> failed_files; - int idx = 0; while (ret == UNZ_OK) { //get filename unz_file_info info; @@ -585,7 +584,6 @@ private: } } - idx++; ret = unzGoToNextFile(pkg); } 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..a7124c130b 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(); @@ -1813,7 +1814,7 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V // Sort by tree order, so re-adding is easy. p_nodes.sort_custom<Node::Comparator>(); - editor_data->get_undo_redo()->create_action(TTR("Reparent Node")); + editor_data->get_undo_redo()->create_action(TTR("Reparent Node"), UndoRedo::MERGE_DISABLE, p_nodes[0]); HashMap<Node *, NodePath> path_renames; Vector<StringName> former_names; @@ -1834,14 +1835,17 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V owners.push_back(E); } - if (new_parent == node->get_parent() && node->get_index() < p_position_in_parent + ni) { + bool same_parent = new_parent == node->get_parent(); + if (same_parent && node->get_index() < p_position_in_parent + ni) { inc--; // If the child will generate a gap when moved, adjust. } - editor_data->get_undo_redo()->add_do_method(node->get_parent(), "remove_child", node); - editor_data->get_undo_redo()->add_do_method(new_parent, "add_child", node, true); + if (!same_parent) { + editor_data->get_undo_redo()->add_do_method(node->get_parent(), "remove_child", node); + editor_data->get_undo_redo()->add_do_method(new_parent, "add_child", node, true); + } - if (p_position_in_parent >= 0) { + if (p_position_in_parent >= 0 || same_parent) { editor_data->get_undo_redo()->add_do_method(new_parent, "move_child", node, p_position_in_parent + inc); } @@ -3568,7 +3572,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_dock.h b/editor/scene_tree_dock.h index 04bb4d93e7..6ec9d31ca8 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -46,6 +46,8 @@ #include "scene/gui/tree.h" #include "scene_tree_editor.h" +class TextureRect; + #include "modules/modules_enabled.gen.h" // For regex. #ifdef MODULE_REGEX_ENABLED class RenameDialog; 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/script_create_dialog.cpp b/editor/script_create_dialog.cpp index cc09c3a432..4a3b0e979f 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -275,7 +275,6 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must bool found = false; bool match = false; - int index = 0; for (const String &E : extensions) { if (E.nocasecmp_to(extension) == 0) { found = true; @@ -284,7 +283,6 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must } break; } - index++; } if (!found) { @@ -373,7 +371,7 @@ void ScriptCreateDialog::_create_new() { const ScriptLanguage::ScriptTemplate sinfo = _get_current_template(); String parent_class = parent_name->get_text(); - if (!ClassDB::class_exists(parent_class) && !ScriptServer::is_global_class(parent_class)) { + if (!parent_name->get_text().is_quoted() && !ClassDB::class_exists(parent_class) && !ScriptServer::is_global_class(parent_class)) { // If base is a custom type, replace with script path instead. const EditorData::CustomType *type = EditorNode::get_editor_data().get_custom_type_by_name(parent_class); ERR_FAIL_NULL(type); @@ -855,7 +853,7 @@ ScriptLanguage::ScriptTemplate ScriptCreateDialog::_parse_template(const ScriptL script_template.inherit = p_inherits; String space_indent = " "; // Get meta delimiter - String meta_delimiter = String(); + String meta_delimiter; List<String> comment_delimiters; p_language->get_comment_delimiters(&comment_delimiters); for (const String &script_delimiter : comment_delimiters) { 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); |