diff options
Diffstat (limited to 'editor')
126 files changed, 1521 insertions, 797 deletions
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index 7aa63f899b..6789b5be00 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -248,10 +248,8 @@ void InputEventConfigurationDialog::_listen_window_input(const Ref<InputEvent> & k->set_pressed(false); // to avoid serialisation of 'pressed' property - doesn't matter for actions anyway. // Maintain physical keycode option state if (physical_key_checkbox->is_pressed()) { - k->set_physical_keycode(k->get_keycode()); k->set_keycode(KEY_NONE); } else { - k->set_keycode((Key)k->get_physical_keycode()); k->set_physical_keycode(KEY_NONE); } } diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 89c2e49814..2944dd9991 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -715,7 +715,27 @@ void CodeTextEditor::input(const Ref<InputEvent> &event) { ERR_FAIL_COND(event.is_null()); const Ref<InputEventKey> key_event = event; - if (!key_event.is_valid() || !key_event->is_pressed() || !text_editor->has_focus()) { + + if (!key_event.is_valid()) { + return; + } + if (!key_event->is_pressed()) { + return; + } + + if (!text_editor->has_focus()) { + if ((find_replace_bar != nullptr && find_replace_bar->is_visible()) && (find_replace_bar->has_focus() || find_replace_bar->is_ancestor_of(get_focus_owner()))) { + if (ED_IS_SHORTCUT("script_text_editor/find_next", key_event)) { + find_replace_bar->search_next(); + accept_event(); + return; + } + if (ED_IS_SHORTCUT("script_text_editor/find_previous", key_event)) { + find_replace_bar->search_prev(); + accept_event(); + return; + } + } return; } @@ -814,11 +834,9 @@ void CodeTextEditor::_line_col_changed() { } StringBuilder sb; - sb.append("("); - sb.append(itos(text_editor->get_caret_line() + 1).lpad(3)); - sb.append(","); + sb.append(itos(text_editor->get_caret_line() + 1).lpad(4)); + sb.append(" : "); sb.append(itos(positional_column + 1).lpad(3)); - sb.append(")"); line_and_col_txt->set_text(sb.as_string()); } @@ -1282,7 +1300,9 @@ void CodeTextEditor::_delete_line(int p_line) { text_editor->set_caret_column(0); } text_editor->backspace(); - text_editor->unfold_line(p_line); + if (p_line < text_editor->get_line_count()) { + text_editor->unfold_line(p_line); + } text_editor->set_caret_line(p_line); } @@ -1635,11 +1655,8 @@ void CodeTextEditor::_set_show_warnings_panel(bool p_show) { } void CodeTextEditor::_toggle_scripts_pressed() { - if (is_layout_rtl()) { - toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->toggle_scripts_panel() ? get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")) : get_theme_icon(SNAME("Back"), SNAME("EditorIcons"))); - } else { - toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->toggle_scripts_panel() ? get_theme_icon(SNAME("Back"), SNAME("EditorIcons")) : get_theme_icon(SNAME("Forward"), SNAME("EditorIcons"))); - } + ScriptEditor::get_singleton()->toggle_scripts_panel(); + update_toggle_scripts_button(); } void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) { @@ -1735,7 +1752,7 @@ void CodeTextEditor::goto_prev_bookmark() { text_editor->set_caret_line(bmarks[bmarks.size() - 1]); text_editor->center_viewport_to_caret(); } else { - for (int i = bmarks.size(); i >= 0; i--) { + for (int i = bmarks.size() - 1; i >= 0; i--) { int bmark_line = bmarks[i]; if (bmark_line < line) { text_editor->unfold_line(bmark_line); @@ -1769,11 +1786,11 @@ void CodeTextEditor::show_toggle_scripts_button() { void CodeTextEditor::update_toggle_scripts_button() { if (is_layout_rtl()) { - toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")) : get_theme_icon(SNAME("Back"), SNAME("EditorIcons"))); + toggle_scripts_button->set_icon(get_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Forward") : SNAME("Back"), SNAME("EditorIcons"))); } else { - toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? get_theme_icon(SNAME("Back"), SNAME("EditorIcons")) : get_theme_icon(SNAME("Forward"), SNAME("EditorIcons"))); + toggle_scripts_button->set_icon(get_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Back") : SNAME("Forward"), SNAME("EditorIcons"))); } - toggle_scripts_button->set_tooltip(TTR("Toggle Scripts Panel") + " (" + ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text() + ")"); + toggle_scripts_button->set_tooltip(vformat("%s (%s)", TTR("Toggle Scripts Panel"), ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text())); } CodeTextEditor::CodeTextEditor() { diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index 07c02eb022..be84e8dec5 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -183,16 +183,16 @@ ScriptEditorDebugger *EditorDebuggerNode::get_default_debugger() const { return Object::cast_to<ScriptEditorDebugger>(tabs->get_tab_control(0)); } -Error EditorDebuggerNode::start(const String &p_protocol) { +Error EditorDebuggerNode::start(const String &p_uri) { stop(); + ERR_FAIL_COND_V(p_uri.find("://") < 0, ERR_INVALID_PARAMETER); if (EDITOR_GET("run/output/always_open_output_on_play")) { EditorNode::get_singleton()->make_bottom_panel_item_visible(EditorNode::get_log()); } else { EditorNode::get_singleton()->make_bottom_panel_item_visible(this); } - - server = Ref<EditorDebuggerServer>(EditorDebuggerServer::create(p_protocol)); - const Error err = server->start(); + server = Ref<EditorDebuggerServer>(EditorDebuggerServer::create(p_uri.substr(0, p_uri.find("://") + 3))); + const Error err = server->start(p_uri); if (err != OK) { return err; } diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h index 39a95326be..4d9e846834 100644 --- a/editor/debugger/editor_debugger_node.h +++ b/editor/debugger/editor_debugger_node.h @@ -188,7 +188,7 @@ public: void set_camera_override(CameraOverride p_override); CameraOverride get_camera_override(); - Error start(const String &p_protocol = "tcp://"); + Error start(const String &p_uri = "tcp://"); void stop(); diff --git a/editor/debugger/editor_debugger_server.cpp b/editor/debugger/editor_debugger_server.cpp index e8524e0702..8c3833af50 100644 --- a/editor/debugger/editor_debugger_server.cpp +++ b/editor/debugger/editor_debugger_server.cpp @@ -45,7 +45,7 @@ private: public: static EditorDebuggerServer *create(const String &p_protocol); virtual void poll() {} - virtual Error start(); + virtual Error start(const String &p_uri); virtual void stop(); virtual bool is_active() const; virtual bool is_connection_available() const; @@ -63,11 +63,18 @@ EditorDebuggerServerTCP::EditorDebuggerServerTCP() { server.instantiate(); } -Error EditorDebuggerServerTCP::start() { - int remote_port = (int)EditorSettings::get_singleton()->get("network/debug/remote_port"); - const Error err = server->listen(remote_port); +Error EditorDebuggerServerTCP::start(const String &p_uri) { + int bind_port = (int)EditorSettings::get_singleton()->get("network/debug/remote_port"); + String bind_host = (String)EditorSettings::get_singleton()->get("network/debug/remote_host"); + if (!p_uri.is_empty() && p_uri != "tcp://") { + String scheme, path; + Error err = p_uri.parse_url(scheme, bind_host, bind_port, path); + ERR_FAIL_COND_V(err != OK, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(!bind_host.is_valid_ip_address() && bind_host != "*", ERR_INVALID_PARAMETER); + } + const Error err = server->listen(bind_port, bind_host); if (err != OK) { - EditorNode::get_log()->add_message(String("Error listening on port ") + itos(remote_port), EditorLog::MSG_TYPE_ERROR); + EditorNode::get_log()->add_message(String("Error listening on port ") + itos(bind_port), EditorLog::MSG_TYPE_ERROR); return err; } return err; diff --git a/editor/debugger/editor_debugger_server.h b/editor/debugger/editor_debugger_server.h index 6216d0df3d..844d1a9e5a 100644 --- a/editor/debugger/editor_debugger_server.h +++ b/editor/debugger/editor_debugger_server.h @@ -48,7 +48,7 @@ public: static void register_protocol_handler(const String &p_protocol, CreateServerFunc p_func); static EditorDebuggerServer *create(const String &p_protocol); virtual void poll() = 0; - virtual Error start() = 0; + virtual Error start(const String &p_uri = "") = 0; virtual void stop() = 0; virtual bool is_active() const = 0; virtual bool is_connection_available() const = 0; diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 2f5bde64a9..989774e943 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -884,8 +884,7 @@ void ScriptEditorDebugger::_clear_breakpoints() { } void ScriptEditorDebugger::start(Ref<RemoteDebuggerPeer> p_peer) { - error_count = 0; - warning_count = 0; + _clear_errors_list(); stop(); peer = p_peer; diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index fad76682b5..fcf79a80a7 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -64,7 +64,12 @@ void EditorAutoloadSettings::_notification(int p_what) { bool EditorAutoloadSettings::_autoload_name_is_valid(const String &p_name, String *r_error) { if (!p_name.is_valid_identifier()) { if (r_error) { - *r_error = TTR("Invalid name.") + "\n" + TTR("Valid characters:") + " a-z, A-Z, 0-9 or _"; + *r_error = TTR("Invalid name.") + " "; + if (p_name.size() > 0 && p_name.left(1).is_numeric()) { + *r_error += TTR("Cannot begin with a digit."); + } else { + *r_error += TTR("Valid characters:") + " a-z, A-Z, 0-9 or _"; + } } return false; @@ -72,7 +77,15 @@ bool EditorAutoloadSettings::_autoload_name_is_valid(const String &p_name, Strin if (ClassDB::class_exists(p_name)) { if (r_error) { - *r_error = TTR("Invalid name.") + "\n" + TTR("Must not collide with an existing engine class name."); + *r_error = TTR("Invalid name.") + " " + TTR("Must not collide with an existing engine class name."); + } + + return false; + } + + if (ScriptServer::is_global_class(p_name)) { + if (r_error) { + *r_error = TTR("Invalid name.") + "\n" + TTR("Must not collide with an existing global script class name."); } return false; @@ -81,7 +94,7 @@ bool EditorAutoloadSettings::_autoload_name_is_valid(const String &p_name, Strin for (int i = 0; i < Variant::VARIANT_MAX; i++) { if (Variant::get_type_name(Variant::Type(i)) == p_name) { if (r_error) { - *r_error = TTR("Invalid name.") + "\n" + TTR("Must not collide with an existing built-in type name."); + *r_error = TTR("Invalid name.") + " " + TTR("Must not collide with an existing built-in type name."); } return false; @@ -91,7 +104,7 @@ bool EditorAutoloadSettings::_autoload_name_is_valid(const String &p_name, Strin for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) { if (CoreConstants::get_global_constant_name(i) == p_name) { if (r_error) { - *r_error = TTR("Invalid name.") + "\n" + TTR("Must not collide with an existing global constant name."); + *r_error = TTR("Invalid name.") + " " + TTR("Must not collide with an existing global constant name."); } return false; @@ -104,7 +117,7 @@ bool EditorAutoloadSettings::_autoload_name_is_valid(const String &p_name, Strin for (const String &E : keywords) { if (E == p_name) { if (r_error) { - *r_error = TTR("Invalid name.") + "\n" + TTR("Keyword cannot be used as an autoload name."); + *r_error = TTR("Invalid name.") + " " + TTR("Keyword cannot be used as an autoload name."); } return false; @@ -338,8 +351,11 @@ void EditorAutoloadSettings::_autoload_path_text_changed(const String p_path) { } void EditorAutoloadSettings::_autoload_text_changed(const String p_name) { - add_autoload->set_disabled( - autoload_add_path->get_text() == "" || !_autoload_name_is_valid(p_name, nullptr)); + String error_string; + bool is_name_valid = _autoload_name_is_valid(p_name, &error_string); + add_autoload->set_disabled(autoload_add_path->get_text() == "" || !is_name_valid); + error_message->set_text(error_string); + error_message->set_visible(autoload_add_name->get_text() != "" && !is_name_valid); } Node *EditorAutoloadSettings::_create_autoload(const String &p_path) { @@ -820,6 +836,12 @@ EditorAutoloadSettings::EditorAutoloadSettings() { HBoxContainer *hbc = memnew(HBoxContainer); add_child(hbc); + error_message = memnew(Label); + error_message->hide(); + error_message->set_align(Label::Align::ALIGN_RIGHT); + error_message->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("error_color"), SNAME("Editor"))); + add_child(error_message); + Label *l = memnew(Label); l->set_text(TTR("Path:")); hbc->add_child(l); diff --git a/editor/editor_autoload_settings.h b/editor/editor_autoload_settings.h index b709728856..b8e054cd14 100644 --- a/editor/editor_autoload_settings.h +++ b/editor/editor_autoload_settings.h @@ -70,6 +70,7 @@ class EditorAutoloadSettings : public VBoxContainer { LineEdit *autoload_add_name; Button *add_autoload; LineEdit *autoload_add_path; + Label *error_message; Button *browse_button; EditorFileDialog *file_dialog; diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp index 25250e231e..4ad45f9649 100644 --- a/editor/editor_command_palette.cpp +++ b/editor/editor_command_palette.cpp @@ -70,6 +70,7 @@ void EditorCommandPalette::_update_command_search(const String &search_text) { r.key_name = command_keys[i]; r.display_name = commands[r.key_name].name; r.shortcut_text = commands[r.key_name].shortcut; + r.last_used = commands[r.key_name].last_used; if (search_text.is_subsequence_ofi(r.display_name)) { if (!search_text.is_empty()) { @@ -94,6 +95,9 @@ void EditorCommandPalette::_update_command_search(const String &search_text) { if (!search_text.is_empty()) { SortArray<CommandEntry, CommandEntryComparator> sorter; sorter.sort(entries.ptrw(), entries.size()); + } else { + SortArray<CommandEntry, CommandHistoryComparator> sorter; + sorter.sort(entries.ptrw(), entries.size()); } const int entry_limit = MIN(entries.size(), 300); @@ -213,7 +217,9 @@ 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_deferred(nullptr, 0); + _save_history(); } void EditorCommandPalette::register_shortcuts_as_command() { @@ -230,6 +236,14 @@ void EditorCommandPalette::register_shortcuts_as_command() { key = unregistered_shortcuts.next(key); } unregistered_shortcuts.clear(); + + // Load command use history. + Dictionary command_history = EditorSettings::get_singleton()->get_project_metadata("command_palette", "command_history", Dictionary()); + Array history_entries = command_history.keys(); + for (int i = 0; i < history_entries.size(); i++) { + const String &history_key = history_entries[i]; + commands[history_key].last_used = command_history[history_key]; + } } Ref<Shortcut> EditorCommandPalette::add_shortcut_command(const String &p_command, const String &p_key, Ref<Shortcut> p_shortcut) { @@ -252,6 +266,19 @@ void EditorCommandPalette::_theme_changed() { command_search_box->set_right_icon(search_options->get_theme_icon("Search", "EditorIcons")); } +void EditorCommandPalette::_save_history() const { + Dictionary command_history; + List<String> command_keys; + commands.get_key_list(&command_keys); + + for (const String &key : command_keys) { + if (commands[key].last_used > 0) { + command_history[key] = commands[key].last_used; + } + } + EditorSettings::get_singleton()->set_project_metadata("command_palette", "command_history", command_history); +} + EditorCommandPalette *EditorCommandPalette::get_singleton() { if (singleton == nullptr) { singleton = memnew(EditorCommandPalette); diff --git a/editor/editor_command_palette.h b/editor/editor_command_palette.h index 093f4b797d..39821a1169 100644 --- a/editor/editor_command_palette.h +++ b/editor/editor_command_palette.h @@ -47,13 +47,15 @@ class EditorCommandPalette : public ConfirmationDialog { Callable callable; String name; String shortcut; + int last_used = 0; // Store time as int, because doubles have problems with text serialization. }; struct CommandEntry { String key_name; String display_name; String shortcut_text; - float score; + int last_used = 0; + float score = 0; }; struct CommandEntryComparator { @@ -62,6 +64,12 @@ class EditorCommandPalette : public ConfirmationDialog { } }; + struct CommandHistoryComparator { + _FORCE_INLINE_ bool operator()(const CommandEntry &A, const CommandEntry &B) const { + return A.last_used > B.last_used; + } + }; + HashMap<String, Command> commands; HashMap<String, Pair<String, Ref<Shortcut>>> unregistered_shortcuts; @@ -74,6 +82,7 @@ class EditorCommandPalette : public ConfirmationDialog { void _update_command_keys(); void _add_command(String p_command_name, String p_key_name, Callable p_binded_action, String p_shortcut_text = "None"); void _theme_changed(); + void _save_history() const; EditorCommandPalette(); protected: diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index aa89a14725..8523833d52 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -444,6 +444,10 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name); + if (importer.is_null()) { + return true; // the importer has possibly changed, try to reimport. + } + if (importer->get_format_version() > version) { return true; // version changed, reimport } diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 490c8f287f..fff9e5e908 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -117,7 +117,7 @@ void EditorHelp::_class_desc_select(const String &p_select) { } else { if (table->has(link)) { // Found in the current page - class_desc->scroll_to_line((*table)[link]); + class_desc->scroll_to_paragraph((*table)[link]); } else { if (topic == "class_enum") { // Try to find the enum in @GlobalScope @@ -480,7 +480,7 @@ void EditorHelp::_update_doc() { } class_desc->push_color(symbol_color); - class_desc->append_bbcode("[url=" + link + "]" + linktxt + "[/url]"); + class_desc->append_text("[url=" + link + "]" + linktxt + "[/url]"); class_desc->pop(); class_desc->add_newline(); } @@ -1180,9 +1180,9 @@ void EditorHelp::_update_doc() { class_desc->add_text(" "); class_desc->push_color(comment_color); if (cd.is_script_doc) { - class_desc->append_bbcode(TTR("There is currently no description for this property.")); + class_desc->append_text(TTR("There is currently no description for this property.")); } else { - class_desc->append_bbcode(TTR("There is currently no description for this property. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text)); + class_desc->append_text(TTR("There is currently no description for this property. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text)); } class_desc->pop(); } @@ -1229,7 +1229,7 @@ void EditorHelp::_update_doc() { class_desc->push_font(doc_font); class_desc->push_indent(1); if (methods_filtered[i].errors_returned.size()) { - class_desc->append_bbcode(TTR("Error codes returned:")); + class_desc->append_text(TTR("Error codes returned:")); class_desc->add_newline(); class_desc->push_list(0, RichTextLabel::LIST_DOTS, false); for (int j = 0; j < methods_filtered[i].errors_returned.size(); j++) { @@ -1246,7 +1246,7 @@ void EditorHelp::_update_doc() { } class_desc->push_bold(); - class_desc->append_bbcode(text); + class_desc->append_text(text); class_desc->pop(); } class_desc->pop(); @@ -1260,9 +1260,9 @@ void EditorHelp::_update_doc() { class_desc->add_text(" "); class_desc->push_color(comment_color); if (cd.is_script_doc) { - class_desc->append_bbcode(TTR("There is currently no description for this method.")); + class_desc->append_text(TTR("There is currently no description for this method.")); } else { - class_desc->append_bbcode(TTR("There is currently no description for this method. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text)); + class_desc->append_text(TTR("There is currently no description for this method. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text)); } class_desc->pop(); } @@ -1345,7 +1345,7 @@ void EditorHelp::_help_callback(const String &p_topic) { } } - class_desc->call_deferred(SNAME("scroll_to_line"), line); + class_desc->call_deferred(SNAME("scroll_to_paragraph"), line); } static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { @@ -1612,6 +1612,11 @@ void EditorHelp::generate_doc() { doc->merge_from(compdoc); //ensure all is up to date } +void EditorHelp::_toggle_scripts_pressed() { + ScriptEditor::get_singleton()->toggle_scripts_panel(); + update_toggle_scripts_button(); +} + void EditorHelp::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: @@ -1622,7 +1627,11 @@ void EditorHelp::_notification(int p_what) { if (is_inside_tree()) { _class_desc_resized(); } + update_toggle_scripts_button(); } break; + case NOTIFICATION_VISIBILITY_CHANGED: + update_toggle_scripts_button(); + break; default: break; } @@ -1653,7 +1662,7 @@ Vector<Pair<String, int>> EditorHelp::get_sections() { void EditorHelp::scroll_to_section(int p_section_index) { int line = section_line[p_section_index].second; - class_desc->scroll_to_line(line); + class_desc->scroll_to_paragraph(line); } void EditorHelp::popup_search() { @@ -1676,6 +1685,15 @@ void EditorHelp::set_scroll(int p_scroll) { class_desc->get_v_scroll()->set_value(p_scroll); } +void EditorHelp::update_toggle_scripts_button() { + if (is_layout_rtl()) { + toggle_scripts_button->set_icon(get_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Forward") : SNAME("Back"), SNAME("EditorIcons"))); + } else { + toggle_scripts_button->set_icon(get_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Back") : SNAME("Forward"), SNAME("EditorIcons"))); + } + toggle_scripts_button->set_tooltip(vformat("%s (%s)", TTR("Toggle Scripts Panel"), ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text())); +} + void EditorHelp::_bind_methods() { ClassDB::bind_method("_class_list_select", &EditorHelp::_class_list_select); ClassDB::bind_method("_request_help", &EditorHelp::_request_help); @@ -1706,6 +1724,16 @@ EditorHelp::EditorHelp() { find_bar->hide(); find_bar->set_rich_text_label(class_desc); + status_bar = memnew(HBoxContainer); + add_child(status_bar); + status_bar->set_h_size_flags(SIZE_EXPAND_FILL); + status_bar->set_custom_minimum_size(Size2(0, 24 * EDSCALE)); + + toggle_scripts_button = memnew(Button); + toggle_scripts_button->set_flat(true); + toggle_scripts_button->connect("pressed", callable_mp(this, &EditorHelp::_toggle_scripts_pressed)); + status_bar->add_child(toggle_scripts_button); + class_desc->set_selection_enabled(true); scroll_locked = false; diff --git a/editor/editor_help.h b/editor/editor_help.h index 0b0821a7f4..7a45b1abc1 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -123,6 +123,8 @@ class EditorHelp : public VBoxContainer { ConfirmationDialog *search_dialog; LineEdit *search; FindBar *find_bar; + HBoxContainer *status_bar; + Button *toggle_scripts_button; String base_path; @@ -159,6 +161,7 @@ class EditorHelp : public VBoxContainer { void _search(bool p_search_previous = false); String _fix_constant(const String &p_constant) const; + void _toggle_scripts_pressed(); protected: void _notification(int p_what); @@ -185,6 +188,8 @@ public: int get_scroll() const; void set_scroll(int p_scroll); + void update_toggle_scripts_button(); + EditorHelp(); ~EditorHelp(); }; diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 66f291bd3e..4832cd6994 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -799,22 +799,39 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) { } void EditorProperty::unhandled_key_input(const Ref<InputEvent> &p_event) { - if (!selected) { + if (!selected || !p_event->is_pressed()) { return; } - if (ED_IS_SHORTCUT("property_editor/copy_property", p_event)) { - menu_option(MENU_COPY_PROPERTY); - accept_event(); - } else if (ED_IS_SHORTCUT("property_editor/paste_property", p_event) && !is_read_only()) { - menu_option(MENU_PASTE_PROPERTY); - accept_event(); - } else if (ED_IS_SHORTCUT("property_editor/copy_property_path", p_event)) { - menu_option(MENU_COPY_PROPERTY_PATH); - accept_event(); + const Ref<InputEventKey> k = p_event; + + if (k.is_valid() && k->is_pressed()) { + if (ED_IS_SHORTCUT("property_editor/copy_property", p_event)) { + menu_option(MENU_COPY_PROPERTY); + accept_event(); + } else if (ED_IS_SHORTCUT("property_editor/paste_property", p_event) && !is_read_only()) { + menu_option(MENU_PASTE_PROPERTY); + accept_event(); + } else if (ED_IS_SHORTCUT("property_editor/copy_property_path", p_event)) { + menu_option(MENU_COPY_PROPERTY_PATH); + accept_event(); + } } } +const Color *EditorProperty::_get_property_colors() { + const Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + const float saturation = base.get_s() * 0.75; + const float value = base.get_v(); + + static Color c[4]; + c[0].set_hsv(0.0 / 3.0 + 0.05, saturation, value); + c[1].set_hsv(1.0 / 3.0 + 0.05, saturation, value); + c[2].set_hsv(2.0 / 3.0 + 0.05, saturation, value); + c[3].set_hsv(1.5 / 3.0 + 0.05, saturation, value); + return c; +} + void EditorProperty::set_label_reference(Control *p_control) { label_reference = p_control; } @@ -1266,9 +1283,13 @@ void EditorInspectorSection::_notification(int p_what) { } header_height += get_theme_constant(SNAME("vseparation"), SNAME("Tree")); + Rect2 header_rect = Rect2(Vector2(), Vector2(get_size().width, header_height)); Color c = bg_color; c.a *= 0.4; - draw_rect(Rect2(Vector2(), Vector2(get_size().width, header_height)), c); + if (foldable && header_rect.has_point(get_local_mouse_position())) { + c = c.lightened(Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT) ? -0.05 : 0.2); + } + draw_rect(header_rect, c); const int arrow_margin = 2; const int arrow_width = arrow.is_valid() ? arrow->get_width() : 0; @@ -1315,12 +1336,14 @@ void EditorInspectorSection::_notification(int p_what) { if (dropping) { dropping_unfold_timer->start(); } + update(); } break; case NOTIFICATION_MOUSE_EXIT: { if (dropping) { dropping_unfold_timer->stop(); } + update(); } break; } } @@ -1395,6 +1418,8 @@ void EditorInspectorSection::gui_input(const Ref<InputEvent> &p_event) { } else { fold(); } + } else if (mb.is_valid() && !mb->is_pressed()) { + update(); } } @@ -2843,10 +2868,8 @@ void EditorInspector::update_tree() { if (ep) { // Eventually, set other properties/signals after the property editor got added to the tree. - ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed)); - if (p.usage & PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED) { - ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed_update_all), varray(), CONNECT_DEFERRED); - } + bool update_all = (p.usage & PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED); + ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed), varray(update_all)); ep->connect("property_keyed", callable_mp(this, &EditorInspector::_property_keyed)); ep->connect("property_deleted", callable_mp(this, &EditorInspector::_property_deleted), varray(), CONNECT_DEFERRED); ep->connect("property_keyed_with_value", callable_mp(this, &EditorInspector::_property_keyed_with_value)); @@ -3175,14 +3198,14 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo } } -void EditorInspector::_property_changed(const String &p_path, const Variant &p_value, const String &p_name, bool p_changing) { +void EditorInspector::_property_changed(const String &p_path, const Variant &p_value, const String &p_name, bool p_changing, bool p_update_all) { // The "changing" variable must be true for properties that trigger events as typing occurs, // like "text_changed" signal. E.g. text property of Label, Button, RichTextLabel, etc. if (p_changing) { this->changing++; } - _edit_set(p_path, p_value, false, p_name); + _edit_set(p_path, p_value, p_update_all, p_name); if (p_changing) { this->changing--; @@ -3193,10 +3216,6 @@ void EditorInspector::_property_changed(const String &p_path, const Variant &p_v } } -void EditorInspector::_property_changed_update_all(const String &p_path, const Variant &p_value, const String &p_name, bool p_changing) { - update_tree(); -} - void EditorInspector::_multiple_properties_changed(Vector<String> p_paths, Array p_values, bool p_changing) { ERR_FAIL_COND(p_paths.size() == 0 || p_values.size() == 0); ERR_FAIL_COND(p_paths.size() != p_values.size()); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index f6b4303f38..b71efe8f19 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -123,6 +123,7 @@ protected: virtual void gui_input(const Ref<InputEvent> &p_event) override; virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override; + const Color *_get_property_colors(); public: void emit_changed(const StringName &p_property, const Variant &p_value, const StringName &p_field = StringName(), bool p_changing = false); @@ -457,8 +458,7 @@ class EditorInspector : public ScrollContainer { void _edit_set(const String &p_name, const Variant &p_value, bool p_refresh_all, const String &p_changed_field); - void _property_changed(const String &p_path, const Variant &p_value, const String &p_name = "", bool p_changing = false); - void _property_changed_update_all(const String &p_path, const Variant &p_value, const String &p_name = "", bool p_changing = false); + void _property_changed(const String &p_path, const Variant &p_value, const String &p_name = "", bool p_changing = false, bool p_update_all = false); void _multiple_properties_changed(Vector<String> p_paths, Array p_values, bool p_changing = false); void _property_keyed(const String &p_path, bool p_advance); void _property_keyed_with_value(const String &p_path, const Variant &p_value, bool p_advance); diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 296a33d917..f91cb7f607 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -195,7 +195,7 @@ void EditorLog::add_message(const String &p_msg, MessageType p_type) { // 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 // also matches that of other IDE's. - Vector<String> lines = p_msg.split("\n", false); + Vector<String> lines = p_msg.split("\n", true); for (int i = 0; i < lines.size(); i++) { _process_message(lines[i], p_type); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 0c985f3724..d8f0367b33 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -524,6 +524,26 @@ void EditorNode::_update_from_settings() { RS::get_singleton()->light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter")))); } +void EditorNode::_select_default_main_screen_plugin() { + if (EDITOR_3D < main_editor_buttons.size() && main_editor_buttons[EDITOR_3D]->is_visible()) { + // If the 3D editor is enabled, use this as the default. + _editor_select(EDITOR_3D); + return; + } + + // Switch to the first main screen plugin that is enabled. Usually this is + // 2D, but may be subsequent ones if 2D is disabled in the feature profile. + for (int i = 0; i < main_editor_buttons.size(); i++) { + Button *editor_button = main_editor_buttons[i]; + if (editor_button->is_visible()) { + _editor_select(i); + return; + } + } + + _editor_select(-1); +} + void EditorNode::_notification(int p_what) { switch (p_what) { case NOTIFICATION_PROCESS: { @@ -595,29 +615,12 @@ void EditorNode::_notification(int p_what) { } break; case NOTIFICATION_READY: { - { - _initializing_addons = true; - Vector<String> addons; - if (ProjectSettings::get_singleton()->has_setting("editor_plugins/enabled")) { - addons = ProjectSettings::get_singleton()->get("editor_plugins/enabled"); - } - - for (int i = 0; i < addons.size(); i++) { - set_addon_plugin_enabled(addons[i], true); - } - _initializing_addons = false; - } - RenderingServer::get_singleton()->viewport_set_disable_2d(get_scene_root()->get_viewport_rid(), true); RenderingServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(), true); feature_profile_manager->notify_changed(); - if (!main_editor_buttons[EDITOR_3D]->is_visible()) { //may be hidden due to feature profile - _editor_select(EDITOR_2D); - } else { - _editor_select(EDITOR_3D); - } + _select_default_main_screen_plugin(); // Save the project after opening to mark it as last modified, except in headless mode. if (DisplayServer::get_singleton()->window_can_draw()) { @@ -970,6 +973,18 @@ void EditorNode::_sources_changed(bool p_exist) { load_scene(defer_load_scene); defer_load_scene = ""; } + + // Only enable addons once resources have been imported + _initializing_addons = true; + Vector<String> addons; + if (ProjectSettings::get_singleton()->has_setting("editor_plugins/enabled")) { + addons = ProjectSettings::get_singleton()->get("editor_plugins/enabled"); + } + + for (int i = 0; i < addons.size(); i++) { + set_addon_plugin_enabled(addons[i], true); + } + _initializing_addons = false; } } @@ -1856,7 +1871,7 @@ void EditorNode::_dialog_action(String p_file) { ml = Ref<MeshLibrary>(memnew(MeshLibrary)); } - MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(), ml, true); + MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(), ml, true, file_export_lib_apply_xforms->is_pressed()); Error err = ResourceSaver::save(p_file, ml); if (err) { @@ -3100,9 +3115,10 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed tb->set_flat(true); tb->set_toggle_mode(true); tb->connect("pressed", callable_mp(singleton, &EditorNode::_editor_select), varray(singleton->main_editor_buttons.size())); + tb->set_name(p_editor->get_name()); tb->set_text(p_editor->get_name()); - Ref<Texture2D> icon = p_editor->get_icon(); + Ref<Texture2D> icon = p_editor->get_icon(); if (icon.is_valid()) { tb->set_icon(icon); } else if (singleton->gui_base->has_theme_icon(p_editor->get_name(), "EditorIcons")) { @@ -3112,7 +3128,6 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed tb->add_theme_font_override("font", singleton->gui_base->get_theme_font(SNAME("main_button_font"), SNAME("EditorFonts"))); tb->add_theme_font_size_override("font_size", singleton->gui_base->get_theme_font_size(SNAME("main_button_font_size"), SNAME("EditorFonts"))); - tb->set_name(p_editor->get_name()); singleton->main_editor_buttons.push_back(tb); singleton->main_editor_button_vb->add_child(tb); singleton->editor_table.push_back(p_editor); @@ -6807,6 +6822,10 @@ EditorNode::EditorNode() { file_export_lib_merge->set_text(TTR("Merge With Existing")); file_export_lib_merge->set_pressed(true); file_export_lib->get_vbox()->add_child(file_export_lib_merge); + file_export_lib_apply_xforms = memnew(CheckBox); + file_export_lib_apply_xforms->set_text(TTR("Apply MeshInstance Transforms")); + file_export_lib_apply_xforms->set_pressed(false); + file_export_lib->get_vbox()->add_child(file_export_lib_apply_xforms); gui_base->add_child(file_export_lib); file_script = memnew(EditorFileDialog); diff --git a/editor/editor_node.h b/editor/editor_node.h index 03c18a8972..2e8b850c7b 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -32,7 +32,6 @@ #define EDITOR_NODE_H #include "core/templates/safe_refcount.h" -#include "editor/editor_command_palette.h" #include "editor/editor_data.h" #include "editor/editor_export.h" #include "editor/editor_folding.h" @@ -335,6 +334,7 @@ private: EditorFileDialog *file_script; EditorFileDialog *file_android_build_source; CheckBox *file_export_lib_merge; + CheckBox *file_export_lib_apply_xforms; String current_path; MenuButton *update_spinner; @@ -681,6 +681,8 @@ private: bool immediate_dialog_confirmed = false; void _immediate_dialog_confirmed(); + void _select_default_main_screen_plugin(); + protected: void _notification(int p_what); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 73ea4fb5ef..5baffb6f9d 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -30,6 +30,7 @@ #include "editor_plugin.h" +#include "editor/editor_command_palette.h" #include "editor/editor_export.h" #include "editor/editor_node.h" #include "editor/editor_paths.h" diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 1729705be5..c1e60e141c 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -1510,11 +1510,9 @@ void EditorPropertyVector2::update_property() { void EditorPropertyVector2::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + const Color *colors = _get_property_colors(); for (int i = 0; i < 2; i++) { - Color c = base; - c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); - spin[i]->set_custom_label_color(true, c); + spin[i]->set_custom_label_color(true, colors[i]); } } } @@ -1603,11 +1601,9 @@ void EditorPropertyRect2::update_property() { void EditorPropertyRect2::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + const Color *colors = _get_property_colors(); for (int i = 0; i < 4; i++) { - Color c = base; - c.set_hsv(float(i % 2) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); - spin[i]->set_custom_label_color(true, c); + spin[i]->set_custom_label_color(true, colors[i % 2]); } } } @@ -1731,11 +1727,9 @@ Vector3 EditorPropertyVector3::get_vector() { void EditorPropertyVector3::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + const Color *colors = _get_property_colors(); for (int i = 0; i < 3; i++) { - Color c = base; - c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); - spin[i]->set_custom_label_color(true, c); + spin[i]->set_custom_label_color(true, colors[i]); } } } @@ -1820,11 +1814,9 @@ void EditorPropertyVector2i::update_property() { void EditorPropertyVector2i::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + const Color *colors = _get_property_colors(); for (int i = 0; i < 2; i++) { - Color c = base; - c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); - spin[i]->set_custom_label_color(true, c); + spin[i]->set_custom_label_color(true, colors[i]); } } } @@ -1913,11 +1905,9 @@ void EditorPropertyRect2i::update_property() { void EditorPropertyRect2i::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + const Color *colors = _get_property_colors(); for (int i = 0; i < 4; i++) { - Color c = base; - c.set_hsv(float(i % 2) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); - spin[i]->set_custom_label_color(true, c); + spin[i]->set_custom_label_color(true, colors[i % 2]); } } } @@ -2014,11 +2004,9 @@ void EditorPropertyVector3i::update_property() { void EditorPropertyVector3i::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + const Color *colors = _get_property_colors(); for (int i = 0; i < 3; i++) { - Color c = base; - c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); - spin[i]->set_custom_label_color(true, c); + spin[i]->set_custom_label_color(true, colors[i]); } } } @@ -2106,11 +2094,9 @@ void EditorPropertyPlane::update_property() { void EditorPropertyPlane::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); - for (int i = 0; i < 3; i++) { - Color c = base; - c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); - spin[i]->set_custom_label_color(true, c); + const Color *colors = _get_property_colors(); + for (int i = 0; i < 4; i++) { + spin[i]->set_custom_label_color(true, colors[i]); } } } @@ -2199,11 +2185,9 @@ void EditorPropertyQuaternion::update_property() { void EditorPropertyQuaternion::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); - for (int i = 0; i < 3; i++) { - Color c = base; - c.set_hsv(float(i) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); - spin[i]->set_custom_label_color(true, c); + const Color *colors = _get_property_colors(); + for (int i = 0; i < 4; i++) { + spin[i]->set_custom_label_color(true, colors[i]); } } } @@ -2295,11 +2279,9 @@ void EditorPropertyAABB::update_property() { void EditorPropertyAABB::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + const Color *colors = _get_property_colors(); for (int i = 0; i < 6; i++) { - Color c = base; - c.set_hsv(float(i % 3) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); - spin[i]->set_custom_label_color(true, c); + spin[i]->set_custom_label_color(true, colors[i % 3]); } } } @@ -2354,10 +2336,10 @@ void EditorPropertyTransform2D::_value_changed(double val, const String &p_name) Transform2D p; p[0][0] = spin[0]->get_value(); - p[0][1] = spin[1]->get_value(); - p[1][0] = spin[2]->get_value(); - p[1][1] = spin[3]->get_value(); - p[2][0] = spin[4]->get_value(); + p[1][0] = spin[1]->get_value(); + p[2][0] = spin[2]->get_value(); + p[0][1] = spin[3]->get_value(); + p[1][1] = spin[4]->get_value(); p[2][1] = spin[5]->get_value(); emit_changed(get_edited_property(), p, p_name); @@ -2367,10 +2349,10 @@ void EditorPropertyTransform2D::update_property() { Transform2D val = get_edited_object()->get(get_edited_property()); setting = true; spin[0]->set_value(val[0][0]); - spin[1]->set_value(val[0][1]); - spin[2]->set_value(val[1][0]); - spin[3]->set_value(val[1][1]); - spin[4]->set_value(val[2][0]); + spin[1]->set_value(val[1][0]); + spin[2]->set_value(val[2][0]); + spin[3]->set_value(val[0][1]); + spin[4]->set_value(val[1][1]); spin[5]->set_value(val[2][1]); setting = false; @@ -2378,11 +2360,14 @@ void EditorPropertyTransform2D::update_property() { void EditorPropertyTransform2D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + const Color *colors = _get_property_colors(); for (int i = 0; i < 6; i++) { - Color c = base; - c.set_hsv(float(i % 2) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); - spin[i]->set_custom_label_color(true, c); + // For Transform2D, use the 4th color (cyan) for the origin vector. + if (i % 3 == 2) { + spin[i]->set_custom_label_color(true, colors[3]); + } else { + spin[i]->set_custom_label_color(true, colors[i % 3]); + } } } } @@ -2402,17 +2387,19 @@ void EditorPropertyTransform2D::setup(double p_min, double p_max, double p_step, } } -EditorPropertyTransform2D::EditorPropertyTransform2D() { +EditorPropertyTransform2D::EditorPropertyTransform2D(bool p_include_origin) { GridContainer *g = memnew(GridContainer); - g->set_columns(2); + g->set_columns(p_include_origin ? 3 : 2); add_child(g); - static const char *desc[6] = { "x", "y", "x", "y", "x", "y" }; + static const char *desc[6] = { "xx", "xy", "xo", "yx", "yy", "yo" }; for (int i = 0; i < 6; i++) { spin[i] = memnew(EditorSpinSlider); spin[i]->set_label(desc[i]); spin[i]->set_flat(true); - g->add_child(spin[i]); + if (p_include_origin || i % 3 != 2) { + g->add_child(spin[i]); + } spin[i]->set_h_size_flags(SIZE_EXPAND_FILL); add_focusable(spin[i]); spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform2D::_value_changed), varray(desc[i])); @@ -2436,13 +2423,13 @@ void EditorPropertyBasis::_value_changed(double val, const String &p_name) { Basis p; p[0][0] = spin[0]->get_value(); - p[1][0] = spin[1]->get_value(); - p[2][0] = spin[2]->get_value(); - p[0][1] = spin[3]->get_value(); + p[0][1] = spin[1]->get_value(); + p[0][2] = spin[2]->get_value(); + p[1][0] = spin[3]->get_value(); p[1][1] = spin[4]->get_value(); - p[2][1] = spin[5]->get_value(); - p[0][2] = spin[6]->get_value(); - p[1][2] = spin[7]->get_value(); + p[1][2] = spin[5]->get_value(); + p[2][0] = spin[6]->get_value(); + p[2][1] = spin[7]->get_value(); p[2][2] = spin[8]->get_value(); emit_changed(get_edited_property(), p, p_name); @@ -2452,13 +2439,13 @@ void EditorPropertyBasis::update_property() { Basis val = get_edited_object()->get(get_edited_property()); setting = true; spin[0]->set_value(val[0][0]); - spin[1]->set_value(val[1][0]); - spin[2]->set_value(val[2][0]); - spin[3]->set_value(val[0][1]); + spin[1]->set_value(val[0][1]); + spin[2]->set_value(val[0][2]); + spin[3]->set_value(val[1][0]); spin[4]->set_value(val[1][1]); - spin[5]->set_value(val[2][1]); - spin[6]->set_value(val[0][2]); - spin[7]->set_value(val[1][2]); + spin[5]->set_value(val[1][2]); + spin[6]->set_value(val[2][0]); + spin[7]->set_value(val[2][1]); spin[8]->set_value(val[2][2]); setting = false; @@ -2466,11 +2453,9 @@ void EditorPropertyBasis::update_property() { void EditorPropertyBasis::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + const Color *colors = _get_property_colors(); for (int i = 0; i < 9; i++) { - Color c = base; - c.set_hsv(float(i % 3) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); - spin[i]->set_custom_label_color(true, c); + spin[i]->set_custom_label_color(true, colors[i % 3]); } } } @@ -2495,7 +2480,7 @@ EditorPropertyBasis::EditorPropertyBasis() { g->set_columns(3); add_child(g); - static const char *desc[9] = { "x", "y", "z", "x", "y", "z", "x", "y", "z" }; + static const char *desc[9] = { "xx", "xy", "xz", "yx", "yy", "yz", "zx", "zy", "zz" }; for (int i = 0; i < 9; i++) { spin[i] = memnew(EditorSpinSlider); spin[i]->set_label(desc[i]); @@ -2524,16 +2509,16 @@ void EditorPropertyTransform3D::_value_changed(double val, const String &p_name) Transform3D p; p.basis[0][0] = spin[0]->get_value(); - p.basis[1][0] = spin[1]->get_value(); - p.basis[2][0] = spin[2]->get_value(); - p.basis[0][1] = spin[3]->get_value(); - p.basis[1][1] = spin[4]->get_value(); - p.basis[2][1] = spin[5]->get_value(); - p.basis[0][2] = spin[6]->get_value(); - p.basis[1][2] = spin[7]->get_value(); - p.basis[2][2] = spin[8]->get_value(); - p.origin[0] = spin[9]->get_value(); - p.origin[1] = spin[10]->get_value(); + p.basis[0][1] = spin[1]->get_value(); + p.basis[0][2] = spin[2]->get_value(); + p.origin[0] = spin[3]->get_value(); + p.basis[1][0] = spin[4]->get_value(); + p.basis[1][1] = spin[5]->get_value(); + p.basis[1][2] = spin[6]->get_value(); + p.origin[1] = spin[7]->get_value(); + p.basis[2][0] = spin[8]->get_value(); + p.basis[2][1] = spin[9]->get_value(); + p.basis[2][2] = spin[10]->get_value(); p.origin[2] = spin[11]->get_value(); emit_changed(get_edited_property(), p, p_name); @@ -2546,27 +2531,25 @@ void EditorPropertyTransform3D::update_property() { void EditorPropertyTransform3D::update_using_transform(Transform3D p_transform) { setting = true; spin[0]->set_value(p_transform.basis[0][0]); - spin[1]->set_value(p_transform.basis[1][0]); - spin[2]->set_value(p_transform.basis[2][0]); - spin[3]->set_value(p_transform.basis[0][1]); - spin[4]->set_value(p_transform.basis[1][1]); - spin[5]->set_value(p_transform.basis[2][1]); - spin[6]->set_value(p_transform.basis[0][2]); - spin[7]->set_value(p_transform.basis[1][2]); - spin[8]->set_value(p_transform.basis[2][2]); - spin[9]->set_value(p_transform.origin[0]); - spin[10]->set_value(p_transform.origin[1]); + spin[1]->set_value(p_transform.basis[0][1]); + spin[2]->set_value(p_transform.basis[0][2]); + spin[3]->set_value(p_transform.origin[0]); + spin[4]->set_value(p_transform.basis[1][0]); + spin[5]->set_value(p_transform.basis[1][1]); + spin[6]->set_value(p_transform.basis[1][2]); + spin[7]->set_value(p_transform.origin[1]); + spin[8]->set_value(p_transform.basis[2][0]); + spin[9]->set_value(p_transform.basis[2][1]); + spin[10]->set_value(p_transform.basis[2][2]); spin[11]->set_value(p_transform.origin[2]); setting = false; } void EditorPropertyTransform3D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); + const Color *colors = _get_property_colors(); for (int i = 0; i < 12; i++) { - Color c = base; - c.set_hsv(float(i % 3) / 3.0 + 0.05, c.get_s() * 0.75, c.get_v()); - spin[i]->set_custom_label_color(true, c); + spin[i]->set_custom_label_color(true, colors[i % 4]); } } } @@ -2588,10 +2571,10 @@ void EditorPropertyTransform3D::setup(double p_min, double p_max, double p_step, EditorPropertyTransform3D::EditorPropertyTransform3D() { GridContainer *g = memnew(GridContainer); - g->set_columns(3); + g->set_columns(4); add_child(g); - static const char *desc[12] = { "x", "y", "z", "x", "y", "z", "x", "y", "z", "x", "y", "z" }; + static const char *desc[12] = { "xx", "xy", "xz", "xo", "yx", "yy", "yz", "yo", "zx", "zy", "zz", "zo" }; for (int i = 0; i < 12; i++) { spin[i] = memnew(EditorSpinSlider); spin[i]->set_label(desc[i]); @@ -3448,7 +3431,6 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step); editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix); return editor; - } break; case Variant::PLANE: { EditorPropertyPlane *editor = memnew(EditorPropertyPlane(p_wide)); diff --git a/editor/editor_properties.h b/editor/editor_properties.h index cee5ab96a7..9a687f1a72 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -554,7 +554,7 @@ protected: public: virtual void update_property() override; void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String()); - EditorPropertyTransform2D(); + EditorPropertyTransform2D(bool p_include_origin = true); }; class EditorPropertyBasis : public EditorProperty { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 8d579753c2..1953270b08 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -300,6 +300,14 @@ bool EditorSettings::has_default_value(const String &p_setting) const { void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _THREAD_SAFE_METHOD_ +// Sets up the editor setting with a default value and hint PropertyInfo. +#define EDITOR_SETTING(m_type, m_property_hint, m_name, m_default_value, m_hint_string) \ + _initial_set(m_name, m_default_value); \ + hints[m_name] = PropertyInfo(m_type, m_name, m_property_hint, m_hint_string); + +#define EDITOR_SETTING_USAGE(m_type, m_property_hint, m_name, m_default_value, m_hint_string, m_usage) \ + _initial_set(m_name, m_default_value); \ + hints[m_name] = PropertyInfo(m_type, m_name, m_property_hint, m_hint_string, m_usage); /* Languages */ @@ -363,103 +371,76 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { best = "en"; } - _initial_set("interface/editor/editor_language", best); - set_restart_if_changed("interface/editor/editor_language", true); - hints["interface/editor/editor_language"] = PropertyInfo(Variant::STRING, "interface/editor/editor_language", PROPERTY_HINT_ENUM, lang_hint, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); + EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_ENUM, "interface/editor/editor_language", best, lang_hint, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); } /* Interface */ // Editor - _initial_set("interface/editor/display_scale", 0); // Display what the Auto display scale setting effectively corresponds to. - float scale = get_auto_display_scale(); + const String display_scale_hint_string = vformat("Auto (%d%%),75%%,100%%,125%%,150%%,175%%,200%%,Custom", Math::round(get_auto_display_scale() * 100)); + EDITOR_SETTING_USAGE(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/display_scale", 0, display_scale_hint_string, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) _initial_set("interface/editor/enable_debugging_pseudolocalization", false); set_restart_if_changed("interface/editor/enable_debugging_pseudolocalization", true); // Use pseudolocalization in editor. - hints["interface/editor/display_scale"] = PropertyInfo(Variant::INT, "interface/editor/display_scale", PROPERTY_HINT_ENUM, vformat("Auto (%d%%),75%%,100%%,125%%,150%%,175%%,200%%,Custom", Math::round(scale * 100)), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); - _initial_set("interface/editor/custom_display_scale", 1.0f); - hints["interface/editor/custom_display_scale"] = PropertyInfo(Variant::FLOAT, "interface/editor/custom_display_scale", PROPERTY_HINT_RANGE, "0.5,3,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); - _initial_set("interface/editor/main_font_size", 14); - hints["interface/editor/main_font_size"] = PropertyInfo(Variant::INT, "interface/editor/main_font_size", PROPERTY_HINT_RANGE, "8,48,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); - _initial_set("interface/editor/code_font_size", 14); - hints["interface/editor/code_font_size"] = PropertyInfo(Variant::INT, "interface/editor/code_font_size", PROPERTY_HINT_RANGE, "8,48,1", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/editor/code_font_contextual_ligatures", 0); - hints["interface/editor/code_font_contextual_ligatures"] = PropertyInfo(Variant::INT, "interface/editor/code_font_contextual_ligatures", PROPERTY_HINT_ENUM, "Default,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set", PROPERTY_USAGE_DEFAULT); + 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_USAGE(Variant::INT, PROPERTY_HINT_RANGE, "interface/editor/main_font_size", 14, "8,48,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) + 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") _initial_set("interface/editor/code_font_custom_opentype_features", ""); _initial_set("interface/editor/code_font_custom_variations", ""); _initial_set("interface/editor/font_antialiased", true); - _initial_set("interface/editor/font_hinting", 0); #ifdef OSX_ENABLED - hints["interface/editor/font_hinting"] = PropertyInfo(Variant::INT, "interface/editor/font_hinting", PROPERTY_HINT_ENUM, "Auto (None),None,Light,Normal", PROPERTY_USAGE_DEFAULT); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (None),None,Light,Normal") #else - hints["interface/editor/font_hinting"] = PropertyInfo(Variant::INT, "interface/editor/font_hinting", PROPERTY_HINT_ENUM, "Auto (Light),None,Light,Normal", PROPERTY_USAGE_DEFAULT); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (Light),None,Light,Normal") #endif - _initial_set("interface/editor/main_font", ""); - hints["interface/editor/main_font"] = PropertyInfo(Variant::STRING, "interface/editor/main_font", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/editor/main_font_bold", ""); - hints["interface/editor/main_font_bold"] = PropertyInfo(Variant::STRING, "interface/editor/main_font_bold", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/editor/code_font", ""); - hints["interface/editor/code_font"] = PropertyInfo(Variant::STRING, "interface/editor/code_font", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/editor/low_processor_mode_sleep_usec", 6900); // ~144 FPS - hints["interface/editor/low_processor_mode_sleep_usec"] = PropertyInfo(Variant::FLOAT, "interface/editor/low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "1,100000,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); - _initial_set("interface/editor/unfocused_low_processor_mode_sleep_usec", 100000); // 10 FPS - // Allow an unfocused FPS limit as low as 1 FPS for those who really need low power usage - // (but don't need to preview particles or shaders while the editor is unfocused). - // With very low FPS limits, the editor can take a small while to become usable after being focused again, - // so this should be used at the user's discretion. - hints["interface/editor/unfocused_low_processor_mode_sleep_usec"] = PropertyInfo(Variant::FLOAT, "interface/editor/unfocused_low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "1,1000000,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/main_font", "", "*.ttf,*.otf") + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/main_font_bold", "", "*.ttf,*.otf") + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/code_font", "", "*.ttf,*.otf") + EDITOR_SETTING_USAGE(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/editor/low_processor_mode_sleep_usec", 6900, "1,100000,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) + // Default unfocused usec sleep is for 10 FPS. Allow an unfocused FPS limit + // as low as 1 FPS for those who really need low power usage (but don't need + // to preview particles or shaders while the editor is unfocused). With very + // low FPS limits, the editor can take a small while to become usable after + // being focused again, so this should be used at the user's discretion. + EDITOR_SETTING_USAGE(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/editor/unfocused_low_processor_mode_sleep_usec", 100000, "1,1000000,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) _initial_set("interface/editor/separate_distraction_mode", false); _initial_set("interface/editor/automatically_open_screenshots", true); - _initial_set("interface/editor/single_window_mode", false); - hints["interface/editor/single_window_mode"] = PropertyInfo(Variant::BOOL, "interface/editor/single_window_mode", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); + EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/single_window_mode", false, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) _initial_set("interface/editor/hide_console_window", false); _initial_set("interface/editor/save_each_scene_on_quit", true); // Regression // Inspector - _initial_set("interface/inspector/max_array_dictionary_items_per_page", 20); - hints["interface/inspector/max_array_dictionary_items_per_page"] = PropertyInfo(Variant::INT, "interface/inspector/max_array_dictionary_items_per_page", PROPERTY_HINT_RANGE, "10,100,1", PROPERTY_USAGE_DEFAULT); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/inspector/max_array_dictionary_items_per_page", 20, "10,100,1") // Theme - _initial_set("interface/theme/preset", "Default"); - hints["interface/theme/preset"] = PropertyInfo(Variant::STRING, "interface/theme/preset", PROPERTY_HINT_ENUM, "Default,Breeze Dark,Godot 2,Grey,Light,Solarized (Dark),Solarized (Light),Custom", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/theme/icon_and_font_color", 0); - hints["interface/theme/icon_and_font_color"] = PropertyInfo(Variant::INT, "interface/theme/icon_and_font_color", PROPERTY_HINT_ENUM, "Auto,Dark,Light", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/theme/base_color", Color(0.2, 0.23, 0.31)); - hints["interface/theme/base_color"] = PropertyInfo(Variant::COLOR, "interface/theme/base_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/theme/accent_color", Color(0.41, 0.61, 0.91)); - hints["interface/theme/accent_color"] = PropertyInfo(Variant::COLOR, "interface/theme/accent_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/theme/contrast", 0.3); - hints["interface/theme/contrast"] = PropertyInfo(Variant::FLOAT, "interface/theme/contrast", PROPERTY_HINT_RANGE, "-1, 1, 0.01"); - _initial_set("interface/theme/icon_saturation", 1.0); - hints["interface/theme/icon_saturation"] = PropertyInfo(Variant::FLOAT, "interface/theme/icon_saturation", PROPERTY_HINT_RANGE, "0,2,0.01", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/theme/relationship_line_opacity", 0.1); - hints["interface/theme/relationship_line_opacity"] = PropertyInfo(Variant::FLOAT, "interface/theme/relationship_line_opacity", PROPERTY_HINT_RANGE, "0.00, 1, 0.01"); - _initial_set("interface/theme/border_size", 0); - hints["interface/theme/border_size"] = PropertyInfo(Variant::INT, "interface/theme/border_size", PROPERTY_HINT_RANGE, "0,2,1", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/theme/corner_radius", 3); - hints["interface/theme/corner_radius"] = PropertyInfo(Variant::INT, "interface/theme/corner_radius", PROPERTY_HINT_RANGE, "0,6,1", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/theme/additional_spacing", 0); - hints["interface/theme/additional_spacing"] = PropertyInfo(Variant::FLOAT, "interface/theme/additional_spacing", PROPERTY_HINT_RANGE, "0,5,0.1", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/theme/custom_theme", ""); - hints["interface/theme/custom_theme"] = PropertyInfo(Variant::STRING, "interface/theme/custom_theme", PROPERTY_HINT_GLOBAL_FILE, "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_ENUM, "interface/theme/preset", "Default", "Default,Breeze Dark,Godot 2,Grey,Light,Solarized (Dark),Solarized (Light),Custom") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/theme/icon_and_font_color", 0, "Auto,Dark,Light") + EDITOR_SETTING(Variant::COLOR, PROPERTY_HINT_NONE, "interface/theme/base_color", Color(0.2, 0.23, 0.31), "") + EDITOR_SETTING(Variant::COLOR, PROPERTY_HINT_NONE, "interface/theme/accent_color", Color(0.41, 0.61, 0.91), "") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/theme/contrast", 0.3, "-1,1,0.01") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/theme/icon_saturation", 1.0, "0,2,0.01") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/theme/relationship_line_opacity", 0.1, "0.00,1,0.01") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/theme/border_size", 0, "0,2,1") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/theme/corner_radius", 3, "0,6,1") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/theme/additional_spacing", 0.0, "0,5,0.1") + EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/theme/custom_theme", "", "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) // Scene tabs _initial_set("interface/scene_tabs/show_thumbnail_on_hover", true); _initial_set("interface/scene_tabs/resize_if_many_tabs", true); - _initial_set("interface/scene_tabs/minimum_width", 50); - hints["interface/scene_tabs/minimum_width"] = PropertyInfo(Variant::INT, "interface/scene_tabs/minimum_width", PROPERTY_HINT_RANGE, "50,500,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); + EDITOR_SETTING_USAGE(Variant::INT, PROPERTY_HINT_RANGE, "interface/scene_tabs/minimum_width", 50, "50,500,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) _initial_set("interface/scene_tabs/show_script_button", false); /* Filesystem */ // Directories - _initial_set("filesystem/directories/autoscan_project_path", ""); - hints["filesystem/directories/autoscan_project_path"] = PropertyInfo(Variant::STRING, "filesystem/directories/autoscan_project_path", PROPERTY_HINT_GLOBAL_DIR); - _initial_set("filesystem/directories/default_project_path", OS::get_singleton()->has_environment("HOME") ? OS::get_singleton()->get_environment("HOME") : OS::get_singleton()->get_system_dir(OS::SYSTEM_DIR_DOCUMENTS)); - hints["filesystem/directories/default_project_path"] = PropertyInfo(Variant::STRING, "filesystem/directories/default_project_path", PROPERTY_HINT_GLOBAL_DIR); + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/directories/autoscan_project_path", "", "") + const String fs_dir_default_project_path = OS::get_singleton()->has_environment("HOME") ? OS::get_singleton()->get_environment("HOME") : OS::get_singleton()->get_system_dir(OS::SYSTEM_DIR_DOCUMENTS); + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/directories/default_project_path", fs_dir_default_project_path, "") // On save _initial_set("filesystem/on_save/compress_binary_resources", true); @@ -467,10 +448,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // File dialog _initial_set("filesystem/file_dialog/show_hidden_files", false); - _initial_set("filesystem/file_dialog/display_mode", 0); - hints["filesystem/file_dialog/display_mode"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"); - _initial_set("filesystem/file_dialog/thumbnail_size", 64); - hints["filesystem/file_dialog/thumbnail_size"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "filesystem/file_dialog/display_mode", 0, "Thumbnails,List") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "filesystem/file_dialog/thumbnail_size", 64, "32,128,16") /* Docks */ @@ -478,40 +457,33 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("docks/scene_tree/start_create_dialog_fully_expanded", false); // FileSystem - _initial_set("docks/filesystem/thumbnail_size", 64); - hints["docks/filesystem/thumbnail_size"] = PropertyInfo(Variant::INT, "docks/filesystem/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "docks/filesystem/thumbnail_size", 64, "32,128,16") _initial_set("docks/filesystem/always_show_folders", true); // Property editor _initial_set("docks/property_editor/auto_refresh_interval", 0.2); //update 5 times per second by default - _initial_set("docks/property_editor/subresource_hue_tint", 0.75); - hints["docks/property_editor/subresource_hue_tint"] = PropertyInfo(Variant::FLOAT, "docks/property_editor/subresource_hue_tint", PROPERTY_HINT_RANGE, "0,1,0.01", PROPERTY_USAGE_DEFAULT); + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "docks/property_editor/subresource_hue_tint", 0.75, "0,1,0.01") /* Text editor */ // Theme - _initial_set("text_editor/theme/color_theme", "Default"); - hints["text_editor/theme/color_theme"] = PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, "Default,Godot 2,Custom"); + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_ENUM, "text_editor/theme/color_theme", "Default", "Default,Godot 2,Custom") // Theme: Highlighting _load_godot2_text_editor_theme(); // Appearance // Appearance: Caret - _initial_set("text_editor/appearance/caret/type", 0); - hints["text_editor/appearance/caret/type"] = PropertyInfo(Variant::INT, "text_editor/appearance/caret/type", PROPERTY_HINT_ENUM, "Line,Block"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "text_editor/appearance/caret/type", 0, "Line,Block") _initial_set("text_editor/appearance/caret/caret_blink", true); - _initial_set("text_editor/appearance/caret/caret_blink_speed", 0.5); - hints["text_editor/appearance/caret/caret_blink_speed"] = PropertyInfo(Variant::FLOAT, "text_editor/appearance/caret/caret_blink_speed", PROPERTY_HINT_RANGE, "0.1, 10, 0.01"); + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "text_editor/appearance/caret/caret_blink_speed", 0.5, "0.1,10,0.01") _initial_set("text_editor/appearance/caret/highlight_current_line", true); _initial_set("text_editor/appearance/caret/highlight_all_occurrences", true); // Appearance: Guidelines _initial_set("text_editor/appearance/guidelines/show_line_length_guidelines", true); - _initial_set("text_editor/appearance/guidelines/line_length_guideline_soft_column", 80); - hints["text_editor/appearance/guidelines/line_length_guideline_soft_column"] = PropertyInfo(Variant::INT, "text_editor/appearance/guidelines/line_length_guideline_soft_column", PROPERTY_HINT_RANGE, "20, 160, 1"); - _initial_set("text_editor/appearance/guidelines/line_length_guideline_hard_column", 100); - hints["text_editor/appearance/guidelines/line_length_guideline_hard_column"] = PropertyInfo(Variant::INT, "text_editor/appearance/guidelines/line_length_guideline_hard_column", PROPERTY_HINT_RANGE, "20, 160, 1"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/appearance/guidelines/line_length_guideline_soft_column", 80, "20,160,1") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/appearance/guidelines/line_length_guideline_hard_column", 100, "20,160,1") // Appearance: Gutters _initial_set("text_editor/appearance/gutters/show_line_numbers", true); @@ -522,19 +494,16 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // Appearance: Minimap _initial_set("text_editor/appearance/minimap/show_minimap", true); - _initial_set("text_editor/appearance/minimap/minimap_width", 80); - hints["text_editor/appearance/minimap/minimap_width"] = PropertyInfo(Variant::INT, "text_editor/appearance/minimap/minimap_width", PROPERTY_HINT_RANGE, "50,250,1"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/appearance/minimap/minimap_width", 80, "50,250,1") // Appearance: Lines _initial_set("text_editor/appearance/lines/code_folding", true); - _initial_set("text_editor/appearance/lines/word_wrap", 0); - hints["text_editor/appearance/lines/word_wrap"] = PropertyInfo(Variant::INT, "text_editor/appearance/lines/word_wrap", PROPERTY_HINT_ENUM, "None,Boundary"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "text_editor/appearance/lines/word_wrap", 0, "None,Boundary") // Appearance: Whitespace _initial_set("text_editor/appearance/whitespace/draw_tabs", true); _initial_set("text_editor/appearance/whitespace/draw_spaces", false); - _initial_set("text_editor/appearance/whitespace/line_spacing", 6); - hints["text_editor/appearance/whitespace/line_spacing"] = PropertyInfo(Variant::INT, "text_editor/appearance/whitespace/line_spacing", PROPERTY_HINT_RANGE, "0,50,1"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/appearance/whitespace/line_spacing", 6, "0,50,1") // Behavior // Behavior: Navigation @@ -544,10 +513,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("text_editor/behavior/navigation/v_scroll_speed", 80); // Behavior: Indent - _initial_set("text_editor/behavior/indent/type", 0); - hints["text_editor/behavior/indent/type"] = PropertyInfo(Variant::INT, "text_editor/behavior/indent/type", PROPERTY_HINT_ENUM, "Tabs,Spaces"); - _initial_set("text_editor/behavior/indent/size", 4); - hints["text_editor/behavior/indent/size"] = PropertyInfo(Variant::INT, "text_editor/behavior/indent/size", PROPERTY_HINT_RANGE, "1, 64, 1"); // size of 0 crashes. + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "text_editor/behavior/indent/type", 0, "Tabs,Spaces") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/behavior/indent/size", 4, "1,64,1") // size of 0 crashes. _initial_set("text_editor/behavior/indent/auto_indent", true); // Behavior: Files @@ -561,11 +528,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("text_editor/script_list/sort_members_outline_alphabetically", false); // Completion - _initial_set("text_editor/completion/idle_parse_delay", 2.0); - hints["text_editor/completion/idle_parse_delay"] = PropertyInfo(Variant::FLOAT, "text_editor/completion/idle_parse_delay", PROPERTY_HINT_RANGE, "0.1, 10, 0.01"); + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "text_editor/completion/idle_parse_delay", 2.0, "0.1,10,0.01") _initial_set("text_editor/completion/auto_brace_complete", true); - _initial_set("text_editor/completion/code_complete_delay", 0.3); - hints["text_editor/completion/code_complete_delay"] = PropertyInfo(Variant::FLOAT, "text_editor/completion/code_complete_delay", PROPERTY_HINT_RANGE, "0.01, 5, 0.01"); + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "text_editor/completion/code_complete_delay", 0.3, "0.01,5,0.01") _initial_set("text_editor/completion/put_callhint_tooltip_below_current_line", true); _initial_set("text_editor/completion/complete_file_paths", true); _initial_set("text_editor/completion/add_type_hints", false); @@ -573,14 +538,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // Help _initial_set("text_editor/help/show_help_index", true); - _initial_set("text_editor/help/help_font_size", 15); - hints["text_editor/help/help_font_size"] = PropertyInfo(Variant::INT, "text_editor/help/help_font_size", PROPERTY_HINT_RANGE, "8,48,1"); - _initial_set("text_editor/help/help_source_font_size", 14); - hints["text_editor/help/help_source_font_size"] = PropertyInfo(Variant::INT, "text_editor/help/help_source_font_size", PROPERTY_HINT_RANGE, "8,48,1"); - _initial_set("text_editor/help/help_title_font_size", 23); - hints["text_editor/help/help_title_font_size"] = PropertyInfo(Variant::INT, "text_editor/help/help_title_font_size", PROPERTY_HINT_RANGE, "8,48,1"); - _initial_set("text_editor/help/class_reference_examples", 0); - hints["text_editor/help/class_reference_examples"] = PropertyInfo(Variant::INT, "text_editor/help/class_reference_examples", PROPERTY_HINT_ENUM, "GDScript,C#,GDScript and C#"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/help/help_font_size", 15, "8,48,1") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/help/help_source_font_size", 14, "8,48,1") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/help/help_title_font_size", 23, "8,48,1") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "text_editor/help/class_reference_examples", 0, "GDScript,C#,GDScript and C#") /* Editors */ @@ -588,39 +549,23 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("editors/grid_map/pick_distance", 5000.0); // 3D - _initial_set("editors/3d/primary_grid_color", Color(0.56, 0.56, 0.56, 0.5)); - hints["editors/3d/primary_grid_color"] = PropertyInfo(Variant::COLOR, "editors/3d/primary_grid_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT); - - _initial_set("editors/3d/secondary_grid_color", Color(0.38, 0.38, 0.38, 0.5)); - hints["editors/3d/secondary_grid_color"] = PropertyInfo(Variant::COLOR, "editors/3d/secondary_grid_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT); + EDITOR_SETTING(Variant::COLOR, PROPERTY_HINT_NONE, "editors/3d/primary_grid_color", Color(0.56, 0.56, 0.56, 0.5), "") + EDITOR_SETTING(Variant::COLOR, PROPERTY_HINT_NONE, "editors/3d/secondary_grid_color", Color(0.38, 0.38, 0.38, 0.5), "") // Use a similar color to the 2D editor selection. - _initial_set("editors/3d/selection_box_color", Color(1.0, 0.5, 0)); - hints["editors/3d/selection_box_color"] = PropertyInfo(Variant::COLOR, "editors/3d/selection_box_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); + EDITOR_SETTING_USAGE(Variant::COLOR, PROPERTY_HINT_NONE, "editors/3d/selection_box_color", Color(1.0, 0.5, 0), "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) // If a line is a multiple of this, it uses the primary grid color. // Use a power of 2 value by default as it's more common to use powers of 2 in level design. - _initial_set("editors/3d/primary_grid_steps", 8); - hints["editors/3d/primary_grid_steps"] = PropertyInfo(Variant::INT, "editors/3d/primary_grid_steps", PROPERTY_HINT_RANGE, "1,100,1", PROPERTY_USAGE_DEFAULT); - - // At 1000, the grid mostly looks like it has no edge. - _initial_set("editors/3d/grid_size", 200); - hints["editors/3d/grid_size"] = PropertyInfo(Variant::INT, "editors/3d/grid_size", PROPERTY_HINT_RANGE, "1,2000,1", PROPERTY_USAGE_DEFAULT); - - // Default largest grid size is 100m, 10^2 (primary grid lines are 1km apart when primary_grid_steps is 10). - _initial_set("editors/3d/grid_division_level_max", 2); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/3d/primary_grid_steps", 8, "1,100,1") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/3d/grid_size", 200, "1,2000,1") // Higher values produce graphical artifacts when far away unless View Z-Far // is increased significantly more than it really should need to be. - hints["editors/3d/grid_division_level_max"] = PropertyInfo(Variant::INT, "editors/3d/grid_division_level_max", PROPERTY_HINT_RANGE, "-1,3,1", PROPERTY_USAGE_DEFAULT); - - // Default smallest grid size is 1m, 10^0. - _initial_set("editors/3d/grid_division_level_min", 0); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/3d/grid_division_level_max", 2, "-1,3,1") // Lower values produce graphical artifacts regardless of view clipping planes, so limit to -2 as a lower bound. - hints["editors/3d/grid_division_level_min"] = PropertyInfo(Variant::INT, "editors/3d/grid_division_level_min", PROPERTY_HINT_RANGE, "-2,2,1", PROPERTY_USAGE_DEFAULT); - + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/3d/grid_division_level_min", 0, "-2,2,1") // -0.2 seems like a sensible default. -1.0 gives Blender-like behavior, 0.5 gives huge grids. - _initial_set("editors/3d/grid_division_level_bias", -0.2); - hints["editors/3d/grid_division_level_bias"] = PropertyInfo(Variant::FLOAT, "editors/3d/grid_division_level_bias", PROPERTY_HINT_RANGE, "-1.0,0.5,0.1", PROPERTY_USAGE_DEFAULT); + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/grid_division_level_bias", -0.2, "-1.0,0.5,0.1") _initial_set("editors/3d/grid_xz_plane", true); _initial_set("editors/3d/grid_xy_plane", false); @@ -629,56 +574,37 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // Use a lower default FOV for the 3D camera compared to the // Camera3D node as the 3D viewport doesn't span the whole screen. // This means it's technically viewed from a further distance, which warrants a narrower FOV. - _initial_set("editors/3d/default_fov", 70.0); - hints["editors/3d/default_fov"] = PropertyInfo(Variant::FLOAT, "editors/3d/default_fov", PROPERTY_HINT_RANGE, "1,179,0.1"); - _initial_set("editors/3d/default_z_near", 0.05); - hints["editors/3d/default_z_near"] = PropertyInfo(Variant::FLOAT, "editors/3d/default_z_near", PROPERTY_HINT_RANGE, "0.01,10,0.01,or_greater"); - _initial_set("editors/3d/default_z_far", 4000.0); - hints["editors/3d/default_z_far"] = PropertyInfo(Variant::FLOAT, "editors/3d/default_z_far", PROPERTY_HINT_RANGE, "0.1,4000,0.1,or_greater"); + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/default_fov", 70.0, "1,179,0.1") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/default_z_near", 0.05, "0.01,10,0.01,or_greater") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/default_z_far", 4000.0, "0.1,4000,0.1,or_greater") // 3D: Navigation - _initial_set("editors/3d/navigation/navigation_scheme", 0); - _initial_set("editors/3d/navigation/invert_y_axis", false); _initial_set("editors/3d/navigation/invert_x_axis", false); - hints["editors/3d/navigation/navigation_scheme"] = PropertyInfo(Variant::INT, "editors/3d/navigation/navigation_scheme", PROPERTY_HINT_ENUM, "Godot,Maya,Modo"); - _initial_set("editors/3d/navigation/zoom_style", 0); - hints["editors/3d/navigation/zoom_style"] = PropertyInfo(Variant::INT, "editors/3d/navigation/zoom_style", PROPERTY_HINT_ENUM, "Vertical, Horizontal"); + _initial_set("editors/3d/navigation/invert_y_axis", false); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "editors/3d/navigation/navigation_scheme", 0, "Godot,Maya,Modo") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "editors/3d/navigation/zoom_style", 0, "Vertical,Horizontal") _initial_set("editors/3d/navigation/emulate_numpad", false); _initial_set("editors/3d/navigation/emulate_3_button_mouse", false); - _initial_set("editors/3d/navigation/orbit_modifier", 0); - hints["editors/3d/navigation/orbit_modifier"] = PropertyInfo(Variant::INT, "editors/3d/navigation/orbit_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl"); - _initial_set("editors/3d/navigation/pan_modifier", 1); - hints["editors/3d/navigation/pan_modifier"] = PropertyInfo(Variant::INT, "editors/3d/navigation/pan_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl"); - _initial_set("editors/3d/navigation/zoom_modifier", 4); - hints["editors/3d/navigation/zoom_modifier"] = PropertyInfo(Variant::INT, "editors/3d/navigation/zoom_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "editors/3d/navigation/orbit_modifier", 0, "None,Shift,Alt,Meta,Ctrl") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "editors/3d/navigation/pan_modifier", 1, "None,Shift,Alt,Meta,Ctrl") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "editors/3d/navigation/zoom_modifier", 4, "None,Shift,Alt,Meta,Ctrl") _initial_set("editors/3d/navigation/warped_mouse_panning", true); // 3D: Navigation feel - _initial_set("editors/3d/navigation_feel/orbit_sensitivity", 0.4); - hints["editors/3d/navigation_feel/orbit_sensitivity"] = PropertyInfo(Variant::FLOAT, "editors/3d/navigation_feel/orbit_sensitivity", PROPERTY_HINT_RANGE, "0.0, 2, 0.01"); - _initial_set("editors/3d/navigation_feel/orbit_inertia", 0.05); - hints["editors/3d/navigation_feel/orbit_inertia"] = PropertyInfo(Variant::FLOAT, "editors/3d/navigation_feel/orbit_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01"); - _initial_set("editors/3d/navigation_feel/translation_inertia", 0.15); - hints["editors/3d/navigation_feel/translation_inertia"] = PropertyInfo(Variant::FLOAT, "editors/3d/navigation_feel/translation_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01"); - _initial_set("editors/3d/navigation_feel/zoom_inertia", 0.075); - hints["editors/3d/navigation_feel/zoom_inertia"] = PropertyInfo(Variant::FLOAT, "editors/3d/navigation_feel/zoom_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01"); - _initial_set("editors/3d/navigation_feel/manipulation_orbit_inertia", 0.075); - hints["editors/3d/navigation_feel/manipulation_orbit_inertia"] = PropertyInfo(Variant::FLOAT, "editors/3d/navigation_feel/manipulation_orbit_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01"); - _initial_set("editors/3d/navigation_feel/manipulation_translation_inertia", 0.075); - hints["editors/3d/navigation_feel/manipulation_translation_inertia"] = PropertyInfo(Variant::FLOAT, "editors/3d/navigation_feel/manipulation_translation_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01"); + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/navigation_feel/orbit_sensitivity", 0.4, "0.0,2,0.01") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/navigation_feel/orbit_inertia", 0.05, "0.0,1,0.01") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/navigation_feel/translation_inertia", 0.15, "0.0,1,0.01") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/navigation_feel/zoom_inertia", 0.075, "0.0,1,0.01") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/navigation_feel/manipulation_orbit_inertia", 0.075, "0.0,1,0.01") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/navigation_feel/manipulation_translation_inertia", 0.075, "0.0,1,0.01") // 3D: Freelook - _initial_set("editors/3d/freelook/freelook_navigation_scheme", false); - hints["editors/3d/freelook/freelook_navigation_scheme"] = PropertyInfo(Variant::INT, "editors/3d/freelook/freelook_navigation_scheme", PROPERTY_HINT_ENUM, "Default,Partially Axis-Locked (id Tech),Fully Axis-Locked (Minecraft)"); - _initial_set("editors/3d/freelook/freelook_sensitivity", 0.4); - hints["editors/3d/freelook/freelook_sensitivity"] = PropertyInfo(Variant::FLOAT, "editors/3d/freelook/freelook_sensitivity", PROPERTY_HINT_RANGE, "0.0, 2, 0.01"); - _initial_set("editors/3d/freelook/freelook_inertia", 0.1); - hints["editors/3d/freelook/freelook_inertia"] = PropertyInfo(Variant::FLOAT, "editors/3d/freelook/freelook_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01"); - _initial_set("editors/3d/freelook/freelook_base_speed", 5.0); - hints["editors/3d/freelook/freelook_base_speed"] = PropertyInfo(Variant::FLOAT, "editors/3d/freelook/freelook_base_speed", PROPERTY_HINT_RANGE, "0.0, 10, 0.01"); - _initial_set("editors/3d/freelook/freelook_activation_modifier", 0); - hints["editors/3d/freelook/freelook_activation_modifier"] = PropertyInfo(Variant::INT, "editors/3d/freelook/freelook_activation_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "editors/3d/freelook/freelook_navigation_scheme", 0, "Default,Partially Axis-Locked (id Tech),Fully Axis-Locked (Minecraft)") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/freelook/freelook_sensitivity", 0.4, "0.0,2,0.01") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/freelook/freelook_inertia", 0.1, "0.0,1,0.01") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/freelook/freelook_base_speed", 5.0, "0.0,10,0.01") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "editors/3d/freelook/freelook_activation_modifier", 0, "None,Shift,Alt,Meta,Ctrl") _initial_set("editors/3d/freelook/freelook_speed_zoom_link", false); // 2D @@ -716,28 +642,24 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("editors/animation/onion_layers_future_color", Color(0, 1, 0)); // Visual editors - _initial_set("editors/visual_editors/minimap_opacity", 0.85); - hints["editors/visual_editors/minimap_opacity"] = PropertyInfo(Variant::FLOAT, "editors/visual_editors/minimap_opacity", PROPERTY_HINT_RANGE, "0.0,1.0,0.01", PROPERTY_USAGE_DEFAULT); + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/visual_editors/minimap_opacity", 0.85, "0.0,1.0,0.01") /* Run */ // Window placement - _initial_set("run/window_placement/rect", 1); - hints["run/window_placement/rect"] = PropertyInfo(Variant::INT, "run/window_placement/rect", PROPERTY_HINT_ENUM, "Top Left,Centered,Custom Position,Force Maximized,Force Fullscreen"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "run/window_placement/rect", 1, "Top Left,Centered,Custom Position,Force Maximized,Force Fullscreen") String screen_hints = "Same as Editor,Previous Monitor,Next Monitor"; for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) { screen_hints += ",Monitor " + itos(i + 1); } _initial_set("run/window_placement/rect_custom_position", Vector2()); - _initial_set("run/window_placement/screen", 0); - hints["run/window_placement/screen"] = PropertyInfo(Variant::INT, "run/window_placement/screen", PROPERTY_HINT_ENUM, screen_hints); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "run/window_placement/screen", 0, screen_hints) // Auto save _initial_set("run/auto_save/save_before_running", true); // Output - _initial_set("run/output/font_size", 13); - hints["run/output/font_size"] = PropertyInfo(Variant::INT, "run/output/font_size", PROPERTY_HINT_RANGE, "8,48,1"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "run/output/font_size", 13, "8,48,1") _initial_set("run/output/always_clear_output_on_play", true); _initial_set("run/output/always_open_output_on_play", true); _initial_set("run/output/always_close_output_on_stop", false); @@ -747,17 +669,14 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // Debug _initial_set("network/debug/remote_host", "127.0.0.1"); // Hints provided in setup_network - _initial_set("network/debug/remote_port", 6007); - hints["network/debug/remote_port"] = PropertyInfo(Variant::INT, "network/debug/remote_port", PROPERTY_HINT_RANGE, "1,65535,1"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "network/debug/remote_port", 6007, "1,65535,1") // SSL - _initial_set("network/ssl/editor_ssl_certificates", _SYSTEM_CERTS_PATH); - hints["network/ssl/editor_ssl_certificates"] = PropertyInfo(Variant::STRING, "network/ssl/editor_ssl_certificates", PROPERTY_HINT_GLOBAL_FILE, "*.crt,*.pem"); + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "network/ssl/editor_ssl_certificates", _SYSTEM_CERTS_PATH, "*.crt,*.pem") /* Extra config */ - _initial_set("project_manager/sorting_order", 0); - hints["project_manager/sorting_order"] = PropertyInfo(Variant::INT, "project_manager/sorting_order", PROPERTY_HINT_ENUM, "Name,Path,Last Edited"); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "project_manager/sorting_order", 0, "Name,Path,Last Edited") if (p_extra_config.is_valid()) { if (p_extra_config->has_section("init_projects") && p_extra_config->has_section_key("init_projects", "list")) { diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 8a08f4e450..6e5b94dc07 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -1154,8 +1154,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("increment", "HScrollBar", empty_icon); theme->set_icon("increment_highlight", "HScrollBar", empty_icon); + theme->set_icon("increment_pressed", "HScrollBar", empty_icon); theme->set_icon("decrement", "HScrollBar", empty_icon); theme->set_icon("decrement_highlight", "HScrollBar", empty_icon); + theme->set_icon("decrement_pressed", "HScrollBar", empty_icon); // VScrollBar theme->set_stylebox("scroll", "VScrollBar", make_stylebox(theme->get_icon("GuiScrollBg", "EditorIcons"), 5, 5, 5, 5, 0, 0, 0, 0)); @@ -1166,8 +1168,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("increment", "VScrollBar", empty_icon); theme->set_icon("increment_highlight", "VScrollBar", empty_icon); + theme->set_icon("increment_pressed", "VScrollBar", empty_icon); theme->set_icon("decrement", "VScrollBar", empty_icon); theme->set_icon("decrement_highlight", "VScrollBar", empty_icon); + theme->set_icon("decrement_pressed", "VScrollBar", empty_icon); // HSlider theme->set_icon("grabber_highlight", "HSlider", theme->get_icon("GuiSliderGrabberHl", "EditorIcons")); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index daee61c2dd..5dd5c050e0 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -2158,6 +2158,14 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da return true; } + if (drag_data.has("type") && String(drag_data["type"]) == "nodes") { + // Save branch as scene. + String to_dir; + bool favorite; + _get_drag_target_folder(to_dir, favorite, p_point, p_from); + return !favorite && Array(drag_data["nodes"]).size() == 1; + } + return false; } @@ -2296,6 +2304,13 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, _update_tree(_compute_uncollapsed_paths()); } } + + if (drag_data.has("type") && String(drag_data["type"]) == "nodes") { + String to_dir; + bool favorite; + _get_drag_target_folder(to_dir, favorite, p_point, p_from); + EditorNode::get_singleton()->get_scene_tree_dock()->save_branch_to_file(to_dir); + } } void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favorites, const Point2 &p_point, Control *p_from) const { diff --git a/editor/icons/AddSplit.svg b/editor/icons/AddSplit.svg deleted file mode 100644 index e46949182c..0000000000 --- a/editor/icons/AddSplit.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 13 10-10" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/><path d="m11 9v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#5fff97"/><circle cx="4" cy="12" fill="none" r="2"/><path d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-10 10a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/AudioListener2D.svg b/editor/icons/AudioListener2D.svg new file mode 100644 index 0000000000..db84dcfed7 --- /dev/null +++ b/editor/icons/AudioListener2D.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1a5 5 0 0 0 -5 5h2a3 3 0 0 1 3-3 3 3 0 0 1 3 3c0 1.75-.54175 2.3583-1.1406 2.8574-.29944.2495-.62954.44071-.97656.69141-.17351.1253-.35729.26529-.53711.49219-.17982.227-.3457.58398-.3457.95898 0 1.2778-.31632 1.5742-.63867 1.7676-.32236.1934-.86133.23242-1.3613.23242h-1v2h1c.5 0 1.461.038922 2.3887-.51758.87316-.5239 1.4826-1.6633 1.5566-3.2266.011365-.0098.027247-.024684.10938-.083984.21547-.1556.63537-.40194 1.0859-.77734.90112-.751 1.8594-2.1445 1.8594-4.3945a5 5 0 0 0 -5-5zm7.9277 1-1.7383 1.0039a6 6 0 0 1 .81055 2.9961 6 6 0 0 1 -.80859 2.998l1.7363 1.002a8 8 0 0 0 0-8z" fill="#a5b7f3"/></svg> diff --git a/editor/icons/Listener3D.svg b/editor/icons/AudioListener3D.svg index c068474d17..c068474d17 100644 --- a/editor/icons/Listener3D.svg +++ b/editor/icons/AudioListener3D.svg diff --git a/editor/icons/AutoEndBackwards.svg b/editor/icons/AutoEndBackwards.svg deleted file mode 100644 index c6de305069..0000000000 --- a/editor/icons/AutoEndBackwards.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m2 14c-.552262-.000055-.999945-.447738-1-1v-10c.000055-.5522619.447738-.9999448 1-1h8c.303863-.0001753.591325.1378063.78125.375l4 5c.291397.3649711.291397.8830289 0 1.248l-4 5c-.189538.237924-.477058.376652-.78125.37695h-8zm1-2h6.5195004l3.1991996-4-3.1991996-4h-6.5195004zm6.0000004-2v-4l1.9999996 2z" fill-rule="evenodd"/><path d="m3.8685125 4.9095434h4.1550816v1.1637426h-2.6154217v1.1117544h2.4594562v1.1637428h-2.4594562v1.3676976h2.7034024v1.1637432h-4.2430623z" stroke-width=".204755"/></g></svg> diff --git a/editor/icons/AutoPlayBackwards.svg b/editor/icons/AutoPlayBackwards.svg deleted file mode 100644 index 20602ba348..0000000000 --- a/editor/icons/AutoPlayBackwards.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13.999798 2a-1.0001 1.0001 0 0 1 1 1v10a-1.0001 1.0001 0 0 1 -1 1h-8.0000003a-1.0001 1.0001 0 0 1 -.78125-.375l-4-5a-1.0001 1.0001 0 0 1 0-1.248l4-5a-1.0001 1.0001 0 0 1 .78125-.37695h8.0000003zm-1 2h-6.5195003l-3.1992 4 3.1992 4h6.5195003zm-3.0000003 1c1.1046003 0 2.0000003.8954 2.0000003 2v4h-1v-2h-2.0000003v2h-1v-4c0-1.1046.89543-2 2-2zm0 1a-1 1 0 0 0 -1 1v1h2.0000003v-1a-1 1 0 0 0 -1.0000003-1zm-3 0v4l-2-2z" fill="#e0e0e0" fill-rule="evenodd"/></svg> diff --git a/editor/icons/BoneTrack.svg b/editor/icons/BoneTrack.svg deleted file mode 100644 index 69a32f3595..0000000000 --- a/editor/icons/BoneTrack.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.478 1037.4a2.4664 2.4663 0 0 0 -1.7804.7205 2.4664 2.4663 0 0 0 -.31408 3.1041l-3.559 3.5608a2.4664 2.4663 0 0 0 -3.1023.3121 2.4664 2.4663 0 0 0 0 3.4876 2.4664 2.4663 0 0 0 1.397.6955 2.4664 2.4663 0 0 0 .69561 1.397 2.4664 2.4663 0 0 0 3.4877 0 2.4664 2.4663 0 0 0 .31408-3.1041l3.5609-3.5608a2.4664 2.4663 0 0 0 3.1004-.3102 2.4664 2.4663 0 0 0 0-3.4875 2.4664 2.4663 0 0 0 -1.397-.6974 2.4664 2.4663 0 0 0 -.69561-1.3971 2.4664 2.4663 0 0 0 -1.7072-.7205z" fill="#c38ef1" transform="translate(0 -1036.4)"/></svg> diff --git a/editor/icons/CanvasItemShader.svg b/editor/icons/CanvasItemShader.svg deleted file mode 100644 index 9aeb2f0fdc..0000000000 --- a/editor/icons/CanvasItemShader.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13.303 1c-.4344 0-.86973.16881-1.2012.50586l-1.4688 1.4941h4.3418c.082839-.52789-.072596-1.0872-.47266-1.4941-.33144-.33705-.76482-.50586-1.1992-.50586z" fill="#ff4545"/><path d="m10.633 3-1.9668 2h4.8008l1.0352-1.0527c.2628-.2673.41824-.60049.47266-.94727h-4.3418z" fill="#ffe345"/><path d="m8.666 5-1.9648 2h4.7988l1.9668-2z" fill="#80ff45"/><path d="m6.7012 7-1.4004 1.4238.56641.57617h3.668l1.9648-2h-4.7988z" fill="#45ffa2"/><path d="m5.8672 9 1.834 1.8652 1.834-1.8652zm-1.752.57812c-.48501-.048725-.90521.12503-1.1953.45508-.21472.24426-.35243.57797-.39844.9668h3.5625c-.10223-.1935-.22224-.37965-.38281-.54297-.55011-.55955-1.1009-.83018-1.5859-.87891z" fill="#45d7ff"/><path d="m1.3242 13c.18414.24071.43707.53374.83789.94141.88382.899 2.6552.67038 3.5391-.22852.20747-.21103.36064-.45476.4707-.71289h-4.8477z" fill="#ff4596"/><path d="m2.5215 11c-.0105.088737-.021484.17696-.021484.27148 0 1.3947-2.2782.28739-1.1758 1.7285h4.8477c.27363-.64173.24047-1.3785-.087891-2h-3.5625z" fill="#8045ff"/></svg> diff --git a/editor/icons/CanvasItemShaderGraph.svg b/editor/icons/CanvasItemShaderGraph.svg deleted file mode 100644 index 70db53a4ba..0000000000 --- a/editor/icons/CanvasItemShaderGraph.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="a"><path d="m8.0625 1025.9a3.375 3 0 0 0 -3.375 3 3.375 3 0 0 0 1.6875 2.5957v9.8115a3.375 3 0 0 0 -1.6875 2.5928 3.375 3 0 0 0 3.375 3 3.375 3 0 0 0 3.375-3 3.375 3 0 0 0 -1.6875-2.5957v-8.7832l11.931 10.605a3.375 3 0 0 0 -.11865.7735 3.375 3 0 0 0 3.375 3 3.375 3 0 0 0 3.375-3 3.375 3 0 0 0 -3.375-3 3.375 3 0 0 0 -.87341.1025l-11.928-10.602h9.8844a3.375 3 0 0 0 2.9169 1.5 3.375 3 0 0 0 3.375-3 3.375 3 0 0 0 -3.375-3 3.375 3 0 0 0 -2.9202 1.5h-11.038a3.375 3 0 0 0 -2.9169-1.5z"/></clipPath><g transform="translate(0 -1036.4)"><g clip-path="url(#a)" transform="matrix(.59259 0 0 .66667 -1.7778 353.45)"><path d="m3 1025.9h27v3h-27z" fill="#ff4545"/><path d="m3 1028.9h27v3h-27z" fill="#ffe345"/><path d="m3 1031.9h27v3h-27z" fill="#80ff45"/><path d="m3 1034.9h27v3h-27z" fill="#45ffa2"/><path d="m3 1037.9h27v3h-27z" fill="#45d7ff"/><path d="m3 1043.9h27v3h-27z" fill="#ff4596"/><path d="m3 1040.9h27v3h-27z" fill="#8045ff"/></g><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/></g></svg> diff --git a/editor/icons/ColorRamp.svg b/editor/icons/ColorRamp.svg deleted file mode 100644 index 13e05dd1ee..0000000000 --- a/editor/icons/ColorRamp.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(.51852 0 0 .7 -.55556 1034.6)" gradientUnits="userSpaceOnUse" x1="4" x2="30" y1="14" y2="14"><stop offset="0" stop-color="#afff68"/><stop offset="1" stop-color="#ff6b6b"/></linearGradient><path d="m1 1051.4h14v-14z" fill="url(#a)" transform="translate(0 -1036.4)"/></svg> diff --git a/editor/icons/ControlAlignCenterLeft.svg b/editor/icons/ControlAlignCenterLeft.svg deleted file mode 100644 index fc4674af48..0000000000 --- a/editor/icons/ControlAlignCenterLeft.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 6h6v4h-6z" fill="#d6d6d6"/></svg> diff --git a/editor/icons/ControlAlignCenterRight.svg b/editor/icons/ControlAlignCenterRight.svg deleted file mode 100644 index c66a3d59b5..0000000000 --- a/editor/icons/ControlAlignCenterRight.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 6h6v4h-6z" fill="#d6d6d6"/></svg> diff --git a/editor/icons/DeleteSplit.svg b/editor/icons/DeleteSplit.svg deleted file mode 100644 index 4ae590f78b..0000000000 --- a/editor/icons/DeleteSplit.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m.623213 6.939446h1.845669v2.085366h-1.845669z" fill="#800000"/><path d="m12.488225 7.179143h1.629941v1.989487h-1.629941z" fill="#800000"/><g fill="#e9afaf"><path d="m2.540791 7.970143h3.164003v.407485h-3.164003z"/><path d="m9.012615 8.042052h3.523549v.527334h-3.523549z"/><g transform="matrix(-.55917959 .82904655 -.82904655 -.55917959 0 0)"><path d="m1.511097-9.732645h3.643398v.455425h-3.643398z"/><path d="m.07207-12.144793h3.643398v.455425h-3.643398z"/></g></g></svg> diff --git a/editor/icons/EditResource.svg b/editor/icons/EditResource.svg deleted file mode 100644 index 3b14428b90..0000000000 --- a/editor/icons/EditResource.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="8" viewBox="0 0 8 8" width="8" xmlns="http://www.w3.org/2000/svg"><path d="m3.9902-.0097656a1.0001 1.0001 0 0 0 -.69727 1.7168l1.293 1.293h-3.5859v2h3.5859l-1.293 1.293a1.0001 1.0001 0 1 0 1.4141 1.4141l3-3a1.0001 1.0001 0 0 0 0-1.4141l-3-3a1.0001 1.0001 0 0 0 -.7168-.30273z" fill="#e0e0e0" fill-opacity=".78431"/></svg> diff --git a/editor/icons/EditorInternalHandle.svg b/editor/icons/EditorInternalHandle.svg deleted file mode 100644 index dbb7bc289f..0000000000 --- a/editor/icons/EditorInternalHandle.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><circle cx="5" cy="5" fill-opacity=".29412" r="5"/><circle cx="5" cy="5" fill="#fff" r="4"/><circle cx="5" cy="5" fill="#84b1ff" r="3"/></svg> diff --git a/editor/icons/ErrorSign.svg b/editor/icons/ErrorSign.svg deleted file mode 100644 index 85a2cda346..0000000000 --- a/editor/icons/ErrorSign.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1020.4)"><path d="m10 1048.4h12l6-6v-12l-6-6h-12l-6 6v12z" fill="#ff5d5d" fill-rule="evenodd"/><path d="m14 8 1 10h2l1-10zm2 12a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#fff" transform="translate(0 1020.4)"/></g></svg> diff --git a/editor/icons/FixedMaterial.svg b/editor/icons/FixedMaterial.svg deleted file mode 100644 index 2c30ecac24..0000000000 --- a/editor/icons/FixedMaterial.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1037.4a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm-2 2a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2-2 2 2 0 0 1 2-2z" fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1036.4)"/></svg> diff --git a/editor/icons/FixedSpatialMaterial.svg b/editor/icons/FixedSpatialMaterial.svg deleted file mode 100644 index 322465a0c7..0000000000 --- a/editor/icons/FixedSpatialMaterial.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -4.8887 2h2.8887 6.8965a7 7 0 0 0 -4.8965-2z" fill="#ff4545"/><path d="m3.1113 3a7 7 0 0 0 -1.4277 2h2.3164a2 2 0 0 1 2-2zm2.8887 0a2 2 0 0 1 2 2h6.3145a7 7 0 0 0 -1.418-2z" fill="#ffe345"/><path d="m1.6836 5a7 7 0 0 0 -.60547 2h4.9219a2 2 0 0 1 -2-2h-2.3164zm4.3164 2h8.9199a7 7 0 0 0 -.60547-2h-6.3145a2 2 0 0 1 -2 2z" fill="#80ff45"/><path d="m1.0781 7a7 7 0 0 0 -.078125 1 7 7 0 0 0 .080078 1h13.842a7 7 0 0 0 .078125-1 7 7 0 0 0 -.080078-1h-8.9199-4.9219z" fill="#45ffa2"/><path d="m1.0801 9a7 7 0 0 0 .60547 2h12.631a7 7 0 0 0 .60547-2h-13.842z" fill="#45d7ff"/><path d="m3.1035 13a7 7 0 0 0 4.8965 2 7 7 0 0 0 4.8887-2z" fill="#ff4596"/><path d="m1.6855 11a7 7 0 0 0 1.418 2h9.7852a7 7 0 0 0 1.4277-2h-12.631z" fill="#8045ff"/></svg> diff --git a/editor/icons/GizmoListener.svg b/editor/icons/GizmoAudioListener3D.svg index 9d3ddf8b85..9d3ddf8b85 100644 --- a/editor/icons/GizmoListener.svg +++ b/editor/icons/GizmoAudioListener3D.svg diff --git a/editor/icons/GizmoCamera.svg b/editor/icons/GizmoCamera.svg deleted file mode 100644 index 1fa2186197..0000000000 --- a/editor/icons/GizmoCamera.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="128" viewBox="0 0 128 128" width="128" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -924.36)"><path d="m76 16a28 28 0 0 0 -26.631 19.4 28 28 0 0 0 -13.369-3.4004 28 28 0 0 0 -28 28 28 28 0 0 0 16 25.26v14.74c0 6.648 5.352 12 12 12h48c6.648 0 12-5.352 12-12l24 16v-64l-24 16v-4.4434a28 28 0 0 0 8-19.557 28 28 0 0 0 -28-28z" fill-opacity=".29412" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="2" transform="translate(0 924.36)"/><path d="m76 944.36a24 24 0 0 0 -23.906 22.219 24 24 0 0 0 -16.094-6.2192 24 24 0 0 0 -24 24 24 24 0 0 0 16 22.594v17.406c0 4.432 3.5679 8 8 8h48c4.4321 0 8-3.568 8-8v-8l24 16v-48l-24 16v-14.156a24 24 0 0 0 8-17.844 24 24 0 0 0 -24-24z" fill="#f7f5cf"/></g></svg> diff --git a/editor/icons/GuiHTick.svg b/editor/icons/GuiHTick.svg deleted file mode 100644 index a8a2fe58f6..0000000000 --- a/editor/icons/GuiHTick.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 4 15.999999" width="4" xmlns="http://www.w3.org/2000/svg"><circle cx="2" cy="2" fill="#fff" fill-opacity=".39216" r="1"/></svg> diff --git a/editor/icons/GuiResizerMirrored.svg b/editor/icons/GuiResizerMirrored.svg deleted file mode 100644 index 8227f5b648..0000000000 --- a/editor/icons/GuiResizerMirrored.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill-opacity=".588" fill="#fff" d="M4 3a1 1 0 0 1 1 1v6h6a1 1 0 0 1 0 2H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"/></svg> diff --git a/editor/icons/GuiTabMirrored.svg b/editor/icons/GuiTabMirrored.svg deleted file mode 100644 index a0011a5b2d..0000000000 --- a/editor/icons/GuiTabMirrored.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8"><path fill-opacity=".196" fill="#fff" d="M2 0v8H0V0zm5.014.002a-1 1 0 0 1 .693.291-1 1 0 0 1 0 1.414L5.414 4l2.293 2.293a-1 1 0 0 1 0 1.414-1 1 0 0 1-1.414 0l-3-3a-1 1 0 0 1 0-1.414l3-3a-1 1 0 0 1 .72-.29z"/></svg> diff --git a/editor/icons/GuiTreeArrowUp.svg b/editor/icons/GuiTreeArrowUp.svg deleted file mode 100644 index f5399bc7f9..0000000000 --- a/editor/icons/GuiTreeArrowUp.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="12" viewBox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="m3 1045.4 3 3 3-3" style="fill:none;stroke:#fff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:.39216" transform="matrix(-1 0 0 -1 12 1052.16952)"/></svg> diff --git a/editor/icons/GuiVTick.svg b/editor/icons/GuiVTick.svg deleted file mode 100644 index c0af1df8fb..0000000000 --- a/editor/icons/GuiVTick.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="4" viewBox="0 0 16 3.9999998" width="16" xmlns="http://www.w3.org/2000/svg"><circle cx="2" cy="2" fill="#fff" fill-opacity=".39216" r="1"/></svg> diff --git a/editor/icons/Headphones.svg b/editor/icons/Headphones.svg deleted file mode 100644 index 76f92d58a7..0000000000 --- a/editor/icons/Headphones.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7v2 3a2 2 0 0 0 2 2h2v-5h-2v-2a5 5 0 0 1 5-5 5 5 0 0 1 5 5v2h-2v3 2h2a2 2 0 0 0 2-2v-3-2a7 7 0 0 0 -7-7z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/InformationSign.svg b/editor/icons/InformationSign.svg deleted file mode 100644 index 8cf1ac78e3..0000000000 --- a/editor/icons/InformationSign.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-width=".570241"><path d="m4.5291945 14.892249h6.8428865l3.421444-3.421444v-6.8428864l-3.421444-3.4214437h-6.8428865l-3.4214436 3.4214437v6.8428864z" fill="#ffb65d" fill-rule="evenodd"/><g fill="#fff"><path d="m6.69985 6.347754h2.624354v6.50621h-2.624354z"/><ellipse cx="8.039363" cy="4.215466" rx="1.394188" ry="1.366851"/></g></g></svg> diff --git a/editor/icons/InverseKinematics.svg b/editor/icons/InverseKinematics.svg deleted file mode 100644 index 4c6dbd4546..0000000000 --- a/editor/icons/InverseKinematics.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v10.27h2v-10.271a2 2 0 0 0 .73047-.72852h4.541a2 2 0 0 0 .72852.73047v3.2695h-2v2l-1 2 3 2v-4h2v4l3-2-1-2v-2h-2v-3.2715a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2 2 2 0 0 0 -1.7305 1h-4.541a2 2 0 0 0 -1.7285-1z" fill="#fc7f7f" fill-rule="evenodd"/></svg> diff --git a/editor/icons/Issue.svg b/editor/icons/Issue.svg deleted file mode 100644 index 457d070d89..0000000000 --- a/editor/icons/Issue.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m5.2902433 14.98657h1.9512087v2.441414h-1.9512087zm0-11.909101h1.9512087v6.2957719l-.1922373 3.4314361h-1.5571222l-.2018492-3.4314361z" transform="matrix(1.2172834 0 0 .60107067 .478728 1.839214)"/><path d="m8.0503291 1.1522775a6.8983747 6.8983747 0 0 0 -6.8980516 6.8980516 6.8983747 6.8983747 0 0 0 6.8980516 6.8997839 6.8983747 6.8983747 0 0 0 6.8997839-6.8997839 6.8983747 6.8983747 0 0 0 -6.8997839-6.8980516zm-.0294418 1.1430364a5.6659852 5.6659852 0 0 1 5.6666897 5.6649578 5.6659852 5.6659852 0 0 1 -5.6666897 5.6666893 5.6659852 5.6659852 0 0 1 -5.6666896-5.6666893 5.6659852 5.6659852 0 0 1 5.6666896-5.6649578z" stroke-width=".886719"/></g></svg> diff --git a/editor/icons/KeyHover.svg b/editor/icons/KeyHover.svg deleted file mode 100644 index b67d7ff78d..0000000000 --- a/editor/icons/KeyHover.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="8" viewBox="0 0 8 8" width="8" xmlns="http://www.w3.org/2000/svg"><rect fill="#fff" height="6.1027" ry=".76286" transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1044.4)" width="6.1027" x="-741.53" y="741.08"/></svg> diff --git a/editor/icons/LoopInterpolation.svg b/editor/icons/LoopInterpolation.svg deleted file mode 100644 index 5e3f919043..0000000000 --- a/editor/icons/LoopInterpolation.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1v2h-2a2 2 0 0 0 -1.7324 1 2 2 0 0 0 -.26562 1h-.0019531v.046875 5.2246a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -1-1.7305v-3.2695-2h2v2l4-3-4-3zm7 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v3.2695 2h-2v-2l-4 3 4 3v-2h2a2 2 0 0 0 1.7324-1 2 2 0 0 0 .26562-1h.001953v-5.2715a2 2 0 0 0 1-1.7285 2 2 0 0 0 -2-2z" fill="#e0e0e0" fill-opacity=".99608"/></svg> diff --git a/editor/icons/MirrorX.svg b/editor/icons/MirrorX.svg deleted file mode 100644 index fa668986ac..0000000000 --- a/editor/icons/MirrorX.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#e0e0e0" stroke-opacity=".99608" stroke-width="2" transform="translate(0 -1036.4)"><path d="m4 1042.4-2 2 2 2" stroke-linecap="round" stroke-linejoin="round"/><path d="m2 1044.4h11"/><path d="m12 1042.4 2 2-2 2" stroke-linecap="round" stroke-linejoin="round"/></g></svg> diff --git a/editor/icons/MirrorY.svg b/editor/icons/MirrorY.svg deleted file mode 100644 index bb4e4d3543..0000000000 --- a/editor/icons/MirrorY.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11.012 1048.4a1.0001 1.0001 0 0 0 -1.7168-.6973l-.29297.293v-7.1719l.29297.293a1.0001 1.0001 0 0 0 1.7148-.7266 1.0001 1.0001 0 0 0 -.30078-.6875l-2-2a1.0001 1.0001 0 0 0 -1.4141 0l-2 2a1.0001 1.0001 0 1 0 1.4141 1.4141l.29297-.293v7.1719l-.29297-.293a1.0001 1.0001 0 1 0 -1.4141 1.4141l2 2a1.0001 1.0001 0 0 0 1.4141 0l2-2a1.0001 1.0001 0 0 0 .30273-.7168z" fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1036.4)"/></svg> diff --git a/editor/icons/MultiEdit.svg b/editor/icons/MultiEdit.svg deleted file mode 100644 index d1409e16ca..0000000000 --- a/editor/icons/MultiEdit.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.554 0-1 .446-1 1v2h4v-2c0-.554-.446-1-1-1zm-1 4v7l2 3 2-3v-7zm1 1h1v5h-1zm8 1v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/MultiLine.svg b/editor/icons/MultiLine.svg deleted file mode 100644 index 634086fd51..0000000000 --- a/editor/icons/MultiLine.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h7v-2zm9 0v2h5v-2zm-9 4v2h11v-2zm0 4v2h4v-2zm6 0v2h8v-2zm-6 4v2h13v-2z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/Portal.svg b/editor/icons/Portal.svg deleted file mode 100644 index 9365c450da..0000000000 --- a/editor/icons/Portal.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a5 7 0 0 0 -5 7 5 7 0 0 0 5 7 5 7 0 0 0 5-7 5 7 0 0 0 -5-7zm0 2a3 5 0 0 1 3 5 3 5 0 0 1 -3 5 3 5 0 0 1 -3-5 3 5 0 0 1 3-5z" fill="#fc7f7f" fill-opacity=".99608"/></svg> diff --git a/editor/icons/Rayito.svg b/editor/icons/Rayito.svg deleted file mode 100644 index 1d4f9ca458..0000000000 --- a/editor/icons/Rayito.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 1-1 7h2.875l-.875 7 9-8h-3.8574l.85742-6h-7z" fill="#ffca5f"/></svg> diff --git a/editor/icons/RigidBody2D.svg b/editor/icons/RigidDynamicBody2D.svg index 5d08e991ae..5d08e991ae 100644 --- a/editor/icons/RigidBody2D.svg +++ b/editor/icons/RigidDynamicBody2D.svg diff --git a/editor/icons/RigidBody3D.svg b/editor/icons/RigidDynamicBody3D.svg index 7f5db4ce88..7f5db4ce88 100644 --- a/editor/icons/RigidBody3D.svg +++ b/editor/icons/RigidDynamicBody3D.svg diff --git a/editor/icons/Room.svg b/editor/icons/Room.svg deleted file mode 100644 index 2bc165e736..0000000000 --- a/editor/icons/Room.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9629 1.002a1.0001 1.0001 0 0 0 -.41016.10352l-6 3a1.0001 1.0001 0 0 0 -.55273.89453v6a1.0001 1.0001 0 0 0 .55273.89453l6 3a1.0001 1.0001 0 0 0 .89453 0l6-3a1.0001 1.0001 0 0 0 .55273-.89453v-6a1.0001 1.0001 0 0 0 -.55273-.89453l-6-3a1.0001 1.0001 0 0 0 -.48438-.10352zm1.0371 2.6172 4 2v3.7637l-4-2zm-1 5.5 3.7637 1.8809-3.7637 1.8828-3.7637-1.8828z" fill="#fc7f7f" fill-opacity=".99608" fill-rule="evenodd"/></svg> diff --git a/editor/icons/RoomBounds.svg b/editor/icons/RoomBounds.svg deleted file mode 100644 index 66901d7895..0000000000 --- a/editor/icons/RoomBounds.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h1v-1h1v-1zm12 0v1h1v1h1v-2zm-5.0371.00195c-.14254.00487-.28238.04016-.41016.10352l-6 3c-.33878.16944-.55276.51574-.55273.89453v6c-.00002576.37879.21395.72509.55273.89453l6 3c.28156.14078.61297.14078.89453 0l6-3c.33878-.16944.55276-.51574.55273-.89453v-6c.000026-.37879-.21395-.72509-.55273-.89453l-6-3c-.15022-.074574-.31679-.11017-.48438-.10352zm1.0371 2.6172 4 2v3.7637l-4-2zm-1 5.5 3.7637 1.8809-3.7637 1.8828-3.7637-1.8828zm-7 3.8809v2h2v-1h-1v-1zm13 0v1h-1v1h2v-2z" fill="#e0e0e0" fill-rule="evenodd"/></svg> diff --git a/editor/icons/Rotate0.svg b/editor/icons/Rotate0.svg deleted file mode 100644 index 670a6f09c3..0000000000 --- a/editor/icons/Rotate0.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm1 2.1016a5 5 0 0 1 4 4.8984 5 5 0 0 1 -5 5 5 5 0 0 1 -5-5 5 5 0 0 1 4-4.8945v5.8945h2z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/Rotate180.svg b/editor/icons/Rotate180.svg deleted file mode 100644 index fdd0882fba..0000000000 --- a/editor/icons/Rotate180.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7s7-3.1458 7-7c0-3.8541-3.1459-7-7-7zm0 2v10c-2.7733 0-5-2.2267-5-5 0-2.7732 2.2267-5 5-5z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/Rotate270.svg b/editor/icons/Rotate270.svg deleted file mode 100644 index 7ffd43d147..0000000000 --- a/editor/icons/Rotate270.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm0 2v5h-5a5 5 0 0 1 5-5z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/Rotate90.svg b/editor/icons/Rotate90.svg deleted file mode 100644 index ef4d631df6..0000000000 --- a/editor/icons/Rotate90.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7 3.7179 0 6.7102-2.9486 6.9219-6.6152a1 1 0 0 0 .078125-.38477 1 1 0 0 0 -.078125-.38867 1 1 0 0 0 -.001953-.0039062c-.21589-3.6627-3.2049-6.6074-6.9199-6.6074zm0 2v5h5c0 2.7733-2.2267 5-5 5s-5-2.2267-5-5c0-2.7732 2.2267-5 5-5z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/RotateLeft.svg b/editor/icons/RotateLeft.svg deleted file mode 100644 index 1200df1dde..0000000000 --- a/editor/icons/RotateLeft.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1036.4)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/></g></svg> diff --git a/editor/icons/RotateRight.svg b/editor/icons/RotateRight.svg deleted file mode 100644 index d69e6a7705..0000000000 --- a/editor/icons/RotateRight.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".99608" transform="matrix(-1 0 0 1 16.026308 -1036.4)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/></g></svg> diff --git a/editor/icons/SoftBody3D.svg b/editor/icons/SoftDynamicBody3D.svg index 7bc9a22c22..7bc9a22c22 100644 --- a/editor/icons/SoftBody3D.svg +++ b/editor/icons/SoftDynamicBody3D.svg diff --git a/editor/icons/TestCube.svg b/editor/icons/TestCube.svg deleted file mode 100644 index 9995f5b5f4..0000000000 --- a/editor/icons/TestCube.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9629 1.002a1.0001 1.0001 0 0 0 -.41016.10352l-6 3a1.0001 1.0001 0 0 0 -.55273.89453v6a1.0001 1.0001 0 0 0 .55273.89453l6 3a1.0001 1.0001 0 0 0 .89453 0l6-3a1.0001 1.0001 0 0 0 .55273-.89453v-6a1.0001 1.0001 0 0 0 -.55273-.89453l-6-3a1.0001 1.0001 0 0 0 -.48438-.10352zm.037109 2.1172 3.7637 1.8809-3.7637 1.8828-3.7637-1.8828zm-5 3.5 4 2v3.7637l-4-2zm10 0v3.7637l-4 2v-3.7637z" fill="#fc7f7f" fill-opacity=".99608" fill-rule="evenodd" transform="translate(0 .000012)"/></svg> diff --git a/editor/icons/TextureArray.svg b/editor/icons/Texture2DArray.svg index a71860023b..a71860023b 100644 --- a/editor/icons/TextureArray.svg +++ b/editor/icons/Texture2DArray.svg diff --git a/editor/icons/TrackAddKey.svg b/editor/icons/TrackAddKey.svg deleted file mode 100644 index 82eff5d2bf..0000000000 --- a/editor/icons/TrackAddKey.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="8" viewBox="0 0 8 8" width="8" xmlns="http://www.w3.org/2000/svg"><path d="m3 0v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#5fff97"/></svg> diff --git a/editor/icons/TrackAddKeyHl.svg b/editor/icons/TrackAddKeyHl.svg deleted file mode 100644 index 03fb90f1e9..0000000000 --- a/editor/icons/TrackAddKeyHl.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="8" viewBox="0 0 8 8" width="8" xmlns="http://www.w3.org/2000/svg"><path d="m3 0v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#5fff97"/><path d="m3 0v3h-3v2h3v3h2v-3h3v-2h-3v-3z" fill="#fff" fill-opacity=".42424"/></svg> diff --git a/editor/icons/Unbone.svg b/editor/icons/Unbone.svg deleted file mode 100644 index 2aa0b8ad8c..0000000000 --- a/editor/icons/Unbone.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.479 1a2.4664 2.4663 0 0 0 -1.7813.7207 2.4664 2.4663 0 0 0 -.31445 3.1035l-1.0723 1.0723 2.791 2.791 1.0762-1.0742a2.4664 2.4663 0 0 0 3.0996-.31055 2.4664 2.4663 0 0 0 0-3.4883 2.4664 2.4663 0 0 0 -1.3965-.69727 2.4664 2.4663 0 0 0 -.69531-1.3965 2.4664 2.4663 0 0 0 -1.707-.7207zm-4.582 6.3105-1.0723 1.0742a2.4664 2.4663 0 0 0 -3.1016.3125 2.4664 2.4663 0 0 0 0 3.4883 2.4664 2.4663 0 0 0 1.3965.69531 2.4664 2.4663 0 0 0 .69531 1.3965 2.4664 2.4663 0 0 0 3.4883 0 2.4664 2.4663 0 0 0 .31445-3.1035l1.0703-1.0723-2.791-2.791z" fill="#e0e0e0" fill-opacity=".99608"/></svg> diff --git a/editor/icons/WorldMarginShape2D.svg b/editor/icons/WorldBoundaryShape2D.svg index f1dbe97c6f..f1dbe97c6f 100644 --- a/editor/icons/WorldMarginShape2D.svg +++ b/editor/icons/WorldBoundaryShape2D.svg diff --git a/editor/icons/WorldMarginShape3D.svg b/editor/icons/WorldBoundaryShape3D.svg index a73e74ad33..a73e74ad33 100644 --- a/editor/icons/WorldMarginShape3D.svg +++ b/editor/icons/WorldBoundaryShape3D.svg diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index c2244befa1..c48d9bb117 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -49,7 +49,7 @@ #include "scene/resources/separation_ray_shape_3d.h" #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" -#include "scene/resources/world_margin_shape_3d.h" +#include "scene/resources/world_boundary_shape_3d.h" uint32_t EditorSceneImporter::get_import_flags() const { int ret; @@ -233,13 +233,14 @@ static String _fixstr(const String &p_what, const String &p_str) { return what; } -static void _pre_gen_shape_list(const Ref<EditorSceneImporterMesh> &mesh, List<Ref<Shape3D>> &r_shape_list, bool p_convex) { +static void _pre_gen_shape_list(Ref<EditorSceneImporterMesh> &mesh, Vector<Ref<Shape3D>> &r_shape_list, bool p_convex) { ERR_FAIL_NULL_MSG(mesh, "Cannot generate shape list with null mesh value"); if (!p_convex) { Ref<Shape3D> shape = mesh->create_trimesh_shape(); r_shape_list.push_back(shape); } else { - Vector<Ref<Shape3D>> cd = mesh->convex_decompose(); + Vector<Ref<Shape3D>> cd; + cd.push_back(mesh->get_mesh()->create_convex_shape(true, /*Passing false, otherwise VHACD will be used to simplify (Decompose) the Mesh.*/ false)); if (cd.size()) { for (int i = 0; i < cd.size(); i++) { r_shape_list.push_back(cd[i]); @@ -248,7 +249,7 @@ static void _pre_gen_shape_list(const Ref<EditorSceneImporterMesh> &mesh, List<R } } -Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map) { +Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map) { // children first for (int i = 0; i < p_node->get_child_count(); i++) { Node *r = _pre_fix_node(p_node->get_child(i), p_root, collision_map); @@ -335,7 +336,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { - List<Ref<Shape3D>> shapes; + Vector<Ref<Shape3D>> shapes; String fixed_name; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; @@ -386,8 +387,8 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E colshape->set_shape(rayShape); Object::cast_to<Node3D>(sb)->rotate_x(Math_PI / 2); } else if (empty_draw_type == "IMAGE") { - WorldMarginShape3D *world_margin_shape = memnew(WorldMarginShape3D); - colshape->set_shape(world_margin_shape); + WorldBoundaryShape3D *world_boundary_shape = memnew(WorldBoundaryShape3D); + colshape->set_shape(world_boundary_shape); } else { SphereShape3D *sphereShape = memnew(SphereShape3D); sphereShape->set_radius(1); @@ -406,15 +407,15 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { - List<Ref<Shape3D>> shapes; + Vector<Ref<Shape3D>> shapes; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else { _pre_gen_shape_list(mesh, shapes, true); } - RigidBody3D *rigid_body = memnew(RigidBody3D); - rigid_body->set_name(_fixstr(name, "rigid")); + RigidDynamicBody3D *rigid_body = memnew(RigidDynamicBody3D); + rigid_body->set_name(_fixstr(name, "rigid_body")); p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform()); p_node = rigid_body; @@ -431,7 +432,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { - List<Ref<Shape3D>> shapes; + Vector<Ref<Shape3D>> shapes; String fixed_name; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; @@ -490,7 +491,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E Ref<EditorSceneImporterMesh> mesh = mi->get_mesh(); if (!mesh.is_null()) { - List<Ref<Shape3D>> shapes; + Vector<Ref<Shape3D>> shapes; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else if (_teststr(mesh->get_name(), "col")) { @@ -516,7 +517,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E return p_node; } -Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) { +Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) { // children first for (int i = 0; i < p_node->get_child_count(); i++) { Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps); @@ -579,28 +580,35 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } if (node_settings.has("generate/physics")) { - int mesh_physics_mode = node_settings["generate/physics"]; - - if (mesh_physics_mode != MESH_PHYSICS_DISABLED) { - List<Ref<Shape3D>> shapes; + int mesh_physics_mode = MeshPhysicsMode::MESH_PHYSICS_DISABLED; + + const bool generate_collider = node_settings["generate/physics"]; + if (generate_collider) { + mesh_physics_mode = MeshPhysicsMode::MESH_PHYSICS_MESH_AND_STATIC_COLLIDER; + if (node_settings.has("physics/body_type")) { + const BodyType body_type = (BodyType)node_settings["physics/body_type"].operator int(); + switch (body_type) { + case BODY_TYPE_STATIC: + mesh_physics_mode = MeshPhysicsMode::MESH_PHYSICS_MESH_AND_STATIC_COLLIDER; + break; + case BODY_TYPE_DYNAMIC: + mesh_physics_mode = MeshPhysicsMode::MESH_PHYSICS_RIGID_BODY_AND_MESH; + break; + case BODY_TYPE_AREA: + mesh_physics_mode = MeshPhysicsMode::MESH_PHYSICS_AREA_ONLY; + break; + } + } + } + if (mesh_physics_mode != MeshPhysicsMode::MESH_PHYSICS_DISABLED) { + Vector<Ref<Shape3D>> shapes; if (collision_map.has(m)) { shapes = collision_map[m]; } else { - switch (mesh_physics_mode) { - case MESH_PHYSICS_MESH_AND_STATIC_COLLIDER: { - _pre_gen_shape_list(m, shapes, false); - } break; - case MESH_PHYSICS_RIGID_BODY_AND_MESH: { - _pre_gen_shape_list(m, shapes, true); - } break; - case MESH_PHYSICS_STATIC_COLLIDER_ONLY: { - _pre_gen_shape_list(m, shapes, false); - } break; - case MESH_PHYSICS_AREA_ONLY: { - _pre_gen_shape_list(m, shapes, true); - } break; - } + shapes = get_collision_shapes( + m->get_mesh(), + node_settings); } if (shapes.size()) { @@ -609,13 +617,15 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< case MESH_PHYSICS_MESH_AND_STATIC_COLLIDER: { StaticBody3D *col = memnew(StaticBody3D); p_node->add_child(col); + col->set_owner(p_node->get_owner()); + col->set_transform(get_collision_shapes_transform(node_settings)); base = col; } break; case MESH_PHYSICS_RIGID_BODY_AND_MESH: { - RigidBody3D *rigid_body = memnew(RigidBody3D); + RigidDynamicBody3D *rigid_body = memnew(RigidDynamicBody3D); rigid_body->set_name(p_node->get_name()); p_node->replace_by(rigid_body); - rigid_body->set_transform(mi->get_transform()); + rigid_body->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); p_node = rigid_body; mi->set_transform(Transform3D()); rigid_body->add_child(mi); @@ -624,7 +634,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } break; case MESH_PHYSICS_STATIC_COLLIDER_ONLY: { StaticBody3D *col = memnew(StaticBody3D); - col->set_transform(mi->get_transform()); + col->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); col->set_name(p_node->get_name()); p_node->replace_by(col); memdelete(p_node); @@ -633,7 +643,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } break; case MESH_PHYSICS_AREA_ONLY: { Area3D *area = memnew(Area3D); - area->set_transform(mi->get_transform()); + area->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); area->set_name(p_node->get_name()); p_node->replace_by(area); memdelete(p_node); @@ -933,8 +943,35 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p } break; case INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE: { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/physics", PROPERTY_HINT_ENUM, "Disabled,Mesh + Static Collider,Rigid Body + Mesh,Static Collider Only,Area Only"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate/physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/navmesh", PROPERTY_HINT_ENUM, "Disabled,Mesh + NavMesh,NavMesh Only"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/body_type", PROPERTY_HINT_ENUM, "Static,Dynamic,Area"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/shape_type", PROPERTY_HINT_ENUM, "Decompose Convex,Simple Convex,Trimesh,Box,Sphere,Cylinder,Capsule", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0)); + + // Decomposition + Mesh::ConvexDecompositionSettings decomposition_default; + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/advanced", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/precision", PROPERTY_HINT_RANGE, "1,10,1"), 5)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/max_concavity", PROPERTY_HINT_RANGE, "0.0,1.0,0.001", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.max_concavity)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/symmetry_planes_clipping_bias", PROPERTY_HINT_RANGE, "0.0,1.0,0.001", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.symmetry_planes_clipping_bias)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/revolution_axes_clipping_bias", PROPERTY_HINT_RANGE, "0.0,1.0,0.001", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.revolution_axes_clipping_bias)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "decomposition/min_volume_per_convex_hull", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.min_volume_per_convex_hull)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/resolution", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.resolution)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/max_num_vertices_per_convex_hull", PROPERTY_HINT_RANGE, "5,512,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.max_num_vertices_per_convex_hull)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/plane_downsampling", PROPERTY_HINT_RANGE, "1,16,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.plane_downsampling)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/convexhull_downsampling", PROPERTY_HINT_RANGE, "1,16,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.convexhull_downsampling)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/normalize_mesh", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.normalize_mesh)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/mode", PROPERTY_HINT_ENUM, "Voxel,Tetrahedron", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), static_cast<int>(decomposition_default.mode))); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/convexhull_approximation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.convexhull_approximation)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/max_convex_hulls", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.max_convex_hulls)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/project_hull_vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.project_hull_vertices)); + + // Primitives: Box, Sphere, Cylinder, Capsule. + r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "primitive/size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Vector3(2.0, 2.0, 2.0))); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "primitive/height", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1.0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "primitive/radius", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1.0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "primitive/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Vector3())); + r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "primitive/rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Vector3())); } break; case INTERNAL_IMPORT_CATEGORY_MESH: { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); @@ -985,6 +1022,65 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor case INTERNAL_IMPORT_CATEGORY_NODE: { } break; case INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE: { + const bool generate_physics = + p_options.has("generate/physics") && + p_options["generate/physics"].operator bool(); + + if ( + p_option == "physics/body_type" || + p_option == "physics/shape_type") { + // Show if need to generate collisions. + return generate_physics; + } + + if (p_option.find("decomposition/") >= 0) { + // Show if need to generate collisions. + if (generate_physics && + // Show if convex is enabled. + p_options["physics/shape_type"] == Variant(SHAPE_TYPE_DECOMPOSE_CONVEX)) { + if (p_option == "decomposition/advanced") { + return true; + } + + const bool decomposition_advanced = + p_options.has("decomposition/advanced") && + p_options["decomposition/advanced"].operator bool(); + + if (p_option == "decomposition/precision") { + return !decomposition_advanced; + } else { + return decomposition_advanced; + } + } + + return false; + } + + if (p_option == "primitive/position" || p_option == "primitive/rotation") { + const ShapeType physics_shape = (ShapeType)p_options["physics/shape_type"].operator int(); + return generate_physics && + physics_shape >= SHAPE_TYPE_BOX; + } + + if (p_option == "primitive/size") { + const ShapeType physics_shape = (ShapeType)p_options["physics/shape_type"].operator int(); + return generate_physics && + physics_shape == SHAPE_TYPE_BOX; + } + + if (p_option == "primitive/radius") { + const ShapeType physics_shape = (ShapeType)p_options["physics/shape_type"].operator int(); + return generate_physics && (physics_shape == SHAPE_TYPE_SPHERE || + physics_shape == SHAPE_TYPE_CYLINDER || + physics_shape == SHAPE_TYPE_CAPSULE); + } + + if (p_option == "primitive/height") { + const ShapeType physics_shape = (ShapeType)p_options["physics/shape_type"].operator int(); + return generate_physics && + (physics_shape == SHAPE_TYPE_CYLINDER || + physics_shape == SHAPE_TYPE_CAPSULE); + } } break; case INTERNAL_IMPORT_CATEGORY_MESH: { if (p_option == "save_to_file/path" || p_option == "save_to_file/make_streamable") { @@ -1021,6 +1117,33 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor return true; } +bool ResourceImporterScene::get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const { + switch (p_category) { + case INTERNAL_IMPORT_CATEGORY_NODE: { + } break; + case INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE: { + if ( + p_option == "generate/physics" || + p_option == "physics/shape_type" || + p_option.find("decomposition/") >= 0 || + p_option.find("primitive/") >= 0) { + return true; + } + } break; + case INTERNAL_IMPORT_CATEGORY_MESH: { + } break; + case INTERNAL_IMPORT_CATEGORY_MATERIAL: { + } break; + case INTERNAL_IMPORT_CATEGORY_ANIMATION: { + } break; + case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: { + } break; + default: { + } + } + return false; +} + void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_type", PROPERTY_HINT_TYPE_STRING, "Node"), "Node3D")); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_name"), "Scene Root")); @@ -1275,7 +1398,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } } -void ResourceImporterScene::_add_shapes(Node *p_node, const List<Ref<Shape3D>> &p_shapes) { +void ResourceImporterScene::_add_shapes(Node *p_node, const Vector<Ref<Shape3D>> &p_shapes) { for (const Ref<Shape3D> &E : p_shapes) { CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E); @@ -1316,7 +1439,7 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) { return nullptr; } - Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> collision_map; + Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> collision_map; _pre_fix_node(scene, scene, collision_map); @@ -1392,7 +1515,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p } Set<Ref<EditorSceneImporterMesh>> scanned_meshes; - Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> collision_map; + Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> collision_map; _pre_fix_node(scene, scene, collision_map); _post_fix_node(scene, scene, collision_map, scanned_meshes, node_data, material_data, animation_data, fps); diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 542959be02..e232b715be 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -63,7 +63,6 @@ public: IMPORT_FAIL_ON_MISSING_DEPENDENCIES = 4, IMPORT_GENERATE_TANGENT_ARRAYS = 8, IMPORT_USE_NAMED_SKIN_BINDS = 16, - }; virtual uint32_t get_import_flags() const; @@ -125,9 +124,25 @@ class ResourceImporterScene : public ResourceImporter { MESH_OVERRIDE_DISABLE, }; + enum BodyType { + BODY_TYPE_STATIC, + BODY_TYPE_DYNAMIC, + BODY_TYPE_AREA + }; + + enum ShapeType { + SHAPE_TYPE_DECOMPOSE_CONVEX, + SHAPE_TYPE_SIMPLE_CONVEX, + SHAPE_TYPE_TRIMESH, + SHAPE_TYPE_BOX, + SHAPE_TYPE_SPHERE, + SHAPE_TYPE_CYLINDER, + SHAPE_TYPE_CAPSULE, + }; + void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner); void _generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<Vector<uint8_t>> &r_lightmap_caches); - void _add_shapes(Node *p_node, const List<Ref<Shape3D>> &p_shapes); + void _add_shapes(Node *p_node, const Vector<Ref<Shape3D>> &p_shapes); public: static ResourceImporterScene *get_singleton() { return singleton; } @@ -159,14 +174,15 @@ public: void get_internal_import_options(InternalImportCategory p_category, List<ImportOption> *r_options) const; bool get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; + bool get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; // Import scenes *after* everything else (such as textures). virtual int get_import_order() const override { return ResourceImporter::IMPORT_ORDER_SCENE; } - Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map); - Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); + Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map); + Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks); void _create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all); @@ -184,6 +200,12 @@ public: virtual bool can_import_threaded() const override { return false; } ResourceImporterScene(); + + template <class M> + static Vector<Ref<Shape3D>> get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options); + + template <class M> + static Transform3D get_collision_shapes_transform(const M &p_options); }; class EditorSceneImporterESCN : public EditorSceneImporter { @@ -196,4 +218,176 @@ public: virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) override; }; +#include "scene/resources/box_shape_3d.h" +#include "scene/resources/capsule_shape_3d.h" +#include "scene/resources/cylinder_shape_3d.h" +#include "scene/resources/sphere_shape_3d.h" + +template <class M> +Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options) { + ShapeType generate_shape_type = SHAPE_TYPE_DECOMPOSE_CONVEX; + if (p_options.has(SNAME("physics/shape_type"))) { + generate_shape_type = (ShapeType)p_options[SNAME("physics/shape_type")].operator int(); + } + + if (generate_shape_type == SHAPE_TYPE_DECOMPOSE_CONVEX) { + Mesh::ConvexDecompositionSettings decomposition_settings; + bool advanced = false; + if (p_options.has(SNAME("decomposition/advanced"))) { + advanced = p_options[SNAME("decomposition/advanced")]; + } + + if (advanced) { + if (p_options.has(SNAME("decomposition/max_concavity"))) { + decomposition_settings.max_concavity = p_options[SNAME("decomposition/max_concavity")]; + } + + if (p_options.has(SNAME("decomposition/symmetry_planes_clipping_bias"))) { + decomposition_settings.symmetry_planes_clipping_bias = p_options[SNAME("decomposition/symmetry_planes_clipping_bias")]; + } + + if (p_options.has(SNAME("decomposition/revolution_axes_clipping_bias"))) { + decomposition_settings.revolution_axes_clipping_bias = p_options[SNAME("decomposition/revolution_axes_clipping_bias")]; + } + + if (p_options.has(SNAME("decomposition/min_volume_per_convex_hull"))) { + decomposition_settings.min_volume_per_convex_hull = p_options[SNAME("decomposition/min_volume_per_convex_hull")]; + } + + if (p_options.has(SNAME("decomposition/resolution"))) { + decomposition_settings.resolution = p_options[SNAME("decomposition/resolution")]; + } + + if (p_options.has(SNAME("decomposition/max_num_vertices_per_convex_hull"))) { + decomposition_settings.max_num_vertices_per_convex_hull = p_options[SNAME("decomposition/max_num_vertices_per_convex_hull")]; + } + + if (p_options.has(SNAME("decomposition/plane_downsampling"))) { + decomposition_settings.plane_downsampling = p_options[SNAME("decomposition/plane_downsampling")]; + } + + if (p_options.has(SNAME("decomposition/convexhull_downsampling"))) { + decomposition_settings.convexhull_downsampling = p_options[SNAME("decomposition/convexhull_downsampling")]; + } + + if (p_options.has(SNAME("decomposition/normalize_mesh"))) { + decomposition_settings.normalize_mesh = p_options[SNAME("decomposition/normalize_mesh")]; + } + + if (p_options.has(SNAME("decomposition/mode"))) { + decomposition_settings.mode = (Mesh::ConvexDecompositionSettings::Mode)p_options[SNAME("decomposition/mode")].operator int(); + } + + if (p_options.has(SNAME("decomposition/convexhull_approximation"))) { + decomposition_settings.convexhull_approximation = p_options[SNAME("decomposition/convexhull_approximation")]; + } + + if (p_options.has(SNAME("decomposition/max_convex_hulls"))) { + decomposition_settings.max_convex_hulls = p_options[SNAME("decomposition/max_convex_hulls")]; + } + + if (p_options.has(SNAME("decomposition/project_hull_vertices"))) { + decomposition_settings.project_hull_vertices = p_options[SNAME("decomposition/project_hull_vertices")]; + } + } else { + int precision_level = 5; + if (p_options.has(SNAME("decomposition/precision"))) { + precision_level = p_options[SNAME("decomposition/precision")]; + } + + const real_t precision = real_t(precision_level - 1) / 9.0; + + decomposition_settings.max_concavity = Math::lerp(real_t(1.0), real_t(0.001), precision); + decomposition_settings.min_volume_per_convex_hull = Math::lerp(real_t(0.01), real_t(0.0001), precision); + decomposition_settings.resolution = Math::lerp(10'000, 100'000, precision); + decomposition_settings.max_num_vertices_per_convex_hull = Math::lerp(32, 64, precision); + decomposition_settings.plane_downsampling = Math::lerp(3, 16, precision); + decomposition_settings.convexhull_downsampling = Math::lerp(3, 16, precision); + decomposition_settings.max_convex_hulls = Math::lerp(1, 32, precision); + } + + return p_mesh->convex_decompose(decomposition_settings); + } else if (generate_shape_type == SHAPE_TYPE_SIMPLE_CONVEX) { + Vector<Ref<Shape3D>> shapes; + shapes.push_back(p_mesh->create_convex_shape(true, /*Passing false, otherwise VHACD will be used to simplify (Decompose) the Mesh.*/ false)); + return shapes; + } else if (generate_shape_type == SHAPE_TYPE_TRIMESH) { + Vector<Ref<Shape3D>> shapes; + shapes.push_back(p_mesh->create_trimesh_shape()); + return shapes; + } else if (generate_shape_type == SHAPE_TYPE_BOX) { + Ref<BoxShape3D> box; + box.instantiate(); + if (p_options.has(SNAME("primitive/size"))) { + box->set_size(p_options[SNAME("primitive/size")]); + } + + Vector<Ref<Shape3D>> shapes; + shapes.push_back(box); + return shapes; + + } else if (generate_shape_type == SHAPE_TYPE_SPHERE) { + Ref<SphereShape3D> sphere; + sphere.instantiate(); + if (p_options.has(SNAME("primitive/radius"))) { + sphere->set_radius(p_options[SNAME("primitive/radius")]); + } + + Vector<Ref<Shape3D>> shapes; + shapes.push_back(sphere); + return shapes; + } else if (generate_shape_type == SHAPE_TYPE_CYLINDER) { + Ref<CylinderShape3D> cylinder; + cylinder.instantiate(); + if (p_options.has(SNAME("primitive/height"))) { + cylinder->set_height(p_options[SNAME("primitive/height")]); + } + if (p_options.has(SNAME("primitive/radius"))) { + cylinder->set_radius(p_options[SNAME("primitive/radius")]); + } + + Vector<Ref<Shape3D>> shapes; + shapes.push_back(cylinder); + return shapes; + } else if (generate_shape_type == SHAPE_TYPE_CAPSULE) { + Ref<CapsuleShape3D> capsule; + capsule.instantiate(); + if (p_options.has(SNAME("primitive/height"))) { + capsule->set_height(p_options[SNAME("primitive/height")]); + } + if (p_options.has(SNAME("primitive/radius"))) { + capsule->set_radius(p_options[SNAME("primitive/radius")]); + } + + Vector<Ref<Shape3D>> shapes; + shapes.push_back(capsule); + return shapes; + } + return Vector<Ref<Shape3D>>(); +} + +template <class M> +Transform3D ResourceImporterScene::get_collision_shapes_transform(const M &p_options) { + Transform3D transform; + + ShapeType generate_shape_type = SHAPE_TYPE_DECOMPOSE_CONVEX; + if (p_options.has(SNAME("physics/shape_type"))) { + generate_shape_type = (ShapeType)p_options[SNAME("physics/shape_type")].operator int(); + } + + if (generate_shape_type == SHAPE_TYPE_BOX || + generate_shape_type == SHAPE_TYPE_SPHERE || + generate_shape_type == SHAPE_TYPE_CYLINDER || + generate_shape_type == SHAPE_TYPE_CAPSULE) { + if (p_options.has(SNAME("primitive/position"))) { + transform.origin = p_options[SNAME("primitive/position")]; + } + + if (p_options.has(SNAME("primitive/rotation"))) { + transform.basis.set_euler((p_options[SNAME("primitive/rotation")].operator Vector3() / 180.0) * Math_PI); + } + } + return transform; +} + #endif // RESOURCEIMPORTERSCENE_H diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 19a8f209bb..4bcb6863fb 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -53,6 +53,11 @@ class SceneImportSettingsData : public Object { } current[p_name] = p_value; + + if (ResourceImporterScene::get_singleton()->get_internal_option_update_view_required(category, p_name, current)) { + SceneImportSettings::get_singleton()->update_view(); + } + return true; } return false; @@ -317,6 +322,13 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { if (mesh_node && mesh_node->get_mesh().is_valid()) { _fill_mesh(scene_tree, mesh_node->get_mesh(), item); + // Add the collider view. + MeshInstance3D *collider_view = memnew(MeshInstance3D); + collider_view->set_name("collider_view"); + collider_view->set_visible(false); + mesh_node->add_child(collider_view); + collider_view->set_owner(mesh_node); + Transform3D accum_xform; Node3D *base = mesh_node; while (base) { @@ -346,6 +358,54 @@ void SceneImportSettings::_update_scene() { _fill_scene(scene, nullptr); } +void SceneImportSettings::_update_view_gizmos() { + for (const KeyValue<String, NodeData> &e : node_map) { + bool generate_collider = false; + if (e.value.settings.has(SNAME("generate/physics"))) { + generate_collider = e.value.settings[SNAME("generate/physics")]; + } + + MeshInstance3D *mesh_node = Object::cast_to<MeshInstance3D>(e.value.node); + if (mesh_node == nullptr || mesh_node->get_mesh().is_null()) { + // Nothing to do + continue; + } + + MeshInstance3D *collider_view = static_cast<MeshInstance3D *>(mesh_node->find_node("collider_view")); + CRASH_COND_MSG(collider_view == nullptr, "This is unreachable, since the collider view is always created even when the collision is not used! If this is triggered there is a bug on the function `_fill_scene`."); + + collider_view->set_visible(generate_collider); + if (generate_collider) { + // This collider_view doesn't have a mesh so we need to generate a new one. + + // Generate the mesh collider. + Vector<Ref<Shape3D>> shapes = ResourceImporterScene::get_collision_shapes(mesh_node->get_mesh(), e.value.settings); + const Transform3D transform = ResourceImporterScene::get_collision_shapes_transform(e.value.settings); + + Ref<ArrayMesh> collider_view_mesh; + collider_view_mesh.instantiate(); + for (Ref<Shape3D> shape : shapes) { + Ref<ArrayMesh> debug_shape_mesh; + if (shape.is_valid()) { + debug_shape_mesh = shape->get_debug_mesh(); + } + if (debug_shape_mesh.is_valid()) { + collider_view_mesh->add_surface_from_arrays( + debug_shape_mesh->surface_get_primitive_type(0), + debug_shape_mesh->surface_get_arrays(0)); + + collider_view_mesh->surface_set_material( + collider_view_mesh->get_surface_count() - 1, + collider_mat); + } + } + + collider_view->set_mesh(collider_view_mesh); + collider_view->set_transform(transform); + } + } +} + void SceneImportSettings::_update_camera() { AABB camera_aabb; @@ -404,11 +464,16 @@ void SceneImportSettings::_load_default_subresource_settings(Map<StringName, Var } } +void SceneImportSettings::update_view() { + _update_view_gizmos(); +} + void SceneImportSettings::open_settings(const String &p_path) { if (scene) { memdelete(scene); scene = nullptr; } + scene_import_settings_data->settings = nullptr; scene = ResourceImporterScene::get_singleton()->pre_import(p_path); if (scene == nullptr) { EditorNode::get_singleton()->show_warning(TTR("Error opening scene")); @@ -463,6 +528,7 @@ void SceneImportSettings::open_settings(const String &p_path) { } popup_centered_ratio(); + _update_view_gizmos(); _update_camera(); set_title(vformat(TTR("Advanced Import Settings for '%s'"), base_path.get_file())); @@ -629,6 +695,7 @@ void SceneImportSettings::_material_tree_selected() { _select(material_tree, type, import_id); } + void SceneImportSettings::_mesh_tree_selected() { if (selecting) { return; @@ -640,6 +707,7 @@ void SceneImportSettings::_mesh_tree_selected() { _select(mesh_tree, type, import_id); } + void SceneImportSettings::_scene_tree_selected() { if (selecting) { return; @@ -1144,6 +1212,12 @@ SceneImportSettings::SceneImportSettings() { material_preview.instantiate(); } + { + collider_mat.instantiate(); + collider_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + collider_mat->set_albedo(Color(0.5, 0.5, 1.0)); + } + inspector = memnew(EditorInspector); inspector->set_custom_minimum_size(Size2(300 * EDSCALE, 0)); diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h index ddcf4a6d5d..c7c94af493 100644 --- a/editor/import/scene_import_settings.h +++ b/editor/import/scene_import_settings.h @@ -84,6 +84,8 @@ class SceneImportSettings : public ConfirmationDialog { MeshInstance3D *mesh_preview; Ref<SphereMesh> material_preview; + Ref<StandardMaterial3D> collider_mat; + float cam_rot_x; float cam_rot_y; float cam_zoom; @@ -145,6 +147,7 @@ class SceneImportSettings : public ConfirmationDialog { bool selecting = false; + void _update_view_gizmos(); void _update_camera(); void _select(Tree *p_from, String p_type, String p_id); void _material_tree_selected(); @@ -190,6 +193,7 @@ protected: void _notification(int p_what); public: + void update_view(); void open_settings(const String &p_path); static SceneImportSettings *get_singleton(); SceneImportSettings(); diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp index 06f373c54f..5e6dd08e79 100644 --- a/editor/import/scene_importer_mesh.cpp +++ b/editor/import/scene_importer_mesh.cpp @@ -33,6 +33,8 @@ #include "core/math/math_defs.h" #include "scene/resources/surface_tool.h" +#include <cstdint> + void EditorSceneImporterMesh::add_blend_shape(const String &p_name) { ERR_FAIL_COND(surfaces.size() > 0); blend_shapes.push_back(p_name); @@ -55,13 +57,14 @@ Mesh::BlendShapeMode EditorSceneImporterMesh::get_blend_shape_mode() const { return blend_shape_mode; } -void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name) { +void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name, const uint32_t p_flags) { ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size()); ERR_FAIL_COND(p_arrays.size() != Mesh::ARRAY_MAX); Surface s; s.primitive = p_primitive; s.arrays = p_arrays; s.name = p_name; + s.flags = p_flags; Vector<Vector3> vertex_array = p_arrays[Mesh::ARRAY_VERTEX]; int vertex_count = vertex_array.size(); @@ -138,6 +141,11 @@ float EditorSceneImporterMesh::get_surface_lod_size(int p_surface, int p_lod) co return surfaces[p_surface].lods[p_lod].distance; } +uint32_t EditorSceneImporterMesh::get_surface_format(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0); + return surfaces[p_surface].flags; +} + Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const { ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Ref<Material>()); return surfaces[p_surface].material; @@ -283,7 +291,7 @@ Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh(const Ref<ArrayMesh> &p_base) { } } - mesh->add_surface_from_arrays(surfaces[i].primitive, surfaces[i].arrays, bs_data, lods); + mesh->add_surface_from_arrays(surfaces[i].primitive, surfaces[i].arrays, bs_data, lods, surfaces[i].flags); if (surfaces[i].material.is_valid()) { mesh->surface_set_material(mesh->get_surface_count() - 1, surfaces[i].material); } @@ -398,7 +406,7 @@ void EditorSceneImporterMesh::create_shadow_mesh() { } } - shadow_mesh->add_surface(surfaces[i].primitive, new_surface, Array(), lods, Ref<Material>(), surfaces[i].name); + shadow_mesh->add_surface(surfaces[i].primitive, new_surface, Array(), lods, Ref<Material>(), surfaces[i].name, surfaces[i].flags); } } @@ -436,7 +444,11 @@ void EditorSceneImporterMesh::_set_data(const Dictionary &p_data) { if (s.has("material")) { material = s["material"]; } - add_surface(prim, arr, blend_shapes, lods, material, name); + uint32_t flags = 0; + if (s.has("flags")) { + flags = s["flags"]; + } + add_surface(prim, arr, blend_shapes, lods, material, name, flags); } } } @@ -473,6 +485,10 @@ Dictionary EditorSceneImporterMesh::_get_data() const { d["name"] = surfaces[i].name; } + if (surfaces[i].flags != 0) { + d["flags"] = surfaces[i].flags; + } + surface_arr.push_back(d); } data["surfaces"] = surface_arr; @@ -508,36 +524,47 @@ Vector<Face3> EditorSceneImporterMesh::get_faces() const { return faces; } -Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose() const { - ERR_FAIL_COND_V(!Mesh::convex_composition_function, Vector<Ref<Shape3D>>()); +Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const { + ERR_FAIL_COND_V(!Mesh::convex_decomposition_function, Vector<Ref<Shape3D>>()); const Vector<Face3> faces = get_faces(); + int face_count = faces.size(); + + Vector<Vector3> vertices; + uint32_t vertex_count = 0; + vertices.resize(face_count * 3); + Vector<uint32_t> indices; + indices.resize(face_count * 3); + { + Map<Vector3, uint32_t> vertex_map; + Vector3 *vertex_w = vertices.ptrw(); + uint32_t *index_w = indices.ptrw(); + for (int i = 0; i < face_count; i++) { + for (int j = 0; j < 3; j++) { + const Vector3 &vertex = faces[i].vertex[j]; + Map<Vector3, uint32_t>::Element *found_vertex = vertex_map.find(vertex); + uint32_t index; + if (found_vertex) { + index = found_vertex->get(); + } else { + index = ++vertex_count; + vertex_map[vertex] = index; + vertex_w[index] = vertex; + } + index_w[i * 3 + j] = index; + } + } + } + vertices.resize(vertex_count); - Vector<Vector<Face3>> decomposed = Mesh::convex_composition_function(faces, -1); + Vector<Vector<Vector3>> decomposed = Mesh::convex_decomposition_function((real_t *)vertices.ptr(), vertex_count, indices.ptr(), face_count, p_settings, nullptr); Vector<Ref<Shape3D>> ret; for (int i = 0; i < decomposed.size(); i++) { - Set<Vector3> points; - for (int j = 0; j < decomposed[i].size(); j++) { - points.insert(decomposed[i][j].vertex[0]); - points.insert(decomposed[i][j].vertex[1]); - points.insert(decomposed[i][j].vertex[2]); - } - - Vector<Vector3> convex_points; - convex_points.resize(points.size()); - { - Vector3 *w = convex_points.ptrw(); - int idx = 0; - for (Set<Vector3>::Element *E = points.front(); E; E = E->next()) { - w[idx++] = E->get(); - } - } - Ref<ConvexPolygonShape3D> shape; shape.instantiate(); - shape->set_points(convex_points); + shape->set_points(decomposed[i]); ret.push_back(shape); } @@ -833,7 +860,7 @@ void EditorSceneImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &EditorSceneImporterMesh::set_blend_shape_mode); ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &EditorSceneImporterMesh::get_blend_shape_mode); - ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material", "name"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String())); + ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material", "name", "flags"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String()), DEFVAL(0)); ClassDB::bind_method(D_METHOD("get_surface_count"), &EditorSceneImporterMesh::get_surface_count); ClassDB::bind_method(D_METHOD("get_surface_primitive_type", "surface_idx"), &EditorSceneImporterMesh::get_surface_primitive_type); @@ -844,6 +871,7 @@ void EditorSceneImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_surface_lod_size", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_size); ClassDB::bind_method(D_METHOD("get_surface_lod_indices", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_indices); ClassDB::bind_method(D_METHOD("get_surface_material", "surface_idx"), &EditorSceneImporterMesh::get_surface_material); + ClassDB::bind_method(D_METHOD("get_surface_format", "surface_idx"), &EditorSceneImporterMesh::get_surface_format); ClassDB::bind_method(D_METHOD("set_surface_name", "surface_idx", "name"), &EditorSceneImporterMesh::set_surface_name); ClassDB::bind_method(D_METHOD("set_surface_material", "surface_idx", "material"), &EditorSceneImporterMesh::set_surface_material); diff --git a/editor/import/scene_importer_mesh.h b/editor/import/scene_importer_mesh.h index e57e479d8e..d32b1fdf74 100644 --- a/editor/import/scene_importer_mesh.h +++ b/editor/import/scene_importer_mesh.h @@ -36,6 +36,9 @@ #include "scene/resources/convex_polygon_shape_3d.h" #include "scene/resources/mesh.h" #include "scene/resources/navigation_mesh.h" + +#include <cstdint> + // The following classes are used by importers instead of ArrayMesh and MeshInstance3D // so the data is not registered (hence, quality loss), importing happens faster and // its easier to modify before saving @@ -57,6 +60,7 @@ class EditorSceneImporterMesh : public Resource { Vector<LOD> lods; Ref<Material> material; String name; + uint32_t flags = 0; }; Vector<Surface> surfaces; Vector<String> blend_shapes; @@ -80,7 +84,7 @@ public: int get_blend_shape_count() const; String get_blend_shape_name(int p_blend_shape) const; - void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref<Material> &p_material = Ref<Material>(), const String &p_name = String()); + void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref<Material> &p_material = Ref<Material>(), const String &p_name = String(), const uint32_t p_flags = 0); int get_surface_count() const; void set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode); @@ -95,6 +99,7 @@ public: Vector<int> get_surface_lod_indices(int p_surface, int p_lod) const; float get_surface_lod_size(int p_surface, int p_lod) const; Ref<Material> get_surface_material(int p_surface) const; + uint32_t get_surface_format(int p_surface) const; void set_surface_material(int p_surface, const Ref<Material> &p_material); @@ -104,7 +109,7 @@ public: Ref<EditorSceneImporterMesh> get_shadow_mesh() const; Vector<Face3> get_faces() const; - Vector<Ref<Shape3D>> convex_decompose() const; + Vector<Ref<Shape3D>> convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const; Ref<Shape3D> create_trimesh_shape() const; Ref<NavigationMesh> create_navigation_mesh(); Error lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 778046f45c..04ddf3552b 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -30,11 +30,22 @@ #include "inspector_dock.h" -#include "editor/editor_node.h" -#include "editor/editor_settings.h" +#include "editor/editor_scale.h" #include "editor/plugins/animation_player_editor_plugin.h" void InspectorDock::_menu_option(int p_option) { + _menu_option_confirm(p_option, false); +} + +void InspectorDock::_menu_confirm_current() { + _menu_option_confirm(current_option, true); +} + +void InspectorDock::_menu_option_confirm(int p_option, bool p_confirmed) { + if (!p_confirmed) { + current_option = p_option; + } + switch (p_option) { case EXPAND_ALL: { _menu_expandall(); @@ -82,39 +93,81 @@ void InspectorDock::_menu_option(int p_option) { } break; case OBJECT_UNIQUE_RESOURCES: { - editor_data->apply_changes_in_editors(); - if (current) { - List<PropertyInfo> props; - current->get_property_list(&props); - Map<RES, RES> duplicates; - for (const PropertyInfo &E : props) { - if (!(E.usage & PROPERTY_USAGE_STORAGE)) { - continue; - } + if (!p_confirmed) { + Vector<String> resource_propnames; - Variant v = current->get(E.name); - if (v.is_ref()) { + if (current) { + List<PropertyInfo> props; + current->get_property_list(&props); + + for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { + continue; + } + + Variant v = current->get(E->get().name); REF ref = v; - if (ref.is_valid()) { - RES res = ref; - if (res.is_valid()) { - if (!duplicates.has(res)) { - duplicates[res] = res->duplicate(); - } - res = duplicates[res]; + RES res = ref; + if (v.is_ref() && ref.is_valid() && res.is_valid()) { + // Valid resource which would be duplicated if action is confirmed. + resource_propnames.append(E->get().name); + } + } + } + + if (resource_propnames.size()) { + unique_resources_list_tree->clear(); + TreeItem *root = unique_resources_list_tree->create_item(); - current->set(E.name, res); - editor->get_inspector()->update_property(E.name); + for (int i = 0; i < resource_propnames.size(); i++) { + String propname = resource_propnames[i].replace("/", " / "); + + TreeItem *ti = unique_resources_list_tree->create_item(root); + ti->set_text(0, bool(EDITOR_GET("interface/inspector/capitalize_properties")) ? propname.capitalize() : propname); + } + + unique_resources_confirmation->popup_centered(); + } else { + unique_resources_confirmation->set_text(TTR("This object has no resources.")); + current_option = -1; + unique_resources_confirmation->popup_centered(); + } + } else { + editor_data->apply_changes_in_editors(); + + if (current) { + List<PropertyInfo> props; + current->get_property_list(&props); + Map<RES, RES> duplicates; + for (const PropertyInfo &prop_info : props) { + if (!(prop_info.usage & PROPERTY_USAGE_STORAGE)) { + continue; + } + + Variant v = current->get(prop_info.name); + if (v.is_ref()) { + REF ref = v; + if (ref.is_valid()) { + RES res = ref; + if (res.is_valid()) { + if (!duplicates.has(res)) { + duplicates[res] = res->duplicate(); + } + res = duplicates[res]; + + current->set(prop_info.name, res); + editor->get_inspector()->update_property(prop_info.name); + } } } } } - } - editor_data->get_undo_redo().clear_history(); + editor_data->get_undo_redo().clear_history(); - editor->get_editor_plugins_over()->edit(nullptr); - editor->get_editor_plugins_over()->edit(current); + editor->get_editor_plugins_over()->edit(nullptr); + editor->get_editor_plugins_over()->edit(current); + } } break; @@ -619,6 +672,29 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { warning->hide(); warning->connect("pressed", callable_mp(this, &InspectorDock::_warning_pressed)); + unique_resources_confirmation = memnew(ConfirmationDialog); + add_child(unique_resources_confirmation); + + VBoxContainer *container = memnew(VBoxContainer); + unique_resources_confirmation->add_child(container); + + Label *top_label = memnew(Label); + top_label->set_text(TTR("The following resources will be duplicated and embedded within this resource/object.")); + container->add_child(top_label); + + unique_resources_list_tree = memnew(Tree); + unique_resources_list_tree->set_hide_root(true); + unique_resources_list_tree->set_columns(1); + unique_resources_list_tree->set_column_title(0, TTR("Property")); + unique_resources_list_tree->set_custom_minimum_size(Size2(0, 200 * EDSCALE)); + container->add_child(unique_resources_list_tree); + + Label *bottom_label = memnew(Label); + bottom_label->set_text(TTR("This cannot be undone. Are you sure?")); + container->add_child(bottom_label); + + unique_resources_confirmation->connect("confirmed", callable_mp(this, &InspectorDock::_menu_confirm_current)); + warning_dialog = memnew(AcceptDialog); editor->get_gui_base()->add_child(warning_dialog); diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h index 6615845b66..5bf6a34617 100644 --- a/editor/inspector_dock.h +++ b/editor/inspector_dock.h @@ -40,8 +40,6 @@ #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/control.h" -#include "scene/gui/label.h" -#include "scene/gui/popup_menu.h" class EditorNode; @@ -92,7 +90,13 @@ class InspectorDock : public VBoxContainer { Button *warning; AcceptDialog *warning_dialog; + int current_option = -1; + ConfirmationDialog *unique_resources_confirmation; + Tree *unique_resources_list_tree; + void _menu_option(int p_option); + void _menu_confirm_current(); + void _menu_option_confirm(int p_option, bool p_confirmed); void _new_resource(); void _load_resource(const String &p_type = ""); diff --git a/editor/multi_node_edit.cpp b/editor/multi_node_edit.cpp index fd4a4334fc..1e707c1a60 100644 --- a/editor/multi_node_edit.cpp +++ b/editor/multi_node_edit.cpp @@ -49,6 +49,11 @@ bool MultiNodeEdit::_set_impl(const StringName &p_name, const Variant &p_value, name = "script"; } + Node *node_path_target = nullptr; + if (p_value.get_type() == Variant::NODE_PATH && p_value != NodePath()) { + node_path_target = es->get_node(p_value); + } + UndoRedo *ur = EditorNode::get_undo_redo(); ur->create_action(TTR("MultiNode Set") + " " + String(name), UndoRedo::MERGE_ENDS); @@ -63,9 +68,11 @@ bool MultiNodeEdit::_set_impl(const StringName &p_name, const Variant &p_value, } if (p_value.get_type() == Variant::NODE_PATH) { - Node *tonode = n->get_node(p_value); - NodePath p_path = n->get_path_to(tonode); - ur->add_do_property(n, name, p_path); + NodePath path; + if (node_path_target) { + path = n->get_path_to(node_path_target); + } + ur->add_do_property(n, name, path); } else { Variant new_value; if (p_field == "") { diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 830b010d01..18b4966f80 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -904,7 +904,7 @@ void AnimationPlayerEditor::edit(AnimationPlayer *p_player) { } } -void AnimationPlayerEditor::forward_canvas_force_draw_over_viewport(Control *p_overlay) { +void AnimationPlayerEditor::forward_force_draw_over_viewport(Control *p_overlay) { if (!onion.can_overlay) { return; } diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h index be80b7f4e3..0a514d3ff1 100644 --- a/editor/plugins/animation_player_editor_plugin.h +++ b/editor/plugins/animation_player_editor_plugin.h @@ -238,7 +238,7 @@ public: void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; } void edit(AnimationPlayer *p_player); - void forward_canvas_force_draw_over_viewport(Control *p_overlay); + void forward_force_draw_over_viewport(Control *p_overlay); AnimationPlayerEditor(EditorNode *p_editor, AnimationPlayerEditorPlugin *p_plugin); }; @@ -262,7 +262,8 @@ public: virtual bool handles(Object *p_object) const override; virtual void make_visible(bool p_visible) override; - virtual void forward_canvas_force_draw_over_viewport(Control *p_overlay) override { anim_editor->forward_canvas_force_draw_over_viewport(p_overlay); } + virtual void forward_canvas_force_draw_over_viewport(Control *p_overlay) override { anim_editor->forward_force_draw_over_viewport(p_overlay); } + virtual void forward_spatial_force_draw_over_viewport(Control *p_overlay) override { anim_editor->forward_force_draw_over_viewport(p_overlay); } AnimationPlayerEditorPlugin(EditorNode *p_node); ~AnimationPlayerEditorPlugin(); diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 5405723d10..664b2f521e 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -230,7 +230,7 @@ void EditorAssetLibraryItemDescription::configure(const String &p_title, int p_a description->add_text(TTR("View Files")); description->pop(); description->add_text("\n" + TTR("Description:") + "\n\n"); - description->append_bbcode(p_description); + description->append_text(p_description); set_title(p_title); } diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index d96cc1cd18..db5be94fd2 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1295,7 +1295,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { // Drag the pivot (in pivot mode / with V key) if (drag_type == DRAG_NONE) { if ((b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) || - (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_V)) { + (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_V && tool == TOOL_SELECT && k->get_modifiers_mask() == 0)) { List<CanvasItem *> selection = _get_edited_canvas_items(); // Filters the selection with nodes that allow setting the pivot @@ -5204,7 +5204,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { snap_rotation = false; snap_scale = false; snap_relative = false; - snap_pixel = false; + // Enable pixel snapping even if pixel snap rendering is disabled in the Project Settings. + // This results in crisper visuals by preventing 2D nodes from being placed at subpixel coordinates. + snap_pixel = true; snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index bfcc293625..fb32d7b1fd 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -39,7 +39,7 @@ #include "scene/resources/rectangle_shape_2d.h" #include "scene/resources/segment_shape_2d.h" #include "scene/resources/separation_ray_shape_2d.h" -#include "scene/resources/world_margin_shape_2d.h" +#include "scene/resources/world_boundary_shape_2d.h" void CollisionShape2DEditor::_node_removed(Node *p_node) { if (p_node == node) { @@ -70,13 +70,13 @@ Variant CollisionShape2DEditor::get_handle_value(int idx) const { case CONVEX_POLYGON_SHAPE: { } break; - case WORLD_MARGIN_SHAPE: { - Ref<WorldMarginShape2D> line = node->get_shape(); + case WORLD_BOUNDARY_SHAPE: { + Ref<WorldBoundaryShape2D> world_boundary = node->get_shape(); if (idx == 0) { - return line->get_distance(); + return world_boundary->get_distance(); } else { - return line->get_normal(); + return world_boundary->get_normal(); } } break; @@ -147,14 +147,14 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { case CONVEX_POLYGON_SHAPE: { } break; - case WORLD_MARGIN_SHAPE: { + case WORLD_BOUNDARY_SHAPE: { if (idx < 2) { - Ref<WorldMarginShape2D> line = node->get_shape(); + Ref<WorldBoundaryShape2D> world_boundary = node->get_shape(); if (idx == 0) { - line->set_distance(p_point.length()); + world_boundary->set_distance(p_point.length()); } else { - line->set_normal(p_point.normalized()); + world_boundary->set_normal(p_point.normalized()); } canvas_item_editor->update_viewport(); @@ -255,18 +255,18 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { // Cannot be edited directly, use CollisionPolygon2D instead. } break; - case WORLD_MARGIN_SHAPE: { - Ref<WorldMarginShape2D> line = node->get_shape(); + case WORLD_BOUNDARY_SHAPE: { + Ref<WorldBoundaryShape2D> world_boundary = node->get_shape(); if (idx == 0) { - undo_redo->add_do_method(line.ptr(), "set_distance", line->get_distance()); + undo_redo->add_do_method(world_boundary.ptr(), "set_distance", world_boundary->get_distance()); undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(line.ptr(), "set_distance", p_org); + undo_redo->add_undo_method(world_boundary.ptr(), "set_distance", p_org); undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); } else { - undo_redo->add_do_method(line.ptr(), "set_normal", line->get_normal()); + undo_redo->add_do_method(world_boundary.ptr(), "set_normal", world_boundary->get_normal()); undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(line.ptr(), "set_normal", p_org); + undo_redo->add_undo_method(world_boundary.ptr(), "set_normal", p_org); undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); } @@ -421,8 +421,8 @@ void CollisionShape2DEditor::_get_current_shape_type() { shape_type = CONCAVE_POLYGON_SHAPE; } else if (Object::cast_to<ConvexPolygonShape2D>(*s)) { shape_type = CONVEX_POLYGON_SHAPE; - } else if (Object::cast_to<WorldMarginShape2D>(*s)) { - shape_type = WORLD_MARGIN_SHAPE; + } else if (Object::cast_to<WorldBoundaryShape2D>(*s)) { + shape_type = WORLD_BOUNDARY_SHAPE; } else if (Object::cast_to<SeparationRayShape2D>(*s)) { shape_type = SEPARATION_RAY_SHAPE; } else if (Object::cast_to<RectangleShape2D>(*s)) { @@ -490,8 +490,8 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla case CONVEX_POLYGON_SHAPE: { } break; - case WORLD_MARGIN_SHAPE: { - Ref<WorldMarginShape2D> shape = node->get_shape(); + case WORLD_BOUNDARY_SHAPE: { + Ref<WorldBoundaryShape2D> shape = node->get_shape(); handles.resize(2); handles.write[0] = shape->get_normal() * shape->get_distance(); diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h index 421e674df8..ab95600a52 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.h +++ b/editor/plugins/collision_shape_2d_editor_plugin.h @@ -46,7 +46,7 @@ class CollisionShape2DEditor : public Control { CIRCLE_SHAPE, CONCAVE_POLYGON_SHAPE, CONVEX_POLYGON_SHAPE, - WORLD_MARGIN_SHAPE, + WORLD_BOUNDARY_SHAPE, SEPARATION_RAY_SHAPE, RECTANGLE_SHAPE, SEGMENT_SHAPE diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index 94966d4fe6..30945826bb 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -278,6 +278,8 @@ Ref<Resource> StandardMaterial3DConversionPlugin::convert(const Ref<Resource> &p } smat->set_render_priority(mat->get_render_priority()); + smat->set_local_to_scene(mat->is_local_to_scene()); + smat->set_name(mat->get_name()); return smat; } @@ -315,6 +317,8 @@ Ref<Resource> ParticlesMaterialConversionPlugin::convert(const Ref<Resource> &p_ } smat->set_render_priority(mat->get_render_priority()); + smat->set_local_to_scene(mat->is_local_to_scene()); + smat->set_name(mat->get_name()); return smat; } @@ -352,6 +356,8 @@ Ref<Resource> CanvasItemMaterialConversionPlugin::convert(const Ref<Resource> &p } smat->set_render_priority(mat->get_render_priority()); + smat->set_local_to_scene(mat->is_local_to_scene()); + smat->set_name(mat->get_name()); return smat; } @@ -389,6 +395,8 @@ Ref<Resource> ProceduralSkyMaterialConversionPlugin::convert(const Ref<Resource> } smat->set_render_priority(mat->get_render_priority()); + smat->set_local_to_scene(mat->is_local_to_scene()); + smat->set_name(mat->get_name()); return smat; } @@ -426,6 +434,8 @@ Ref<Resource> PanoramaSkyMaterialConversionPlugin::convert(const Ref<Resource> & } smat->set_render_priority(mat->get_render_priority()); + smat->set_local_to_scene(mat->is_local_to_scene()); + smat->set_name(mat->get_name()); return smat; } @@ -463,5 +473,7 @@ Ref<Resource> PhysicalSkyMaterialConversionPlugin::convert(const Ref<Resource> & } smat->set_render_priority(mat->get_render_priority()); + smat->set_local_to_scene(mat->is_local_to_scene()); + smat->set_name(mat->get_name()); return smat; } diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp index 9a2b222f21..574d3ef27e 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp @@ -202,7 +202,8 @@ void MeshInstance3DEditor::_menu_option(int p_option) { return; } - Vector<Ref<Shape3D>> shapes = mesh->convex_decompose(); + Mesh::ConvexDecompositionSettings settings; + Vector<Ref<Shape3D>> shapes = mesh->convex_decompose(settings); if (!shapes.size()) { err_dialog->set_text(TTR("Couldn't create any collision shapes.")); diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index b3f92c9d95..18e7480287 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -47,23 +47,25 @@ void MeshLibraryEditor::edit(const Ref<MeshLibrary> &p_mesh_library) { } } -void MeshLibraryEditor::_menu_confirm() { +void MeshLibraryEditor::_menu_remove_confirm() { switch (option) { case MENU_OPTION_REMOVE_ITEM: { mesh_library->remove_item(to_erase); } break; - case MENU_OPTION_UPDATE_FROM_SCENE: { - String existing = mesh_library->get_meta("_editor_source_scene"); - ERR_FAIL_COND(existing == ""); - _import_scene_cbk(existing); - - } break; default: { }; } } -void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge) { +void MeshLibraryEditor::_menu_update_confirm(bool p_apply_xforms) { + cd_update->hide(); + apply_xforms = p_apply_xforms; + String existing = mesh_library->get_meta("_editor_source_scene"); + ERR_FAIL_COND(existing == ""); + _import_scene_cbk(existing); +} + +void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge, bool p_apply_xforms) { if (!p_merge) { p_library->clear(); } @@ -108,6 +110,13 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, } p_library->set_item_mesh(id, mesh); + + if (p_apply_xforms) { + p_library->set_item_mesh_transform(id, mi->get_transform()); + } else { + p_library->set_item_mesh_transform(id, Transform3D()); + } + mesh_instances[id] = mi; Vector<MeshLibrary::ShapeData> collisions; @@ -197,15 +206,16 @@ void MeshLibraryEditor::_import_scene_cbk(const String &p_str) { ERR_FAIL_COND_MSG(!scene, "Cannot create an instance from PackedScene '" + p_str + "'."); - _import_scene(scene, mesh_library, option == MENU_OPTION_UPDATE_FROM_SCENE); + _import_scene(scene, mesh_library, option == MENU_OPTION_UPDATE_FROM_SCENE, apply_xforms); memdelete(scene); mesh_library->set_meta("_editor_source_scene", p_str); + menu->get_popup()->set_item_disabled(menu->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE), false); } -Error MeshLibraryEditor::update_library_file(Node *p_base_scene, Ref<MeshLibrary> ml, bool p_merge) { - _import_scene(p_base_scene, ml, p_merge); +Error MeshLibraryEditor::update_library_file(Node *p_base_scene, Ref<MeshLibrary> ml, bool p_merge, bool p_apply_xforms) { + _import_scene(p_base_scene, ml, p_merge, p_apply_xforms); return OK; } @@ -219,16 +229,21 @@ void MeshLibraryEditor::_menu_cbk(int p_option) { String p = editor->get_inspector()->get_selected_path(); if (p.begins_with("/MeshLibrary/item") && p.get_slice_count("/") >= 3) { to_erase = p.get_slice("/", 3).to_int(); - cd->set_text(vformat(TTR("Remove item %d?"), to_erase)); - cd->popup_centered(Size2(300, 60)); + cd_remove->set_text(vformat(TTR("Remove item %d?"), to_erase)); + cd_remove->popup_centered(Size2(300, 60)); } } break; case MENU_OPTION_IMPORT_FROM_SCENE: { + apply_xforms = false; + file->popup_file_dialog(); + } break; + case MENU_OPTION_IMPORT_FROM_SCENE_APPLY_XFORMS: { + apply_xforms = true; file->popup_file_dialog(); } break; case MENU_OPTION_UPDATE_FROM_SCENE: { - cd->set_text(vformat(TTR("Update from existing scene?:\n%s"), String(mesh_library->get_meta("_editor_source_scene")))); - cd->popup_centered(Size2(500, 60)); + cd_update->set_text(vformat(TTR("Update from existing scene?:\n%s"), String(mesh_library->get_meta("_editor_source_scene")))); + cd_update->popup_centered(Size2(500, 60)); } break; } } @@ -258,16 +273,22 @@ MeshLibraryEditor::MeshLibraryEditor(EditorNode *p_editor) { menu->get_popup()->add_item(TTR("Add Item"), MENU_OPTION_ADD_ITEM); menu->get_popup()->add_item(TTR("Remove Selected Item"), MENU_OPTION_REMOVE_ITEM); menu->get_popup()->add_separator(); - menu->get_popup()->add_item(TTR("Import from Scene"), MENU_OPTION_IMPORT_FROM_SCENE); + menu->get_popup()->add_item(TTR("Import from Scene (Ignore Transforms)"), MENU_OPTION_IMPORT_FROM_SCENE); + menu->get_popup()->add_item(TTR("Import from Scene (Apply Transforms)"), MENU_OPTION_IMPORT_FROM_SCENE_APPLY_XFORMS); menu->get_popup()->add_item(TTR("Update from Scene"), MENU_OPTION_UPDATE_FROM_SCENE); menu->get_popup()->set_item_disabled(menu->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE), true); menu->get_popup()->connect("id_pressed", callable_mp(this, &MeshLibraryEditor::_menu_cbk)); menu->hide(); editor = p_editor; - cd = memnew(ConfirmationDialog); - add_child(cd); - cd->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_confirm)); + cd_remove = memnew(ConfirmationDialog); + add_child(cd_remove); + cd_remove->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_remove_confirm)); + cd_update = memnew(ConfirmationDialog); + add_child(cd_update); + cd_update->get_ok_button()->set_text("Apply without Transforms"); + cd_update->get_ok_button()->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm), varray(false)); + cd_update->add_button("Apply with Transforms")->connect("pressed", callable_mp(this, &MeshLibraryEditor::_menu_update_confirm), varray(true)); } void MeshLibraryEditorPlugin::edit(Object *p_node) { diff --git a/editor/plugins/mesh_library_editor_plugin.h b/editor/plugins/mesh_library_editor_plugin.h index 6c33c8bb9e..9e225ffb9b 100644 --- a/editor/plugins/mesh_library_editor_plugin.h +++ b/editor/plugins/mesh_library_editor_plugin.h @@ -41,23 +41,27 @@ class MeshLibraryEditor : public Control { EditorNode *editor; MenuButton *menu; - ConfirmationDialog *cd; + ConfirmationDialog *cd_remove; + ConfirmationDialog *cd_update; EditorFileDialog *file; + bool apply_xforms; int to_erase; enum { MENU_OPTION_ADD_ITEM, MENU_OPTION_REMOVE_ITEM, MENU_OPTION_UPDATE_FROM_SCENE, - MENU_OPTION_IMPORT_FROM_SCENE + MENU_OPTION_IMPORT_FROM_SCENE, + MENU_OPTION_IMPORT_FROM_SCENE_APPLY_XFORMS }; int option; void _import_scene_cbk(const String &p_str); void _menu_cbk(int p_option); - void _menu_confirm(); + void _menu_remove_confirm(); + void _menu_update_confirm(bool p_apply_xforms); - static void _import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge); + static void _import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge, bool p_apply_xforms); protected: static void _bind_methods(); @@ -66,7 +70,7 @@ public: MenuButton *get_menu_button() const { return menu; } void edit(const Ref<MeshLibrary> &p_mesh_library); - static Error update_library_file(Node *p_base_scene, Ref<MeshLibrary> ml, bool p_merge = true); + static Error update_library_file(Node *p_base_scene, Ref<MeshLibrary> ml, bool p_merge = true, bool p_apply_xforms = false); MeshLibraryEditor(EditorNode *p_editor); }; diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index d04e88e915..0f98629370 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -34,6 +34,7 @@ #include "core/math/geometry_2d.h" #include "core/math/geometry_3d.h" #include "editor/plugins/node_3d_editor_plugin.h" +#include "scene/3d/audio_listener_3d.h" #include "scene/3d/audio_stream_player_3d.h" #include "scene/3d/camera_3d.h" #include "scene/3d/collision_polygon_3d.h" @@ -45,7 +46,6 @@ #include "scene/3d/light_3d.h" #include "scene/3d/lightmap_gi.h" #include "scene/3d/lightmap_probe.h" -#include "scene/3d/listener_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/3d/navigation_region_3d.h" #include "scene/3d/occluder_instance_3d.h" @@ -53,7 +53,7 @@ #include "scene/3d/position_3d.h" #include "scene/3d/ray_cast_3d.h" #include "scene/3d/reflection_probe.h" -#include "scene/3d/soft_body_3d.h" +#include "scene/3d/soft_dynamic_body_3d.h" #include "scene/3d/spring_arm_3d.h" #include "scene/3d/sprite_3d.h" #include "scene/3d/vehicle_body_3d.h" @@ -69,7 +69,7 @@ #include "scene/resources/separation_ray_shape_3d.h" #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" -#include "scene/resources/world_margin_shape_3d.h" +#include "scene/resources/world_boundary_shape_3d.h" #define HANDLE_HALF_SIZE 9.5 @@ -1003,7 +1003,9 @@ String EditorNode3DGizmoPlugin::get_gizmo_name() const { if (get_script_instance() && get_script_instance()->has_method("_get_gizmo_name")) { return get_script_instance()->call("_get_gizmo_name"); } - return TTR("Nameless gizmo"); + + WARN_PRINT_ONCE("A 3D editor gizmo has no name defined (it will appear as \"Unnamed Gizmo\" in the \"View > Gizmos\" menu). To resolve this, override the `_get_gizmo_name()` function to return a String in the script that extends EditorNode3DGizmoPlugin."); + return TTR("Unnamed Gizmo"); } int EditorNode3DGizmoPlugin::get_priority() const { @@ -1481,8 +1483,6 @@ void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { } } -////// - //// player gizmo AudioStreamPlayer3DGizmoPlugin::AudioStreamPlayer3DGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/stream_player_3d", Color(0.4, 0.8, 1)); @@ -1621,6 +1621,29 @@ void AudioStreamPlayer3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { ////// +AudioListener3DGizmoPlugin::AudioListener3DGizmoPlugin() { + create_icon_material("audio_listener_3d_icon", Node3DEditor::get_singleton()->get_theme_icon("GizmoAudioListener3D", "EditorIcons")); +} + +bool AudioListener3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to<AudioListener3D>(p_spatial) != nullptr; +} + +String AudioListener3DGizmoPlugin::get_gizmo_name() const { + return "AudioListener3D"; +} + +int AudioListener3DGizmoPlugin::get_priority() const { + return -1; +} + +void AudioListener3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + const Ref<Material> icon = get_material("audio_listener_3d_icon", p_gizmo); + p_gizmo->add_unscaled_billboard(icon, 0.05); +} + +////// + Camera3DGizmoPlugin::Camera3DGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/camera", Color(0.8, 0.4, 0.8)); @@ -1866,7 +1889,7 @@ MeshInstance3DGizmoPlugin::MeshInstance3DGizmoPlugin() { } bool MeshInstance3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { - return Object::cast_to<MeshInstance3D>(p_spatial) != nullptr && Object::cast_to<SoftBody3D>(p_spatial) == nullptr; + return Object::cast_to<MeshInstance3D>(p_spatial) != nullptr && Object::cast_to<SoftDynamicBody3D>(p_spatial) == nullptr; } String MeshInstance3DGizmoPlugin::get_gizmo_name() const { @@ -2097,7 +2120,6 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Color bonecolor = Color(1.0, 0.4, 0.4, 0.3); Color rootcolor = Color(0.4, 1.0, 0.4, 0.1); - //LocalVector<int> bones_to_process = skel->get_parentless_bones(); LocalVector<int> bones_to_process; bones_to_process = skel->get_parentless_bones(); @@ -2109,19 +2131,18 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { child_bones_vector = skel->get_bone_children(current_bone_idx); int child_bones_size = child_bones_vector.size(); - // You have children but no parent, then you must be a root/parentless bone. - if (child_bones_size >= 0 && skel->get_bone_parent(current_bone_idx) <= 0) { - grests[current_bone_idx] = skel->global_pose_to_local_pose(current_bone_idx, skel->get_bone_global_pose(current_bone_idx)); + if (skel->get_bone_parent(current_bone_idx) < 0) { + grests[current_bone_idx] = skel->get_bone_rest(current_bone_idx); } for (int i = 0; i < child_bones_size; i++) { int child_bone_idx = child_bones_vector[i]; - grests[child_bone_idx] = skel->global_pose_to_local_pose(child_bone_idx, skel->get_bone_global_pose(child_bone_idx)); + grests[child_bone_idx] = grests[current_bone_idx] * skel->get_bone_rest(child_bone_idx); Vector3 v0 = grests[current_bone_idx].origin; Vector3 v1 = grests[child_bone_idx].origin; - Vector3 d = skel->get_bone_rest(child_bone_idx).origin.normalized(); - real_t dist = skel->get_bone_rest(child_bone_idx).origin.length(); + Vector3 d = (v1 - v0).normalized(); + real_t dist = v0.distance_to(v1); // Find closest axis. int closest = -1; @@ -2491,30 +2512,30 @@ void VehicleWheel3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { /////////// -SoftBody3DGizmoPlugin::SoftBody3DGizmoPlugin() { +SoftDynamicBody3DGizmoPlugin::SoftDynamicBody3DGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1)); create_material("shape_material", gizmo_color); create_handle_material("handles"); } -bool SoftBody3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { - return Object::cast_to<SoftBody3D>(p_spatial) != nullptr; +bool SoftDynamicBody3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to<SoftDynamicBody3D>(p_spatial) != nullptr; } -String SoftBody3DGizmoPlugin::get_gizmo_name() const { - return "SoftBody3D"; +String SoftDynamicBody3DGizmoPlugin::get_gizmo_name() const { + return "SoftDynamicBody3D"; } -int SoftBody3DGizmoPlugin::get_priority() const { +int SoftDynamicBody3DGizmoPlugin::get_priority() const { return -1; } -bool SoftBody3DGizmoPlugin::is_selectable_when_hidden() const { +bool SoftDynamicBody3DGizmoPlugin::is_selectable_when_hidden() const { return true; } -void SoftBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node()); +void SoftDynamicBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + SoftDynamicBody3D *soft_body = Object::cast_to<SoftDynamicBody3D>(p_gizmo->get_spatial_node()); p_gizmo->clear(); @@ -2550,22 +2571,22 @@ void SoftBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->add_collision_triangles(tm); } -String SoftBody3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const { - return "SoftBody3D pin point"; +String SoftDynamicBody3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const { + return "SoftDynamicBody3D pin point"; } -Variant SoftBody3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const { - SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node()); +Variant SoftDynamicBody3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const { + SoftDynamicBody3D *soft_body = Object::cast_to<SoftDynamicBody3D>(p_gizmo->get_spatial_node()); return Variant(soft_body->is_point_pinned(p_id)); } -void SoftBody3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) { - SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node()); +void SoftDynamicBody3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) { + SoftDynamicBody3D *soft_body = Object::cast_to<SoftDynamicBody3D>(p_gizmo->get_spatial_node()); soft_body->pin_point_toggle(p_id); } -bool SoftBody3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id) const { - SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node()); +bool SoftDynamicBody3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id) const { + SoftDynamicBody3D *soft_body = Object::cast_to<SoftDynamicBody3D>(p_gizmo->get_spatial_node()); return soft_body->is_point_pinned(p_id); } @@ -4539,9 +4560,9 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->add_handles(handles, handles_material); } - if (Object::cast_to<WorldMarginShape3D>(*s)) { - Ref<WorldMarginShape3D> ps = s; - Plane p = ps->get_plane(); + if (Object::cast_to<WorldBoundaryShape3D>(*s)) { + Ref<WorldBoundaryShape3D> wbs = s; + const Plane &p = wbs->get_plane(); Vector<Vector3> points; Vector3 n1 = p.get_any_perpendicular_normal(); diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h index 415ed5da5c..24b4a23d4b 100644 --- a/editor/plugins/node_3d_editor_gizmos.h +++ b/editor/plugins/node_3d_editor_gizmos.h @@ -249,6 +249,19 @@ public: AudioStreamPlayer3DGizmoPlugin(); }; +class AudioListener3DGizmoPlugin : public EditorNode3DGizmoPlugin { + GDCLASS(AudioListener3DGizmoPlugin, EditorNode3DGizmoPlugin); + +public: + bool has_gizmo(Node3D *p_spatial) override; + String get_gizmo_name() const override; + int get_priority() const override; + + void redraw(EditorNode3DGizmo *p_gizmo) override; + + AudioListener3DGizmoPlugin(); +}; + class Camera3DGizmoPlugin : public EditorNode3DGizmoPlugin { GDCLASS(Camera3DGizmoPlugin, EditorNode3DGizmoPlugin); @@ -379,8 +392,8 @@ public: VehicleWheel3DGizmoPlugin(); }; -class SoftBody3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(SoftBody3DGizmoPlugin, EditorNode3DGizmoPlugin); +class SoftDynamicBody3DGizmoPlugin : public EditorNode3DGizmoPlugin { + GDCLASS(SoftDynamicBody3DGizmoPlugin, EditorNode3DGizmoPlugin); public: bool has_gizmo(Node3D *p_spatial) override; @@ -394,7 +407,7 @@ public: void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) override; bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id) const override; - SoftBody3DGizmoPlugin(); + SoftDynamicBody3DGizmoPlugin(); }; class VisibleOnScreenNotifier3DGizmoPlugin : public EditorNode3DGizmoPlugin { diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 291cafab2b..5263352502 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -1831,6 +1831,8 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { motion = Vector3(scale, scale, scale); } + motion /= click.distance_to(_edit.center); + // Disable local transformation for TRANSFORM_VIEW bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); @@ -6861,9 +6863,10 @@ void Node3DEditor::_register_all_gizmos() { add_gizmo_plugin(Ref<Camera3DGizmoPlugin>(memnew(Camera3DGizmoPlugin))); add_gizmo_plugin(Ref<Light3DGizmoPlugin>(memnew(Light3DGizmoPlugin))); add_gizmo_plugin(Ref<AudioStreamPlayer3DGizmoPlugin>(memnew(AudioStreamPlayer3DGizmoPlugin))); + add_gizmo_plugin(Ref<AudioListener3DGizmoPlugin>(memnew(AudioListener3DGizmoPlugin))); add_gizmo_plugin(Ref<MeshInstance3DGizmoPlugin>(memnew(MeshInstance3DGizmoPlugin))); add_gizmo_plugin(Ref<OccluderInstance3DGizmoPlugin>(memnew(OccluderInstance3DGizmoPlugin))); - add_gizmo_plugin(Ref<SoftBody3DGizmoPlugin>(memnew(SoftBody3DGizmoPlugin))); + add_gizmo_plugin(Ref<SoftDynamicBody3DGizmoPlugin>(memnew(SoftDynamicBody3DGizmoPlugin))); add_gizmo_plugin(Ref<Sprite3DGizmoPlugin>(memnew(Sprite3DGizmoPlugin))); add_gizmo_plugin(Ref<Skeleton3DGizmoPlugin>(memnew(Skeleton3DGizmoPlugin))); add_gizmo_plugin(Ref<Position3DGizmoPlugin>(memnew(Position3DGizmoPlugin))); diff --git a/editor/plugins/packed_scene_translation_parser_plugin.cpp b/editor/plugins/packed_scene_translation_parser_plugin.cpp index 0a949c8610..53c5b8dd70 100644 --- a/editor/plugins/packed_scene_translation_parser_plugin.cpp +++ b/editor/plugins/packed_scene_translation_parser_plugin.cpp @@ -31,6 +31,7 @@ #include "packed_scene_translation_parser_plugin.h" #include "core/io/resource_loader.h" +#include "scene/gui/option_button.h" #include "scene/resources/packed_scene.h" void PackedSceneEditorTranslationParserPlugin::get_recognized_extensions(List<String> *r_extensions) const { @@ -50,21 +51,31 @@ Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path, Ref<SceneState> state = Ref<PackedScene>(loaded_res)->get_state(); Vector<String> parsed_strings; - String property_name; - Variant property_value; for (int i = 0; i < state->get_node_count(); i++) { - if (!ClassDB::is_parent_class(state->get_node_type(i), "Control") && !ClassDB::is_parent_class(state->get_node_type(i), "Viewport")) { + String node_type = state->get_node_type(i); + if (!ClassDB::is_parent_class(node_type, "Control") && !ClassDB::is_parent_class(node_type, "Window")) { continue; } + // Find the `auto_translate` property, and abort the string parsing of the node if disabled. + bool auto_translating = true; for (int j = 0; j < state->get_node_property_count(i); j++) { - property_name = state->get_node_property_name(i, j); - if (!lookup_properties.has(property_name)) { - continue; + if (state->get_node_property_name(i, j) == "auto_translate" && (bool)state->get_node_property_value(i, j) == false) { + auto_translating = false; + break; } + } + if (!auto_translating) { + continue; + } - property_value = state->get_node_property_value(i, j); + for (int j = 0; j < state->get_node_property_count(i); j++) { + String property_name = state->get_node_property_name(i, j); + if (!lookup_properties.has(property_name) || (exception_list.has(node_type) && exception_list[node_type].has(property_name))) { + continue; + } + Variant property_value = state->get_node_property_value(i, j); if (property_name == "script" && property_value.get_type() == Variant::OBJECT && !property_value.is_null()) { // Parse built-in script. Ref<Script> s = Object::cast_to<Script>(property_value); @@ -76,7 +87,16 @@ Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path, parsed_strings.append_array(temp); r_ids_ctx_plural->append_array(ids_context_plural); } - } else if (property_name == "filters") { + } else if ((node_type == "MenuButton" || node_type == "OptionButton") && property_name == "items") { + Vector<String> str_values = property_value; + int incr_value = node_type == "MenuButton" ? PopupMenu::ITEM_PROPERTY_SIZE : OptionButton::ITEM_PROPERTY_SIZE; + for (int k = 0; k < str_values.size(); k += incr_value) { + String desc = str_values[k].get_slice(";", 1).strip_edges(); + if (!desc.is_empty()) { + parsed_strings.push_back(desc); + } + } + } else if (node_type == "FileDialog" && property_name == "filters") { // Extract FileDialog's filters property with values in format "*.png ; PNG Images","*.gd ; GDScript Files". Vector<String> str_values = property_value; for (int k = 0; k < str_values.size(); k++) { @@ -105,12 +125,17 @@ PackedSceneEditorTranslationParserPlugin::PackedSceneEditorTranslationParserPlug lookup_properties.insert("text"); lookup_properties.insert("hint_tooltip"); lookup_properties.insert("placeholder_text"); + lookup_properties.insert("items"); + lookup_properties.insert("title"); lookup_properties.insert("dialog_text"); lookup_properties.insert("filters"); lookup_properties.insert("script"); - //Add exception list (to prevent false positives) - //line edit, text edit, richtextlabel - //Set<String> exception_list; - //exception_list.insert("RichTextLabel"); + // Exception list (to prevent false positives). + exception_list.insert("LineEdit", Vector<StringName>()); + exception_list["LineEdit"].append("text"); + exception_list.insert("TextEdit", Vector<StringName>()); + exception_list["TextEdit"].append("text"); + exception_list.insert("CodeEdit", Vector<StringName>()); + exception_list["CodeEdit"].append("text"); } diff --git a/editor/plugins/packed_scene_translation_parser_plugin.h b/editor/plugins/packed_scene_translation_parser_plugin.h index e51d65414e..af0291b69c 100644 --- a/editor/plugins/packed_scene_translation_parser_plugin.h +++ b/editor/plugins/packed_scene_translation_parser_plugin.h @@ -37,7 +37,9 @@ class PackedSceneEditorTranslationParserPlugin : public EditorTranslationParserP GDCLASS(PackedSceneEditorTranslationParserPlugin, EditorTranslationParserPlugin); // Scene Node's properties that contain translation strings. - Set<String> lookup_properties; + Set<StringName> lookup_properties; + // Properties from specific Nodes that should be ignored. + Map<StringName, Vector<StringName>> exception_list; public: virtual Error parse_file(const String &p_path, Vector<String> *r_ids, Vector<Vector<String>> *r_ids_ctx_plural) override; diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 7ef5993ec5..ee9103be44 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -46,6 +46,7 @@ #include "editor/find_in_files.h" #include "editor/node_dock.h" #include "editor/plugins/shader_editor_plugin.h" +#include "modules/visual_script/visual_script_editor.h" #include "scene/main/window.h" #include "scene/scene_string_names.h" #include "script_text_editor.h" @@ -1236,14 +1237,15 @@ void ScriptEditor::_menu_option(int p_option) { _update_script_names(); } break; case TOGGLE_SCRIPTS_PANEL: { + toggle_scripts_panel(); if (current) { - ScriptTextEditor *editor = Object::cast_to<ScriptTextEditor>(current); - toggle_scripts_panel(); - if (editor) { - editor->update_toggle_scripts_button(); - } + current->update_toggle_scripts_button(); } else { - toggle_scripts_panel(); + Control *tab = tab_container->get_current_tab_control(); + EditorHelp *editor_help = Object::cast_to<EditorHelp>(tab); + if (editor_help) { + editor_help->update_toggle_scripts_button(); + } } } } diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index e2420b4623..920c3070e6 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -161,6 +161,7 @@ public: virtual void update_settings() = 0; virtual void set_debugger_active(bool p_active) = 0; virtual bool can_lose_focus_on_node_selection() { return true; } + virtual void update_toggle_scripts_button() {} virtual bool show_members_overview() = 0; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index c44760807f..ebd46be3b4 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -158,7 +158,6 @@ void ScriptTextEditor::enable_editor() { editor_enabled = true; _enable_code_editor(); - _set_theme_for_script(); _validate_script(); } @@ -877,9 +876,7 @@ String ScriptTextEditor::_get_absolute_path(const String &rel_path) { } void ScriptTextEditor::update_toggle_scripts_button() { - if (code_editor != nullptr) { - code_editor->update_toggle_scripts_button(); - } + code_editor->update_toggle_scripts_button(); } void ScriptTextEditor::_update_connected_methods() { @@ -1243,7 +1240,7 @@ void ScriptTextEditor::_edit_option(int p_op) { tx->set_caret_line(bpoints[bpoints.size() - 1]); tx->center_viewport_to_caret(); } else { - for (int i = bpoints.size(); i >= 0; i--) { + for (int i = bpoints.size() - 1; i >= 0; i--) { int bline = bpoints[i]; if (bline < line) { tx->unfold_line(bline); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index 4208d67f17..afe9a7453d 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -197,7 +197,7 @@ public: virtual void add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) override; virtual void set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) override; - void update_toggle_scripts_button(); + void update_toggle_scripts_button() override; virtual void apply_code() override; virtual RES get_edited_resource() const override; diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp index 7ef680d7ef..c350004f0f 100644 --- a/editor/plugins/skeleton_2d_editor_plugin.cpp +++ b/editor/plugins/skeleton_2d_editor_plugin.cpp @@ -98,9 +98,10 @@ Skeleton2DEditor::Skeleton2DEditor() { options->set_text(TTR("Skeleton2D")); options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Skeleton2D"), SNAME("EditorIcons"))); - options->get_popup()->add_item(TTR("Make Rest Pose (From Bones)"), MENU_OPTION_MAKE_REST); + options->get_popup()->add_item(TTR("Reset to Rest Pose"), MENU_OPTION_MAKE_REST); options->get_popup()->add_separator(); - options->get_popup()->add_item(TTR("Set Bones to Rest Pose"), MENU_OPTION_SET_REST); + // Use the "Overwrite" word to highlight that this is a destructive operation. + options->get_popup()->add_item(TTR("Overwrite Rest Pose"), MENU_OPTION_SET_REST); options->set_switch_on_hover(true); options->get_popup()->connect("id_pressed", callable_mp(this, &Skeleton2DEditor::_menu_option)); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 400f9f560f..8a8d80891a 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -54,22 +54,46 @@ void SpriteFramesEditor::_open_sprite_sheet() { file_split_sheet->popup_file_dialog(); } +int SpriteFramesEditor::_sheet_preview_position_to_frame_index(const Point2 &p_position) { + if (p_position.x < 0 || p_position.y < 0) { + return -1; + } + + Size2i texture_size = split_sheet_preview->get_texture()->get_size(); + int h = split_sheet_h->get_value(); + int v = split_sheet_v->get_value(); + if (h > texture_size.width || v > texture_size.height) { + return -1; + } + + int x = int(p_position.x / sheet_zoom) / (texture_size.width / h); + int y = int(p_position.y / sheet_zoom) / (texture_size.height / v); + if (x >= h || y >= v) { + return -1; + } + return h * y + x; +} + void SpriteFramesEditor::_sheet_preview_draw() { - Size2i size = split_sheet_preview->get_size(); + Size2i texture_size = split_sheet_preview->get_texture()->get_size(); int h = split_sheet_h->get_value(); int v = split_sheet_v->get_value(); - int width = size.width / h; - int height = size.height / v; + + real_t width = (texture_size.width / h) * sheet_zoom; + real_t height = (texture_size.height / v) * sheet_zoom; const float a = 0.3; - for (int i = 1; i < h; i++) { - int x = i * width; - split_sheet_preview->draw_line(Point2(x, 0), Point2(x, size.height), Color(1, 1, 1, a)); - split_sheet_preview->draw_line(Point2(x + 1, 0), Point2(x + 1, size.height), Color(0, 0, 0, a)); + + real_t y_end = v * height; + for (int i = 0; i <= h; i++) { + real_t x = i * width; + split_sheet_preview->draw_line(Point2(x, 0), Point2(x, y_end), Color(1, 1, 1, a)); + split_sheet_preview->draw_line(Point2(x + 1, 0), Point2(x + 1, y_end), Color(0, 0, 0, a)); } - for (int i = 1; i < v; i++) { - int y = i * height; - split_sheet_preview->draw_line(Point2(0, y), Point2(size.width, y), Color(1, 1, 1, a)); - split_sheet_preview->draw_line(Point2(0, y + 1), Point2(size.width, y + 1), Color(0, 0, 0, a)); + real_t x_end = h * width; + for (int i = 0; i <= v; i++) { + real_t y = i * height; + split_sheet_preview->draw_line(Point2(0, y), Point2(x_end, y), Color(1, 1, 1, a)); + split_sheet_preview->draw_line(Point2(0, y + 1), Point2(x_end, y + 1), Color(0, 0, 0, a)); } if (frames_selected.size() == 0) { @@ -83,9 +107,9 @@ void SpriteFramesEditor::_sheet_preview_draw() { for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) { int idx = E->get(); int xp = idx % h; - int yp = (idx - xp) / h; - int x = xp * width; - int y = yp * height; + int yp = idx / h; + real_t x = xp * width; + real_t y = yp * height; split_sheet_preview->draw_rect(Rect2(x + 5, y + 5, width - 10, height - 10), Color(0, 0, 0, 0.35), true); split_sheet_preview->draw_rect(Rect2(x + 0, y + 0, width - 0, height - 0), Color(0, 0, 0, 1), false); @@ -103,46 +127,43 @@ void SpriteFramesEditor::_sheet_preview_draw() { void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) { const Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { - const Size2i size = split_sheet_preview->get_size(); - const int h = split_sheet_h->get_value(); - const int v = split_sheet_v->get_value(); - - const int x = CLAMP(int(mb->get_position().x) * h / size.width, 0, h - 1); - const int y = CLAMP(int(mb->get_position().y) * v / size.height, 0, v - 1); - - const int idx = h * y + x; + const int idx = _sheet_preview_position_to_frame_index(mb->get_position()); + + if (idx != -1) { + if (mb->is_shift_pressed() && last_frame_selected >= 0) { + //select multiple + int from = idx; + int to = last_frame_selected; + if (from > to) { + SWAP(from, to); + } - if (mb->is_shift_pressed() && last_frame_selected >= 0) { - //select multiple - int from = idx; - int to = last_frame_selected; - if (from > to) { - SWAP(from, to); - } + for (int i = from; i <= to; i++) { + // Prevent double-toggling the same frame when moving the mouse when the mouse button is still held. + frames_toggled_by_mouse_hover.insert(idx); - for (int i = from; i <= to; i++) { + if (mb->is_ctrl_pressed()) { + frames_selected.erase(i); + } else { + frames_selected.insert(i); + } + } + } else { // Prevent double-toggling the same frame when moving the mouse when the mouse button is still held. frames_toggled_by_mouse_hover.insert(idx); - if (mb->is_ctrl_pressed()) { - frames_selected.erase(i); + if (frames_selected.has(idx)) { + frames_selected.erase(idx); } else { - frames_selected.insert(i); + frames_selected.insert(idx); } } - } else { - // Prevent double-toggling the same frame when moving the mouse when the mouse button is still held. - frames_toggled_by_mouse_hover.insert(idx); - - if (frames_selected.has(idx)) { - frames_selected.erase(idx); - } else { - frames_selected.insert(idx); - } } - last_frame_selected = idx; - split_sheet_preview->update(); + if (last_frame_selected != idx || idx != -1) { + last_frame_selected = idx; + split_sheet_preview->update(); + } } if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { @@ -152,16 +173,9 @@ void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) { const Ref<InputEventMouseMotion> mm = p_event; if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { // Select by holding down the mouse button on frames. - const Size2i size = split_sheet_preview->get_size(); - const int h = split_sheet_h->get_value(); - const int v = split_sheet_v->get_value(); - - const int x = CLAMP(int(mm->get_position().x) * h / size.width, 0, h - 1); - const int y = CLAMP(int(mm->get_position().y) * v / size.height, 0, v - 1); - - const int idx = h * y + x; + const int idx = _sheet_preview_position_to_frame_index(mm->get_position()); - if (!frames_toggled_by_mouse_hover.has(idx)) { + if (idx != -1 && !frames_toggled_by_mouse_hover.has(idx)) { // Only allow toggling each tile once per mouse hold. // Otherwise, the selection would constantly "flicker" in and out when moving the mouse cursor. // The mouse button must be released before it can be toggled again. @@ -199,17 +213,17 @@ void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) { } void SpriteFramesEditor::_sheet_add_frames() { - Size2i size = split_sheet_preview->get_texture()->get_size(); + Size2i texture_size = split_sheet_preview->get_texture()->get_size(); int frame_count_x = split_sheet_h->get_value(); int frame_count_y = split_sheet_v->get_value(); - Size2 frame_size(size.width / frame_count_x, size.height / frame_count_y); + Size2 frame_size(texture_size.width / frame_count_x, texture_size.height / frame_count_y); undo_redo->create_action(TTR("Add Frame")); int fc = frames->get_frame_count(edited_anim); Point2 src_origin; - Rect2 src_region(Point2(), size); + Rect2 src_region(Point2(), texture_size); AtlasTexture *src_atlas = Object::cast_to<AtlasTexture>(*split_sheet_preview->get_texture()); if (src_atlas && src_atlas->get_atlas().is_valid()) { diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index 17e30f0cab..5e3b2fb8c1 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -135,6 +135,7 @@ class SpriteFramesEditor : public HSplitContainer { void _open_sprite_sheet(); void _prepare_sprite_sheet(const String &p_file); + int _sheet_preview_position_to_frame_index(const Vector2 &p_position); void _sheet_preview_draw(); void _sheet_spin_changed(double); void _sheet_preview_input(const Ref<InputEvent> &p_event); diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 32bcc1a4e6..06ba8a6168 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -513,6 +513,10 @@ void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is context_menu->popup(); } +void TextEditor::update_toggle_scripts_button() { + code_editor->update_toggle_scripts_button(); +} + TextEditor::TextEditor() { code_editor = memnew(CodeTextEditor); add_child(code_editor); @@ -521,6 +525,7 @@ TextEditor::TextEditor() { code_editor->connect("validate_script", callable_mp(this, &TextEditor::_validate_script)); code_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE); code_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); + code_editor->show_toggle_scripts_button(); update_settings(); diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h index 6bf0042393..9308fec210 100644 --- a/editor/plugins/text_editor.h +++ b/editor/plugins/text_editor.h @@ -139,6 +139,7 @@ public: virtual void set_debugger_active(bool p_active) override; virtual void set_tooltip_request_func(String p_method, Object *p_obj) override; virtual void add_callback(const String &p_function, PackedStringArray p_args) override; + void update_toggle_scripts_button() override; virtual Control *get_edit_menu() override; virtual void clear_edit_menu() override; diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 1a6eb7b63b..50ad12635b 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -63,16 +63,16 @@ void draw_margin_line(Control *edit_draw, Vector2 from, Vector2 to) { void TextureRegionEditor::_region_draw() { Ref<Texture2D> base_tex = nullptr; - if (node_sprite) { - base_tex = node_sprite->get_texture(); + if (atlas_tex.is_valid()) { + base_tex = atlas_tex->get_atlas(); + } else if (node_sprite_2d) { + base_tex = node_sprite_2d->get_texture(); } else if (node_sprite_3d) { base_tex = node_sprite_3d->get_texture(); } else if (node_ninepatch) { base_tex = node_ninepatch->get_texture(); } else if (obj_styleBox.is_valid()) { base_tex = obj_styleBox->get_texture(); - } else if (atlas_tex.is_valid()) { - base_tex = atlas_tex->get_atlas(); } if (base_tex.is_null()) { @@ -332,24 +332,27 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { rect = E; if (Input::get_singleton()->is_key_pressed(KEY_CTRL) && !(Input::get_singleton()->is_key_pressed(Key(KEY_SHIFT | KEY_ALT)))) { Rect2 r; - if (node_sprite) { - r = node_sprite->get_region_rect(); + if (atlas_tex.is_valid()) { + r = atlas_tex->get_region(); + } else if (node_sprite_2d) { + r = node_sprite_2d->get_region_rect(); } else if (node_sprite_3d) { r = node_sprite_3d->get_region_rect(); } else if (node_ninepatch) { r = node_ninepatch->get_region_rect(); } else if (obj_styleBox.is_valid()) { r = obj_styleBox->get_region_rect(); - } else if (atlas_tex.is_valid()) { - r = atlas_tex->get_region(); } rect.expand_to(r.position); rect.expand_to(r.position + r.size); } undo_redo->create_action(TTR("Set Region Rect")); - if (node_sprite) { - undo_redo->add_do_method(node_sprite, "set_region_rect", rect); - undo_redo->add_undo_method(node_sprite, "set_region_rect", node_sprite->get_region_rect()); + if (atlas_tex.is_valid()) { + undo_redo->add_do_method(atlas_tex.ptr(), "set_region", rect); + undo_redo->add_undo_method(atlas_tex.ptr(), "set_region", atlas_tex->get_region()); + } else if (node_sprite_2d) { + undo_redo->add_do_method(node_sprite_2d, "set_region_rect", rect); + undo_redo->add_undo_method(node_sprite_2d, "set_region_rect", node_sprite_2d->get_region_rect()); } else if (node_sprite_3d) { undo_redo->add_do_method(node_sprite_3d, "set_region_rect", rect); undo_redo->add_undo_method(node_sprite_3d, "set_region_rect", node_sprite_3d->get_region_rect()); @@ -359,9 +362,6 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { } else if (obj_styleBox.is_valid()) { undo_redo->add_do_method(obj_styleBox.ptr(), "set_region_rect", rect); undo_redo->add_undo_method(obj_styleBox.ptr(), "set_region_rect", obj_styleBox->get_region_rect()); - } else if (atlas_tex.is_valid()) { - undo_redo->add_do_method(atlas_tex.ptr(), "set_region", rect); - undo_redo->add_undo_method(atlas_tex.ptr(), "set_region", atlas_tex->get_region()); } undo_redo->add_do_method(this, "_update_rect"); undo_redo->add_undo_method(this, "_update_rect"); @@ -379,16 +379,16 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { drag_from = snap_point(drag_from); } drag = true; - if (node_sprite) { - rect_prev = node_sprite->get_region_rect(); + if (atlas_tex.is_valid()) { + rect_prev = atlas_tex->get_region(); + } else if (node_sprite_2d) { + rect_prev = node_sprite_2d->get_region_rect(); } else if (node_sprite_3d) { rect_prev = node_sprite_3d->get_region_rect(); } else if (node_ninepatch) { rect_prev = node_ninepatch->get_region_rect(); } else if (obj_styleBox.is_valid()) { rect_prev = obj_styleBox->get_region_rect(); - } else if (atlas_tex.is_valid()) { - rect_prev = atlas_tex->get_region(); } for (int i = 0; i < 8; i++) { @@ -419,15 +419,15 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { edited_margin = -1; } else { undo_redo->create_action(TTR("Set Region Rect")); - if (node_sprite) { - undo_redo->add_do_method(node_sprite, "set_region_rect", node_sprite->get_region_rect()); - undo_redo->add_undo_method(node_sprite, "set_region_rect", rect_prev); + if (atlas_tex.is_valid()) { + undo_redo->add_do_method(atlas_tex.ptr(), "set_region", atlas_tex->get_region()); + undo_redo->add_undo_method(atlas_tex.ptr(), "set_region", rect_prev); + } else if (node_sprite_2d) { + undo_redo->add_do_method(node_sprite_2d, "set_region_rect", node_sprite_2d->get_region_rect()); + undo_redo->add_undo_method(node_sprite_2d, "set_region_rect", rect_prev); } else if (node_sprite_3d) { undo_redo->add_do_method(node_sprite_3d, "set_region_rect", node_sprite_3d->get_region_rect()); undo_redo->add_undo_method(node_sprite_3d, "set_region_rect", rect_prev); - } else if (atlas_tex.is_valid()) { - undo_redo->add_do_method(atlas_tex.ptr(), "set_region", atlas_tex->get_region()); - undo_redo->add_undo_method(atlas_tex.ptr(), "set_region", rect_prev); } else if (node_ninepatch) { undo_redo->add_do_method(node_ninepatch, "set_region_rect", node_ninepatch->get_region_rect()); undo_redo->add_undo_method(node_ninepatch, "set_region_rect", rect_prev); @@ -693,22 +693,24 @@ void TextureRegionEditor::_zoom_out() { } void TextureRegionEditor::apply_rect(const Rect2 &p_rect) { - if (node_sprite) { - node_sprite->set_region_rect(p_rect); + if (atlas_tex.is_valid()) { + atlas_tex->set_region(p_rect); + } else if (node_sprite_2d) { + node_sprite_2d->set_region_rect(p_rect); } else if (node_sprite_3d) { node_sprite_3d->set_region_rect(p_rect); } else if (node_ninepatch) { node_ninepatch->set_region_rect(p_rect); } else if (obj_styleBox.is_valid()) { obj_styleBox->set_region_rect(p_rect); - } else if (atlas_tex.is_valid()) { - atlas_tex->set_region(p_rect); } } void TextureRegionEditor::_update_rect() { - if (node_sprite) { - rect = node_sprite->get_region_rect(); + if (atlas_tex.is_valid()) { + rect = atlas_tex->get_region(); + } else if (node_sprite_2d) { + rect = node_sprite_2d->get_region_rect(); } else if (node_sprite_3d) { rect = node_sprite_3d->get_region_rect(); } else if (node_ninepatch) { @@ -718,8 +720,6 @@ void TextureRegionEditor::_update_rect() { } } else if (obj_styleBox.is_valid()) { rect = obj_styleBox->get_region_rect(); - } else if (atlas_tex.is_valid()) { - rect = atlas_tex->get_region(); } } @@ -728,16 +728,16 @@ void TextureRegionEditor::_update_autoslice() { autoslice_cache.clear(); Ref<Texture2D> texture = nullptr; - if (node_sprite) { - texture = node_sprite->get_texture(); + if (atlas_tex.is_valid()) { + texture = atlas_tex->get_atlas(); + } else if (node_sprite_2d) { + texture = node_sprite_2d->get_texture(); } else if (node_sprite_3d) { texture = node_sprite_3d->get_texture(); } else if (node_ninepatch) { texture = node_ninepatch->get_texture(); } else if (obj_styleBox.is_valid()) { texture = obj_styleBox->get_texture(); - } else if (atlas_tex.is_valid()) { - texture = atlas_tex->get_atlas(); } if (texture.is_null()) { @@ -823,8 +823,8 @@ void TextureRegionEditor::_notification(int p_what) { } void TextureRegionEditor::_node_removed(Object *p_obj) { - if (p_obj == node_sprite || p_obj == node_sprite_3d || p_obj == node_ninepatch || p_obj == obj_styleBox.ptr() || p_obj == atlas_tex.ptr()) { - node_sprite = nullptr; + if (p_obj == node_sprite_2d || p_obj == node_sprite_3d || p_obj == node_ninepatch || p_obj == obj_styleBox.ptr() || p_obj == atlas_tex.ptr()) { + node_sprite_2d = nullptr; node_sprite_3d = nullptr; node_ninepatch = nullptr; obj_styleBox = Ref<StyleBox>(nullptr); @@ -852,17 +852,17 @@ bool TextureRegionEditor::is_ninepatch() { return node_ninepatch != nullptr; } -Sprite3D *TextureRegionEditor::get_sprite_3d() { - return node_sprite_3d; +Sprite2D *TextureRegionEditor::get_sprite_2d() { + return node_sprite_2d; } -Sprite2D *TextureRegionEditor::get_sprite() { - return node_sprite; +Sprite3D *TextureRegionEditor::get_sprite_3d() { + return node_sprite_3d; } void TextureRegionEditor::edit(Object *p_obj) { - if (node_sprite) { - node_sprite->disconnect("texture_changed", callable_mp(this, &TextureRegionEditor::_texture_changed)); + if (node_sprite_2d) { + node_sprite_2d->disconnect("texture_changed", callable_mp(this, &TextureRegionEditor::_texture_changed)); } if (node_sprite_3d) { node_sprite_3d->disconnect("texture_changed", callable_mp(this, &TextureRegionEditor::_texture_changed)); @@ -877,7 +877,7 @@ void TextureRegionEditor::edit(Object *p_obj) { atlas_tex->disconnect("changed", callable_mp(this, &TextureRegionEditor::_texture_changed)); } if (p_obj) { - node_sprite = Object::cast_to<Sprite2D>(p_obj); + node_sprite_2d = Object::cast_to<Sprite2D>(p_obj); node_sprite_3d = Object::cast_to<Sprite3D>(p_obj); node_ninepatch = Object::cast_to<NinePatchRect>(p_obj); @@ -898,14 +898,14 @@ void TextureRegionEditor::edit(Object *p_obj) { } _edit_region(); } else { - node_sprite = nullptr; + node_sprite_2d = nullptr; node_sprite_3d = nullptr; node_ninepatch = nullptr; obj_styleBox = Ref<StyleBoxTexture>(nullptr); atlas_tex = Ref<AtlasTexture>(nullptr); } edit_draw->update(); - if ((node_sprite && !node_sprite->is_region_enabled()) || (node_sprite_3d && !node_sprite_3d->is_region_enabled())) { + if ((node_sprite_2d && !node_sprite_2d->is_region_enabled()) || (node_sprite_3d && !node_sprite_3d->is_region_enabled())) { set_process(true); } if (!p_obj) { @@ -922,16 +922,16 @@ void TextureRegionEditor::_texture_changed() { void TextureRegionEditor::_edit_region() { Ref<Texture2D> texture = nullptr; - if (node_sprite) { - texture = node_sprite->get_texture(); + if (atlas_tex.is_valid()) { + texture = atlas_tex->get_atlas(); + } else if (node_sprite_2d) { + texture = node_sprite_2d->get_texture(); } else if (node_sprite_3d) { texture = node_sprite_3d->get_texture(); } else if (node_ninepatch) { texture = node_ninepatch->get_texture(); } else if (obj_styleBox.is_valid()) { texture = obj_styleBox->get_texture(); - } else if (atlas_tex.is_valid()) { - texture = atlas_tex->get_atlas(); } if (texture.is_null()) { @@ -967,7 +967,7 @@ Vector2 TextureRegionEditor::snap_point(Vector2 p_target) const { } TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { - node_sprite = nullptr; + node_sprite_2d = nullptr; node_sprite_3d = nullptr; node_ninepatch = nullptr; obj_styleBox = Ref<StyleBoxTexture>(nullptr); @@ -1122,7 +1122,9 @@ void TextureRegionEditorPlugin::_editor_visiblity_changed() { void TextureRegionEditorPlugin::make_visible(bool p_visible) { if (p_visible) { texture_region_button->show(); - bool is_node_configured = region_editor->is_stylebox() || region_editor->is_atlas_texture() || region_editor->is_ninepatch() || (region_editor->get_sprite() && region_editor->get_sprite()->is_region_enabled()) || (region_editor->get_sprite_3d() && region_editor->get_sprite_3d()->is_region_enabled()); + bool is_node_configured = region_editor->is_stylebox() || region_editor->is_atlas_texture() || region_editor->is_ninepatch(); + is_node_configured |= region_editor->get_sprite_2d() && region_editor->get_sprite_2d()->is_region_enabled(); + is_node_configured |= region_editor->get_sprite_3d() && region_editor->get_sprite_3d()->is_region_enabled(); if ((is_node_configured && !manually_hidden) || texture_region_button->is_pressed()) { editor->make_bottom_panel_item_visible(region_editor); } diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index d3db0a08a9..c043d6ae33 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -83,7 +83,7 @@ class TextureRegionEditor : public VBoxContainer { Vector2 snap_step; Vector2 snap_separation; - Sprite2D *node_sprite; + Sprite2D *node_sprite_2d; Sprite3D *node_sprite_3d; NinePatchRect *node_ninepatch; Ref<StyleBoxTexture> obj_styleBox; @@ -134,8 +134,8 @@ public: bool is_stylebox(); bool is_atlas_texture(); bool is_ninepatch(); + Sprite2D *get_sprite_2d(); Sprite3D *get_sprite_3d(); - Sprite2D *get_sprite(); void edit(Object *p_obj); TextureRegionEditor(EditorNode *p_editor); diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 0add83f64d..6e0a5b00b9 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -327,10 +327,12 @@ void TileAtlasView::_draw_base_tiles_shape_grid() { Vector2i tile_id = tile_set_atlas_source->get_tile_id(i); Vector2 in_tile_base_offset = tile_set_atlas_source->get_tile_effective_texture_offset(tile_id, 0); Rect2i texture_region = tile_set_atlas_source->get_tile_texture_region(tile_id); - Vector2 origin = texture_region.position + (texture_region.size - tile_shape_size) / 2 + in_tile_base_offset; // Draw only if the tile shape fits in the texture region - tile_set->draw_tile_shape(base_tiles_shape_grid, Rect2(origin, tile_shape_size), grid_color); + Transform2D tile_xform; + tile_xform.set_origin(texture_region.position + texture_region.size / 2 + in_tile_base_offset); + tile_xform.set_scale(tile_shape_size); + tile_set->draw_tile_shape(base_tiles_shape_grid, tile_xform, grid_color); } } diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index d406c2514c..2a75a743a7 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -124,7 +124,9 @@ void GenericTilePolygonEditor::_base_control_draw() { base_control->draw_set_transform_matrix(xform); // Draw the tile shape filled. - tile_set->draw_tile_shape(base_control, Rect2(-tile_size / 2, tile_size), Color(1.0, 1.0, 1.0, 0.3), true); + Transform2D tile_xform; + tile_xform.set_scale(tile_size); + tile_set->draw_tile_shape(base_control, tile_xform, Color(1.0, 1.0, 1.0, 0.3), true); // Draw the background. if (background_texture.is_valid()) { @@ -213,7 +215,7 @@ void GenericTilePolygonEditor::_base_control_draw() { // Draw the tile shape line. base_control->draw_set_transform_matrix(xform); - tile_set->draw_tile_shape(base_control, Rect2(-tile_size / 2, tile_size), grid_color, false); + tile_set->draw_tile_shape(base_control, tile_xform, grid_color, false); base_control->draw_set_transform_matrix(Transform2D()); } @@ -1072,14 +1074,15 @@ void TileDataTextureOffsetEditor::draw_over_tile(CanvasItem *p_canvas_item, Tran ERR_FAIL_COND(!tile_data); Vector2i tile_set_tile_size = tile_set->get_tile_size(); - Rect2i rect = Rect2i(-tile_set_tile_size / 2, tile_set_tile_size); Color color = Color(1.0, 0.0, 0.0); if (p_selected) { Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color"); Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0); color = selection_color; } - tile_set->draw_tile_shape(p_canvas_item, p_transform.xform(rect), color); + Transform2D tile_xform; + tile_xform.set_scale(tile_set_tile_size); + tile_set->draw_tile_shape(p_canvas_item, p_transform * tile_xform, color); } void TileDataPositionEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2D p_transform, TileMapCell p_cell, bool p_selected) { @@ -1465,12 +1468,13 @@ void TileDataTerrainsEditor::_tile_set_changed() { ERR_FAIL_COND(!tile_set.is_valid()); // Fix if wrong values are selected. - if (int(dummy_object->get("terrain_set")) > tile_set->get_terrain_sets_count()) { + int terrain_set = int(dummy_object->get("terrain_set")); + if (terrain_set >= tile_set->get_terrain_sets_count()) { + terrain_set = -1; dummy_object->set("terrain_set", -1); } - int terrain_set = int(dummy_object->get("terrain")); if (terrain_set >= 0) { - if (int(dummy_object->get("terrain")) > tile_set->get_terrains_count(terrain_set)) { + if (int(dummy_object->get("terrain")) >= tile_set->get_terrains_count(terrain_set)) { dummy_object->set("terrain", -1); } } @@ -1513,9 +1517,10 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas } } else { // Draw hovered tile. - Vector2i tile_size = tile_set->get_tile_size(); - Rect2i rect = p_transform.xform(Rect2i(position - tile_size / 2, tile_size)); - tile_set->draw_tile_shape(p_canvas_item, rect, Color(1.0, 1.0, 1.0, 0.5), true); + Transform2D tile_xform; + tile_xform.set_origin(position); + tile_xform.set_scale(tile_set->get_tile_size()); + tile_set->draw_tile_shape(p_canvas_item, p_transform * tile_xform, Color(1.0, 1.0, 1.0, 0.5), true); } } } @@ -1685,9 +1690,10 @@ void TileDataTerrainsEditor::forward_draw_over_alternatives(TileAtlasView *p_til } } else { // Draw hovered tile. - Vector2i tile_size = tile_set->get_tile_size(); - Rect2i rect = p_transform.xform(Rect2i(position - tile_size / 2, tile_size)); - tile_set->draw_tile_shape(p_canvas_item, rect, Color(1.0, 1.0, 1.0, 0.5), true); + Transform2D tile_xform; + tile_xform.set_origin(position); + tile_xform.set_scale(tile_set->get_tile_size()); + tile_set->draw_tile_shape(p_canvas_item, p_transform * tile_xform, Color(1.0, 1.0, 1.0, 0.5), true); } } } diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index b5e070b4d6..acbd5d70ff 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -636,8 +636,10 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over for (int y = rect.position.y; y < rect.get_end().y; y++) { Vector2i coords = Vector2i(x, y); if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) { - Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(coords) - tile_shape_size / 2, tile_shape_size)); - tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 1.0, 1.0), false); + Transform2D tile_xform; + tile_xform.set_origin(tile_map->map_to_world(coords)); + tile_xform.set_scale(tile_shape_size); + tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0), false); } } } @@ -734,10 +736,12 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over float bottom_opacity = CLAMP(Math::inverse_lerp((float)drawn_grid_rect.size.y, (float)(drawn_grid_rect.size.y - fading), (float)pos_in_rect.y), 0.0f, 1.0f); float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f); - Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(Vector2(x, y)) - tile_shape_size / 2, tile_shape_size)); + Transform2D tile_xform; + tile_xform.set_origin(tile_map->map_to_world(Vector2(x, y))); + tile_xform.set_scale(tile_shape_size); Color color = grid_color; color.a = color.a * opacity; - tile_set->draw_tile_shape(p_overlay, cell_region, color, false); + tile_set->draw_tile_shape(p_overlay, xform * tile_xform, color, false); } } } @@ -745,11 +749,11 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Draw the preview. for (Map<Vector2i, TileMapCell>::Element *E = preview.front(); E; E = E->next()) { - Vector2i size = tile_set->get_tile_size(); - Vector2 position = tile_map->map_to_world(E->key()) - size / 2; - Rect2 cell_region = xform.xform(Rect2(position, size)); + Transform2D tile_xform; + tile_xform.set_origin(tile_map->map_to_world(E->key())); + tile_xform.set_scale(tile_set->get_tile_size()); if (!erase_button->is_pressed() && random_tile_checkbox->is_pressed()) { - tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 1.0, 1.0, 0.5), true); + tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0, 0.5), true); } else { if (tile_set->has_source(E->get().source_id)) { TileSetSource *source = *tile_set->get_source(E->get().source_id); @@ -791,10 +795,10 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Draw the tile. p_overlay->draw_texture_rect_region(atlas_source->get_texture(), dest_rect, source_rect, modulate * Color(1.0, 1.0, 1.0, 0.5), transpose, tile_set->is_uv_clipping()); } else { - tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 1.0, 1.0, 0.5), true); + tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0, 0.5), true); } } else { - tile_set->draw_tile_shape(p_overlay, cell_region, Color(0.0, 0.0, 0.0, 0.5), true); + tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(0.0, 0.0, 0.0, 0.5), true); } } } @@ -3689,8 +3693,10 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { 0.8); // Draw the scaled tile. - Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(coords) - Vector2(tile_shape_size) / 2, Vector2(tile_shape_size))); - tile_set->draw_tile_shape(p_overlay, cell_region, color, true, warning_pattern_texture); + Transform2D tile_xform; + tile_xform.set_origin(tile_map->map_to_world(coords)); + tile_xform.set_scale(tile_shape_size); + tile_set->draw_tile_shape(p_overlay, xform * tile_xform, color, true, warning_pattern_texture); } // Draw the warning icon. @@ -3746,10 +3752,12 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { float bottom_opacity = CLAMP(Math::inverse_lerp((float)displayed_rect.size.y, (float)(displayed_rect.size.y - fading), (float)pos_in_rect.y), 0.0f, 1.0f); float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f); - Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(Vector2(x, y)) - tile_shape_size / 2, tile_shape_size)); + Transform2D tile_xform; + tile_xform.set_origin(tile_map->map_to_world(Vector2(x, y))); + tile_xform.set_scale(tile_shape_size); Color color = grid_color; color.a = color.a * opacity; - tile_set->draw_tile_shape(p_overlay, cell_region, color, false); + tile_set->draw_tile_shape(p_overlay, xform * tile_xform, color, false); } } } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 50808a25af..aaa085675c 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -4042,7 +4042,7 @@ VisualShaderEditor::VisualShaderEditor() { graph->get_zoom_hbox()->add_child(add_node); add_node->set_text(TTR("Add Node...")); graph->get_zoom_hbox()->move_child(add_node, 0); - add_node->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_members_dialog), varray(false)); + add_node->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_members_dialog), varray(false, VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PORT_TYPE_MAX)); preview_shader = memnew(Button); preview_shader->set_flat(true); diff --git a/editor/pot_generator.cpp b/editor/pot_generator.cpp index b58b7e4cac..d57345cac1 100644 --- a/editor/pot_generator.cpp +++ b/editor/pot_generator.cpp @@ -108,7 +108,6 @@ void POTGenerator::_write_to_pot(const String &p_file) { const String header = "# LANGUAGE translation for " + project_name + " for the following files:\n" + extracted_files + "#\n" - "#\n" "# FIRST AUTHOR < EMAIL @ADDRESS>, YEAR.\n" "#\n" "#, fuzzy\n" @@ -116,8 +115,9 @@ void POTGenerator::_write_to_pot(const String &p_file) { "msgstr \"\"\n" "\"Project-Id-Version: " + project_name + "\\n\"\n" + "\"MIME-Version: 1.0\\n\"\n" "\"Content-Type: text/plain; charset=UTF-8\\n\"\n" - "\"Content-Transfer-Encoding: 8-bit\\n\"\n\n"; + "\"Content-Transfer-Encoding: 8-bit\\n\"\n"; file->store_string(header); @@ -129,6 +129,9 @@ void POTGenerator::_write_to_pot(const String &p_file) { String plural = v_msgid_data[i].plural; const Set<String> &locations = v_msgid_data[i].locations; + // Put the blank line at the start, to avoid a double at the end when closing the file. + file->store_line(""); + // Write file locations. for (Set<String>::Element *E = locations.front(); E; E = E->next()) { file->store_line("#: " + E->get().trim_prefix("res://")); @@ -142,13 +145,13 @@ void POTGenerator::_write_to_pot(const String &p_file) { // Write msgid. _write_msgid(file, msgid, false); - // Write msgid_plural + // Write msgid_plural. if (!plural.is_empty()) { _write_msgid(file, plural, true); file->store_line("msgstr[0] \"\""); - file->store_line("msgstr[1] \"\"\n"); + file->store_line("msgstr[1] \"\""); } else { - file->store_line("msgstr \"\"\n"); + file->store_line("msgstr \"\""); } } } diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 05cf3791f4..81554c9550 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -2051,6 +2051,10 @@ void ProjectManager::_open_selected_projects() { args.push_back("--disable-crash-handler"); } + if (OS::get_singleton()->is_single_window()) { + args.push_back("--single-window"); + } + String exec = OS::get_singleton()->get_executable_path(); Error err = OS::get_singleton()->create_process(exec, args); ERR_FAIL_COND(err); diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index d86e2656d4..9063b5c6f8 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -30,23 +30,19 @@ #include "rename_dialog.h" +#ifdef MODULE_REGEX_ENABLED + #include "core/string/print_string.h" #include "editor_node.h" #include "editor_scale.h" #include "editor_settings.h" #include "editor_themes.h" +#include "modules/regex/regex.h" #include "plugins/script_editor_plugin.h" #include "scene/gui/control.h" #include "scene/gui/label.h" #include "scene/gui/tab_container.h" -#include "modules/modules_enabled.gen.h" -#ifdef MODULE_REGEX_ENABLED -#include "modules/regex/regex.h" -#else -#error "Can't build editor rename dialog without RegEx module." -#endif - RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_undo_redo) { scene_tree_editor = p_scene_tree_editor; undo_redo = p_undo_redo; @@ -655,3 +651,5 @@ void RenameDialog::_features_toggled(bool pressed) { size.y = 0; set_size(size); } + +#endif // MODULE_REGEX_ENABLED diff --git a/editor/rename_dialog.h b/editor/rename_dialog.h index 76e99e3b66..7990862b37 100644 --- a/editor/rename_dialog.h +++ b/editor/rename_dialog.h @@ -31,6 +31,9 @@ #ifndef RENAME_DIALOG_H #define RENAME_DIALOG_H +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_REGEX_ENABLED + #include "scene/gui/check_box.h" #include "scene/gui/dialogs.h" #include "scene/gui/option_button.h" @@ -113,4 +116,6 @@ public: ~RenameDialog() {} }; -#endif +#endif // MODULE_REGEX_ENABLED + +#endif // RENAME_DIALOG_H diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 2ec4a088a2..4bc0905163 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -83,10 +83,12 @@ void SceneTreeDock::unhandled_key_input(const Ref<InputEvent> &p_event) { return; } - if (ED_IS_SHORTCUT("scene_tree/batch_rename", p_event)) { - _tool_selected(TOOL_BATCH_RENAME); - } else if (ED_IS_SHORTCUT("scene_tree/rename", p_event)) { + if (ED_IS_SHORTCUT("scene_tree/rename", p_event)) { _tool_selected(TOOL_RENAME); +#ifdef MODULE_REGEX_ENABLED + } else if (ED_IS_SHORTCUT("scene_tree/batch_rename", p_event)) { + _tool_selected(TOOL_BATCH_RENAME); +#endif // MODULE_REGEX_ENABLED } else if (ED_IS_SHORTCUT("scene_tree/add_child_node", p_event)) { _tool_selected(TOOL_NEW); } else if (ED_IS_SHORTCUT("scene_tree/instance_scene", p_event)) { @@ -336,6 +338,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { current_option = p_tool; switch (p_tool) { +#ifdef MODULE_REGEX_ENABLED case TOOL_BATCH_RENAME: { if (!profile_allow_editing) { break; @@ -344,6 +347,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { rename_dialog->popup_centered(); } } break; +#endif // MODULE_REGEX_ENABLED case TOOL_RENAME: { if (!profile_allow_editing) { break; @@ -2807,11 +2811,13 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { } } +#ifdef MODULE_REGEX_ENABLED if (profile_allow_editing && selection.size() > 1) { //this is not a commonly used action, it makes no sense for it to be where it was nor always present. menu->add_separator(); menu->add_icon_shortcut(get_theme_icon(SNAME("Rename"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME); } +#endif // MODULE_REGEX_ENABLED menu->add_separator(); menu->add_icon_item(get_theme_icon(SNAME("Help"), SNAME("EditorIcons")), TTR("Open Documentation"), TOOL_OPEN_DOCUMENTATION); @@ -2837,6 +2843,11 @@ void SceneTreeDock::set_filter(const String &p_filter) { scene_tree->set_filter(p_filter); } +void SceneTreeDock::save_branch_to_file(String p_directory) { + new_scene_from_dialog->set_current_dir(p_directory); + _tool_selected(TOOL_NEW_SCENE_FROM); +} + void SceneTreeDock::_focus_node() { Node *node = scene_tree->get_selected(); ERR_FAIL_COND(!node); @@ -3316,8 +3327,10 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel create_dialog->connect("create", callable_mp(this, &SceneTreeDock::_create)); create_dialog->connect("favorites_updated", callable_mp(this, &SceneTreeDock::_update_create_root_dialog)); +#ifdef MODULE_REGEX_ENABLED rename_dialog = memnew(RenameDialog(scene_tree, &editor_data->get_undo_redo())); add_child(rename_dialog); +#endif // MODULE_REGEX_ENABLED script_create_dialog = memnew(ScriptCreateDialog); script_create_dialog->set_inheritance_base_type("Node"); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 387a35acbb..ece0ca5ca4 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -62,7 +62,9 @@ class SceneTreeDock : public VBoxContainer { TOOL_COPY, TOOL_PASTE, TOOL_RENAME, +#ifdef MODULE_REGEX_ENABLED TOOL_BATCH_RENAME, +#endif // MODULE_REGEX_ENABLED TOOL_REPLACE, TOOL_EXTEND_SCRIPT, TOOL_ATTACH_SCRIPT, @@ -105,7 +107,9 @@ class SceneTreeDock : public VBoxContainer { int current_option; CreateDialog *create_dialog; +#ifdef MODULE_REGEX_ENABLED RenameDialog *rename_dialog; +#endif // MODULE_REGEX_ENABLED Button *button_add; Button *button_instance; @@ -269,6 +273,7 @@ protected: public: String get_filter(); void set_filter(const String &p_filter); + void save_branch_to_file(String p_directory); void _focus_node(); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index e7ba80677d..d54bf73028 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -291,10 +291,12 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll } } + // Display the node name in all tooltips so that long node names can be previewed + // without having to rename them. if (p_node == get_scene_node() && p_node->get_scene_inherited_state().is_valid()) { item->add_button(0, get_theme_icon(SNAME("InstanceOptions"), SNAME("EditorIcons")), BUTTON_SUBSCENE, false, TTR("Open in Editor")); - String tooltip = TTR("Inherits:") + " " + p_node->get_scene_inherited_state()->get_path() + "\n" + TTR("Type:") + " " + p_node->get_class(); + String tooltip = String(p_node->get_name()) + "\n" + TTR("Inherits:") + " " + p_node->get_scene_inherited_state()->get_path() + "\n" + TTR("Type:") + " " + p_node->get_class(); if (p_node->get_editor_description() != String()) { tooltip += "\n\n" + p_node->get_editor_description(); } @@ -303,7 +305,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll } else if (p_node != get_scene_node() && p_node->get_filename() != "" && can_open_instance) { item->add_button(0, get_theme_icon(SNAME("InstanceOptions"), SNAME("EditorIcons")), BUTTON_SUBSCENE, false, TTR("Open in Editor")); - String tooltip = TTR("Instance:") + " " + p_node->get_filename() + "\n" + TTR("Type:") + " " + p_node->get_class(); + String tooltip = String(p_node->get_name()) + "\n" + TTR("Instance:") + " " + p_node->get_filename() + "\n" + TTR("Type:") + " " + p_node->get_class(); if (p_node->get_editor_description() != String()) { tooltip += "\n\n" + p_node->get_editor_description(); } @@ -315,7 +317,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll type = p_node->get_class(); } - String tooltip = TTR("Type:") + " " + type; + String tooltip = String(p_node->get_name()) + "\n" + TTR("Type:") + " " + type; if (p_node->get_editor_description() != String()) { tooltip += "\n\n" + p_node->get_editor_description(); } diff --git a/editor/translations/el.po b/editor/translations/el.po index e773b011a4..93b5941f64 100644 --- a/editor/translations/el.po +++ b/editor/translations/el.po @@ -6,7 +6,7 @@ # Georgios Katsanakis <geo.elgeo@gmail.com>, 2019. # Overloaded <manoschool@yahoo.gr>, 2019. # Eternal Death <eternaldeath0001@gmail.com>, 2019. -# Overloaded @ Orama Interactive https://orama-interactive.com/ <manoschool@yahoo.gr>, 2020. +# Overloaded @ Orama Interactive http://orama-interactive.com/ <manoschool@yahoo.gr>, 2020. # pandektis <pandektis@gmail.com>, 2020. # KostasMSC <kargyris@athtech.gr>, 2020. # lawfulRobot <czavantias@gmail.com>, 2020, 2021. |