diff options
Diffstat (limited to 'editor')
93 files changed, 1702 insertions, 1254 deletions
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index 7cfedffcbf..b6348c5952 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -66,6 +66,14 @@ String InputEventConfigurationDialog::get_event_text(const Ref<InputEvent> &p_ev String text = p_event->as_text(); + Ref<InputEventKey> key = p_event; + if (key.is_valid() && key->is_command_or_control_autoremap()) { +#ifdef MACOS_ENABLED + text = text.replace("Command", "Command/Ctrl"); +#else + text = text.replace("Ctrl", "Command/Ctrl"); +#endif + } Ref<InputEventMouse> mouse = p_event; Ref<InputEventJoypadMotion> jp_motion = p_event; Ref<InputEventJoypadButton> jp_button = p_event; @@ -108,11 +116,10 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event, b show_mods = true; mod_checkboxes[MOD_ALT]->set_pressed(mod->is_alt_pressed()); mod_checkboxes[MOD_SHIFT]->set_pressed(mod->is_shift_pressed()); - mod_checkboxes[MOD_COMMAND]->set_pressed(mod->is_command_pressed()); mod_checkboxes[MOD_CTRL]->set_pressed(mod->is_ctrl_pressed()); mod_checkboxes[MOD_META]->set_pressed(mod->is_meta_pressed()); - store_command_checkbox->set_pressed(mod->is_storing_command()); + autoremap_command_or_control_checkbox->set_pressed(mod->is_command_or_control_autoremap()); } if (k.is_valid()) { @@ -287,8 +294,6 @@ void InputEventConfigurationDialog::_listen_window_input(const Ref<InputEvent> & Ref<InputEventWithModifiers> mod = received_event; if (mod.is_valid()) { - // Maintain store command option state - mod->set_store_command(store_command_checkbox->is_pressed()); mod->set_window_id(0); } @@ -419,41 +424,31 @@ void InputEventConfigurationDialog::_mod_toggled(bool p_checked, int p_index) { } else if (p_index == 1) { ie->set_shift_pressed(p_checked); } else if (p_index == 2) { - ie->set_command_pressed(p_checked); + if (!autoremap_command_or_control_checkbox->is_pressed()) { + ie->set_ctrl_pressed(p_checked); + } } else if (p_index == 3) { - ie->set_ctrl_pressed(p_checked); - } else if (p_index == 4) { - ie->set_meta_pressed(p_checked); + if (!autoremap_command_or_control_checkbox->is_pressed()) { + ie->set_meta_pressed(p_checked); + } } _set_event(ie); } -void InputEventConfigurationDialog::_store_command_toggled(bool p_checked) { +void InputEventConfigurationDialog::_autoremap_command_or_control_toggled(bool p_checked) { Ref<InputEventWithModifiers> ie = event; if (ie.is_valid()) { - ie->set_store_command(p_checked); + ie->set_command_or_control_autoremap(p_checked); _set_event(ie); } if (p_checked) { - // If storing Command, show it's checkbox and hide Control (Win/Lin) or Meta (Mac) -#ifdef APPLE_STYLE_KEYS mod_checkboxes[MOD_META]->hide(); - - mod_checkboxes[MOD_COMMAND]->show(); - mod_checkboxes[MOD_COMMAND]->set_text("Meta (Command)"); -#else mod_checkboxes[MOD_CTRL]->hide(); - - mod_checkboxes[MOD_COMMAND]->show(); - mod_checkboxes[MOD_COMMAND]->set_text("Control (Command)"); -#endif } else { - // If not, hide Command, show Control and Meta. - mod_checkboxes[MOD_COMMAND]->hide(); - mod_checkboxes[MOD_CTRL]->show(); mod_checkboxes[MOD_META]->show(); + mod_checkboxes[MOD_CTRL]->show(); } } @@ -502,10 +497,12 @@ void InputEventConfigurationDialog::_input_list_item_selected() { // Maintain modifier state from checkboxes k->set_alt_pressed(mod_checkboxes[MOD_ALT]->is_pressed()); k->set_shift_pressed(mod_checkboxes[MOD_SHIFT]->is_pressed()); - k->set_command_pressed(mod_checkboxes[MOD_COMMAND]->is_pressed()); - k->set_ctrl_pressed(mod_checkboxes[MOD_CTRL]->is_pressed()); - k->set_meta_pressed(mod_checkboxes[MOD_META]->is_pressed()); - k->set_store_command(store_command_checkbox->is_pressed()); + if (autoremap_command_or_control_checkbox->is_pressed()) { + k->set_command_or_control_autoremap(true); + } else { + k->set_ctrl_pressed(mod_checkboxes[MOD_CTRL]->is_pressed()); + k->set_meta_pressed(mod_checkboxes[MOD_META]->is_pressed()); + } _set_event(k, false); } break; @@ -517,10 +514,12 @@ void InputEventConfigurationDialog::_input_list_item_selected() { // Maintain modifier state from checkboxes mb->set_alt_pressed(mod_checkboxes[MOD_ALT]->is_pressed()); mb->set_shift_pressed(mod_checkboxes[MOD_SHIFT]->is_pressed()); - mb->set_command_pressed(mod_checkboxes[MOD_COMMAND]->is_pressed()); - mb->set_ctrl_pressed(mod_checkboxes[MOD_CTRL]->is_pressed()); - mb->set_meta_pressed(mod_checkboxes[MOD_META]->is_pressed()); - mb->set_store_command(store_command_checkbox->is_pressed()); + if (autoremap_command_or_control_checkbox->is_pressed()) { + mb->set_command_or_control_autoremap(true); + } else { + mb->set_ctrl_pressed(mod_checkboxes[MOD_CTRL]->is_pressed()); + mb->set_meta_pressed(mod_checkboxes[MOD_META]->is_pressed()); + } // Maintain selected device mb->set_device(_get_current_device()); @@ -611,7 +610,7 @@ void InputEventConfigurationDialog::popup_and_configure(const Ref<InputEvent> &p // This is especially important for WASD movement layouts. physical_key_checkbox->set_pressed(true); - store_command_checkbox->set_pressed(true); + autoremap_command_or_control_checkbox->set_pressed(false); _set_current_device(0); // Switch to "Listen" tab @@ -722,21 +721,18 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() { mod_checkboxes[i] = memnew(CheckBox); mod_checkboxes[i]->connect("toggled", callable_mp(this, &InputEventConfigurationDialog::_mod_toggled).bind(i)); mod_checkboxes[i]->set_text(name); + mod_checkboxes[i]->set_tooltip_text(TTR(mods_tip[i])); mod_container->add_child(mod_checkboxes[i]); } mod_container->add_child(memnew(VSeparator)); - store_command_checkbox = memnew(CheckBox); - store_command_checkbox->connect("toggled", callable_mp(this, &InputEventConfigurationDialog::_store_command_toggled)); - store_command_checkbox->set_pressed(true); - store_command_checkbox->set_text(TTR("Store Command")); -#ifdef APPLE_STYLE_KEYS - store_command_checkbox->set_tooltip_text(TTR("Toggles between serializing 'command' and 'meta'. Used for compatibility with Windows/Linux style keyboard.")); -#else - store_command_checkbox->set_tooltip_text(TTR("Toggles between serializing 'command' and 'control'. Used for compatibility with Apple Style keyboards.")); -#endif - mod_container->add_child(store_command_checkbox); + autoremap_command_or_control_checkbox = memnew(CheckBox); + autoremap_command_or_control_checkbox->connect("toggled", callable_mp(this, &InputEventConfigurationDialog::_autoremap_command_or_control_toggled)); + autoremap_command_or_control_checkbox->set_pressed(false); + autoremap_command_or_control_checkbox->set_text(TTR("Command / Control (auto)")); + autoremap_command_or_control_checkbox->set_tooltip_text(TTR("Automatically remaps between 'Meta' ('Command') and 'Control' depending on current platform.")); + mod_container->add_child(autoremap_command_or_control_checkbox); mod_container->hide(); additional_options_container->add_child(mod_container); diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h index 1ca3c5bac0..36d21fe258 100644 --- a/editor/action_map_editor.h +++ b/editor/action_map_editor.h @@ -85,15 +85,21 @@ private: enum ModCheckbox { MOD_ALT, MOD_SHIFT, - MOD_COMMAND, MOD_CTRL, MOD_META, MOD_MAX }; - String mods[MOD_MAX] = { "Alt", "Shift", "Command", "Ctrl", "Metakey" }; +#if defined(MACOS_ENABLED) + String mods[MOD_MAX] = { "Option", "Shift", "Ctrl", "Command" }; +#elif defined(WINDOWS_ENABLED) + String mods[MOD_MAX] = { "Alt", "Shift", "Ctrl", "Windows" }; +#else + String mods[MOD_MAX] = { "Alt", "Shift", "Ctrl", "Meta" }; +#endif + String mods_tip[MOD_MAX] = { "Alt or Option key", "Shift key", "Control key", "Meta/Windows or Command key" }; CheckBox *mod_checkboxes[MOD_MAX]; - CheckBox *store_command_checkbox = nullptr; + CheckBox *autoremap_command_or_control_checkbox = nullptr; CheckBox *physical_key_checkbox = nullptr; @@ -107,7 +113,7 @@ private: void _input_list_item_selected(); void _mod_toggled(bool p_checked, int p_index); - void _store_command_toggled(bool p_checked); + void _autoremap_command_or_control_toggled(bool p_checked); void _physical_keycode_toggled(bool p_checked); void _device_selection_changed(int p_option_button_index); diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 0183d08733..219f3fdbe1 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -1088,7 +1088,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { //first check point //command makes it ignore the main point, so control point editors can be force-edited //path 2D editing in the 3D and 2D editors works the same way - if (!mb->is_command_pressed()) { + if (!mb->is_command_or_control_pressed()) { if (edit_points[i].point_rect.has_point(mb->get_position())) { IntPair pair = IntPair(edit_points[i].track, edit_points[i].key); if (mb->is_shift_pressed()) { @@ -1152,7 +1152,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } //insert new point - if (mb->get_position().x >= limit && mb->get_position().x < get_size().width && mb->is_command_pressed()) { + if (mb->get_position().x >= limit && mb->get_position().x < get_size().width && mb->is_command_or_control_pressed()) { Array new_point; new_point.resize(5); @@ -1684,8 +1684,8 @@ AnimationBezierTrackEdit::AnimationBezierTrackEdit() { set_clip_contents(true); ED_SHORTCUT("animation_bezier_editor/focus", TTR("Focus"), Key::F); - ED_SHORTCUT("animation_bezier_editor/select_all_keys", TTR("Select All Keys"), KeyModifierMask::CMD | Key::A); - ED_SHORTCUT("animation_bezier_editor/deselect_all_keys", TTR("Deselect All Keys"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::A); + ED_SHORTCUT("animation_bezier_editor/select_all_keys", TTR("Select All Keys"), KeyModifierMask::CMD_OR_CTRL | Key::A); + ED_SHORTCUT("animation_bezier_editor/deselect_all_keys", TTR("Deselect All Keys"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::A); menu = memnew(PopupMenu); add_child(menu); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 4991b2cfaf..70b5501692 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -52,13 +52,9 @@ public: bool setting = false; bool animation_read_only = false; - bool _hide_script_from_inspector() { - return true; - } - - bool _dont_undo_redo() { - return true; - } + bool _hide_script_from_inspector() { return true; } + bool _hide_metadata_from_inspector() { return true; } + bool _dont_undo_redo() { return true; } bool _is_read_only() { return animation_read_only; @@ -68,6 +64,7 @@ public: ClassDB::bind_method(D_METHOD("_update_obj"), &AnimationTrackKeyEdit::_update_obj); ClassDB::bind_method(D_METHOD("_key_ofs_changed"), &AnimationTrackKeyEdit::_key_ofs_changed); ClassDB::bind_method(D_METHOD("_hide_script_from_inspector"), &AnimationTrackKeyEdit::_hide_script_from_inspector); + ClassDB::bind_method(D_METHOD("_hide_metadata_from_inspector"), &AnimationTrackKeyEdit::_hide_metadata_from_inspector); ClassDB::bind_method(D_METHOD("get_root_path"), &AnimationTrackKeyEdit::get_root_path); ClassDB::bind_method(D_METHOD("_dont_undo_redo"), &AnimationTrackKeyEdit::_dont_undo_redo); ClassDB::bind_method(D_METHOD("_is_read_only"), &AnimationTrackKeyEdit::_is_read_only); @@ -719,13 +716,9 @@ public: bool setting = false; bool animation_read_only = false; - bool _hide_script_from_inspector() { - return true; - } - - bool _dont_undo_redo() { - return true; - } + bool _hide_script_from_inspector() { return true; } + bool _hide_metadata_from_inspector() { return true; } + bool _dont_undo_redo() { return true; } bool _is_read_only() { return animation_read_only; @@ -735,6 +728,7 @@ public: ClassDB::bind_method(D_METHOD("_update_obj"), &AnimationMultiTrackKeyEdit::_update_obj); ClassDB::bind_method(D_METHOD("_key_ofs_changed"), &AnimationMultiTrackKeyEdit::_key_ofs_changed); ClassDB::bind_method(D_METHOD("_hide_script_from_inspector"), &AnimationMultiTrackKeyEdit::_hide_script_from_inspector); + ClassDB::bind_method(D_METHOD("_hide_metadata_from_inspector"), &AnimationMultiTrackKeyEdit::_hide_metadata_from_inspector); ClassDB::bind_method(D_METHOD("get_root_path"), &AnimationMultiTrackKeyEdit::get_root_path); ClassDB::bind_method(D_METHOD("_dont_undo_redo"), &AnimationMultiTrackKeyEdit::_dont_undo_redo); ClassDB::bind_method(D_METHOD("_is_read_only"), &AnimationMultiTrackKeyEdit::_is_read_only); @@ -2417,7 +2411,7 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool draw_texture( icon_to_draw, ofs, - p_index == hovering_key_idx ? get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog")) : Color(1, 1, 1)); + p_index == hovering_key_idx ? get_theme_color(SNAME("folder_icon_color"), SNAME("FileDialog")) : Color(1, 1, 1)); } // Helper. @@ -2936,7 +2930,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } if (key_idx != -1) { - if (mb->is_command_pressed() || mb->is_shift_pressed()) { + if (mb->is_command_or_control_pressed() || mb->is_shift_pressed()) { if (editor->is_key_selected(track, key_idx)) { emit_signal(SNAME("deselect_key"), key_idx); } else { @@ -3524,7 +3518,7 @@ void AnimationTrackEditor::set_root(Node *p_root) { root = p_root; if (root) { - root->connect("tree_exiting", callable_mp(this, &AnimationTrackEditor::_root_removed), CONNECT_ONESHOT); + root->connect("tree_exiting", callable_mp(this, &AnimationTrackEditor::_root_removed), CONNECT_ONE_SHOT); } _update_tracks(); @@ -4772,7 +4766,7 @@ void AnimationTrackEditor::_notification(int p_what) { view_group->set_icon(get_theme_icon(view_group->is_pressed() ? SNAME("AnimationTrackList") : SNAME("AnimationTrackGroup"), SNAME("EditorIcons"))); selected_filter->set_icon(get_theme_icon(SNAME("AnimationFilter"), SNAME("EditorIcons"))); imported_anim_warning->set_icon(get_theme_icon(SNAME("NodeWarning"), SNAME("EditorIcons"))); - main_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + main_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); edit->get_popup()->set_item_icon(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); } break; @@ -5474,7 +5468,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) { for (int i = 0; i < track_edits.size(); i++) { Rect2 local_rect = box_select_rect; local_rect.position -= track_edits[i]->get_global_position(); - track_edits[i]->append_to_selection(local_rect, mb->is_command_pressed()); + track_edits[i]->append_to_selection(local_rect, mb->is_command_or_control_pressed()); } if (_get_track_selected() == -1 && track_edits.size() > 0) { // Minimal hack to make shortcuts work. @@ -5500,7 +5494,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) { } if (!box_selection->is_visible_in_tree()) { - if (!mm->is_command_pressed() && !mm->is_shift_pressed()) { + if (!mm->is_command_or_control_pressed() && !mm->is_shift_pressed()) { _clear_selection(true); } box_selection->show(); @@ -6714,15 +6708,15 @@ AnimationTrackEditor::AnimationTrackEditor() { edit->get_popup()->add_separator(); edit->get_popup()->add_item(TTR("Make Easing Selection"), EDIT_EASE_SELECTION); edit->get_popup()->add_separator(); - edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/duplicate_selection", TTR("Duplicate Selection"), KeyModifierMask::CMD | Key::D), EDIT_DUPLICATE_SELECTION); - edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/duplicate_selection_transposed", TTR("Duplicate Transposed"), KeyModifierMask::SHIFT | KeyModifierMask::CMD | Key::D), EDIT_DUPLICATE_TRANSPOSED); + edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/duplicate_selection", TTR("Duplicate Selection"), KeyModifierMask::CMD_OR_CTRL | Key::D), EDIT_DUPLICATE_SELECTION); + edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/duplicate_selection_transposed", TTR("Duplicate Transposed"), KeyModifierMask::SHIFT | KeyModifierMask::CMD_OR_CTRL | Key::D), EDIT_DUPLICATE_TRANSPOSED); edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/add_reset_value", TTR("Add RESET Value(s)"))); edit->get_popup()->add_separator(); edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/delete_selection", TTR("Delete Selection"), Key::KEY_DELETE), EDIT_DELETE_SELECTION); edit->get_popup()->add_separator(); - edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_next_step", TTR("Go to Next Step"), KeyModifierMask::CMD | Key::RIGHT), EDIT_GOTO_NEXT_STEP); - edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_prev_step", TTR("Go to Previous Step"), KeyModifierMask::CMD | Key::LEFT), EDIT_GOTO_PREV_STEP); + edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_next_step", TTR("Go to Next Step"), KeyModifierMask::CMD_OR_CTRL | Key::RIGHT), EDIT_GOTO_NEXT_STEP); + edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_prev_step", TTR("Go to Previous Step"), KeyModifierMask::CMD_OR_CTRL | Key::LEFT), EDIT_GOTO_PREV_STEP); edit->get_popup()->add_separator(); edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/apply_reset", TTR("Apply Reset")), EDIT_APPLY_RESET); edit->get_popup()->add_separator(); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 2d5e70e1ff..11a6912aa5 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -800,7 +800,7 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->is_pressed() && mb->is_command_pressed()) { + if (mb->is_pressed() && mb->is_command_or_control_pressed()) { if (mb->get_button_index() == MouseButton::WHEEL_UP) { _zoom_in(); } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN) { @@ -1001,7 +1001,7 @@ void CodeTextEditor::update_editor_settings() { // Appearance: Caret text_editor->set_caret_type((TextEdit::CaretType)EditorSettings::get_singleton()->get("text_editor/appearance/caret/type").operator int()); text_editor->set_caret_blink_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/caret/caret_blink")); - text_editor->set_caret_blink_speed(EditorSettings::get_singleton()->get("text_editor/appearance/caret/caret_blink_speed")); + text_editor->set_caret_blink_interval(EditorSettings::get_singleton()->get("text_editor/appearance/caret/caret_blink_interval")); text_editor->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/appearance/caret/highlight_current_line")); text_editor->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/appearance/caret/highlight_all_occurrences")); @@ -1867,10 +1867,10 @@ void CodeTextEditor::update_toggle_scripts_button() { CodeTextEditor::CodeTextEditor() { code_complete_func = nullptr; - ED_SHORTCUT("script_editor/zoom_in", TTR("Zoom In"), KeyModifierMask::CMD | Key::EQUAL); - ED_SHORTCUT("script_editor/zoom_out", TTR("Zoom Out"), KeyModifierMask::CMD | Key::MINUS); + ED_SHORTCUT("script_editor/zoom_in", TTR("Zoom In"), KeyModifierMask::CMD_OR_CTRL | Key::EQUAL); + ED_SHORTCUT("script_editor/zoom_out", TTR("Zoom Out"), KeyModifierMask::CMD_OR_CTRL | Key::MINUS); ED_SHORTCUT_ARRAY("script_editor/reset_zoom", TTR("Reset Zoom"), - { int32_t(KeyModifierMask::CMD | Key::KEY_0), int32_t(KeyModifierMask::CMD | Key::KP_0) }); + { int32_t(KeyModifierMask::CMD_OR_CTRL | Key::KEY_0), int32_t(KeyModifierMask::CMD_OR_CTRL | Key::KP_0) }); text_editor = memnew(CodeEdit); add_child(text_editor); diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index dce9ca2b93..861d05f17a 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -289,8 +289,8 @@ bool ConnectDialog::get_deferred() const { return deferred->is_pressed(); } -bool ConnectDialog::get_oneshot() const { - return oneshot->is_pressed(); +bool ConnectDialog::get_one_shot() const { + return one_shot->is_pressed(); } /* @@ -322,10 +322,10 @@ void ConnectDialog::init(ConnectionData p_cd, bool p_edit) { _update_ok_enabled(); bool b_deferred = (p_cd.flags & CONNECT_DEFERRED) == CONNECT_DEFERRED; - bool b_oneshot = (p_cd.flags & CONNECT_ONESHOT) == CONNECT_ONESHOT; + bool b_oneshot = (p_cd.flags & CONNECT_ONE_SHOT) == CONNECT_ONE_SHOT; deferred->set_pressed(b_deferred); - oneshot->set_pressed(b_oneshot); + one_shot->set_pressed(b_oneshot); MethodInfo r_signal; Ref<Script> source_script = source->get_script(); @@ -484,11 +484,11 @@ ConnectDialog::ConnectDialog() { deferred->set_tooltip_text(TTR("Defers the signal, storing it in a queue and only firing it at idle time.")); vbc_right->add_child(deferred); - oneshot = memnew(CheckBox); - oneshot->set_h_size_flags(0); - oneshot->set_text(TTR("Oneshot")); - oneshot->set_tooltip_text(TTR("Disconnects the signal after its first emission.")); - vbc_right->add_child(oneshot); + one_shot = memnew(CheckBox); + one_shot->set_h_size_flags(0); + one_shot->set_text(TTR("Oneshot")); + one_shot->set_tooltip_text(TTR("Disconnects the signal after its first emission.")); + vbc_right->add_child(one_shot); cdbinds = memnew(ConnectDialogBinds); @@ -564,8 +564,8 @@ void ConnectionsDock::_make_or_edit_connection() { cd.binds = connect_dialog->get_binds(); } bool b_deferred = connect_dialog->get_deferred(); - bool b_oneshot = connect_dialog->get_oneshot(); - cd.flags = CONNECT_PERSIST | (b_deferred ? CONNECT_DEFERRED : 0) | (b_oneshot ? CONNECT_ONESHOT : 0); + bool b_oneshot = connect_dialog->get_one_shot(); + cd.flags = CONNECT_PERSIST | (b_deferred ? CONNECT_DEFERRED : 0) | (b_oneshot ? CONNECT_ONE_SHOT : 0); // Conditions to add function: must have a script and must not have the method already // (in the class, the script itself, or inherited). @@ -1083,8 +1083,8 @@ void ConnectionsDock::update_tree() { if (cd.flags & CONNECT_DEFERRED) { path += " (deferred)"; } - if (cd.flags & CONNECT_ONESHOT) { - path += " (oneshot)"; + if (cd.flags & CONNECT_ONE_SHOT) { + path += " (one-shot)"; } if (cd.unbinds > 0) { path += " unbinds(" + itos(cd.unbinds) + ")"; diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h index 352c5c99d6..e37246e7a0 100644 --- a/editor/connections_dialog.h +++ b/editor/connections_dialog.h @@ -121,7 +121,7 @@ private: EditorInspector *bind_editor = nullptr; OptionButton *type_list = nullptr; CheckBox *deferred = nullptr; - CheckBox *oneshot = nullptr; + CheckBox *one_shot = nullptr; CheckButton *advanced = nullptr; Vector<Control *> bind_controls; @@ -153,7 +153,7 @@ public: Vector<Variant> get_binds() const; bool get_deferred() const; - bool get_oneshot() const; + bool get_one_shot() const; bool is_editing() const; void init(ConnectionData p_cd, bool p_edit = false); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 8ccfda1145..4ac32d7317 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -38,7 +38,7 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" -void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const String &p_select_type, const String &p_select_name) { +void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const String &p_current_type, const String &p_current_name) { _fill_type_list(); icon_fallback = search_options->has_theme_icon(base_type, SNAME("EditorIcons")) ? base_type : "Object"; @@ -50,18 +50,14 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const St } if (p_replace_mode) { - search_box->set_text(p_select_type); + search_box->set_text(p_current_type); } search_box->grab_focus(); _update_search(); if (p_replace_mode) { - if (!p_select_name.is_empty()) { - set_title(vformat(TTR("Convert %s from %s"), p_select_name, p_select_type)); - } else { - set_title(vformat(TTR("Convert %s"), p_select_type)); - } + set_title(vformat(TTR("Change Type of \"%s\""), p_current_name)); set_ok_button_text(TTR("Change")); } else { set_title(vformat(TTR("Create New %s"), base_type)); @@ -665,7 +661,7 @@ void CreateDialog::_save_and_update_favorite_list() { for (int i = 0; i < favorite_list.size(); i++) { String l = favorite_list[i]; String name = l.get_slicec(' ', 0); - if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) { + if (!EditorNode::get_editor_data().is_type_recognized(name)) { continue; } f->store_line(l); @@ -692,7 +688,7 @@ void CreateDialog::_load_favorites_and_history() { String l = f->get_line().strip_edges(); String name = l.get_slicec(' ', 0); - if ((ClassDB::class_exists(name) || ScriptServer::is_global_class(name)) && !_is_class_disabled_by_feature_profile(name)) { + if (EditorNode::get_editor_data().is_type_recognized(name) && !_is_class_disabled_by_feature_profile(name)) { recent->add_item(l, EditorNode::get_singleton()->get_class_icon(name, icon_fallback)); } } diff --git a/editor/create_dialog.h b/editor/create_dialog.h index f7731d2726..f2e741624f 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -120,7 +120,7 @@ public: void set_preferred_search_result_type(const String &p_preferred_type) { preferred_search_result_type = p_preferred_type; } String get_preferred_search_result_type() { return preferred_search_result_type; } - void popup_create(bool p_dont_clear, bool p_replace_mode = false, const String &p_select_type = "Node", const String &p_select_name = ""); + void popup_create(bool p_dont_clear, bool p_replace_mode = false, const String &p_current_type = "", const String &p_current_name = ""); CreateDialog(); }; diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index b1253ed7cb..09dce869c9 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -940,7 +940,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { hbc->add_child(bus_options); bus_popup = bus_options->get_popup(); - bus_popup->add_shortcut(ED_SHORTCUT("audio_bus_editor/duplicate_selected_bus", TTR("Duplicate Bus"), KeyModifierMask::CMD | Key::D)); + bus_popup->add_shortcut(ED_SHORTCUT("audio_bus_editor/duplicate_selected_bus", TTR("Duplicate Bus"), KeyModifierMask::CMD_OR_CTRL | Key::D)); bus_popup->add_shortcut(ED_SHORTCUT("audio_bus_editor/delete_selected_bus", TTR("Delete Bus"), Key::KEY_DELETE)); bus_popup->set_item_disabled(1, is_master); bus_popup->add_item(TTR("Reset Volume")); @@ -1027,7 +1027,7 @@ void EditorAudioBuses::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - bus_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + bus_scroll->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); } break; case NOTIFICATION_READY: { diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 231ae198d2..d1ea0f2814 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -509,6 +509,32 @@ Variant EditorData::instance_custom_type(const String &p_type, const String &p_i return Variant(); } +const EditorData::CustomType *EditorData::get_custom_type_by_name(const String &p_type) const { + for (const KeyValue<String, Vector<CustomType>> &E : custom_types) { + for (const CustomType &F : E.value) { + if (F.name == p_type) { + return &F; + } + } + } + return nullptr; +} + +const EditorData::CustomType *EditorData::get_custom_type_by_path(const String &p_path) const { + for (const KeyValue<String, Vector<CustomType>> &E : custom_types) { + for (const CustomType &F : E.value) { + if (F.script->get_path() == p_path) { + return &F; + } + } + } + return nullptr; +} + +bool EditorData::is_type_recognized(const String &p_type) const { + return ClassDB::class_exists(p_type) || ScriptServer::is_global_class(p_type) || get_custom_type_by_name(p_type); +} + void EditorData::remove_custom_type(const String &p_type) { for (KeyValue<String, Vector<CustomType>> &E : custom_types) { for (int i = 0; i < E.value.size(); i++) { @@ -1056,7 +1082,7 @@ void EditorSelection::add_node(Node *p_node) { } selection[p_node] = meta; - p_node->connect("tree_exiting", callable_mp(this, &EditorSelection::_node_removed).bind(p_node), CONNECT_ONESHOT); + p_node->connect("tree_exiting", callable_mp(this, &EditorSelection::_node_removed).bind(p_node), CONNECT_ONE_SHOT); } void EditorSelection::remove_node(Node *p_node) { diff --git a/editor/editor_data.h b/editor/editor_data.h index 1da188c546..4f1740d4f0 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -184,6 +184,9 @@ public: Variant instance_custom_type(const String &p_type, const String &p_inherits); void remove_custom_type(const String &p_type); const HashMap<String, Vector<CustomType>> &get_custom_types() const { return custom_types; } + const CustomType *get_custom_type_by_name(const String &p_name) const; + const CustomType *get_custom_type_by_path(const String &p_path) const; + bool is_type_recognized(const String &p_type) const; void instantiate_object_properties(Object *p_object); diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp index 3bb050ce77..f464ca3b3c 100644 --- a/editor/editor_dir_dialog.cpp +++ b/editor/editor_dir_dialog.cpp @@ -44,7 +44,7 @@ void EditorDirDialog::_update_dir(TreeItem *p_item, EditorFileSystemDirectory *p p_item->set_metadata(0, p_dir->get_path()); p_item->set_icon(0, tree->get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); - p_item->set_icon_modulate(0, tree->get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"))); + p_item->set_icon_modulate(0, tree->get_theme_color(SNAME("folder_icon_color"), SNAME("FileDialog"))); if (!p_item->get_parent()) { p_item->set_text(0, "res://"); diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index c953efc528..9fa08a0adb 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -84,7 +84,7 @@ void EditorFileDialog::_update_theme_item_cache() { theme_cache.favorites_down = get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")); theme_cache.folder = get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")); - theme_cache.folder_icon_modulate = get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog")); + theme_cache.folder_icon_color = get_theme_color(SNAME("folder_icon_color"), SNAME("FileDialog")); theme_cache.action_copy = get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")); theme_cache.action_delete = get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")); @@ -145,6 +145,8 @@ void EditorFileDialog::_notification(int p_what) { if (!is_visible()) { set_process_shortcut_input(false); } + + invalidate(); // For consistency with the standard FileDialog. } break; case NOTIFICATION_WM_WINDOW_FOCUS_IN: { @@ -304,10 +306,6 @@ void EditorFileDialog::_post_popup() { } set_current_dir(current); - if (invalidated) { - update_file_list(); - invalidated = false; - } if (mode == FILE_MODE_SAVE_FILE) { file->grab_focus(); } else { @@ -320,19 +318,13 @@ void EditorFileDialog::_post_popup() { file_box->set_visible(true); } - if (is_visible() && !get_current_file().is_empty()) { + if (!get_current_file().is_empty()) { _request_single_thumbnail(get_current_dir().path_join(get_current_file())); } - if (is_visible()) { - _update_recent(); - - local_history.clear(); - local_history_pos = -1; - _push_history(); - - _update_favorites(); - } + local_history.clear(); + local_history_pos = -1; + _push_history(); set_process_shortcut_input(true); } @@ -657,7 +649,7 @@ void EditorFileDialog::_item_list_empty_clicked(const Vector2 &p_pos, MouseButto item_menu->reset_size(); if (can_create_dir) { - item_menu->add_icon_item(theme_cache.folder, TTR("New Folder..."), ITEM_MENU_NEW_FOLDER, KeyModifierMask::CMD | Key::N); + item_menu->add_icon_item(theme_cache.folder, TTR("New Folder..."), ITEM_MENU_NEW_FOLDER, KeyModifierMask::CMD_OR_CTRL | Key::N); } item_menu->add_icon_item(theme_cache.reload, TTR("Refresh"), ITEM_MENU_REFRESH, Key::F5); item_menu->add_separator(); @@ -839,7 +831,7 @@ void EditorFileDialog::update_file_list() { d["dir"] = true; item_list->set_item_metadata(-1, d); - item_list->set_item_icon_modulate(-1, theme_cache.folder_icon_modulate); + item_list->set_item_icon_modulate(-1, theme_cache.folder_icon_color); dirs.pop_front(); } @@ -1385,7 +1377,7 @@ void EditorFileDialog::_update_favorites() { for (int i = 0; i < favorited_paths.size(); i++) { favorites->add_item(favorited_names[i], theme_cache.folder); favorites->set_item_metadata(-1, favorited_paths[i]); - favorites->set_item_icon_modulate(-1, theme_cache.folder_icon_modulate); + favorites->set_item_icon_modulate(-1, theme_cache.folder_icon_color); if (i == current_favorite) { favorite->set_pressed(true); @@ -1468,7 +1460,7 @@ void EditorFileDialog::_update_recent() { for (int i = 0; i < recentd_paths.size(); i++) { recent->add_item(recentd_names[i], theme_cache.folder); recent->set_item_metadata(-1, recentd_paths[i]); - recent->set_item_icon_modulate(-1, theme_cache.folder_icon_modulate); + recent->set_item_icon_modulate(-1, theme_cache.folder_icon_color); } EditorSettings::get_singleton()->set_recent_dirs(recentd); } @@ -1672,14 +1664,14 @@ EditorFileDialog::EditorFileDialog() { ED_SHORTCUT("file_dialog/go_forward", TTR("Go Forward"), KeyModifierMask::ALT | Key::RIGHT); ED_SHORTCUT("file_dialog/go_up", TTR("Go Up"), KeyModifierMask::ALT | Key::UP); ED_SHORTCUT("file_dialog/refresh", TTR("Refresh"), Key::F5); - ED_SHORTCUT("file_dialog/toggle_hidden_files", TTR("Toggle Hidden Files"), KeyModifierMask::CMD | Key::H); + ED_SHORTCUT("file_dialog/toggle_hidden_files", TTR("Toggle Hidden Files"), KeyModifierMask::CMD_OR_CTRL | Key::H); ED_SHORTCUT("file_dialog/toggle_favorite", TTR("Toggle Favorite"), KeyModifierMask::ALT | Key::F); ED_SHORTCUT("file_dialog/toggle_mode", TTR("Toggle Mode"), KeyModifierMask::ALT | Key::V); - ED_SHORTCUT("file_dialog/create_folder", TTR("Create Folder"), KeyModifierMask::CMD | Key::N); + ED_SHORTCUT("file_dialog/create_folder", TTR("Create Folder"), KeyModifierMask::CMD_OR_CTRL | Key::N); ED_SHORTCUT("file_dialog/delete", TTR("Delete"), Key::KEY_DELETE); - ED_SHORTCUT("file_dialog/focus_path", TTR("Focus Path"), KeyModifierMask::CMD | Key::D); - ED_SHORTCUT("file_dialog/move_favorite_up", TTR("Move Favorite Up"), KeyModifierMask::CMD | Key::UP); - ED_SHORTCUT("file_dialog/move_favorite_down", TTR("Move Favorite Down"), KeyModifierMask::CMD | Key::DOWN); + ED_SHORTCUT("file_dialog/focus_path", TTR("Focus Path"), KeyModifierMask::CMD_OR_CTRL | Key::D); + ED_SHORTCUT("file_dialog/move_favorite_up", TTR("Move Favorite Up"), KeyModifierMask::CMD_OR_CTRL | Key::UP); + ED_SHORTCUT("file_dialog/move_favorite_down", TTR("Move Favorite Down"), KeyModifierMask::CMD_OR_CTRL | Key::DOWN); HBoxContainer *pathhb = memnew(HBoxContainer); diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h index 528050ba4f..6d11cb10ed 100644 --- a/editor/editor_file_dialog.h +++ b/editor/editor_file_dialog.h @@ -161,7 +161,7 @@ private: Ref<Texture2D> favorites_down; Ref<Texture2D> folder; - Color folder_icon_modulate; + Color folder_icon_color; Ref<Texture2D> action_copy; Ref<Texture2D> action_delete; diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index de89cd8df4..b8f115e82e 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1662,19 +1662,19 @@ void EditorHelp::_help_callback(const String &p_topic) { } } -static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { +static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt, Control *p_owner_node) { DocTools *doc = EditorHelp::get_doc_data(); String base_path; - Ref<Font> doc_font = p_rt->get_theme_font(SNAME("doc"), SNAME("EditorFonts")); - Ref<Font> doc_bold_font = p_rt->get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts")); - Ref<Font> doc_italic_font = p_rt->get_theme_font(SNAME("doc_italic"), SNAME("EditorFonts")); - Ref<Font> doc_code_font = p_rt->get_theme_font(SNAME("doc_source"), SNAME("EditorFonts")); - Ref<Font> doc_kbd_font = p_rt->get_theme_font(SNAME("doc_keyboard"), SNAME("EditorFonts")); + Ref<Font> doc_font = p_owner_node->get_theme_font(SNAME("doc"), SNAME("EditorFonts")); + Ref<Font> doc_bold_font = p_owner_node->get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts")); + Ref<Font> doc_italic_font = p_owner_node->get_theme_font(SNAME("doc_italic"), SNAME("EditorFonts")); + Ref<Font> doc_code_font = p_owner_node->get_theme_font(SNAME("doc_source"), SNAME("EditorFonts")); + Ref<Font> doc_kbd_font = p_owner_node->get_theme_font(SNAME("doc_keyboard"), SNAME("EditorFonts")); - Color link_color = p_rt->get_theme_color(SNAME("link_color"), SNAME("EditorHelp")); - Color code_color = p_rt->get_theme_color(SNAME("code_color"), SNAME("EditorHelp")); - Color kbd_color = p_rt->get_theme_color(SNAME("kbd_color"), SNAME("EditorHelp")); + Color link_color = p_owner_node->get_theme_color(SNAME("link_color"), SNAME("EditorHelp")); + Color code_color = p_owner_node->get_theme_color(SNAME("code_color"), SNAME("EditorHelp")); + Color kbd_color = p_owner_node->get_theme_color(SNAME("kbd_color"), SNAME("EditorHelp")); String bbcode = p_bbcode.dedent().replace("\t", "").replace("\r", "").strip_edges(); @@ -1966,7 +1966,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { } void EditorHelp::_add_text(const String &p_bbcode) { - _add_text_to_rt(p_bbcode, class_desc); + _add_text_to_rt(p_bbcode, class_desc, this); } Thread EditorHelp::thread; @@ -2192,11 +2192,10 @@ void EditorHelpBit::_bind_methods() { void EditorHelpBit::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { rich_text->add_theme_color_override("selection_color", get_theme_color(SNAME("selection_color"), SNAME("EditorHelp"))); rich_text->clear(); - _add_text_to_rt(text, rich_text); + _add_text_to_rt(text, rich_text, this); rich_text->reset_size(); // Force recalculating size after parsing bbcode. } break; } @@ -2205,7 +2204,7 @@ void EditorHelpBit::_notification(int p_what) { void EditorHelpBit::set_text(const String &p_text) { text = p_text; rich_text->clear(); - _add_text_to_rt(text, rich_text); + _add_text_to_rt(text, rich_text, this); } EditorHelpBit::EditorHelpBit() { diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index 2e35f21e47..af0cff9ad6 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -231,6 +231,7 @@ EditorHelpSearch::EditorHelpSearch() { filter_combo->add_item(TTR("Methods Only"), SEARCH_METHODS); filter_combo->add_item(TTR("Operators Only"), SEARCH_OPERATORS); filter_combo->add_item(TTR("Signals Only"), SEARCH_SIGNALS); + filter_combo->add_item(TTR("Annotations Only"), SEARCH_ANNOTATIONS); filter_combo->add_item(TTR("Constants Only"), SEARCH_CONSTANTS); filter_combo->add_item(TTR("Properties Only"), SEARCH_PROPERTIES); filter_combo->add_item(TTR("Theme Properties Only"), SEARCH_THEME_ITEMS); @@ -339,8 +340,9 @@ bool EditorHelpSearch::Runner::_phase_match_classes() { match.name = (term.is_empty() && (!class_doc.is_script_doc || class_doc.name[0] != '\"')) || _match_string(term, class_doc.name); } - // Match members if the term is long enough. - if (term.length() > 1) { + // Match members only if the term is long enough, to avoid slow performance from building a large tree. + // Make an exception for annotations, since there are not that many of them. + if (term.length() > 1 || term == "@") { if (search_flags & SEARCH_CONSTRUCTORS) { for (int i = 0; i < class_doc.constructors.size(); i++) { String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? class_doc.constructors[i].name : class_doc.constructors[i].name.to_lower(); @@ -402,6 +404,13 @@ bool EditorHelpSearch::Runner::_phase_match_classes() { } } } + if (search_flags & SEARCH_ANNOTATIONS) { + for (int i = 0; i < class_doc.annotations.size(); i++) { + if (_match_string(term, class_doc.annotations[i].name)) { + match.annotations.push_back(const_cast<DocData::MethodDoc *>(&class_doc.annotations[i])); + } + } + } matches[class_doc.name] = match; } matches[class_doc.name] = match; @@ -485,6 +494,10 @@ bool EditorHelpSearch::Runner::_phase_member_items() { for (int i = 0; i < match.theme_properties.size(); i++) { _create_theme_property_item(parent, match.doc, match.theme_properties[i]); } + for (int i = 0; i < match.annotations.size(); i++) { + // Hide the redundant leading @ symbol. + _create_annotation_item(parent, match.doc, match.annotations[i]->name.substr(1), match.annotations[i]); + } ++iterator_match; return !iterator_match; @@ -523,6 +536,22 @@ void EditorHelpSearch::Runner::_match_item(TreeItem *p_item, const String &p_tex } } +String EditorHelpSearch::Runner::_build_method_tooltip(const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc) const { + String tooltip = p_doc->return_type + " " + p_class_doc->name + "." + p_doc->name + "("; + for (int i = 0; i < p_doc->arguments.size(); i++) { + const DocData::ArgumentDoc &arg = p_doc->arguments[i]; + tooltip += arg.type + " " + arg.name; + if (!arg.default_value.is_empty()) { + tooltip += " = " + arg.default_value; + } + if (i < p_doc->arguments.size() - 1) { + tooltip += ", "; + } + } + tooltip += ")"; + return tooltip; +} + TreeItem *EditorHelpSearch::Runner::_create_class_hierarchy(const ClassMatch &p_match) { if (p_match.doc->name.is_empty()) { return nullptr; @@ -576,37 +605,20 @@ TreeItem *EditorHelpSearch::Runner::_create_class_item(TreeItem *p_parent, const } TreeItem *EditorHelpSearch::Runner::_create_method_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const String &p_text, const DocData::MethodDoc *p_doc) { - String tooltip = p_doc->return_type + " " + p_class_doc->name + "." + p_doc->name + "("; - for (int i = 0; i < p_doc->arguments.size(); i++) { - const DocData::ArgumentDoc &arg = p_doc->arguments[i]; - tooltip += arg.type + " " + arg.name; - if (!arg.default_value.is_empty()) { - tooltip += " = " + arg.default_value; - } - if (i < p_doc->arguments.size() - 1) { - tooltip += ", "; - } - } - tooltip += ")"; + String tooltip = _build_method_tooltip(p_class_doc, p_doc); return _create_member_item(p_parent, p_class_doc->name, "MemberMethod", p_doc->name, p_text, TTRC("Method"), "method", tooltip); } TreeItem *EditorHelpSearch::Runner::_create_signal_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc) { - String tooltip = p_doc->return_type + " " + p_class_doc->name + "." + p_doc->name + "("; - for (int i = 0; i < p_doc->arguments.size(); i++) { - const DocData::ArgumentDoc &arg = p_doc->arguments[i]; - tooltip += arg.type + " " + arg.name; - if (!arg.default_value.is_empty()) { - tooltip += " = " + arg.default_value; - } - if (i < p_doc->arguments.size() - 1) { - tooltip += ", "; - } - } - tooltip += ")"; + String tooltip = _build_method_tooltip(p_class_doc, p_doc); return _create_member_item(p_parent, p_class_doc->name, "MemberSignal", p_doc->name, p_doc->name, TTRC("Signal"), "signal", tooltip); } +TreeItem *EditorHelpSearch::Runner::_create_annotation_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const String &p_text, const DocData::MethodDoc *p_doc) { + String tooltip = _build_method_tooltip(p_class_doc, p_doc); + return _create_member_item(p_parent, p_class_doc->name, "MemberAnnotation", p_doc->name, p_text, TTRC("Annotation"), "annotation", tooltip); +} + TreeItem *EditorHelpSearch::Runner::_create_constant_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ConstantDoc *p_doc) { String tooltip = p_class_doc->name + "." + p_doc->name; return _create_member_item(p_parent, p_class_doc->name, "MemberConstant", p_doc->name, p_doc->name, TTRC("Constant"), "constant", tooltip); diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h index 3f17c992ac..26abaec6e6 100644 --- a/editor/editor_help_search.h +++ b/editor/editor_help_search.h @@ -50,7 +50,8 @@ class EditorHelpSearch : public ConfirmationDialog { SEARCH_CONSTANTS = 1 << 5, SEARCH_PROPERTIES = 1 << 6, SEARCH_THEME_ITEMS = 1 << 7, - SEARCH_ALL = SEARCH_CLASSES | SEARCH_CONSTRUCTORS | SEARCH_METHODS | SEARCH_OPERATORS | SEARCH_SIGNALS | SEARCH_CONSTANTS | SEARCH_PROPERTIES | SEARCH_THEME_ITEMS, + SEARCH_ANNOTATIONS = 1 << 8, + SEARCH_ALL = SEARCH_CLASSES | SEARCH_CONSTRUCTORS | SEARCH_METHODS | SEARCH_OPERATORS | SEARCH_SIGNALS | SEARCH_CONSTANTS | SEARCH_PROPERTIES | SEARCH_THEME_ITEMS | SEARCH_ANNOTATIONS, SEARCH_CASE_SENSITIVE = 1 << 29, SEARCH_SHOW_HIERARCHY = 1 << 30 }; @@ -108,9 +109,10 @@ class EditorHelpSearch::Runner : public RefCounted { Vector<DocData::ConstantDoc *> constants; Vector<DocData::PropertyDoc *> properties; Vector<DocData::ThemeItemDoc *> theme_properties; + Vector<DocData::MethodDoc *> annotations; bool required() { - return name || methods.size() || signals.size() || constants.size() || properties.size() || theme_properties.size(); + return name || methods.size() || signals.size() || constants.size() || properties.size() || theme_properties.size() || annotations.size(); } }; @@ -141,12 +143,15 @@ class EditorHelpSearch::Runner : public RefCounted { bool _phase_member_items(); bool _phase_select_match(); + String _build_method_tooltip(const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc) const; + bool _match_string(const String &p_term, const String &p_string) const; void _match_item(TreeItem *p_item, const String &p_text); TreeItem *_create_class_hierarchy(const ClassMatch &p_match); TreeItem *_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray); TreeItem *_create_method_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const String &p_text, const DocData::MethodDoc *p_doc); TreeItem *_create_signal_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc); + TreeItem *_create_annotation_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const String &p_text, const DocData::MethodDoc *p_doc); TreeItem *_create_constant_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ConstantDoc *p_doc); TreeItem *_create_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::PropertyDoc *p_doc); TreeItem *_create_theme_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ThemeItemDoc *p_doc); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index bdf1c314f8..7bbdc16c61 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -2711,6 +2711,11 @@ void EditorInspector::update_tree() { continue; } + // Hide the "MultiNodeEdit" category for MultiNodeEdit. + if (Object::cast_to<MultiNodeEdit>(object) && p.name == "MultiNodeEdit") { + continue; + } + // Iterate over remaining properties. If no properties in category, skip the category. List<PropertyInfo>::Element *N = E_property->next(); bool valid = true; @@ -2738,7 +2743,7 @@ void EditorInspector::update_tree() { doc_name = p.name; // Set the category icon. - if (!ClassDB::class_exists(type) && !ScriptServer::is_global_class(type) && p.hint_string.length() && FileAccess::exists(p.hint_string)) { + if (!EditorNode::get_editor_data().is_type_recognized(type) && p.hint_string.length() && FileAccess::exists(p.hint_string)) { // If we have a category inside a script, search for the first script with a valid icon. Ref<Script> script = ResourceLoader::load(p.hint_string, "Script"); StringName base_type; @@ -2757,10 +2762,16 @@ void EditorInspector::update_tree() { while (script.is_valid()) { name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name); - if (name != StringName() && icon_path.length()) { + if (name != StringName() && !icon_path.is_empty()) { category->icon = ResourceLoader::load(icon_path, "Texture"); break; } + + const EditorData::CustomType *ctype = EditorNode::get_editor_data().get_custom_type_by_path(script->get_path()); + if (ctype) { + category->icon = ctype->icon; + break; + } script = script->get_base_script(); } if (category->icon.is_null() && has_theme_icon(base_type, SNAME("EditorIcons"))) { @@ -2819,6 +2830,11 @@ void EditorInspector::update_tree() { continue; } + if (p.name.begins_with("metadata/") && bool(object->call("_hide_metadata_from_inspector"))) { + // Hide metadata from inspector if required. + continue; + } + // Get the path for property. String path = p.name; @@ -3089,6 +3105,8 @@ void EditorInspector::update_tree() { StringName classname = doc_name == "" ? object->get_class_name() : doc_name; if (!object_class.is_empty()) { classname = object_class; + } else if (Object::cast_to<MultiNodeEdit>(object)) { + classname = Object::cast_to<MultiNodeEdit>(object)->get_edited_class_name(); } StringName propname = property_prefix + p.name; @@ -3242,7 +3260,7 @@ void EditorInspector::update_tree() { } } - if (!hide_metadata) { + if (!hide_metadata && !object->call("_hide_metadata_from_inspector")) { // Add 4px of spacing between the "Add Metadata" button and the content above it. Control *spacer = memnew(Control); spacer->set_custom_minimum_size(Size2(0, 4) * EDSCALE); @@ -3475,9 +3493,9 @@ void EditorInspector::_update_inspector_bg() { n = n->get_parent(); } count_subinspectors = MIN(15, count_subinspectors); - add_theme_style_override("bg", get_theme_stylebox("sub_inspector_bg" + itos(count_subinspectors), SNAME("Editor"))); + add_theme_style_override("panel", get_theme_stylebox("sub_inspector_bg" + itos(count_subinspectors), SNAME("Editor"))); } else { - add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); } } void EditorInspector::set_sub_inspector(bool p_enable) { @@ -4064,7 +4082,7 @@ EditorInspector::EditorInspector() { refresh_countdown = 0.33; } - ED_SHORTCUT("property_editor/copy_property", TTR("Copy Property"), KeyModifierMask::CMD | Key::C); - ED_SHORTCUT("property_editor/paste_property", TTR("Paste Property"), KeyModifierMask::CMD | Key::V); - ED_SHORTCUT("property_editor/copy_property_path", TTR("Copy Property Path"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::C); + ED_SHORTCUT("property_editor/copy_property", TTR("Copy Property"), KeyModifierMask::CMD_OR_CTRL | Key::C); + ED_SHORTCUT("property_editor/paste_property", TTR("Paste Property"), KeyModifierMask::CMD_OR_CTRL | Key::V); + ED_SHORTCUT("property_editor/copy_property_path", TTR("Copy Property Path"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::C); } diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index a3d4296edb..6e6a898757 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -396,7 +396,7 @@ EditorLog::EditorLog() { clear_button = memnew(Button); clear_button->set_flat(true); clear_button->set_focus_mode(FOCUS_NONE); - clear_button->set_shortcut(ED_SHORTCUT("editor/clear_output", TTR("Clear Output"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::K)); + clear_button->set_shortcut(ED_SHORTCUT("editor/clear_output", TTR("Clear Output"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::K)); clear_button->set_shortcut_context(this); clear_button->connect("pressed", callable_mp(this, &EditorLog::_clear_request)); hb_tools->add_child(clear_button); @@ -405,7 +405,7 @@ EditorLog::EditorLog() { copy_button = memnew(Button); copy_button->set_flat(true); copy_button->set_focus_mode(FOCUS_NONE); - copy_button->set_shortcut(ED_SHORTCUT("editor/copy_output", TTR("Copy Selection"), KeyModifierMask::CMD | Key::C)); + copy_button->set_shortcut(ED_SHORTCUT("editor/copy_output", TTR("Copy Selection"), KeyModifierMask::CMD_OR_CTRL | Key::C)); copy_button->set_shortcut_context(this); copy_button->connect("pressed", callable_mp(this, &EditorLog::_copy_request)); hb_tools->add_child(copy_button); @@ -431,7 +431,7 @@ EditorLog::EditorLog() { show_search_button->set_focus_mode(FOCUS_NONE); show_search_button->set_toggle_mode(true); show_search_button->set_pressed(true); - show_search_button->set_shortcut(ED_SHORTCUT("editor/open_search", TTR("Focus Search/Filter Bar"), KeyModifierMask::CMD | Key::F)); + show_search_button->set_shortcut(ED_SHORTCUT("editor/open_search", TTR("Focus Search/Filter Bar"), KeyModifierMask::CMD_OR_CTRL | Key::F)); show_search_button->set_shortcut_context(this); show_search_button->connect("toggled", callable_mp(this, &EditorLog::_set_search_visible)); hb_tools2->add_child(show_search_button); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 58377eef0f..1d2540f0fd 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -37,7 +37,7 @@ #include "core/io/image_loader.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" -#include "core/io/stream_peer_ssl.h" +#include "core/io/stream_peer_tls.h" #include "core/object/class_db.h" #include "core/object/message_queue.h" #include "core/os/keyboard.h" @@ -566,8 +566,6 @@ void EditorNode::_update_from_settings() { SceneTree *tree = get_tree(); tree->set_debug_collisions_color(GLOBAL_GET("debug/shapes/collision/shape_color")); tree->set_debug_collision_contact_color(GLOBAL_GET("debug/shapes/collision/contact_color")); - tree->set_debug_navigation_color(GLOBAL_GET("debug/shapes/navigation/geometry_color")); - tree->set_debug_navigation_disabled_color(GLOBAL_GET("debug/shapes/navigation/disabled_geometry_color")); #ifdef DEBUG_ENABLED NavigationServer3D::get_singleton_mut()->set_debug_navigation_edge_connection_color(GLOBAL_GET("debug/shapes/navigation/edge_connection_color")); @@ -762,11 +760,8 @@ void EditorNode::_notification(int p_what) { gui_base->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Background"), SNAME("EditorStyles"))); scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Content"), SNAME("EditorStyles"))); - bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); - + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), SNAME("EditorStyles"))); tabbar_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("tabbar_background"), SNAME("TabContainer"))); - scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox(SNAME("SceneTabFG"), SNAME("EditorStyles"))); - scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox(SNAME("SceneTabBG"), SNAME("EditorStyles"))); main_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); } @@ -2660,22 +2655,36 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT: { if (!p_confirmed) { tab_closing_idx = _next_unsaved_scene(false); - _scene_tab_changed(tab_closing_idx); + if (tab_closing_idx == -1) { + tab_closing_idx = -2; // Only external resources are unsaved. + } else { + _scene_tab_changed(tab_closing_idx); + } if (unsaved_cache || p_option == FILE_CLOSE_ALL_AND_QUIT || p_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER || p_option == FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT) { - Node *scene_root = editor_data.get_edited_scene_root(tab_closing_idx); - if (scene_root) { - String scene_filename = scene_root->get_scene_file_path(); + if (tab_closing_idx == -2) { if (p_option == FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT) { save_confirmation->set_ok_button_text(TTR("Save & Reload")); - save_confirmation->set_text(vformat(TTR("Save changes to '%s' before reloading?"), !scene_filename.is_empty() ? scene_filename : "unsaved scene")); + save_confirmation->set_text(TTR("Save modified resources before reloading?")); } else { save_confirmation->set_ok_button_text(TTR("Save & Quit")); - save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), !scene_filename.is_empty() ? scene_filename : "unsaved scene")); + save_confirmation->set_text(TTR("Save modified resources before closing?")); + } + } else { + Node *scene_root = editor_data.get_edited_scene_root(tab_closing_idx); + if (scene_root) { + String scene_filename = scene_root->get_scene_file_path(); + if (p_option == FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT) { + save_confirmation->set_ok_button_text(TTR("Save & Reload")); + save_confirmation->set_text(vformat(TTR("Save changes to '%s' before reloading?"), !scene_filename.is_empty() ? scene_filename : "unsaved scene")); + } else { + save_confirmation->set_ok_button_text(TTR("Save & Quit")); + save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), !scene_filename.is_empty() ? scene_filename : "unsaved scene")); + } } - save_confirmation->popup_centered(); - break; } + save_confirmation->popup_centered(); + break; } } if (!editor_data.get_edited_scene_root(tab_closing_idx)) { @@ -2948,7 +2957,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case RELOAD_CURRENT_PROJECT: { if (!p_confirmed) { bool save_each = EDITOR_GET("interface/editor/save_each_scene_on_quit"); - if (_next_unsaved_scene(!save_each) == -1) { + if (_next_unsaved_scene(!save_each) == -1 && !get_undo_redo()->is_history_unsaved(EditorUndoRedoManager::GLOBAL_HISTORY)) { _discard_changes(); break; } else { @@ -3098,14 +3107,14 @@ void EditorNode::_screenshot(bool p_use_utc) { } void EditorNode::_save_screenshot(NodePath p_path) { - Control *editor_main_control = EditorInterface::get_singleton()->get_editor_main_control(); - ERR_FAIL_COND_MSG(!editor_main_control, "Cannot get editor main control."); - Viewport *viewport = editor_main_control->get_viewport(); - ERR_FAIL_COND_MSG(!viewport, "Cannot get editor main control viewport."); + Control *editor_main_screen = EditorInterface::get_singleton()->get_editor_main_screen(); + ERR_FAIL_COND_MSG(!editor_main_screen, "Cannot get the editor main screen control."); + Viewport *viewport = editor_main_screen->get_viewport(); + ERR_FAIL_COND_MSG(!viewport, "Cannot get a viewport from the editor main screen."); Ref<ViewportTexture> texture = viewport->get_texture(); - ERR_FAIL_COND_MSG(texture.is_null(), "Cannot get editor main control viewport texture."); + ERR_FAIL_COND_MSG(texture.is_null(), "Cannot get a viewport texture from the editor main screen."); Ref<Image> img = texture->get_image(); - ERR_FAIL_COND_MSG(img.is_null(), "Cannot get editor main control viewport texture image."); + ERR_FAIL_COND_MSG(img.is_null(), "Cannot get an image from a viewport texture of the editor main screen."); Error error = img->save_png(p_path); ERR_FAIL_COND_MSG(error != OK, "Cannot save screenshot to file '" + p_path + "'."); } @@ -3259,8 +3268,12 @@ void EditorNode::_discard_changes(const String &p_str) { for (const String &a : Main::get_forwardable_cli_arguments(Main::CLI_SCOPE_TOOL)) { args.push_back(a); } - args.push_back("--path"); - args.push_back(exec.get_base_dir()); + + String exec_base_dir = exec.get_base_dir(); + if (!exec_base_dir.is_empty()) { + args.push_back("--path"); + args.push_back(exec_base_dir); + } args.push_back("--project-manager"); Error err = OS::get_singleton()->create_instance(args); @@ -3289,8 +3302,8 @@ void EditorNode::_update_file_menu_closed() { file_menu->set_item_disabled(file_menu->get_item_index(FILE_OPEN_PREV), false); } -Control *EditorNode::get_main_control() { - return main_control; +VBoxContainer *EditorNode::get_main_screen_control() { + return main_screen_vbox; } void EditorNode::_editor_select(int p_which) { @@ -3378,7 +3391,7 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed singleton->main_editor_button_vb->add_child(tb); singleton->editor_table.push_back(p_editor); - singleton->distraction_free->raise(); + singleton->distraction_free->move_to_front(); } singleton->editor_data.add_editor_plugin(p_editor); singleton->add_child(p_editor); @@ -4338,16 +4351,8 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p } } - const HashMap<String, Vector<EditorData::CustomType>> &p_map = EditorNode::get_editor_data().get_custom_types(); - for (const KeyValue<String, Vector<EditorData::CustomType>> &E : p_map) { - const Vector<EditorData::CustomType> &ct = E.value; - for (int i = 0; i < ct.size(); ++i) { - if (ct[i].name == p_class) { - if (ct[i].icon.is_valid()) { - return ct[i].icon; - } - } - } + if (const EditorData::CustomType *ctype = EditorNode::get_editor_data().get_custom_type_by_name(p_class)) { + return ctype->icon; } if (gui_base->has_theme_icon(p_class, SNAME("EditorIcons"))) { @@ -4968,7 +4973,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String } if (atidx == i) { - node->raise(); + node->move_to_front(); continue; } @@ -5393,7 +5398,7 @@ Button *EditorNode::add_bottom_panel_item(String p_text, Control *p_item) { tb->set_toggle_mode(true); tb->set_focus_mode(Control::FOCUS_NONE); bottom_panel_vb->add_child(p_item); - bottom_panel_hb->raise(); + bottom_panel_hb->move_to_front(); bottom_panel_hb_editors->add_child(tb); p_item->set_v_size_flags(Control::SIZE_EXPAND_FILL); p_item->hide(); @@ -5427,7 +5432,7 @@ void EditorNode::make_bottom_panel_item_visible(Control *p_item) { void EditorNode::raise_bottom_panel_item(Control *p_item) { for (int i = 0; i < bottom_panel_items.size(); i++) { if (bottom_panel_items[i].control == p_item) { - bottom_panel_items[i].button->raise(); + bottom_panel_items[i].button->move_to_front(); SWAP(bottom_panel_items.write[i], bottom_panel_items.write[bottom_panel_items.size() - 1]); break; } @@ -5475,7 +5480,7 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { // This is the debug panel which uses tabs, so the top section should be smaller. bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), SNAME("EditorStyles"))); } else { - bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), SNAME("EditorStyles"))); } center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE); center_split->set_collapsed(false); @@ -5485,7 +5490,7 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { bottom_panel_raise->show(); } else { - bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), SNAME("EditorStyles"))); bottom_panel_items[p_idx].button->set_pressed(false); bottom_panel_items[p_idx].control->set_visible(false); center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN); @@ -6528,8 +6533,6 @@ EditorNode::EditorNode() { tabbar_panel->add_child(tabbar_container); scene_tabs = memnew(TabBar); - scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox(SNAME("SceneTabFG"), SNAME("EditorStyles"))); - scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox(SNAME("SceneTabBG"), SNAME("EditorStyles"))); scene_tabs->set_select_with_rmb(true); scene_tabs->add_tab("unsaved"); scene_tabs->set_tab_close_display_policy((TabBar::CloseButtonDisplayPolicy)EDITOR_GET("interface/scene_tabs/display_close_button").operator int()); @@ -6565,8 +6568,8 @@ EditorNode::EditorNode() { distraction_free = memnew(Button); distraction_free->set_flat(true); - ED_SHORTCUT_AND_COMMAND("editor/distraction_free_mode", TTR("Distraction Free Mode"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F11); - ED_SHORTCUT_OVERRIDE("editor/distraction_free_mode", "macos", KeyModifierMask::CMD | KeyModifierMask::CTRL | Key::D); + ED_SHORTCUT_AND_COMMAND("editor/distraction_free_mode", TTR("Distraction Free Mode"), KeyModifierMask::CTRL | KeyModifierMask::SHIFT | Key::F11); + ED_SHORTCUT_OVERRIDE("editor/distraction_free_mode", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::D); distraction_free->set_shortcut(ED_GET_SHORTCUT("editor/distraction_free_mode")); distraction_free->set_tooltip_text(TTR("Toggle distraction-free mode.")); distraction_free->connect("pressed", callable_mp(this, &EditorNode::_toggle_distraction_free_mode)); @@ -6588,10 +6591,11 @@ EditorNode::EditorNode() { scene_root->set_disable_input(true); scene_root->set_as_audio_listener_2d(true); - main_control = memnew(VBoxContainer); - main_control->set_v_size_flags(Control::SIZE_EXPAND_FILL); - main_control->add_theme_constant_override("separation", 0); - scene_root_parent->add_child(main_control); + main_screen_vbox = memnew(VBoxContainer); + main_screen_vbox->set_name("MainScreen"); + main_screen_vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL); + main_screen_vbox->add_theme_constant_override("separation", 0); + scene_root_parent->add_child(main_screen_vbox); bool global_menu = !bool(EDITOR_GET("interface/editor/use_embedded_menu")) && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU); bool can_expand = bool(EDITOR_GET("interface/editor/expand_to_title")) && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_EXTEND_TO_TITLE); @@ -6677,30 +6681,30 @@ EditorNode::EditorNode() { gui_base->add_child(warning); warning->connect("custom_action", callable_mp(this, &EditorNode::_copy_warning)); - ED_SHORTCUT("editor/next_tab", TTR("Next Scene Tab"), KeyModifierMask::CMD + Key::TAB); - ED_SHORTCUT("editor/prev_tab", TTR("Previous Scene Tab"), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::TAB); - ED_SHORTCUT("editor/filter_files", TTR("Focus FileSystem Filter"), KeyModifierMask::CMD + KeyModifierMask::ALT + Key::P); + ED_SHORTCUT("editor/next_tab", TTR("Next Scene Tab"), KeyModifierMask::CMD_OR_CTRL + Key::TAB); + ED_SHORTCUT("editor/prev_tab", TTR("Previous Scene Tab"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::TAB); + ED_SHORTCUT("editor/filter_files", TTR("Focus FileSystem Filter"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::ALT + Key::P); command_palette = EditorCommandPalette::get_singleton(); command_palette->set_title(TTR("Command Palette")); gui_base->add_child(command_palette); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_scene", TTR("New Scene"), KeyModifierMask::CMD + Key::N), FILE_NEW_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_inherited_scene", TTR("New Inherited Scene..."), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::N), FILE_NEW_INHERITED_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/open_scene", TTR("Open Scene..."), KeyModifierMask::CMD + Key::O), FILE_OPEN_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reopen_closed_scene", TTR("Reopen Closed Scene"), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::T), FILE_OPEN_PREV); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_scene", TTR("New Scene"), KeyModifierMask::CMD_OR_CTRL + Key::N), FILE_NEW_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_inherited_scene", TTR("New Inherited Scene..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::N), FILE_NEW_INHERITED_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/open_scene", TTR("Open Scene..."), KeyModifierMask::CMD_OR_CTRL + Key::O), FILE_OPEN_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reopen_closed_scene", TTR("Reopen Closed Scene"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::T), FILE_OPEN_PREV); file_menu->add_submenu_item(TTR("Open Recent"), "RecentScenes", FILE_OPEN_RECENT); file_menu->add_separator(); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene", TTR("Save Scene"), KeyModifierMask::CMD + Key::S), FILE_SAVE_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene_as", TTR("Save Scene As..."), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::S), FILE_SAVE_AS_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_all_scenes", TTR("Save All Scenes"), KeyModifierMask::CMD + KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::S), FILE_SAVE_ALL_SCENES); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene", TTR("Save Scene"), KeyModifierMask::CMD_OR_CTRL + Key::S), FILE_SAVE_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene_as", TTR("Save Scene As..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::S), FILE_SAVE_AS_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_all_scenes", TTR("Save All Scenes"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::S), FILE_SAVE_ALL_SCENES); file_menu->add_separator(); file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open", TTR("Quick Open..."), KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::O), FILE_QUICK_OPEN); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_scene", TTR("Quick Open Scene..."), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::O), FILE_QUICK_OPEN_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_script", TTR("Quick Open Script..."), KeyModifierMask::CMD + KeyModifierMask::ALT + Key::O), FILE_QUICK_OPEN_SCRIPT); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_scene", TTR("Quick Open Scene..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::O), FILE_QUICK_OPEN_SCENE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_script", TTR("Quick Open Script..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::ALT + Key::O), FILE_QUICK_OPEN_SCRIPT); file_menu->add_separator(); export_as_menu = memnew(PopupMenu); @@ -6716,7 +6720,7 @@ EditorNode::EditorNode() { file_menu->add_separator(); file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reload_saved_scene", TTR("Reload Saved Scene")), EDIT_RELOAD_SAVED_SCENE); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/close_scene", TTR("Close Scene"), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::W), FILE_CLOSE); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/close_scene", TTR("Close Scene"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::W), FILE_CLOSE); recent_scenes = memnew(PopupMenu); recent_scenes->set_name("RecentScenes"); @@ -6726,7 +6730,7 @@ EditorNode::EditorNode() { if (!global_menu || !OS::get_singleton()->has_feature("macos")) { // On macOS "Quit" and "About" options are in the "app" menu. file_menu->add_separator(); - file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/file_quit", TTR("Quit"), KeyModifierMask::CMD + Key::Q), FILE_QUIT, true); + file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/file_quit", TTR("Quit"), KeyModifierMask::CMD_OR_CTRL + Key::Q), FILE_QUIT, true); } project_menu = memnew(PopupMenu); @@ -6767,7 +6771,7 @@ EditorNode::EditorNode() { project_menu->add_separator(); project_menu->add_shortcut(ED_SHORTCUT("editor/reload_current_project", TTR("Reload Current Project")), RELOAD_CURRENT_PROJECT); - ED_SHORTCUT_AND_COMMAND("editor/quit_to_project_list", TTR("Quit to Project List"), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::Q); + ED_SHORTCUT_AND_COMMAND("editor/quit_to_project_list", TTR("Quit to Project List"), KeyModifierMask::CTRL + KeyModifierMask::SHIFT + Key::Q); ED_SHORTCUT_OVERRIDE("editor/quit_to_project_list", "macos", KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::Q); project_menu->add_shortcut(ED_GET_SHORTCUT("editor/quit_to_project_list"), RUN_PROJECT_MANAGER, true); @@ -6793,9 +6797,9 @@ EditorNode::EditorNode() { main_menu->add_child(settings_menu); ED_SHORTCUT_AND_COMMAND("editor/editor_settings", TTR("Editor Settings...")); - ED_SHORTCUT_OVERRIDE("editor/editor_settings", "macos", KeyModifierMask::CMD + Key::COMMA); + ED_SHORTCUT_OVERRIDE("editor/editor_settings", "macos", KeyModifierMask::META + Key::COMMA); settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/editor_settings"), SETTINGS_PREFERENCES); - settings_menu->add_shortcut(ED_SHORTCUT("editor/command_palette", TTR("Command Palette..."), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::P), HELP_COMMAND_PALETTE); + settings_menu->add_shortcut(ED_SHORTCUT("editor/command_palette", TTR("Command Palette..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::P), HELP_COMMAND_PALETTE); settings_menu->add_separator(); editor_layouts = memnew(PopupMenu); @@ -6806,13 +6810,13 @@ EditorNode::EditorNode() { settings_menu->add_separator(); ED_SHORTCUT_AND_COMMAND("editor/take_screenshot", TTR("Take Screenshot"), KeyModifierMask::CTRL | Key::F12); - ED_SHORTCUT_OVERRIDE("editor/take_screenshot", "macos", KeyModifierMask::CMD | Key::F12); + ED_SHORTCUT_OVERRIDE("editor/take_screenshot", "macos", KeyModifierMask::META | Key::F12); settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/take_screenshot"), EDITOR_SCREENSHOT); settings_menu->set_item_tooltip(-1, TTR("Screenshots are stored in the Editor Data/Settings Folder.")); ED_SHORTCUT_AND_COMMAND("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KeyModifierMask::SHIFT | Key::F11); - ED_SHORTCUT_OVERRIDE("editor/fullscreen_mode", "macos", KeyModifierMask::CMD | KeyModifierMask::CTRL | Key::F); + ED_SHORTCUT_OVERRIDE("editor/fullscreen_mode", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::F); settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/fullscreen_mode"), SETTINGS_TOGGLE_FULLSCREEN); settings_menu->add_separator(); @@ -6873,7 +6877,7 @@ EditorNode::EditorNode() { play_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY)); ED_SHORTCUT_AND_COMMAND("editor/play", TTR("Play"), Key::F5); - ED_SHORTCUT_OVERRIDE("editor/play", "macos", KeyModifierMask::CMD | Key::B); + ED_SHORTCUT_OVERRIDE("editor/play", "macos", KeyModifierMask::META | Key::B); play_button->set_shortcut(ED_GET_SHORTCUT("editor/play")); pause_button = memnew(Button); @@ -6886,7 +6890,7 @@ EditorNode::EditorNode() { launch_pad_hb->add_child(pause_button); ED_SHORTCUT("editor/pause_scene", TTR("Pause Scene"), Key::F7); - ED_SHORTCUT_OVERRIDE("editor/pause_scene", "macos", KeyModifierMask::CMD | KeyModifierMask::CTRL | Key::Y); + ED_SHORTCUT_OVERRIDE("editor/pause_scene", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::Y); pause_button->set_shortcut(ED_GET_SHORTCUT("editor/pause_scene")); stop_button = memnew(Button); @@ -6899,7 +6903,7 @@ EditorNode::EditorNode() { stop_button->set_disabled(true); ED_SHORTCUT("editor/stop", TTR("Stop"), Key::F8); - ED_SHORTCUT_OVERRIDE("editor/stop", "macos", KeyModifierMask::CMD | Key::PERIOD); + ED_SHORTCUT_OVERRIDE("editor/stop", "macos", KeyModifierMask::META | Key::PERIOD); stop_button->set_shortcut(ED_GET_SHORTCUT("editor/stop")); run_native = memnew(EditorRunNative); @@ -6914,7 +6918,7 @@ EditorNode::EditorNode() { play_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY_SCENE)); ED_SHORTCUT_AND_COMMAND("editor/play_scene", TTR("Play Scene"), Key::F6); - ED_SHORTCUT_OVERRIDE("editor/play_scene", "macos", KeyModifierMask::CMD | Key::R); + ED_SHORTCUT_OVERRIDE("editor/play_scene", "macos", KeyModifierMask::META | Key::R); play_scene_button->set_shortcut(ED_GET_SHORTCUT("editor/play_scene")); play_custom_scene_button = memnew(Button); @@ -6926,8 +6930,8 @@ EditorNode::EditorNode() { _reset_play_buttons(); - ED_SHORTCUT_AND_COMMAND("editor/play_custom_scene", TTR("Play Custom Scene"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F5); - ED_SHORTCUT_OVERRIDE("editor/play_custom_scene", "macos", KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::R); + ED_SHORTCUT_AND_COMMAND("editor/play_custom_scene", TTR("Play Custom Scene"), KeyModifierMask::CTRL | KeyModifierMask::SHIFT | Key::F5); + ED_SHORTCUT_OVERRIDE("editor/play_custom_scene", "macos", KeyModifierMask::META | KeyModifierMask::SHIFT | Key::R); play_custom_scene_button->set_shortcut(ED_GET_SHORTCUT("editor/play_custom_scene")); write_movie_panel = memnew(PanelContainer); @@ -7093,7 +7097,7 @@ EditorNode::EditorNode() { // Bottom panels. bottom_panel = memnew(PanelContainer); - bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), SNAME("EditorStyles"))); center_split->add_child(bottom_panel); center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN); diff --git a/editor/editor_node.h b/editor/editor_node.h index c3b4c985cc..df3d2ae0f8 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -323,7 +323,7 @@ private: Control *vp_base = nullptr; EditorTitleBar *menu_hb = nullptr; - Control *main_control = nullptr; + VBoxContainer *main_screen_vbox = nullptr; MenuBar *main_menu = nullptr; PopupMenu *file_menu = nullptr; PopupMenu *project_menu = nullptr; @@ -788,7 +788,7 @@ public: bool is_changing_scene() const; - Control *get_main_control(); + VBoxContainer *get_main_screen_control(); SubViewport *get_scene_root() { return scene_root; } // Root of the scene being edited. void set_edited_scene(Node *p_scene); diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp index a8f8f7ab97..d1f41dad84 100644 --- a/editor/editor_path.cpp +++ b/editor/editor_path.cpp @@ -33,6 +33,7 @@ #include "editor/editor_data.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/multi_node_edit.h" void EditorPath::_add_children_to_popup(Object *p_obj, int p_depth) { if (p_depth > 8) { @@ -121,14 +122,22 @@ void EditorPath::update_path() { continue; } - Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(obj); + Ref<Texture2D> icon; + if (Object::cast_to<MultiNodeEdit>(obj)) { + icon = EditorNode::get_singleton()->get_class_icon(Object::cast_to<MultiNodeEdit>(obj)->get_edited_class_name()); + } else { + icon = EditorNode::get_singleton()->get_object_icon(obj); + } + if (icon.is_valid()) { current_object_icon->set_texture(icon); } if (i == history->get_path_size() - 1) { String name; - if (Object::cast_to<Resource>(obj)) { + if (obj->has_method("_get_editor_name")) { + name = obj->call("_get_editor_name"); + } else if (Object::cast_to<Resource>(obj)) { Resource *r = Object::cast_to<Resource>(obj); if (r->get_path().is_resource_file()) { name = r->get_path().get_file(); @@ -149,7 +158,7 @@ void EditorPath::update_path() { name = obj->get_class(); } - current_object_label->set_text(" " + name); // An extra space so the text is not too close of the icon. + current_object_label->set_text(name); set_tooltip_text(obj->get_class()); } } @@ -161,12 +170,12 @@ void EditorPath::clear_path() { current_object_label->set_text(""); current_object_icon->set_texture(nullptr); - sub_objects_icon->set_visible(false); + sub_objects_icon->hide(); } void EditorPath::enable_path() { set_disabled(false); - sub_objects_icon->set_visible(true); + sub_objects_icon->show(); } void EditorPath::_id_pressed(int p_idx) { @@ -186,7 +195,7 @@ void EditorPath::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { update_path(); - sub_objects_icon->set_texture(get_theme_icon(SNAME("select_arrow"), SNAME("Tree"))); + sub_objects_icon->set_texture(get_theme_icon(SNAME("arrow"), SNAME("OptionButton"))); current_object_label->add_theme_font_override("font", get_theme_font(SNAME("main"), SNAME("EditorFonts"))); } break; @@ -216,13 +225,12 @@ EditorPath::EditorPath(EditorSelectionHistory *p_history) { main_hb->add_child(current_object_icon); current_object_label = memnew(Label); - current_object_label->set_clip_text(true); - current_object_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_LEFT); + current_object_label->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS); current_object_label->set_h_size_flags(SIZE_EXPAND_FILL); main_hb->add_child(current_object_label); sub_objects_icon = memnew(TextureRect); - sub_objects_icon->set_visible(false); + sub_objects_icon->hide(); sub_objects_icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); main_hb->add_child(sub_objects_icon); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 1efbb7e40f..f3ac8f4ba0 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -156,8 +156,8 @@ void EditorInterface::set_main_screen_editor(const String &p_name) { EditorNode::get_singleton()->select_editor_by_name(p_name); } -Control *EditorInterface::get_editor_main_control() { - return EditorNode::get_singleton()->get_main_control(); +VBoxContainer *EditorInterface::get_editor_main_screen() { + return EditorNode::get_singleton()->get_main_screen_control(); } void EditorInterface::edit_resource(const Ref<Resource> &p_resource) { @@ -352,7 +352,7 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &EditorInterface::get_edited_scene_root); ClassDB::bind_method(D_METHOD("get_resource_previewer"), &EditorInterface::get_resource_previewer); ClassDB::bind_method(D_METHOD("get_resource_filesystem"), &EditorInterface::get_resource_file_system); - ClassDB::bind_method(D_METHOD("get_editor_main_control"), &EditorInterface::get_editor_main_control); + ClassDB::bind_method(D_METHOD("get_editor_main_screen"), &EditorInterface::get_editor_main_screen); ClassDB::bind_method(D_METHOD("make_mesh_previews", "meshes", "preview_size"), &EditorInterface::_make_mesh_previews); ClassDB::bind_method(D_METHOD("select_file", "file"), &EditorInterface::select_file); ClassDB::bind_method(D_METHOD("get_selected_path"), &EditorInterface::get_selected_path); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 1d6f48caa3..fe01524bea 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -72,7 +72,7 @@ protected: public: static EditorInterface *get_singleton() { return singleton; } - Control *get_editor_main_control(); + VBoxContainer *get_editor_main_screen(); void edit_resource(const Ref<Resource> &p_resource); void edit_node(Node *p_node); void edit_script(const Ref<Script> &p_script, int p_line = -1, int p_col = 0, bool p_grab_focus = true); diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h index 82aeebe14a..ae61418528 100644 --- a/editor/editor_properties_array_dict.h +++ b/editor/editor_properties_array_dict.h @@ -151,7 +151,7 @@ class EditorPropertyDictionary : public EditorProperty { Button *edit = nullptr; MarginContainer *container = nullptr; VBoxContainer *property_vbox = nullptr; - EditorSpinSlider *size_sliderv; + EditorSpinSlider *size_sliderv = nullptr; Button *button_add_item = nullptr; EditorPaginator *paginator = nullptr; diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index f717188b3b..5346052f4d 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -769,7 +769,7 @@ void EditorResourcePicker::_notification(int p_what) { } break; case NOTIFICATION_DRAW: { - draw_style_box(get_theme_stylebox(SNAME("bg"), SNAME("Tree")), Rect2(Point2(), get_size())); + draw_style_box(get_theme_stylebox(SNAME("panel"), SNAME("Tree")), Rect2(Point2(), get_size())); } break; case NOTIFICATION_DRAG_BEGIN: { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 73acab3876..74445e6caa 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -510,7 +510,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // Appearance: Caret EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "text_editor/appearance/caret/type", 0, "Line,Block") _initial_set("text_editor/appearance/caret/caret_blink", true); - EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "text_editor/appearance/caret/caret_blink_speed", 0.5, "0.1,10,0.01") + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "text_editor/appearance/caret/caret_blink_interval", 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); @@ -717,7 +717,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "network/debug/remote_port", 6007, "1,65535,1") // SSL - EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "network/ssl/editor_ssl_certificates", _SYSTEM_CERTS_PATH, "*.crt,*.pem", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); + EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "network/tls/editor_tls_certificates", _SYSTEM_CERTS_PATH, "*.crt,*.pem", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); // Profiler EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "debugger/profiler_frame_history_size", 3600, "60,10000,1") @@ -1467,9 +1467,10 @@ void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, c #ifdef MACOS_ENABLED // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS if (keycode == Key::KEY_DELETE) { - keycode = KeyModifierMask::CMD | Key::BACKSPACE; + keycode = KeyModifierMask::META | Key::BACKSPACE; } #endif + Ref<InputEventKey> ie; if (keycode != Key::NONE) { ie = InputEventKey::create_reference(keycode); @@ -1500,7 +1501,7 @@ Ref<Shortcut> ED_SHORTCUT_ARRAY(const String &p_path, const String &p_name, cons #ifdef MACOS_ENABLED // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS if (keycode == Key::KEY_DELETE) { - keycode = KeyModifierMask::CMD | Key::BACKSPACE; + keycode = KeyModifierMask::META | Key::BACKSPACE; } #endif diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp index d190ab57c3..ec67cde112 100644 --- a/editor/editor_settings_dialog.cpp +++ b/editor/editor_settings_dialog.cpp @@ -175,7 +175,7 @@ void EditorSettingsDialog::shortcut_input(const Ref<InputEvent> &p_event) { handled = true; } - if (k->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::F)) { + if (k->is_match(InputEventKey::create_reference(KeyModifierMask::CMD_OR_CTRL | Key::F))) { _focus_current_search_box(); handled = true; } @@ -193,7 +193,7 @@ void EditorSettingsDialog::_update_icons() { shortcut_search_box->set_clear_button_enabled(true); restart_close_button->set_icon(shortcuts->get_theme_icon(SNAME("Close"), SNAME("EditorIcons"))); - restart_container->add_theme_style_override("panel", shortcuts->get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + restart_container->add_theme_style_override("panel", shortcuts->get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); restart_icon->set_texture(shortcuts->get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); restart_label->add_theme_color_override("font_color", shortcuts->get_theme_color(SNAME("warning_color"), SNAME("Editor"))); } diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index 33632649c8..4cd046e811 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -42,7 +42,7 @@ String EditorSpinSlider::get_tooltip(const Point2 &p_pos) const { #else Key key = Key::CTRL; #endif - return TS->format_number(rtos(get_value())) + "\n\n" + vformat(TTR("Hold %s to round to integers. Hold Shift for more precise changes."), find_keycode_name(key)); + return TS->format_number(rtos(get_value())) + "\n\n" + vformat(TTR("Hold %s to round to integers.\nHold Shift for more precise changes."), find_keycode_name(key)); } return TS->format_number(rtos(get_value())); } @@ -121,7 +121,7 @@ void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) { pre_grab_value = get_max(); } - if (mm->is_command_pressed()) { + if (mm->is_command_or_control_pressed()) { // If control was just pressed, don't make the value do a huge jump in magnitude. if (grabbing_spinner_dist_cache != 0) { pre_grab_value += grabbing_spinner_dist_cache * get_step(); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 76d5daadfb..9e983839f9 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -157,24 +157,15 @@ void EditorColorMap::create() { static Ref<StyleBoxTexture> make_stylebox(Ref<Texture2D> p_texture, float p_left, float p_top, float p_right, float p_bottom, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1, bool p_draw_center = true) { Ref<StyleBoxTexture> style(memnew(StyleBoxTexture)); style->set_texture(p_texture); - style->set_margin_size(SIDE_LEFT, p_left * EDSCALE); - style->set_margin_size(SIDE_RIGHT, p_right * EDSCALE); - style->set_margin_size(SIDE_BOTTOM, p_bottom * EDSCALE); - style->set_margin_size(SIDE_TOP, p_top * EDSCALE); - style->set_default_margin(SIDE_LEFT, p_margin_left * EDSCALE); - style->set_default_margin(SIDE_RIGHT, p_margin_right * EDSCALE); - style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * EDSCALE); - style->set_default_margin(SIDE_TOP, p_margin_top * EDSCALE); + style->set_margin_size_individual(p_left * EDSCALE, p_top * EDSCALE, p_right * EDSCALE, p_bottom * EDSCALE); + style->set_default_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE); style->set_draw_center(p_draw_center); return style; } static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty)); - style->set_default_margin(SIDE_LEFT, p_margin_left * EDSCALE); - style->set_default_margin(SIDE_RIGHT, p_margin_right * EDSCALE); - style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * EDSCALE); - style->set_default_margin(SIDE_TOP, p_margin_top * EDSCALE); + style->set_default_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE); return style; } @@ -184,10 +175,7 @@ static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = // Adjust level of detail based on the corners' effective sizes. style->set_corner_detail(Math::ceil(0.8 * p_corner_width * EDSCALE)); style->set_corner_radius_all(p_corner_width * EDSCALE); - style->set_default_margin(SIDE_LEFT, p_margin_left * EDSCALE); - style->set_default_margin(SIDE_RIGHT, p_margin_right * EDSCALE); - style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * EDSCALE); - style->set_default_margin(SIDE_TOP, p_margin_top * EDSCALE); + style->set_default_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE); // Work around issue about antialiased edges being blurrier (GH-35279). style->set_anti_aliased(false); return style; @@ -600,10 +588,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Vector2 widget_default_margin = Vector2(extra_spacing + 6, extra_spacing + default_margin_size + 1) * EDSCALE; Ref<StyleBoxFlat> style_widget = style_default->duplicate(); - style_widget->set_default_margin(SIDE_LEFT, widget_default_margin.x); - style_widget->set_default_margin(SIDE_TOP, widget_default_margin.y); - style_widget->set_default_margin(SIDE_RIGHT, widget_default_margin.x); - style_widget->set_default_margin(SIDE_BOTTOM, widget_default_margin.y); + style_widget->set_default_margin_individual(widget_default_margin.x, widget_default_margin.y, widget_default_margin.x, widget_default_margin.y); style_widget->set_bg_color(dark_color_1); style_widget->set_border_color(dark_color_2); @@ -626,10 +611,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Style for windows, popups, etc.. Ref<StyleBoxFlat> style_popup = style_default->duplicate(); const int popup_margin_size = default_margin_size * EDSCALE * 3; - style_popup->set_default_margin(SIDE_LEFT, popup_margin_size); - style_popup->set_default_margin(SIDE_TOP, popup_margin_size); - style_popup->set_default_margin(SIDE_RIGHT, popup_margin_size); - style_popup->set_default_margin(SIDE_BOTTOM, popup_margin_size); + style_popup->set_default_margin_all(popup_margin_size); style_popup->set_border_color(contrast_color_1); const Color shadow_color = Color(0, 0, 0, dark_theme ? 0.3 : 0.1); style_popup->set_shadow_color(shadow_color); @@ -666,9 +648,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_tab_base->set_corner_radius(CORNER_BOTTOM_LEFT, 0); style_tab_base->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); - // Prevent visible artifacts and cover the top-left rounded corner of the panel below the tab if selected - // We can't prevent them with both rounded corners and non-zero border width, though - style_tab_base->set_expand_margin_size(SIDE_BOTTOM, corner_width > 0 ? corner_width : border_width); // When using a border width greater than 0, visually line up the left of the selected tab with the underlying panel. style_tab_base->set_expand_margin_size(SIDE_LEFT, -border_width); @@ -897,15 +876,15 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("hover", "CheckButton", style_menu); theme->set_stylebox("hover_pressed", "CheckButton", style_menu); - theme->set_icon("on", "CheckButton", theme->get_icon(SNAME("GuiToggleOn"), SNAME("EditorIcons"))); - theme->set_icon("on_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabled"), SNAME("EditorIcons"))); - theme->set_icon("off", "CheckButton", theme->get_icon(SNAME("GuiToggleOff"), SNAME("EditorIcons"))); - theme->set_icon("off_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOffDisabled"), SNAME("EditorIcons"))); + theme->set_icon("checked", "CheckButton", theme->get_icon(SNAME("GuiToggleOn"), SNAME("EditorIcons"))); + theme->set_icon("checked_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabled"), SNAME("EditorIcons"))); + theme->set_icon("unchecked", "CheckButton", theme->get_icon(SNAME("GuiToggleOff"), SNAME("EditorIcons"))); + theme->set_icon("unchecked_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOffDisabled"), SNAME("EditorIcons"))); - theme->set_icon("on_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOnMirrored"), SNAME("EditorIcons"))); - theme->set_icon("on_disabled_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabledMirrored"), SNAME("EditorIcons"))); - theme->set_icon("off_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOffMirrored"), SNAME("EditorIcons"))); - theme->set_icon("off_disabled_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOffDisabledMirrored"), SNAME("EditorIcons"))); + theme->set_icon("checked_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOnMirrored"), SNAME("EditorIcons"))); + theme->set_icon("checked_disabled_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabledMirrored"), SNAME("EditorIcons"))); + theme->set_icon("unchecked_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOffMirrored"), SNAME("EditorIcons"))); + theme->set_icon("unchecked_disabled_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOffDisabledMirrored"), SNAME("EditorIcons"))); theme->set_color("font_color", "CheckButton", font_color); theme->set_color("font_hover_color", "CheckButton", font_hover_color); @@ -921,14 +900,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("icon_disabled_color", "CheckButton", icon_disabled_color); theme->set_constant("h_separation", "CheckButton", 8 * EDSCALE); - theme->set_constant("check_v_adjust", "CheckButton", 0 * EDSCALE); + theme->set_constant("check_v_offset", "CheckButton", 0 * EDSCALE); // Checkbox Ref<StyleBoxFlat> sb_checkbox = style_menu->duplicate(); - sb_checkbox->set_default_margin(SIDE_LEFT, default_margin_size * EDSCALE); - sb_checkbox->set_default_margin(SIDE_RIGHT, default_margin_size * EDSCALE); - sb_checkbox->set_default_margin(SIDE_TOP, default_margin_size * EDSCALE); - sb_checkbox->set_default_margin(SIDE_BOTTOM, default_margin_size * EDSCALE); + sb_checkbox->set_default_margin_all(default_margin_size * EDSCALE); theme->set_stylebox("normal", "CheckBox", sb_checkbox); theme->set_stylebox("pressed", "CheckBox", sb_checkbox); @@ -958,7 +934,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("icon_disabled_color", "CheckBox", icon_disabled_color); theme->set_constant("h_separation", "CheckBox", 8 * EDSCALE); - theme->set_constant("check_v_adjust", "CheckBox", 0 * EDSCALE); + theme->set_constant("check_v_offset", "CheckBox", 0 * EDSCALE); // PopupDialog theme->set_stylebox("panel", "PopupDialog", style_popup); @@ -968,10 +944,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Use 1 pixel for the sides, since if 0 is used, the highlight of hovered items is drawn // on top of the popup border. This causes a 'gap' in the panel border when an item is highlighted, // and it looks weird. 1px solves this. - style_popup_menu->set_default_margin(SIDE_LEFT, EDSCALE); - style_popup_menu->set_default_margin(SIDE_TOP, 2 * EDSCALE); - style_popup_menu->set_default_margin(SIDE_RIGHT, EDSCALE); - style_popup_menu->set_default_margin(SIDE_BOTTOM, 2 * EDSCALE); + style_popup_menu->set_default_margin_individual(EDSCALE, 2 * EDSCALE, EDSCALE, 2 * EDSCALE); // Always display a border for PopupMenus so they can be distinguished from their background. style_popup_menu->set_border_width_all(EDSCALE); style_popup_menu->set_border_color(dark_color_2); @@ -1027,10 +1000,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { sub_inspector_bg->set_bg_color(dark_color_1.lerp(si_base_color, 0.08)); sub_inspector_bg->set_border_width_all(2 * EDSCALE); sub_inspector_bg->set_border_color(si_base_color * Color(0.7, 0.7, 0.7, 0.8)); - sub_inspector_bg->set_default_margin(SIDE_LEFT, 4 * EDSCALE); - sub_inspector_bg->set_default_margin(SIDE_RIGHT, 4 * EDSCALE); - sub_inspector_bg->set_default_margin(SIDE_BOTTOM, 4 * EDSCALE); - sub_inspector_bg->set_default_margin(SIDE_TOP, 4 * EDSCALE); + sub_inspector_bg->set_default_margin_all(4 * EDSCALE); sub_inspector_bg->set_corner_radius(CORNER_TOP_LEFT, 0); sub_inspector_bg->set_corner_radius(CORNER_TOP_RIGHT, 0); @@ -1098,7 +1068,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Make Trees easier to distinguish from other controls by using a darker background color. style_tree_bg->set_bg_color(dark_color_1.lerp(dark_color_2, 0.5)); style_tree_bg->set_border_color(dark_color_3); - theme->set_stylebox("bg", "Tree", style_tree_bg); + theme->set_stylebox("panel", "Tree", style_tree_bg); // Tree theme->set_icon("checked", "Tree", theme->get_icon(SNAME("GuiChecked"), SNAME("EditorIcons"))); @@ -1109,7 +1079,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("arrow_collapsed_mirrored", "Tree", theme->get_icon(SNAME("GuiTreeArrowLeft"), SNAME("EditorIcons"))); theme->set_icon("updown", "Tree", theme->get_icon(SNAME("GuiTreeUpdown"), SNAME("EditorIcons"))); theme->set_icon("select_arrow", "Tree", theme->get_icon(SNAME("GuiDropdown"), SNAME("EditorIcons"))); - theme->set_stylebox("bg_focus", "Tree", style_widget_focus); + theme->set_stylebox("focus", "Tree", style_widget_focus); theme->set_stylebox("custom_button", "Tree", make_empty_stylebox()); theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox()); theme->set_stylebox("custom_button_hover", "Tree", style_widget); @@ -1200,26 +1170,24 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_itemlist_cursor->set_draw_center(false); style_itemlist_cursor->set_border_width_all(border_width); style_itemlist_cursor->set_border_color(highlight_color); + theme->set_stylebox("panel", "ItemList", style_itemlist_bg); + theme->set_stylebox("focus", "ItemList", style_widget_focus); theme->set_stylebox("cursor", "ItemList", style_itemlist_cursor); theme->set_stylebox("cursor_unfocused", "ItemList", style_itemlist_cursor); theme->set_stylebox("selected_focus", "ItemList", style_tree_focus); theme->set_stylebox("selected", "ItemList", style_tree_selected); - theme->set_stylebox("bg_focus", "ItemList", style_widget_focus); - theme->set_stylebox("bg", "ItemList", style_itemlist_bg); theme->set_color("font_color", "ItemList", font_color); theme->set_color("font_selected_color", "ItemList", mono_color); theme->set_color("guide_color", "ItemList", guide_color); - theme->set_constant("v_separation", "ItemList", widget_default_margin.y - EDSCALE); + theme->set_constant("v_separation", "ItemList", force_even_vsep * 0.5 * EDSCALE); theme->set_constant("h_separation", "ItemList", 6 * EDSCALE); theme->set_constant("icon_margin", "ItemList", 6 * EDSCALE); theme->set_constant("line_separation", "ItemList", 3 * EDSCALE); // TabBar & TabContainer - Ref<StyleBoxFlat> style_tabbar_background = make_flat_stylebox(dark_color_1, 0, 0, 0, 0); - style_tabbar_background->set_expand_margin_size(SIDE_BOTTOM, corner_width > 0 ? corner_width : border_width); - style_tabbar_background->set_corner_detail(corner_width); - style_tabbar_background->set_corner_radius(CORNER_TOP_LEFT, corner_radius * EDSCALE); - style_tabbar_background->set_corner_radius(CORNER_TOP_RIGHT, corner_radius * EDSCALE); + Ref<StyleBoxFlat> style_tabbar_background = make_flat_stylebox(dark_color_1, 0, 0, 0, 0, corner_radius * EDSCALE); + style_tabbar_background->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + style_tabbar_background->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); theme->set_stylebox("tabbar_background", "TabContainer", style_tabbar_background); theme->set_stylebox("tab_selected", "TabContainer", style_tab_selected); @@ -1230,8 +1198,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled); theme->set_stylebox("button_pressed", "TabBar", style_menu); theme->set_stylebox("button_highlight", "TabBar", style_menu); - theme->set_stylebox("SceneTabFG", "EditorStyles", style_tab_selected); - theme->set_stylebox("SceneTabBG", "EditorStyles", style_tab_unselected); theme->set_color("font_selected_color", "TabContainer", font_color); theme->set_color("font_unselected_color", "TabContainer", font_disabled_color); theme->set_color("font_selected_color", "TabBar", font_color); @@ -1251,22 +1217,25 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("decrement_highlight", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowLeftHl"), SNAME("EditorIcons"))); theme->set_icon("drop_mark", "TabContainer", theme->get_icon(SNAME("GuiTabDropMark"), SNAME("EditorIcons"))); theme->set_icon("drop_mark", "TabBar", theme->get_icon(SNAME("GuiTabDropMark"), SNAME("EditorIcons"))); + theme->set_constant("side_margin", "TabContainer", 0); theme->set_constant("h_separation", "TabBar", 4 * EDSCALE); - // Content of each tab + // Content of each tab. Ref<StyleBoxFlat> style_content_panel = style_default->duplicate(); style_content_panel->set_border_color(dark_color_3); style_content_panel->set_border_width_all(border_width); style_content_panel->set_border_width(Side::SIDE_TOP, 0); style_content_panel->set_corner_radius(CORNER_TOP_LEFT, 0); style_content_panel->set_corner_radius(CORNER_TOP_RIGHT, 0); - // compensate the border - style_content_panel->set_default_margin(SIDE_TOP, (2 + margin_size_extra) * EDSCALE); - style_content_panel->set_default_margin(SIDE_RIGHT, margin_size_extra * EDSCALE); - style_content_panel->set_default_margin(SIDE_BOTTOM, margin_size_extra * EDSCALE); - style_content_panel->set_default_margin(SIDE_LEFT, margin_size_extra * EDSCALE); + // Compensate for the border. + style_content_panel->set_default_margin_individual(margin_size_extra * EDSCALE, (2 + margin_size_extra) * EDSCALE, margin_size_extra * EDSCALE, margin_size_extra * EDSCALE); theme->set_stylebox("panel", "TabContainer", style_content_panel); + // Bottom panel. + Ref<StyleBoxFlat> style_bottom_panel = style_content_panel->duplicate(); + style_bottom_panel->set_corner_radius_all(corner_radius * EDSCALE); + theme->set_stylebox("BottomPanel", "EditorStyles", style_bottom_panel); + // TabContainerOdd can be used on tabs against the base color background (e.g. nested tabs). theme->set_type_variation("TabContainerOdd", "TabContainer"); @@ -1280,10 +1249,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // This stylebox is used in 3d and 2d viewports (no borders). Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate(); - style_content_panel_vp->set_default_margin(SIDE_LEFT, border_width * 2); - style_content_panel_vp->set_default_margin(SIDE_TOP, default_margin_size * EDSCALE); - style_content_panel_vp->set_default_margin(SIDE_RIGHT, border_width * 2); - style_content_panel_vp->set_default_margin(SIDE_BOTTOM, border_width * 2); + style_content_panel_vp->set_default_margin_individual(border_width * 2, default_margin_size * EDSCALE, border_width * 2, border_width * 2); theme->set_stylebox("Content", "EditorStyles", style_content_panel_vp); // This stylebox is used by preview tabs in the Theme Editor. @@ -1345,7 +1311,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("normal", "TextEdit", style_line_edit); theme->set_stylebox("focus", "TextEdit", style_widget_focus); theme->set_stylebox("read_only", "TextEdit", style_line_edit_disabled); - theme->set_constant("side_margin", "TabContainer", 0); theme->set_icon("tab", "TextEdit", theme->get_icon(SNAME("GuiTab"), SNAME("EditorIcons"))); theme->set_icon("space", "TextEdit", theme->get_icon(SNAME("GuiSpace"), SNAME("EditorIcons"))); theme->set_color("font_color", "TextEdit", font_color); @@ -1363,6 +1328,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_constant("separation", "HSplitContainer", default_margin_size * 2 * EDSCALE); theme->set_constant("separation", "VSplitContainer", default_margin_size * 2 * EDSCALE); + theme->set_constant("minimum_grab_thickness", "HSplitContainer", 6 * EDSCALE); + theme->set_constant("minimum_grab_thickness", "VSplitContainer", 6 * EDSCALE); + // Containers theme->set_constant("separation", "BoxContainer", default_margin_size * EDSCALE); theme->set_constant("separation", "HBoxContainer", default_margin_size * EDSCALE); @@ -1422,6 +1390,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // AcceptDialog theme->set_stylebox("panel", "AcceptDialog", style_window_title); + theme->set_constant("buttons_separation", "AcceptDialog", 8 * EDSCALE); // HScrollBar Ref<Texture2D> empty_icon = memnew(ImageTexture); @@ -1520,10 +1489,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // is only relevant for default tooltips. Ref<StyleBoxFlat> style_tooltip = style_popup->duplicate(); style_tooltip->set_shadow_size(0); - style_tooltip->set_default_margin(SIDE_LEFT, default_margin_size * EDSCALE * 0.5); - style_tooltip->set_default_margin(SIDE_TOP, default_margin_size * EDSCALE * 0.5); - style_tooltip->set_default_margin(SIDE_RIGHT, default_margin_size * EDSCALE * 0.5); - style_tooltip->set_default_margin(SIDE_BOTTOM, default_margin_size * EDSCALE * 0.5); + style_tooltip->set_default_margin_all(default_margin_size * EDSCALE * 0.5); style_tooltip->set_bg_color(dark_color_3 * Color(0.8, 0.8, 0.8, 0.9)); style_tooltip->set_border_width_all(0); theme->set_color("font_color", "TooltipLabel", font_hover_color); @@ -1549,8 +1515,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("updown_disabled", "SpinBox", theme->get_icon(SNAME("GuiSpinboxUpdownDisabled"), SNAME("EditorIcons"))); // ProgressBar - theme->set_stylebox("bg", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressBar"), SNAME("EditorIcons")), 4, 4, 4, 4, 0, 0, 0, 0)); - theme->set_stylebox("fg", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressFill"), SNAME("EditorIcons")), 6, 6, 6, 6, 2, 1, 2, 1)); + theme->set_stylebox("background", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressBar"), SNAME("EditorIcons")), 4, 4, 4, 4, 0, 0, 0, 0)); + theme->set_stylebox("fill", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressFill"), SNAME("EditorIcons")), 6, 6, 6, 6, 2, 1, 2, 1)); theme->set_color("font_color", "ProgressBar", font_color); // GraphEdit @@ -1696,7 +1662,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("toggle_hidden", "FileDialog", theme->get_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons"))); // Use a different color for folder icons to make them easier to distinguish from files. // On a light theme, the icon will be dark, so we need to lighten it before blending it with the accent color. - theme->set_color("folder_icon_modulate", "FileDialog", (dark_theme ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25)).lerp(accent_color, 0.7)); + theme->set_color("folder_icon_color", "FileDialog", (dark_theme ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25)).lerp(accent_color, 0.7)); theme->set_color("files_disabled", "FileDialog", font_disabled_color); // ColorPicker diff --git a/editor/editor_toaster.cpp b/editor/editor_toaster.cpp index 5b015fc95c..6a5242f0c6 100644 --- a/editor/editor_toaster.cpp +++ b/editor/editor_toaster.cpp @@ -284,7 +284,7 @@ void EditorToaster::_draw_button() { void EditorToaster::_draw_progress(Control *panel) { if (toasts.has(panel) && toasts[panel].remaining_time > 0 && toasts[panel].duration > 0) { Size2 size = panel->get_size(); - size.x *= MIN(1, Math::range_lerp(toasts[panel].remaining_time, 0, toasts[panel].duration, 0, 2)); + size.x *= MIN(1, Math::remap(toasts[panel].remaining_time, 0, toasts[panel].duration, 0, 2)); Ref<StyleBoxFlat> stylebox; switch (toasts[panel].severity) { @@ -498,10 +498,7 @@ EditorToaster::EditorToaster() { Ref<StyleBoxFlat> boxes[] = { info_panel_style_background, warning_panel_style_background, error_panel_style_background }; for (int i = 0; i < 3; i++) { - boxes[i]->set_default_margin(SIDE_LEFT, int(stylebox_radius * 2.5)); - boxes[i]->set_default_margin(SIDE_RIGHT, int(stylebox_radius * 2.5)); - boxes[i]->set_default_margin(SIDE_TOP, 3); - boxes[i]->set_default_margin(SIDE_BOTTOM, 3); + boxes[i]->set_default_margin_individual(int(stylebox_radius * 2.5), 3, int(stylebox_radius * 2.5), 3); } // Theming (progress). diff --git a/editor/editor_zoom_widget.cpp b/editor/editor_zoom_widget.cpp index e4beea5e5f..88e99d9b30 100644 --- a/editor/editor_zoom_widget.cpp +++ b/editor/editor_zoom_widget.cpp @@ -167,7 +167,7 @@ EditorZoomWidget::EditorZoomWidget() { zoom_minus->set_flat(true); add_child(zoom_minus); zoom_minus->connect("pressed", callable_mp(this, &EditorZoomWidget::_button_zoom_minus)); - zoom_minus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_minus", TTR("Zoom Out"), KeyModifierMask::CMD | Key::MINUS)); + zoom_minus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_minus", TTR("Zoom Out"), KeyModifierMask::CMD_OR_CTRL | Key::MINUS)); zoom_minus->set_shortcut_context(this); zoom_minus->set_focus_mode(FOCUS_NONE); @@ -189,7 +189,7 @@ EditorZoomWidget::EditorZoomWidget() { zoom_plus->set_flat(true); add_child(zoom_plus); zoom_plus->connect("pressed", callable_mp(this, &EditorZoomWidget::_button_zoom_plus)); - zoom_plus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_plus", TTR("Zoom In"), KeyModifierMask::CMD | Key::EQUAL)); // Usually direct access key for PLUS + zoom_plus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_plus", TTR("Zoom In"), KeyModifierMask::CMD_OR_CTRL | Key::EQUAL)); // Usually direct access key for PLUS zoom_plus->set_shortcut_context(this); zoom_plus->set_focus_mode(FOCUS_NONE); diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index 525a962222..2a444bb04f 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -287,7 +287,7 @@ Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_pat Ref<ImageTexture> EditorExportPlatform::get_option_icon(int p_index) const { Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme(); ERR_FAIL_COND_V(theme.is_null(), Ref<ImageTexture>()); - if (EditorNode::get_singleton()->get_main_control()->is_layout_rtl()) { + if (EditorNode::get_singleton()->get_main_screen_control()->is_layout_rtl()) { return theme->get_icon(SNAME("PlayBackwards"), SNAME("EditorIcons")); } else { return theme->get_icon(SNAME("Play"), SNAME("EditorIcons")); diff --git a/editor/export/export_template_manager.cpp b/editor/export/export_template_manager.cpp index 0ecbc9a8a3..ceb5b63293 100644 --- a/editor/export/export_template_manager.cpp +++ b/editor/export/export_template_manager.cpp @@ -172,7 +172,7 @@ void ExportTemplateManager::_download_template_completed(int p_status, int p_cod case HTTPRequest::RESULT_BODY_SIZE_LIMIT_EXCEEDED: case HTTPRequest::RESULT_CONNECTION_ERROR: case HTTPRequest::RESULT_CHUNKED_BODY_SIZE_MISMATCH: - case HTTPRequest::RESULT_SSL_HANDSHAKE_ERROR: + case HTTPRequest::RESULT_TLS_HANDSHAKE_ERROR: case HTTPRequest::RESULT_CANT_CONNECT: { _set_current_progress_status(TTR("Can't connect to the mirror."), true); } break; @@ -345,8 +345,8 @@ bool ExportTemplateManager::_humanize_http_status(HTTPRequest *p_request, String *r_status = TTR("Connection Error"); success = false; break; - case HTTPClient::STATUS_SSL_HANDSHAKE_ERROR: - *r_status = TTR("SSL Handshake Error"); + case HTTPClient::STATUS_TLS_HANDSHAKE_ERROR: + *r_status = TTR("TLS Handshake Error"); success = false; break; } diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 19788e70da..19b4932d3d 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -76,7 +76,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory subdirectory_item->set_text(0, dname); subdirectory_item->set_structured_text_bidi_override(0, TextServer::STRUCTURED_TEXT_FILE); subdirectory_item->set_icon(0, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); - subdirectory_item->set_icon_modulate(0, get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"))); + subdirectory_item->set_icon_modulate(0, get_theme_color(SNAME("folder_icon_color"), SNAME("FileDialog"))); subdirectory_item->set_selectable(0, true); String lpath = p_dir->get_path(); subdirectory_item->set_metadata(0, lpath); @@ -246,7 +246,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo } Ref<Texture2D> folder_icon = get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")); - const Color folder_color = get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog")); + const Color folder_color = get_theme_color(SNAME("folder_icon_color"), SNAME("FileDialog")); String text; Ref<Texture2D> icon; @@ -778,7 +778,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) { } Ref<Texture2D> folder_icon = (use_thumbnails) ? folder_thumbnail : get_theme_icon(SNAME("folder"), SNAME("FileDialog")); - const Color folder_color = get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog")); + const Color folder_color = get_theme_color(SNAME("folder_icon_color"), SNAME("FileDialog")); // Build the FileInfo list. List<FileInfo> file_list; @@ -3021,10 +3021,10 @@ FileSystemDock::FileSystemDock() { set_name("FileSystem"); path = "res://"; - // `KeyModifierMask::CMD | Key::C` conflicts with other editor shortcuts. - ED_SHORTCUT("filesystem_dock/copy_path", TTR("Copy Path"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::C); + // `KeyModifierMask::CMD_OR_CTRL | Key::C` conflicts with other editor shortcuts. + ED_SHORTCUT("filesystem_dock/copy_path", TTR("Copy Path"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::C); ED_SHORTCUT("filesystem_dock/copy_uid", TTR("Copy UID")); - ED_SHORTCUT("filesystem_dock/duplicate", TTR("Duplicate..."), KeyModifierMask::CMD | Key::D); + ED_SHORTCUT("filesystem_dock/duplicate", TTR("Duplicate..."), KeyModifierMask::CMD_OR_CTRL | Key::D); ED_SHORTCUT("filesystem_dock/delete", TTR("Delete"), Key::KEY_DELETE); ED_SHORTCUT("filesystem_dock/rename", TTR("Rename..."), Key::F2); ED_SHORTCUT_OVERRIDE("filesystem_dock/rename", "macos", Key::ENTER); diff --git a/editor/icons/MemberAnnotation.svg b/editor/icons/MemberAnnotation.svg new file mode 100644 index 0000000000..c73ebf7b9b --- /dev/null +++ b/editor/icons/MemberAnnotation.svg @@ -0,0 +1 @@ +<svg width="16" height="16" version="1.0" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><script id="custom-useragent-string-page-script"/><path d="m13.821 12.756c-5.0033 3.9148-12.551 2.248-12.49-4.538 0.67424-11.471 17.312-7.4502 12.446 2.1173-1.0549 1.1955-2.0737 1.4617-3.1983 0.4329-0.21023-0.19282-0.44783-1.1594-0.3819-1.5089 0.35827-1.8946 1.0885-4.0778-0.72151-4.7234-2.4171-0.86457-4.5592 1.6495-4.9697 4.0193-0.47396 2.7343 2.284 3.3749 4.1487 1.9879 0.4553-0.36324 1.6433-1.3796 1.6806-1.9742" fill="none" stroke="#e0e0e0" stroke-linejoin="round" stroke-width="1.4928"/></svg> diff --git a/editor/icons/SceneUniqueName.svg b/editor/icons/SceneUniqueName.svg index 34279a14a6..c8aca7b3e6 100644 --- a/editor/icons/SceneUniqueName.svg +++ b/editor/icons/SceneUniqueName.svg @@ -1 +1,2 @@ -<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M4.378 2.224q1.235 0 2.084.866.865.85.865 2.083 0 1.17-.881 2.036-.866.85-2.068.85-1.218 0-2.083-.85-.866-.866-.866-2.068t.866-2.051q.865-.866 2.083-.866zm.962 1.988q-.4-.4-.962-.4-.56 0-.961.4-.401.384-.401.93 0 .56.4.961.401.385.962.385.561 0 .962-.385.4-.4.4-.946 0-.56-.4-.945zm5.45-2.116h1.218L5.677 13.78H4.442Zm1.17 5.722q1.234 0 2.083.866.866.849.866 2.1 0 1.17-.882 2.035-.865.85-2.068.85-1.218 0-2.083-.85-.866-.866-.866-2.084 0-1.202.866-2.051.865-.866 2.083-.866zm.961 1.987q-.4-.4-.962-.4-.56 0-.961.4-.4.385-.4.946 0 .561.4.962.4.384.961.384.561 0 .962-.384.4-.4.4-.946 0-.56-.4-.962z" aria-label="%" style="font-weight:600;font-size:16.0277px;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';letter-spacing:0;word-spacing:0;fill:#e0e0e0;fill-opacity:.996078;stroke-width:.400692"/></svg> +<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4.378 2.224q1.235 0 2.084.866.865.85.865 2.083 0 1.17-.881 2.036-.866.85-2.068.85-1.218 0-2.083-.85-.866-.866-.866-2.068t.866-2.051q.865-.866 2.083-.866zm.962 1.988q-.4-.4-.962-.4-.56 0-.961.4-.401.384-.401.93 0 .56.4.961.401.385.962.385.561 0 .962-.385.4-.4.4-.946 0-.56-.4-.945zm5.45-2.116h1.218l-6.331 11.684h-1.235zm1.17 5.722q1.234 0 2.083.866.866.849.866 2.1 0 1.17-.882 2.035-.865.85-2.068.85-1.218 0-2.083-.85-.866-.866-.866-2.084 0-1.202.866-2.051.865-.866 2.083-.866zm.961 1.987q-.4-.4-.962-.4-.56 0-.961.4-.4.385-.4.946 0 .561.4.962.4.384.961.384.561 0 .962-.384.4-.4.4-.946 0-.56-.4-.962z" fill="#e0e0e0" stroke-width=".400692"/></svg> + diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index 405d8d2169..d1f37179f3 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -1343,8 +1343,8 @@ DynamicFontImportSettings::DynamicFontImportSettings() { for (int i = 0; i < 16; i++) { glyph_table->set_column_title(i + 1, String::num_int64(i, 16)); } - glyph_table->add_theme_style_override("selected", glyph_table->get_theme_stylebox(SNAME("bg"))); - glyph_table->add_theme_style_override("selected_focus", glyph_table->get_theme_stylebox(SNAME("bg"))); + glyph_table->add_theme_style_override("selected", glyph_table->get_theme_stylebox(SNAME("panel"))); + glyph_table->add_theme_style_override("selected_focus", glyph_table->get_theme_stylebox(SNAME("panel"))); glyph_table->add_theme_constant_override("h_separation", 0); glyph_table->set_h_size_flags(Control::SIZE_EXPAND_FILL); glyph_table->set_v_size_flags(Control::SIZE_EXPAND_FILL); diff --git a/editor/import/post_import_plugin_skeleton_renamer.cpp b/editor/import/post_import_plugin_skeleton_renamer.cpp index 69c0a047e4..72ccb832c7 100644 --- a/editor/import/post_import_plugin_skeleton_renamer.cpp +++ b/editor/import/post_import_plugin_skeleton_renamer.cpp @@ -143,7 +143,7 @@ void PostImportPluginSkeletonRenamer::internal_process(InternalImportCategory p_ // Make unique skeleton. if (bool(p_options["retarget/bone_renamer/unique_node/make_unique"])) { String unique_name = String(p_options["retarget/bone_renamer/unique_node/skeleton_name"]); - ERR_FAIL_COND_MSG(unique_name == String(), "Skeleton unique name cannot be empty."); + ERR_FAIL_COND_MSG(unique_name.is_empty(), "Skeleton unique name cannot be empty."); TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer"); while (nodes.size()) { diff --git a/editor/import/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/post_import_plugin_skeleton_rest_fixer.cpp index 6f775c7ea8..a5ef2e7f97 100644 --- a/editor/import/post_import_plugin_skeleton_rest_fixer.cpp +++ b/editor/import/post_import_plugin_skeleton_rest_fixer.cpp @@ -90,16 +90,9 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory } } - // Apply node transforms. + // Get global transform. + Transform3D global_transform; if (bool(p_options["retarget/rest_fixer/apply_node_transforms"])) { - LocalVector<Transform3D> old_skeleton_rest; - LocalVector<Transform3D> old_skeleton_global_rest; - for (int i = 0; i < src_skeleton->get_bone_count(); i++) { - old_skeleton_rest.push_back(src_skeleton->get_bone_rest(i)); - old_skeleton_global_rest.push_back(src_skeleton->get_bone_global_rest(i)); - } - - Transform3D global_transform; Node *pr = src_skeleton; while (pr) { Node3D *pr3d = Object::cast_to<Node3D>(pr); @@ -109,6 +102,47 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory } pr = pr->get_parent(); } + global_transform.origin = Vector3(); // Translation by a Node is not a bone animation, so the retargeted model should be at the origin. + } + + // Calc IBM difference. + LocalVector<Vector<Transform3D>> ibm_diffs; + { + TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D"); + while (nodes.size()) { + ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back()); + ERR_CONTINUE(!mi); + + Ref<Skin> skin = mi->get_skin(); + ERR_CONTINUE(!skin.is_valid()); + + Node *node = mi->get_node(mi->get_skeleton_path()); + ERR_CONTINUE(!node); + + Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node); + if (!mesh_skeleton || mesh_skeleton != src_skeleton) { + continue; + } + + Vector<Transform3D> ibm_diff; + ibm_diff.resize(src_skeleton->get_bone_count()); + Transform3D *ibm_diff_w = ibm_diff.ptrw(); + + int skin_len = skin->get_bind_count(); + for (int i = 0; i < skin_len; i++) { + StringName bn = skin->get_bind_name(i); + int bone_idx = src_skeleton->find_bone(bn); + if (bone_idx >= 0) { + ibm_diff_w[bone_idx] = global_transform * src_skeleton->get_bone_global_rest(bone_idx) * skin->get_bind_pose(i); + } + } + + ibm_diffs.push_back(ibm_diff); + } + } + + // Apply node transforms. + if (bool(p_options["retarget/rest_fixer/apply_node_transforms"])) { Vector3 scl = global_transform.basis.get_scale_local(); Vector<int> bones_to_process = src_skeleton->get_parentless_bones(); @@ -148,38 +182,42 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory String track_path = String(anim->track_get_path(i).get_concatenated_names()); Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path)); - if (node) { - Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); - if (track_skeleton && track_skeleton == src_skeleton) { - StringName bn = anim->track_get_path(i).get_subname(0); - if (bn) { - int bone_idx = src_skeleton->find_bone(bn); - int key_len = anim->track_get_key_count(i); - if (anim->track_get_type(i) == Animation::TYPE_POSITION_3D) { - if (bones_to_process.has(bone_idx)) { - for (int j = 0; j < key_len; j++) { - Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j)); - anim->track_set_key_value(i, j, global_transform.basis.xform(ps) + global_transform.origin); - } - } else { - for (int j = 0; j < key_len; j++) { - Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j)); - anim->track_set_key_value(i, j, ps * scl); - } - } - } else if (bones_to_process.has(bone_idx)) { - if (anim->track_get_type(i) == Animation::TYPE_ROTATION_3D) { - for (int j = 0; j < key_len; j++) { - Quaternion qt = static_cast<Quaternion>(anim->track_get_key_value(i, j)); - anim->track_set_key_value(i, j, global_transform.basis.get_rotation_quaternion() * qt); - } - } else { - for (int j = 0; j < key_len; j++) { - Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j))); - anim->track_set_key_value(i, j, (global_transform.basis * sc).get_scale()); - } - } - } + ERR_CONTINUE(!node); + + Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); + if (!track_skeleton || track_skeleton != src_skeleton) { + continue; + } + + StringName bn = anim->track_get_path(i).get_subname(0); + if (!bn) { + continue; + } + + int bone_idx = src_skeleton->find_bone(bn); + int key_len = anim->track_get_key_count(i); + if (anim->track_get_type(i) == Animation::TYPE_POSITION_3D) { + if (bones_to_process.has(bone_idx)) { + for (int j = 0; j < key_len; j++) { + Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j)); + anim->track_set_key_value(i, j, global_transform.basis.xform(ps) + global_transform.origin); + } + } else { + for (int j = 0; j < key_len; j++) { + Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j)); + anim->track_set_key_value(i, j, ps * scl); + } + } + } else if (bones_to_process.has(bone_idx)) { + if (anim->track_get_type(i) == Animation::TYPE_ROTATION_3D) { + for (int j = 0; j < key_len; j++) { + Quaternion qt = static_cast<Quaternion>(anim->track_get_key_value(i, j)); + anim->track_set_key_value(i, j, global_transform.basis.get_rotation_quaternion() * qt); + } + } else { + for (int j = 0; j < key_len; j++) { + Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j))); + anim->track_set_key_value(i, j, (global_transform.basis * sc).get_scale()); } } } @@ -220,24 +258,26 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory } } - if (found_skeleton) { - // Search and insert rot track if it doesn't exist. - for (int prof_idx = 0; prof_idx < prof_skeleton->get_bone_count(); prof_idx++) { - String bone_name = is_renamed ? prof_skeleton->get_bone_name(prof_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_idx))); - if (bone_name == String()) { - continue; - } - int src_idx = src_skeleton->find_bone(bone_name); - if (src_idx == -1) { - continue; - } - String insert_path = track_path + ":" + bone_name; - int rot_track = anim->find_track(insert_path, Animation::TYPE_ROTATION_3D); - if (rot_track == -1) { - int track = anim->add_track(Animation::TYPE_ROTATION_3D); - anim->track_set_path(track, insert_path); - anim->rotation_track_insert_key(track, 0, src_skeleton->get_bone_rest(src_idx).basis.get_rotation_quaternion()); - } + if (!found_skeleton) { + continue; + } + + // Search and insert rot track if it doesn't exist. + for (int prof_idx = 0; prof_idx < prof_skeleton->get_bone_count(); prof_idx++) { + String bone_name = is_renamed ? prof_skeleton->get_bone_name(prof_idx) : String(bone_map->get_skeleton_bone_name(prof_skeleton->get_bone_name(prof_idx))); + if (bone_name.is_empty()) { + continue; + } + int src_idx = src_skeleton->find_bone(bone_name); + if (src_idx == -1) { + continue; + } + String insert_path = track_path + ":" + bone_name; + int rot_track = anim->find_track(insert_path, Animation::TYPE_ROTATION_3D); + if (rot_track == -1) { + int track = anim->add_track(Animation::TYPE_ROTATION_3D); + anim->track_set_path(track, insert_path); + anim->rotation_track_insert_key(track, 0, src_skeleton->get_bone_rest(src_idx).basis.get_rotation_quaternion()); } } } @@ -385,19 +425,23 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory String track_path = String(anim->track_get_path(i).get_concatenated_names()); Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path)); - if (node) { - Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); - if (track_skeleton && track_skeleton == src_skeleton) { - StringName bn = anim->track_get_path(i).get_concatenated_subnames(); - if (bn == scale_base_bone_name) { - int key_len = anim->track_get_key_count(i); - for (int j = 0; j < key_len; j++) { - Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j)); - pos.y += base_adjustment; - anim->track_set_key_value(i, j, pos); - } - } - } + ERR_CONTINUE(!node); + + Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); + if (!track_skeleton || track_skeleton != src_skeleton) { + continue; + } + + StringName bn = anim->track_get_path(i).get_concatenated_subnames(); + if (bn != scale_base_bone_name) { + continue; + } + + int key_len = anim->track_get_key_count(i); + for (int j = 0; j < key_len; j++) { + Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j)); + pos.y += base_adjustment; + anim->track_set_key_value(i, j, pos); } } } @@ -441,16 +485,18 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory String track_path = String(anim->track_get_path(i).get_concatenated_names()); Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path)); - if (node) { - Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); - if (track_skeleton && track_skeleton == src_skeleton) { - real_t mlt = 1 / src_skeleton->get_motion_scale(); - int key_len = anim->track_get_key_count(i); - for (int j = 0; j < key_len; j++) { - Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j)); - anim->track_set_key_value(i, j, pos * mlt); - } - } + ERR_CONTINUE(!node); + + Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); + if (!track_skeleton || track_skeleton != src_skeleton) { + continue; + } + + real_t mlt = 1 / src_skeleton->get_motion_scale(); + int key_len = anim->track_get_key_count(i); + for (int j = 0; j < key_len; j++) { + Vector3 pos = static_cast<Vector3>(anim->track_get_key_value(i, j)); + anim->track_set_key_value(i, j, pos * mlt); } } } @@ -518,6 +564,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer"); while (nodes.size()) { AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back()); + ERR_CONTINUE(!ap); List<StringName> anims; ap->get_animation_list(&anims); for (const StringName &name : anims) { @@ -534,53 +581,57 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory String track_path = String(anim->track_get_path(i).get_concatenated_names()); Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path)); - if (node) { - Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); - if (track_skeleton && track_skeleton == src_skeleton) { - StringName bn = anim->track_get_path(i).get_subname(0); - if (bn) { - int bone_idx = src_skeleton->find_bone(bn); - - Transform3D old_rest = old_skeleton_rest[bone_idx]; - Transform3D new_rest = src_skeleton->get_bone_rest(bone_idx); - Transform3D old_pg; - Transform3D new_pg; - int parent_idx = src_skeleton->get_bone_parent(bone_idx); - if (parent_idx >= 0) { - old_pg = old_skeleton_global_rest[parent_idx]; - new_pg = src_skeleton->get_bone_global_rest(parent_idx); - } - - int key_len = anim->track_get_key_count(i); - if (anim->track_get_type(i) == Animation::TYPE_ROTATION_3D) { - Quaternion old_rest_q = old_rest.basis.get_rotation_quaternion(); - Quaternion new_rest_q = new_rest.basis.get_rotation_quaternion(); - Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion(); - Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion(); - for (int j = 0; j < key_len; j++) { - Quaternion qt = static_cast<Quaternion>(anim->track_get_key_value(i, j)); - anim->track_set_key_value(i, j, new_pg_q.inverse() * old_pg_q * qt * old_rest_q.inverse() * old_pg_q.inverse() * new_pg_q * new_rest_q); - } - } else if (anim->track_get_type(i) == Animation::TYPE_SCALE_3D) { - Basis old_rest_b = old_rest.basis; - Basis new_rest_b = new_rest.basis; - Basis old_pg_b = old_pg.basis; - Basis new_pg_b = new_pg.basis; - for (int j = 0; j < key_len; j++) { - Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j))); - anim->track_set_key_value(i, j, (new_pg_b.inverse() * old_pg_b * sc * old_rest_b.inverse() * old_pg_b.inverse() * new_pg_b * new_rest_b).get_scale()); - } - } else { - Vector3 old_rest_o = old_rest.origin; - Vector3 new_rest_o = new_rest.origin; - Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion(); - Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion(); - for (int j = 0; j < key_len; j++) { - Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j)); - anim->track_set_key_value(i, j, new_pg_q.xform_inv(old_pg_q.xform(ps - old_rest_o)) + new_rest_o); - } - } - } + ERR_CONTINUE(!node); + + Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); + if (!track_skeleton || track_skeleton != src_skeleton) { + continue; + } + + StringName bn = anim->track_get_path(i).get_subname(0); + if (!bn) { + continue; + } + + int bone_idx = src_skeleton->find_bone(bn); + + Transform3D old_rest = old_skeleton_rest[bone_idx]; + Transform3D new_rest = src_skeleton->get_bone_rest(bone_idx); + Transform3D old_pg; + Transform3D new_pg; + int parent_idx = src_skeleton->get_bone_parent(bone_idx); + if (parent_idx >= 0) { + old_pg = old_skeleton_global_rest[parent_idx]; + new_pg = src_skeleton->get_bone_global_rest(parent_idx); + } + + int key_len = anim->track_get_key_count(i); + if (anim->track_get_type(i) == Animation::TYPE_ROTATION_3D) { + Quaternion old_rest_q = old_rest.basis.get_rotation_quaternion(); + Quaternion new_rest_q = new_rest.basis.get_rotation_quaternion(); + Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion(); + Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion(); + for (int j = 0; j < key_len; j++) { + Quaternion qt = static_cast<Quaternion>(anim->track_get_key_value(i, j)); + anim->track_set_key_value(i, j, new_pg_q.inverse() * old_pg_q * qt * old_rest_q.inverse() * old_pg_q.inverse() * new_pg_q * new_rest_q); + } + } else if (anim->track_get_type(i) == Animation::TYPE_SCALE_3D) { + Basis old_rest_b = old_rest.basis; + Basis new_rest_b = new_rest.basis; + Basis old_pg_b = old_pg.basis; + Basis new_pg_b = new_pg.basis; + for (int j = 0; j < key_len; j++) { + Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j))); + anim->track_set_key_value(i, j, (new_pg_b.inverse() * old_pg_b * sc * old_rest_b.inverse() * old_pg_b.inverse() * new_pg_b * new_rest_b).get_scale()); + } + } else { + Vector3 old_rest_o = old_rest.origin; + Vector3 new_rest_o = new_rest.origin; + Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion(); + Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion(); + for (int j = 0; j < key_len; j++) { + Vector3 ps = static_cast<Vector3>(anim->track_get_key_value(i, j)); + anim->track_set_key_value(i, j, new_pg_q.xform_inv(old_pg_q.xform(ps - old_rest_o)) + new_rest_o); } } } @@ -595,26 +646,35 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory // Fix skin. { TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D"); + int skin_idx = 0; while (nodes.size()) { ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back()); + ERR_CONTINUE(!mi); + Ref<Skin> skin = mi->get_skin(); - if (skin.is_valid()) { - Node *node = mi->get_node(mi->get_skeleton_path()); - if (node) { - Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node); - if (mesh_skeleton && node == src_skeleton) { - int skin_len = skin->get_bind_count(); - for (int i = 0; i < skin_len; i++) { - StringName bn = skin->get_bind_name(i); - int bone_idx = src_skeleton->find_bone(bn); - if (bone_idx >= 0) { - Transform3D new_rest = silhouette_diff[i] * src_skeleton->get_bone_global_rest(bone_idx); - skin->set_bind_pose(i, new_rest.inverse()); - } - } - } + ERR_CONTINUE(!skin.is_valid()); + + Node *node = mi->get_node(mi->get_skeleton_path()); + ERR_CONTINUE(!node); + + Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node); + if (!mesh_skeleton || mesh_skeleton != src_skeleton) { + continue; + } + + Vector<Transform3D> ibm_diff = ibm_diffs[skin_idx]; + + int skin_len = skin->get_bind_count(); + for (int i = 0; i < skin_len; i++) { + StringName bn = skin->get_bind_name(i); + int bone_idx = src_skeleton->find_bone(bn); + if (bone_idx >= 0) { + Transform3D new_rest = silhouette_diff[i] * src_skeleton->get_bone_global_rest(bone_idx); + skin->set_bind_pose(i, new_rest.inverse() * ibm_diff[bone_idx]); } } + + skin_idx++; } } diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 62cb6e4167..41061c3fc3 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -368,6 +368,185 @@ static void _pre_gen_shape_list(Ref<ImporterMesh> &mesh, Vector<Ref<Shape3D>> &r } } +struct ScalableNodeCollection { + HashSet<Node3D *> node_3ds; + HashSet<Ref<ImporterMesh>> importer_meshes; + HashSet<Ref<Skin>> skins; + HashSet<Ref<Animation>> animations; +}; + +void _rescale_importer_mesh(Vector3 p_scale, Ref<ImporterMesh> p_mesh, bool is_shadow = false) { + // MESH and SKIN data divide, to compensate for object position multiplying. + + const int surf_count = p_mesh->get_surface_count(); + const int blendshape_count = p_mesh->get_blend_shape_count(); + struct LocalSurfData { + Mesh::PrimitiveType prim = {}; + Array arr; + Array bsarr; + Dictionary lods; + String name; + Ref<Material> mat; + int fmt_compress_flags = 0; + }; + + Vector<LocalSurfData> surf_data_by_mesh; + + Vector<String> blendshape_names; + for (int bsidx = 0; bsidx < blendshape_count; bsidx++) { + blendshape_names.append(p_mesh->get_blend_shape_name(bsidx)); + } + + for (int surf_idx = 0; surf_idx < surf_count; surf_idx++) { + Mesh::PrimitiveType prim = p_mesh->get_surface_primitive_type(surf_idx); + const int fmt_compress_flags = p_mesh->get_surface_format(surf_idx); + Array arr = p_mesh->get_surface_arrays(surf_idx); + String name = p_mesh->get_surface_name(surf_idx); + Dictionary lods = Dictionary(); + Ref<Material> mat = p_mesh->get_surface_material(surf_idx); + { + Vector<Vector3> vertex_array = arr[ArrayMesh::ARRAY_VERTEX]; + for (int vert_arr_i = 0; vert_arr_i < vertex_array.size(); vert_arr_i++) { + vertex_array.write[vert_arr_i] = vertex_array[vert_arr_i] * p_scale; + } + arr[ArrayMesh::ARRAY_VERTEX] = vertex_array; + } + Array blendshapes; + for (int bsidx = 0; bsidx < blendshape_count; bsidx++) { + Array current_bsarr = p_mesh->get_surface_blend_shape_arrays(surf_idx, bsidx); + Vector<Vector3> current_bs_vertex_array = current_bsarr[ArrayMesh::ARRAY_VERTEX]; + int current_bs_vert_arr_len = current_bs_vertex_array.size(); + for (int32_t bs_vert_arr_i = 0; bs_vert_arr_i < current_bs_vert_arr_len; bs_vert_arr_i++) { + current_bs_vertex_array.write[bs_vert_arr_i] = current_bs_vertex_array[bs_vert_arr_i] * p_scale; + } + current_bsarr[ArrayMesh::ARRAY_VERTEX] = current_bs_vertex_array; + blendshapes.push_back(current_bsarr); + } + + LocalSurfData surf_data_dictionary = LocalSurfData(); + surf_data_dictionary.prim = prim; + surf_data_dictionary.arr = arr; + surf_data_dictionary.bsarr = blendshapes; + surf_data_dictionary.lods = lods; + surf_data_dictionary.fmt_compress_flags = fmt_compress_flags; + surf_data_dictionary.name = name; + surf_data_dictionary.mat = mat; + + surf_data_by_mesh.push_back(surf_data_dictionary); + } + + p_mesh->clear(); + + for (int bsidx = 0; bsidx < blendshape_count; bsidx++) { + p_mesh->add_blend_shape(blendshape_names[bsidx]); + } + + for (int surf_idx = 0; surf_idx < surf_count; surf_idx++) { + const Mesh::PrimitiveType prim = surf_data_by_mesh[surf_idx].prim; + const Array arr = surf_data_by_mesh[surf_idx].arr; + const Array bsarr = surf_data_by_mesh[surf_idx].bsarr; + const Dictionary lods = surf_data_by_mesh[surf_idx].lods; + const int fmt_compress_flags = surf_data_by_mesh[surf_idx].fmt_compress_flags; + const String name = surf_data_by_mesh[surf_idx].name; + const Ref<Material> mat = surf_data_by_mesh[surf_idx].mat; + + p_mesh->add_surface(prim, arr, bsarr, lods, mat, name, fmt_compress_flags); + } + + if (!is_shadow && p_mesh->get_shadow_mesh() != p_mesh && p_mesh->get_shadow_mesh().is_valid()) { + _rescale_importer_mesh(p_scale, p_mesh->get_shadow_mesh(), true); + } +} + +void _rescale_skin(Vector3 p_scale, Ref<Skin> p_skin) { + // MESH and SKIN data divide, to compensate for object position multiplying. + for (int i = 0; i < p_skin->get_bind_count(); i++) { + Transform3D transform = p_skin->get_bind_pose(i); + p_skin->set_bind_pose(i, Transform3D(transform.basis, p_scale * transform.origin)); + } +} + +void _rescale_animation(Vector3 p_scale, Ref<Animation> p_animation) { + for (int track_idx = 0; track_idx < p_animation->get_track_count(); track_idx++) { + if (p_animation->track_get_type(track_idx) == Animation::TYPE_POSITION_3D) { + for (int key_idx = 0; key_idx < p_animation->track_get_key_count(track_idx); key_idx++) { + Vector3 value = p_animation->track_get_key_value(track_idx, key_idx); + value = p_scale * value; + p_animation->track_set_key_value(track_idx, key_idx, value); + } + } + } +} + +void _apply_basis_to_scalable_node_collection(ScalableNodeCollection &p_dictionary, Vector3 p_scale) { + for (Node3D *node_3d : p_dictionary.node_3ds) { + if (node_3d) { + node_3d->set_position(p_scale * node_3d->get_position()); + + Skeleton3D *skeleton_3d = Object::cast_to<Skeleton3D>(node_3d); + if (skeleton_3d) { + for (int i = 0; i < skeleton_3d->get_bone_count(); i++) { + Transform3D rest = skeleton_3d->get_bone_rest(i); + skeleton_3d->set_bone_rest(i, Transform3D(rest.basis, p_scale * rest.origin)); + skeleton_3d->set_bone_pose_position(i, p_scale * rest.origin); + } + } + } + } + for (Ref<ImporterMesh> mesh : p_dictionary.importer_meshes) { + _rescale_importer_mesh(p_scale, mesh, false); + } + for (Ref<Skin> skin : p_dictionary.skins) { + _rescale_skin(p_scale, skin); + } + for (Ref<Animation> animation : p_dictionary.animations) { + _rescale_animation(p_scale, animation); + } +} + +void _populate_scalable_nodes_collection(Node *p_node, ScalableNodeCollection &p_dictionary) { + if (!p_node) { + return; + } + Node3D *node_3d = Object::cast_to<Node3D>(p_node); + if (node_3d) { + p_dictionary.node_3ds.insert(node_3d); + ImporterMeshInstance3D *mesh_instance_3d = Object::cast_to<ImporterMeshInstance3D>(p_node); + if (mesh_instance_3d) { + Ref<ImporterMesh> mesh = mesh_instance_3d->get_mesh(); + if (mesh.is_valid()) { + p_dictionary.importer_meshes.insert(mesh); + } + Ref<Skin> skin = mesh_instance_3d->get_skin(); + if (skin.is_valid()) { + p_dictionary.skins.insert(skin); + } + } + } + AnimationPlayer *animation_player = Object::cast_to<AnimationPlayer>(p_node); + if (animation_player) { + List<StringName> animation_list; + animation_player->get_animation_list(&animation_list); + + for (const StringName &E : animation_list) { + Ref<Animation> animation = animation_player->get_animation(E); + p_dictionary.animations.insert(animation); + } + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + Node *child = p_node->get_child(i); + _populate_scalable_nodes_collection(child, p_dictionary); + } +} + +void _apply_permanent_rotation_scale_to_node(Node *p_node) { + Transform3D transform = Object::cast_to<Node3D>(p_node)->get_transform(); + ScalableNodeCollection scalable_node_collection; + _populate_scalable_nodes_collection(p_node, scalable_node_collection); + _apply_basis_to_scalable_node_collection(scalable_node_collection, transform.basis.get_scale()); +} + Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &r_collision_map, Pair<PackedVector3Array, PackedInt32Array> *r_occluder_arrays, List<Pair<NodePath, Node *>> &r_node_renames) { // Children first. for (int i = 0; i < p_node->get_child_count(); i++) { @@ -1678,6 +1857,7 @@ void ResourceImporterScene::get_import_options(const String &p_path, List<Import script_ext_hint += "*." + E; } + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "nodes/apply_root_scale"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "nodes/root_scale", PROPERTY_HINT_RANGE, "0.001,1000,0.001"), 1.0)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/generate_lods"), true)); @@ -2144,6 +2324,21 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p return err; } + bool apply_root = true; + if (p_options.has("nodes/apply_root_scale")) { + apply_root = p_options["nodes/apply_root_scale"]; + } + real_t root_scale = 1; + if (p_options.has("nodes/root_scale")) { + root_scale = p_options["nodes/root_scale"]; + } + if (Object::cast_to<Node3D>(scene)) { + Object::cast_to<Node3D>(scene)->scale(Vector3(root_scale, root_scale, root_scale)); + } + if (apply_root) { + _apply_permanent_rotation_scale_to_node(scene); + Object::cast_to<Node3D>(scene)->scale(Vector3(root_scale, root_scale, root_scale).inverse()); + } Dictionary subresources = p_options["_subresources"]; Dictionary node_data; @@ -2199,12 +2394,6 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p scene->set_script(Variant(root_script)); } - float root_scale = 1.0; - if (Object::cast_to<Node3D>(scene)) { - root_scale = p_options["nodes/root_scale"]; - Object::cast_to<Node3D>(scene)->scale(Vector3(root_scale, root_scale, root_scale)); - } - if (p_options["nodes/root_name"] != "Scene Root") { scene->set_name(p_options["nodes/root_name"]); } else { diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h index 104a7a9f7e..0e12a83116 100644 --- a/editor/import/scene_import_settings.h +++ b/editor/import/scene_import_settings.h @@ -192,7 +192,7 @@ class SceneImportSettings : public ConfirmationDialog { bool editing_animation = false; - Timer *update_view_timer; + Timer *update_view_timer = nullptr; protected: void _notification(int p_what); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 7af04e17c1..74fdbdebd7 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -311,7 +311,6 @@ void InspectorDock::_prepare_history() { history_menu->get_popup()->clear(); - Ref<Texture2D> base_icon = get_theme_icon(SNAME("Object"), SNAME("EditorIcons")); HashSet<ObjectID> already; for (int i = editor_history->get_history_len() - 1; i >= history_to; i--) { ObjectID id = editor_history->get_history_obj(i); @@ -325,13 +324,12 @@ void InspectorDock::_prepare_history() { already.insert(id); - Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(obj, ""); - if (icon.is_null()) { - icon = base_icon; - } + Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(obj, "Object"); String text; - if (Object::cast_to<Resource>(obj)) { + if (obj->has_method("_get_editor_name")) { + text = obj->call("_get_editor_name"); + } else if (Object::cast_to<Resource>(obj)) { Resource *r = Object::cast_to<Resource>(obj); if (r->get_path().is_resource_file()) { text = r->get_path().get_file(); @@ -349,14 +347,14 @@ void InspectorDock::_prepare_history() { } if (i == editor_history->get_history_pos() && current) { - text = "[" + text + "]"; + text += " " + TTR("(Current)"); } history_menu->get_popup()->add_icon_item(icon, text, i); } } void InspectorDock::_select_history(int p_idx) { - //push it to the top, it is not correct, but it's more useful + // Push it to the top, it is not correct, but it's more useful. ObjectID id = EditorNode::get_singleton()->get_editor_selection_history()->get_history_obj(p_idx); Object *obj = ObjectDB::get_instance(id); if (!obj) { diff --git a/editor/multi_node_edit.cpp b/editor/multi_node_edit.cpp index 70cc54668d..a386fba84d 100644 --- a/editor/multi_node_edit.cpp +++ b/editor/multi_node_edit.cpp @@ -46,7 +46,7 @@ bool MultiNodeEdit::_set_impl(const StringName &p_name, const Variant &p_value, String name = p_name; - if (name == "scripts") { // script set is intercepted at object level (check Variant Object::get() ) ,so use a different name + if (name == "scripts") { // Script set is intercepted at object level (check Variant Object::get()), so use a different name. name = "script"; } @@ -57,13 +57,9 @@ bool MultiNodeEdit::_set_impl(const StringName &p_name, const Variant &p_value, Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo(); - ur->create_action(TTR("MultiNode Set") + " " + String(name), UndoRedo::MERGE_ENDS); + ur->create_action(vformat(TTR("Set %s on %d nodes"), name, get_node_count()), UndoRedo::MERGE_ENDS); for (const NodePath &E : nodes) { - if (!es->has_node(E)) { - continue; - } - - Node *n = es->get_node(E); + Node *n = es->get_node_or_null(E); if (!n) { continue; } @@ -100,16 +96,12 @@ bool MultiNodeEdit::_get(const StringName &p_name, Variant &r_ret) const { } String name = p_name; - if (name == "scripts") { // script set is intercepted at object level (check Variant Object::get() ) ,so use a different name + if (name == "scripts") { // Script set is intercepted at object level (check Variant Object::get()), so use a different name. name = "script"; } for (const NodePath &E : nodes) { - if (!es->has_node(E)) { - continue; - } - - const Node *n = es->get_node(E); + const Node *n = es->get_node_or_null(E); if (!n) { continue; } @@ -137,11 +129,7 @@ void MultiNodeEdit::_get_property_list(List<PropertyInfo> *p_list) const { List<PLData *> data_list; for (const NodePath &E : nodes) { - if (!es->has_node(E)) { - continue; - } - - Node *n = es->get_node(E); + Node *n = es->get_node_or_null(E); if (!n) { continue; } @@ -151,7 +139,7 @@ void MultiNodeEdit::_get_property_list(List<PropertyInfo> *p_list) const { for (const PropertyInfo &F : plist) { if (F.name == "script") { - continue; //added later manually, since this is intercepted before being set (check Variant Object::get() ) + continue; // Added later manually, since this is intercepted before being set (check Variant Object::get()). } if (!usage.has(F.name)) { PLData pld; @@ -161,7 +149,7 @@ void MultiNodeEdit::_get_property_list(List<PropertyInfo> *p_list) const { data_list.push_back(usage.getptr(F.name)); } - // Make sure only properties with the same exact PropertyInfo data will appear + // Make sure only properties with the same exact PropertyInfo data will appear. if (usage[F.name].info == F) { usage[F.name].uses++; } @@ -179,6 +167,66 @@ void MultiNodeEdit::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::OBJECT, "scripts", PROPERTY_HINT_RESOURCE_TYPE, "Script")); } +String MultiNodeEdit::_get_editor_name() const { + return vformat(TTR("%s (%d Selected)"), get_edited_class_name(), get_node_count()); +} + +bool MultiNodeEdit::_property_can_revert(const StringName &p_name) const { + Node *es = EditorNode::get_singleton()->get_edited_scene(); + if (!es) { + return false; + } + + if (ClassDB::has_property(get_edited_class_name(), p_name)) { + StringName class_name; + for (const NodePath &E : nodes) { + Node *node = es->get_node_or_null(E); + if (!node) { + continue; + } + + class_name = node->get_class_name(); + } + + Variant default_value = ClassDB::class_get_default_property_value(class_name, p_name); + for (const NodePath &E : nodes) { + Node *node = es->get_node_or_null(E); + if (!node) { + continue; + } + + if (node->get(p_name) != default_value) { + // A node that doesn't have the default value has been found, so show the revert button. + return true; + } + } + + return false; + } + + // Don't show the revert button if the edited class doesn't have the property. + return false; +} + +bool MultiNodeEdit::_property_get_revert(const StringName &p_name, Variant &r_property) const { + Node *es = EditorNode::get_singleton()->get_edited_scene(); + if (!es) { + return false; + } + + for (const NodePath &E : nodes) { + Node *node = es->get_node_or_null(E); + if (!node) { + continue; + } + + r_property = ClassDB::class_get_default_property_value(node->get_class_name(), p_name); + return true; + } + + return false; +} + void MultiNodeEdit::add_node(const NodePath &p_node) { nodes.push_back(p_node); } @@ -192,9 +240,69 @@ NodePath MultiNodeEdit::get_node(int p_index) const { return nodes[p_index]; } +StringName MultiNodeEdit::get_edited_class_name() const { + Node *es = EditorNode::get_singleton()->get_edited_scene(); + if (!es) { + return SNAME("Node"); + } + + // Get the class name of the first node. + StringName class_name; + for (const NodePath &E : nodes) { + Node *node = es->get_node_or_null(E); + if (!node) { + continue; + } + + class_name = node->get_class_name(); + break; + } + + if (class_name == StringName()) { + return SNAME("Node"); + } + + bool check_again = true; + while (check_again) { + check_again = false; + + if (class_name == SNAME("Node") || class_name == StringName()) { + // All nodes inherit from Node, so no need to continue checking. + return SNAME("Node"); + } + + // Check that all nodes inherit from class_name. + for (const NodePath &E : nodes) { + Node *node = es->get_node_or_null(E); + if (!node) { + continue; + } + + const StringName node_class_name = node->get_class_name(); + if (class_name == node_class_name || ClassDB::is_parent_class(node_class_name, class_name)) { + // class_name is the same or a parent of the node's class. + continue; + } + + // class_name is not a parent of the node's class, so check again with the parent class. + class_name = ClassDB::get_parent_class(class_name); + check_again = true; + break; + } + } + + return class_name; +} + void MultiNodeEdit::set_property_field(const StringName &p_property, const Variant &p_value, const String &p_field) { _set_impl(p_property, p_value, p_field); } +void MultiNodeEdit::_bind_methods() { + ClassDB::bind_method("_hide_script_from_inspector", &MultiNodeEdit::_hide_script_from_inspector); + ClassDB::bind_method("_hide_metadata_from_inspector", &MultiNodeEdit::_hide_metadata_from_inspector); + ClassDB::bind_method("_get_editor_name", &MultiNodeEdit::_get_editor_name); +} + MultiNodeEdit::MultiNodeEdit() { } diff --git a/editor/multi_node_edit.h b/editor/multi_node_edit.h index 31678d7b01..9c0ec85e20 100644 --- a/editor/multi_node_edit.h +++ b/editor/multi_node_edit.h @@ -45,15 +45,25 @@ class MultiNodeEdit : public RefCounted { bool _set_impl(const StringName &p_name, const Variant &p_value, const String &p_field); protected: + static void _bind_methods(); + bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; public: + bool _hide_script_from_inspector() { return true; } + bool _hide_metadata_from_inspector() { return true; } + + bool _property_can_revert(const StringName &p_name) const; + bool _property_get_revert(const StringName &p_name, Variant &r_property) const; + String _get_editor_name() const; + void add_node(const NodePath &p_node); int get_node_count() const; NodePath get_node(int p_index) const; + StringName get_edited_class_name() const; void set_property_field(const StringName &p_property, const Variant &p_value, const String &p_field); diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index b79f4c90bf..0e941ad433 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -552,9 +552,9 @@ void AnimationNodeBlendSpace1DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); - panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); tool_blend->set_icon(get_theme_icon(SNAME("EditPivot"), SNAME("EditorIcons"))); tool_select->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons"))); tool_create->set_icon(get_theme_icon(SNAME("EditKey"), SNAME("EditorIcons"))); diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index 1646a1cef4..f75dcdf2d6 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -774,9 +774,9 @@ void AnimationNodeBlendSpace2DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); - panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); tool_blend->set_icon(get_theme_icon(SNAME("EditPivot"), SNAME("EditorIcons"))); tool_select->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons"))); tool_create->set_icon(get_theme_icon(SNAME("EditKey"), SNAME("EditorIcons"))); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 8dd3223b19..f1e6c70549 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -242,7 +242,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { } } - pb->set_percent_visible(false); + pb->set_show_percentage(false); pb->set_custom_minimum_size(Vector2(0, 14) * EDSCALE); animations[E] = pb; node->add_child(pb); @@ -800,7 +800,7 @@ void AnimationNodeBlendTreeEditor::_update_editor_settings() { } void AnimationNodeBlendTreeEditor::_update_theme() { - error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); } diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index 2809eb01cd..461326a47b 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -267,6 +267,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv for (int i = node_rects.size() - 1; i >= 0; i--) { //inverse to draw order if (node_rects[i].node.has_point(mb->get_position())) { //select node since nothing else was selected connecting = true; + connection_follows_cursor = true; connecting_from = node_rects[i].node_name; connecting_to = mb->get_position(); connecting_to_node = StringName(); @@ -296,6 +297,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv _open_menu(mb->get_position()); } connecting_to_node = StringName(); + connection_follows_cursor = false; state_machine_draw->queue_redraw(); } @@ -332,7 +334,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } // Move mouse while connecting - if (mm.is_valid() && connecting && !read_only) { + if (mm.is_valid() && connecting && connection_follows_cursor && !read_only) { connecting_to = mm->get_position(); connecting_to_node = StringName(); state_machine_draw->queue_redraw(); @@ -1023,11 +1025,9 @@ void AnimationNodeStateMachineEditor::_add_menu_type(int p_index) { } updating = true; - undo_redo->create_action(TTR("Add Node")); + undo_redo->create_action(TTR("Add Node and Transition")); undo_redo->add_do_method(state_machine.ptr(), "add_node", name, node, add_node_pos); undo_redo->add_undo_method(state_machine.ptr(), "remove_node", name); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); connecting_to_node = name; _add_transition(true); undo_redo->commit_action(); @@ -1051,11 +1051,9 @@ void AnimationNodeStateMachineEditor::_add_animation_type(int p_index) { } updating = true; - undo_redo->create_action(TTR("Add Node")); + undo_redo->create_action(TTR("Add Node and Transition")); undo_redo->add_do_method(state_machine.ptr(), "add_node", name, anim, add_node_pos); undo_redo->add_undo_method(state_machine.ptr(), "remove_node", name); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); connecting_to_node = name; _add_transition(true); undo_redo->commit_action(); @@ -1083,16 +1081,16 @@ void AnimationNodeStateMachineEditor::_add_transition(const bool p_nested_action if (!p_nested_action) { updating = true; + undo_redo->create_action(TTR("Add Transition")); } - undo_redo->create_action(TTR("Add Transition")); undo_redo->add_do_method(state_machine.ptr(), "add_transition", connecting_from, connecting_to_node, tr); undo_redo->add_undo_method(state_machine.ptr(), "remove_transition", connecting_from, connecting_to_node); undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); - undo_redo->commit_action(); if (!p_nested_action) { + undo_redo->commit_action(); updating = false; } @@ -1553,9 +1551,9 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: case NOTIFICATION_TRANSLATION_CHANGED: { - error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); - panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); tool_select->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons"))); tool_create->set_icon(get_theme_icon(SNAME("ToolAddNode"), SNAME("EditorIcons"))); diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index 3a59e94a5f..d0828a5f52 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -100,8 +100,8 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { Vector2 add_node_pos; - ConfirmationDialog *delete_window; - Tree *delete_tree; + ConfirmationDialog *delete_window = nullptr; + Tree *delete_tree = nullptr; bool box_selecting = false; Point2 box_selecting_from; @@ -117,6 +117,7 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { StringName snap_y; bool connecting = false; + bool connection_follows_cursor = false; StringName connecting_from; Vector2 connecting_to; StringName connecting_to_node; diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 41383edafe..436113093f 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -32,7 +32,7 @@ #include "core/input/input.h" #include "core/io/json.h" -#include "core/io/stream_peer_ssl.h" +#include "core/io/stream_peer_tls.h" #include "core/os/keyboard.h" #include "core/version.h" #include "editor/editor_file_dialog.h" @@ -101,10 +101,7 @@ void EditorAssetLibraryItem::_bind_methods() { EditorAssetLibraryItem::EditorAssetLibraryItem() { Ref<StyleBoxEmpty> border; border.instantiate(); - border->set_default_margin(SIDE_LEFT, 5 * EDSCALE); - border->set_default_margin(SIDE_RIGHT, 5 * EDSCALE); - border->set_default_margin(SIDE_BOTTOM, 5 * EDSCALE); - border->set_default_margin(SIDE_TOP, 5 * EDSCALE); + border->set_default_margin_all(5 * EDSCALE); add_theme_style_override("panel", border); HBoxContainer *hb = memnew(HBoxContainer); @@ -324,7 +321,7 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int status->set_text(TTR("Can't connect.")); } break; case HTTPRequest::RESULT_CANT_CONNECT: - case HTTPRequest::RESULT_SSL_HANDSHAKE_ERROR: { + case HTTPRequest::RESULT_TLS_HANDSHAKE_ERROR: { error_text = TTR("Can't connect to host:") + " " + host; status->set_text(TTR("Can't connect.")); } break; @@ -577,24 +574,26 @@ void EditorAssetLibrary::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("AssetLib"))); - error_label->raise(); + error_label->move_to_front(); } break; case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { error_tr->set_texture(get_theme_icon(SNAME("Error"), SNAME("EditorIcons"))); filter->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); - library_scroll_bg->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); - downloads_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + library_scroll_bg->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); + downloads_scroll->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); error_label->add_theme_color_override("color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); } break; case NOTIFICATION_VISIBILITY_CHANGED: { if (is_visible()) { +#ifndef ANDROID_ENABLED // Focus the search box automatically when switching to the Templates tab (in the Project Manager) // or switching to the AssetLib tab (in the editor). // The Project Manager's project filter box is automatically focused in the project manager code. filter->grab_focus(); +#endif if (initial_loading) { _repository_changed(0); // Update when shown for the first time. @@ -649,7 +648,7 @@ void EditorAssetLibrary::shortcut_input(const Ref<InputEvent> &p_event) { const Ref<InputEventKey> key = p_event; if (key.is_valid() && key->is_pressed()) { - if (key->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::F) && is_visible_in_tree()) { + if (key->is_match(InputEventKey::create_reference(KeyModifierMask::CMD_OR_CTRL | Key::F))) { filter->grab_focus(); filter->select_all(); accept_event(); @@ -1100,7 +1099,7 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const case HTTPRequest::RESULT_CHUNKED_BODY_SIZE_MISMATCH: { error_label->set_text(TTR("Connection error, please try again.")); } break; - case HTTPRequest::RESULT_SSL_HANDSHAKE_ERROR: + case HTTPRequest::RESULT_TLS_HANDSHAKE_ERROR: case HTTPRequest::RESULT_CANT_CONNECT: { error_label->set_text(TTR("Can't connect to host:") + " " + host); } break; @@ -1508,10 +1507,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { Ref<StyleBoxEmpty> border2; border2.instantiate(); - border2->set_default_margin(SIDE_LEFT, 15 * EDSCALE); - border2->set_default_margin(SIDE_RIGHT, 35 * EDSCALE); - border2->set_default_margin(SIDE_BOTTOM, 15 * EDSCALE); - border2->set_default_margin(SIDE_TOP, 15 * EDSCALE); + border2->set_default_margin_individual(15 * EDSCALE, 15 * EDSCALE, 35 * EDSCALE, 15 * EDSCALE); PanelContainer *library_vb_border = memnew(PanelContainer); library_scroll->add_child(library_vb_border); @@ -1600,7 +1596,7 @@ bool AssetLibraryEditorPlugin::is_available() { // directly from GitHub which does not set CORS. return false; #else - return StreamPeerSSL::is_available(); + return StreamPeerTLS::is_available(); #endif } @@ -1615,7 +1611,7 @@ void AssetLibraryEditorPlugin::make_visible(bool p_visible) { AssetLibraryEditorPlugin::AssetLibraryEditorPlugin() { addon_library = memnew(EditorAssetLibrary); addon_library->set_v_size_flags(Control::SIZE_EXPAND_FILL); - EditorNode::get_singleton()->get_main_control()->add_child(addon_library); + EditorNode::get_singleton()->get_main_screen_control()->add_child(addon_library); addon_library->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); addon_library->hide(); } diff --git a/editor/plugins/bone_map_editor_plugin.h b/editor/plugins/bone_map_editor_plugin.h index 0541ce6eac..55261ab477 100644 --- a/editor/plugins/bone_map_editor_plugin.h +++ b/editor/plugins/bone_map_editor_plugin.h @@ -62,7 +62,7 @@ private: bool selected = false; bool require = false; - TextureRect *circle; + TextureRect *circle = nullptr; void fetch_textures(); @@ -87,8 +87,8 @@ class BoneMapperItem : public VBoxContainer { Ref<BoneMap> bone_map; - EditorPropertyText *skeleton_bone_selector; - Button *picker_button; + EditorPropertyText *skeleton_bone_selector = nullptr; + Button *picker_button = nullptr; void _update_property(); void _open_picker(); @@ -135,24 +135,24 @@ public: class BoneMapper : public VBoxContainer { GDCLASS(BoneMapper, VBoxContainer); - Skeleton3D *skeleton; + Skeleton3D *skeleton = nullptr; Ref<BoneMap> bone_map; - EditorPropertyResource *profile_selector; + EditorPropertyResource *profile_selector = nullptr; Vector<BoneMapperItem *> bone_mapper_items; - Button *clear_mapping_button; + Button *clear_mapping_button = nullptr; - VBoxContainer *mapper_item_vbox; + VBoxContainer *mapper_item_vbox = nullptr; int current_group_idx = 0; int current_bone_idx = -1; - AspectRatioContainer *bone_mapper_field; - EditorPropertyEnum *profile_group_selector; - ColorRect *profile_bg; - TextureRect *profile_texture; + AspectRatioContainer *bone_mapper_field = nullptr; + EditorPropertyEnum *profile_group_selector = nullptr; + ColorRect *profile_bg = nullptr; + TextureRect *profile_texture = nullptr; Vector<BoneMapperButton *> bone_mapper_buttons; void create_editor(); @@ -201,9 +201,9 @@ public: class BoneMapEditor : public VBoxContainer { GDCLASS(BoneMapEditor, VBoxContainer); - Skeleton3D *skeleton; + Skeleton3D *skeleton = nullptr; Ref<BoneMap> bone_map; - BoneMapper *bone_mapper; + BoneMapper *bone_mapper = nullptr; void fetch_objects(); void clear_editors(); @@ -219,7 +219,7 @@ public: class EditorInspectorPluginBoneMap : public EditorInspectorPlugin { GDCLASS(EditorInspectorPluginBoneMap, EditorInspectorPlugin); - BoneMapEditor *editor; + BoneMapEditor *editor = nullptr; public: virtual bool can_handle(Object *p_object) override; diff --git a/editor/plugins/camera_3d_editor_plugin.cpp b/editor/plugins/camera_3d_editor_plugin.cpp index 141837244a..1aedb3b4ce 100644 --- a/editor/plugins/camera_3d_editor_plugin.cpp +++ b/editor/plugins/camera_3d_editor_plugin.cpp @@ -98,7 +98,7 @@ void Camera3DEditorPlugin::make_visible(bool p_visible) { Camera3DEditorPlugin::Camera3DEditorPlugin() { /* camera_editor = memnew( CameraEditor ); - EditorNode::get_singleton()->get_main_control()->add_child(camera_editor); + EditorNode::get_singleton()->get_main_screen_control()->add_child(camera_editor); camera_editor->set_anchor(SIDE_LEFT,Control::ANCHOR_END); camera_editor->set_anchor(SIDE_RIGHT,Control::ANCHOR_END); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index c4a32d6d4b..070834b33b 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1394,7 +1394,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { // Start rotation if (drag_type == DRAG_NONE) { if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed()) { - if ((b->is_command_pressed() && !b->is_alt_pressed() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) { + if ((b->is_command_or_control_pressed() && !b->is_alt_pressed() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) { List<CanvasItem *> selection = _get_edited_canvas_items(); // Remove not movable nodes @@ -3959,10 +3959,8 @@ void CanvasItemEditor::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { select_sb->set_texture(get_theme_icon(SNAME("EditorRect2D"), SNAME("EditorIcons"))); - for (int i = 0; i < 4; i++) { - select_sb->set_margin_size(Side(i), 4); - select_sb->set_default_margin(Side(i), 4); - } + select_sb->set_margin_size_all(4); + select_sb->set_default_margin_all(4); AnimationPlayerEditor::get_singleton()->get_track_editor()->connect("visibility_changed", callable_mp(this, &CanvasItemEditor::_keying_changed)); _keying_changed(); @@ -5045,7 +5043,7 @@ CanvasItemEditor::CanvasItemEditor() { { int32_t(KeyModifierMask::SHIFT | Key::KEY_1), int32_t(KeyModifierMask::SHIFT | Key::KP_1) }); ED_SHORTCUT_ARRAY("canvas_item_editor/zoom_100_percent", TTR("Zoom to 100%"), - { int32_t(Key::KEY_1), int32_t(KeyModifierMask::CMD | Key::KEY_0), int32_t(Key::KP_1), int32_t(KeyModifierMask::CMD | Key::KP_0) }); + { int32_t(Key::KEY_1), int32_t(KeyModifierMask::CMD_OR_CTRL | Key::KEY_0), int32_t(Key::KP_1), int32_t(KeyModifierMask::CMD_OR_CTRL | Key::KP_0) }); ED_SHORTCUT_ARRAY("canvas_item_editor/zoom_200_percent", TTR("Zoom to 200%"), { int32_t(Key::KEY_2), int32_t(Key::KP_2) }); @@ -5104,7 +5102,7 @@ CanvasItemEditor::CanvasItemEditor() { select_button->set_pressed(true); select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), Key::Q)); select_button->set_shortcut_context(this); - select_button->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Alt+Drag: Scale selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("RMB: Add node at position clicked.")); + select_button->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Alt+Drag: Scale selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("RMB: Add node at position clicked.")); main_menu_hbox->add_child(memnew(VSeparator)); @@ -5229,7 +5227,7 @@ CanvasItemEditor::CanvasItemEditor() { lock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(LOCK_SELECTED)); lock_button->set_tooltip_text(TTR("Lock selected node, preventing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - lock_button->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KeyModifierMask::CMD | Key::L)); + lock_button->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | Key::L)); unlock_button = memnew(Button); unlock_button->set_flat(true); @@ -5237,7 +5235,7 @@ CanvasItemEditor::CanvasItemEditor() { unlock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(UNLOCK_SELECTED)); unlock_button->set_tooltip_text(TTR("Unlock selected node, allowing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - unlock_button->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::L)); + unlock_button->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::L)); group_button = memnew(Button); group_button->set_flat(true); @@ -5245,7 +5243,7 @@ CanvasItemEditor::CanvasItemEditor() { group_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(GROUP_SELECTED)); group_button->set_tooltip_text(TTR("Make selected node's children not selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - group_button->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD | Key::G)); + group_button->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | Key::G)); ungroup_button = memnew(Button); ungroup_button->set_flat(true); @@ -5253,7 +5251,7 @@ CanvasItemEditor::CanvasItemEditor() { ungroup_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(UNGROUP_SELECTED)); ungroup_button->set_tooltip_text(TTR("Make selected node's children selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - ungroup_button->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G)); + ungroup_button->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::G)); main_menu_hbox->add_child(memnew(VSeparator)); @@ -5267,7 +5265,7 @@ CanvasItemEditor::CanvasItemEditor() { p->set_hide_on_checkable_item_selection(false); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES); p->add_separator(); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bone2D Node(s) from Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::B), SKELETON_MAKE_BONES); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bone2D Node(s) from Node(s)"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::B), SKELETON_MAKE_BONES); p->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_popup_callback)); main_menu_hbox->add_child(memnew(VSeparator)); @@ -5301,7 +5299,7 @@ CanvasItemEditor::CanvasItemEditor() { grid_menu->add_radio_check_item(TTR("Show When Snapping"), GRID_VISIBILITY_SHOW_WHEN_SNAPPING); grid_menu->add_radio_check_item(TTR("Hide"), GRID_VISIBILITY_HIDE); grid_menu->add_separator(); - grid_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/toggle_grid", TTR("Toggle Grid"), KeyModifierMask::CMD | Key::APOSTROPHE)); + grid_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/toggle_grid", TTR("Toggle Grid"), KeyModifierMask::CMD_OR_CTRL | Key::APOSTROPHE)); p->add_child(grid_menu); p->add_submenu_item(TTR("Grid"), "GridMenu"); @@ -5318,7 +5316,7 @@ CanvasItemEditor::CanvasItemEditor() { p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KeyModifierMask::SHIFT | Key::F), VIEW_FRAME_TO_SELECTION); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/clear_guides", TTR("Clear Guides")), CLEAR_GUIDES); p->add_separator(); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale"), KeyModifierMask::SHIFT | KeyModifierMask::CMD | Key::P), PREVIEW_CANVAS_SCALE); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale"), KeyModifierMask::SHIFT | KeyModifierMask::CMD_OR_CTRL | Key::P), PREVIEW_CANVAS_SCALE); main_menu_hbox->add_child(memnew(VSeparator)); @@ -5388,7 +5386,7 @@ CanvasItemEditor::CanvasItemEditor() { p = animation_menu->get_popup(); p->add_shortcut(ED_GET_SHORTCUT("canvas_item_editor/anim_insert_key"), ANIM_INSERT_KEY); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key_existing_tracks", TTR("Insert Key (Existing Tracks)"), KeyModifierMask::CMD + Key::INSERT), ANIM_INSERT_KEY_EXISTING); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key_existing_tracks", TTR("Insert Key (Existing Tracks)"), KeyModifierMask::CMD_OR_CTRL + Key::INSERT), ANIM_INSERT_KEY_EXISTING); p->add_separator(); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_copy_pose", TTR("Copy Pose")), ANIM_COPY_POSE); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_paste_pose", TTR("Paste Pose")), ANIM_PASTE_POSE); @@ -5459,7 +5457,7 @@ void CanvasItemEditorPlugin::set_state(const Dictionary &p_state) { CanvasItemEditorPlugin::CanvasItemEditorPlugin() { canvas_item_editor = memnew(CanvasItemEditor); canvas_item_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); - EditorNode::get_singleton()->get_main_control()->add_child(canvas_item_editor); + EditorNode::get_singleton()->get_main_screen_control()->add_child(canvas_item_editor); canvas_item_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); canvas_item_editor->hide(); } diff --git a/editor/plugins/cast_2d_editor_plugin.h b/editor/plugins/cast_2d_editor_plugin.h index 85ff497bc7..ceed9b9111 100644 --- a/editor/plugins/cast_2d_editor_plugin.h +++ b/editor/plugins/cast_2d_editor_plugin.h @@ -42,7 +42,7 @@ class Cast2DEditor : public Control { Ref<EditorUndoRedoManager> undo_redo; CanvasItemEditor *canvas_item_editor = nullptr; - Node2D *node; + Node2D *node = nullptr; bool pressed = false; Point2 original_target_position; diff --git a/editor/plugins/control_editor_plugin.h b/editor/plugins/control_editor_plugin.h index 584d05aab0..22267cbc04 100644 --- a/editor/plugins/control_editor_plugin.h +++ b/editor/plugins/control_editor_plugin.h @@ -186,7 +186,7 @@ public: class SizeFlagPresetPicker : public ControlEditorPresetPicker { GDCLASS(SizeFlagPresetPicker, ControlEditorPresetPicker); - CheckBox *expand_button; + CheckBox *expand_button = nullptr; bool vertical = false; diff --git a/editor/plugins/cpu_particles_3d_editor_plugin.cpp b/editor/plugins/cpu_particles_3d_editor_plugin.cpp index 775c2dbb2a..ad12b8bef0 100644 --- a/editor/plugins/cpu_particles_3d_editor_plugin.cpp +++ b/editor/plugins/cpu_particles_3d_editor_plugin.cpp @@ -126,7 +126,7 @@ void CPUParticles3DEditorPlugin::make_visible(bool p_visible) { CPUParticles3DEditorPlugin::CPUParticles3DEditorPlugin() { particles_editor = memnew(CPUParticles3DEditor); - EditorNode::get_singleton()->get_main_control()->add_child(particles_editor); + EditorNode::get_singleton()->get_main_screen_control()->add_child(particles_editor); particles_editor->hide(); } diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 0e84381279..8d1df0b32c 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -640,7 +640,7 @@ void CurveEditor::_draw() { // Background Vector2 view_size = get_rect().size; - draw_style_box(get_theme_stylebox(SNAME("bg"), SNAME("Tree")), Rect2(Point2(), view_size)); + draw_style_box(get_theme_stylebox(SNAME("panel"), SNAME("Tree")), Rect2(Point2(), view_size)); // Grid diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 0ec36736bd..59b8f31720 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -307,7 +307,7 @@ Ref<Texture2D> EditorMaterialPreviewPlugin::generate(const Ref<Resource> &p_from if (material->get_shader_mode() == Shader::MODE_SPATIAL) { RS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid()); - RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMaterialPreviewPlugin *>(this), &EditorMaterialPreviewPlugin::_generate_frame_started), Object::CONNECT_ONESHOT); + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMaterialPreviewPlugin *>(this), &EditorMaterialPreviewPlugin::_generate_frame_started), Object::CONNECT_ONE_SHOT); preview_done.wait(); @@ -709,7 +709,7 @@ Ref<Texture2D> EditorMeshPreviewPlugin::generate(const Ref<Resource> &p_from, co xform.origin.z -= rot_aabb.size.z * 2; RS::get_singleton()->instance_set_transform(mesh_instance, xform); - RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMeshPreviewPlugin *>(this), &EditorMeshPreviewPlugin::_generate_frame_started), Object::CONNECT_ONESHOT); + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorMeshPreviewPlugin *>(this), &EditorMeshPreviewPlugin::_generate_frame_started), Object::CONNECT_ONE_SHOT); preview_done.wait(); @@ -826,7 +826,7 @@ Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path, const float fg = c.get_luminance() < 0.5 ? 1.0 : 0.0; sampled_font->draw_string(canvas_item, pos, sample, HORIZONTAL_ALIGNMENT_LEFT, -1.f, 50, Color(fg, fg, fg)); - RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_generate_frame_started), Object::CONNECT_ONESHOT); + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_generate_frame_started), Object::CONNECT_ONE_SHOT); preview_done.wait(); diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp index ebc92bf531..d91cbb6571 100644 --- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp @@ -454,7 +454,7 @@ void GPUParticles3DEditorPlugin::make_visible(bool p_visible) { GPUParticles3DEditorPlugin::GPUParticles3DEditorPlugin() { particles_editor = memnew(GPUParticles3DEditor); - EditorNode::get_singleton()->get_main_control()->add_child(particles_editor); + EditorNode::get_singleton()->get_main_screen_control()->add_child(particles_editor); particles_editor->hide(); } diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index 76d05624d6..fe7713f175 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -40,6 +40,19 @@ #include "scene/resources/particle_process_material.h" #include "scene/resources/sky_material.h" +void MaterialEditor::gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(p_event.is_null()); + + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { + rot.x -= mm->get_relative().y * 0.01; + rot.y -= mm->get_relative().x * 0.01; + + rot.x = CLAMP(rot.x, -Math_PI / 2, Math_PI / 2); + _update_rotation(); + } +} + void MaterialEditor::_update_theme_item_cache() { Control::_update_theme_item_cache(); @@ -77,6 +90,13 @@ void MaterialEditor::_notification(int p_what) { } } +void MaterialEditor::_update_rotation() { + Transform3D t; + t.basis.rotate(Vector3(0, 1, 0), -rot.y); + t.basis.rotate(Vector3(1, 0, 0), -rot.x); + rotation->set_transform(t); +} + void MaterialEditor::edit(Ref<Material> p_material, const Ref<Environment> &p_env) { material = p_material; camera->set_environment(p_env); @@ -102,6 +122,10 @@ void MaterialEditor::edit(Ref<Material> p_material, const Ref<Environment> &p_en } else { hide(); } + + rot.x = Math::deg_to_rad(-15.0); + rot.y = Math::deg_to_rad(30.0); + _update_rotation(); } void MaterialEditor::_button_pressed(Node *p_button) { @@ -130,9 +154,6 @@ void MaterialEditor::_button_pressed(Node *p_button) { } } -void MaterialEditor::_bind_methods() { -} - MaterialEditor::MaterialEditor() { // canvas item @@ -163,7 +184,7 @@ MaterialEditor::MaterialEditor() { viewport->set_msaa_3d(Viewport::MSAA_4X); camera = memnew(Camera3D); - camera->set_transform(Transform3D(Basis(), Vector3(0, 0, 3))); + camera->set_transform(Transform3D(Basis(), Vector3(0, 0, 1.1))); // Use low field of view so the sphere/box is fully encompassed within the preview, // without much distortion. camera->set_perspective(20, 0.1, 10); @@ -183,18 +204,17 @@ MaterialEditor::MaterialEditor() { light2->set_color(Color(0.7, 0.7, 0.7)); viewport->add_child(light2); + rotation = memnew(Node3D); + viewport->add_child(rotation); + sphere_instance = memnew(MeshInstance3D); - viewport->add_child(sphere_instance); + rotation->add_child(sphere_instance); box_instance = memnew(MeshInstance3D); - viewport->add_child(box_instance); - - Transform3D box_xform; - box_xform.basis.rotate(Vector3(1, 0, 0), Math::deg_to_rad(25.0)); - box_xform.basis = box_xform.basis * Basis().rotated(Vector3(0, 1, 0), Math::deg_to_rad(-25.0)); - box_xform.basis.scale(Vector3(0.7, 0.7, 0.7)); - box_xform.origin.y = 0.05; - box_instance->set_transform(box_xform); + rotation->add_child(box_instance); + + box_instance->set_transform(Transform3D() * 0.25); + sphere_instance->set_transform(Transform3D() * 0.375); sphere_mesh.instantiate(); sphere_instance->set_mesh(sphere_mesh); diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h index 7ce6deee65..8e64434d8b 100644 --- a/editor/plugins/material_editor_plugin.h +++ b/editor/plugins/material_editor_plugin.h @@ -45,11 +45,14 @@ class SubViewportContainer; class MaterialEditor : public Control { GDCLASS(MaterialEditor, Control); + Vector2 rot = Vector2(); + HBoxContainer *layout_2d = nullptr; ColorRect *rect_instance = nullptr; SubViewportContainer *vc = nullptr; SubViewport *viewport = nullptr; + Node3D *rotation = nullptr; MeshInstance3D *sphere_instance = nullptr; MeshInstance3D *box_instance = nullptr; DirectionalLight3D *light1 = nullptr; @@ -87,7 +90,8 @@ class MaterialEditor : public Control { protected: virtual void _update_theme_item_cache() override; void _notification(int p_what); - static void _bind_methods(); + void gui_input(const Ref<InputEvent> &p_event) override; + void _update_rotation(); public: void edit(Ref<Material> p_material, const Ref<Environment> &p_env); diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp index 7bd406b869..c502d47669 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp @@ -567,7 +567,7 @@ void MeshInstance3DEditorPlugin::make_visible(bool p_visible) { MeshInstance3DEditorPlugin::MeshInstance3DEditorPlugin() { mesh_editor = memnew(MeshInstance3DEditor); - EditorNode::get_singleton()->get_main_control()->add_child(mesh_editor); + EditorNode::get_singleton()->get_main_screen_control()->add_child(mesh_editor); mesh_editor->options->hide(); } diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index 319f6ee9de..420ebe5942 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -319,7 +319,7 @@ void MeshLibraryEditorPlugin::make_visible(bool p_visible) { MeshLibraryEditorPlugin::MeshLibraryEditorPlugin() { mesh_library_editor = memnew(MeshLibraryEditor); - EditorNode::get_singleton()->get_main_control()->add_child(mesh_library_editor); + EditorNode::get_singleton()->get_main_screen_control()->add_child(mesh_library_editor); mesh_library_editor->set_anchors_and_offsets_preset(Control::PRESET_TOP_WIDE); mesh_library_editor->set_end(Point2(0, 22)); mesh_library_editor->hide(); diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp index fc4dc5bc2f..b0e206b020 100644 --- a/editor/plugins/multimesh_editor_plugin.cpp +++ b/editor/plugins/multimesh_editor_plugin.cpp @@ -379,7 +379,7 @@ void MultiMeshEditorPlugin::make_visible(bool p_visible) { MultiMeshEditorPlugin::MultiMeshEditorPlugin() { multimesh_editor = memnew(MultiMeshEditor); - EditorNode::get_singleton()->get_main_control()->add_child(multimesh_editor); + EditorNode::get_singleton()->get_main_screen_control()->add_child(multimesh_editor); multimesh_editor->options->hide(); } diff --git a/editor/plugins/navigation_link_2d_editor_plugin.h b/editor/plugins/navigation_link_2d_editor_plugin.h index 1c1251bec7..0a3d9b8810 100644 --- a/editor/plugins/navigation_link_2d_editor_plugin.h +++ b/editor/plugins/navigation_link_2d_editor_plugin.h @@ -42,7 +42,7 @@ class NavigationLink2DEditor : public Control { Ref<EditorUndoRedoManager> undo_redo; CanvasItemEditor *canvas_item_editor = nullptr; - NavigationLink2D *node; + NavigationLink2D *node = nullptr; bool start_grabbed = false; Vector2 original_start_location; diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 03cf9abed9..b9f3015837 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -1586,7 +1586,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { clicked = ObjectID(); - if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->is_command_pressed()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) { + if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->is_command_or_control_pressed()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) { begin_transform(TRANSFORM_ROTATE, false); break; } @@ -2624,14 +2624,14 @@ void Node3DEditorViewport::_notification(int p_what) { cpu_time_label->add_theme_color_override( "font_color", frame_time_gradient->get_color_at_offset( - Math::range_lerp(cpu_time, 0, 30, 0, 1))); + Math::remap(cpu_time, 0, 30, 0, 1))); gpu_time_label->set_text(vformat(TTR("GPU Time: %s ms"), rtos(gpu_time).pad_decimals(2))); // Middle point is at 15 ms. gpu_time_label->add_theme_color_override( "font_color", frame_time_gradient->get_color_at_offset( - Math::range_lerp(gpu_time, 0, 30, 0, 1))); + Math::remap(gpu_time, 0, 30, 0, 1))); const double fps = 1000.0 / gpu_time; fps_label->set_text(vformat(TTR("FPS: %d"), fps)); @@ -2639,7 +2639,7 @@ void Node3DEditorViewport::_notification(int p_what) { fps_label->add_theme_color_override( "font_color", frame_time_gradient->get_color_at_offset( - Math::range_lerp(fps, 110, 10, 0, 1))); + Math::remap(fps, 110, 10, 0, 1))); } bool show_cinema = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_CINEMATIC_PREVIEW)); @@ -4817,7 +4817,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p preview_camera = memnew(CheckBox); preview_camera->set_text(TTR("Preview")); - preview_camera->set_shortcut(ED_SHORTCUT("spatial_editor/toggle_camera_preview", TTR("Toggle Camera Preview"), KeyModifierMask::CMD | Key::P)); + preview_camera->set_shortcut(ED_SHORTCUT("spatial_editor/toggle_camera_preview", TTR("Toggle Camera Preview"), KeyModifierMask::CMD_OR_CTRL | Key::P)); vbox->add_child(preview_camera); preview_camera->set_h_size_flags(0); preview_camera->hide(); @@ -7751,7 +7751,7 @@ Node3DEditor::Node3DEditor() { tool_button[TOOL_MODE_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_SELECT)); tool_button[TOOL_MODE_SELECT]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), Key::Q)); tool_button[TOOL_MODE_SELECT]->set_shortcut_context(this); - tool_button[TOOL_MODE_SELECT]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); + tool_button[TOOL_MODE_SELECT]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); main_menu_hbox->add_child(memnew(VSeparator)); tool_button[TOOL_MODE_MOVE] = memnew(Button); @@ -7794,7 +7794,7 @@ Node3DEditor::Node3DEditor() { tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_LOCK_SELECTED)); tool_button[TOOL_LOCK_SELECTED]->set_tooltip_text(TTR("Lock selected node, preventing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - tool_button[TOOL_LOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KeyModifierMask::CMD | Key::L)); + tool_button[TOOL_LOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | Key::L)); tool_button[TOOL_UNLOCK_SELECTED] = memnew(Button); main_menu_hbox->add_child(tool_button[TOOL_UNLOCK_SELECTED]); @@ -7802,7 +7802,7 @@ Node3DEditor::Node3DEditor() { tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNLOCK_SELECTED)); tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip_text(TTR("Unlock selected node, allowing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - tool_button[TOOL_UNLOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::L)); + tool_button[TOOL_UNLOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::L)); tool_button[TOOL_GROUP_SELECTED] = memnew(Button); main_menu_hbox->add_child(tool_button[TOOL_GROUP_SELECTED]); @@ -7810,7 +7810,7 @@ Node3DEditor::Node3DEditor() { tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_GROUP_SELECTED)); tool_button[TOOL_GROUP_SELECTED]->set_tooltip_text(TTR("Make selected node's children not selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD | Key::G)); + tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | Key::G)); tool_button[TOOL_UNGROUP_SELECTED] = memnew(Button); main_menu_hbox->add_child(tool_button[TOOL_UNGROUP_SELECTED]); @@ -7818,7 +7818,7 @@ Node3DEditor::Node3DEditor() { tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNGROUP_SELECTED)); tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip_text(TTR("Make selected node's children selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G)); + tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::G)); main_menu_hbox->add_child(memnew(VSeparator)); @@ -7895,12 +7895,12 @@ Node3DEditor::Node3DEditor() { ED_SHORTCUT("spatial_editor/insert_anim_key", TTR("Insert Animation Key"), Key::K); ED_SHORTCUT("spatial_editor/focus_origin", TTR("Focus Origin"), Key::O); ED_SHORTCUT("spatial_editor/focus_selection", TTR("Focus Selection"), Key::F); - ED_SHORTCUT("spatial_editor/align_transform_with_view", TTR("Align Transform with View"), KeyModifierMask::ALT + KeyModifierMask::CMD + Key::M); - ED_SHORTCUT("spatial_editor/align_rotation_with_view", TTR("Align Rotation with View"), KeyModifierMask::ALT + KeyModifierMask::CMD + Key::F); + ED_SHORTCUT("spatial_editor/align_transform_with_view", TTR("Align Transform with View"), KeyModifierMask::ALT + KeyModifierMask::CMD_OR_CTRL + Key::M); + ED_SHORTCUT("spatial_editor/align_rotation_with_view", TTR("Align Rotation with View"), KeyModifierMask::ALT + KeyModifierMask::CMD_OR_CTRL + Key::F); ED_SHORTCUT("spatial_editor/freelook_toggle", TTR("Toggle Freelook"), KeyModifierMask::SHIFT + Key::F); - ED_SHORTCUT("spatial_editor/decrease_fov", TTR("Decrease Field of View"), KeyModifierMask::CMD + Key::EQUAL); // Usually direct access key for `KEY_PLUS`. - ED_SHORTCUT("spatial_editor/increase_fov", TTR("Increase Field of View"), KeyModifierMask::CMD + Key::MINUS); - ED_SHORTCUT("spatial_editor/reset_fov", TTR("Reset Field of View to Default"), KeyModifierMask::CMD + Key::KEY_0); + ED_SHORTCUT("spatial_editor/decrease_fov", TTR("Decrease Field of View"), KeyModifierMask::CMD_OR_CTRL + Key::EQUAL); // Usually direct access key for `KEY_PLUS`. + ED_SHORTCUT("spatial_editor/increase_fov", TTR("Increase Field of View"), KeyModifierMask::CMD_OR_CTRL + Key::MINUS); + ED_SHORTCUT("spatial_editor/reset_fov", TTR("Reset Field of View to Default"), KeyModifierMask::CMD_OR_CTRL + Key::KEY_0); PopupMenu *p; @@ -7940,12 +7940,12 @@ Node3DEditor::Node3DEditor() { accept = memnew(AcceptDialog); EditorNode::get_singleton()->get_gui_base()->add_child(accept); - p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/1_viewport", TTR("1 Viewport"), KeyModifierMask::CMD + Key::KEY_1), MENU_VIEW_USE_1_VIEWPORT); - p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports", TTR("2 Viewports"), KeyModifierMask::CMD + Key::KEY_2), MENU_VIEW_USE_2_VIEWPORTS); - p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports_alt", TTR("2 Viewports (Alt)"), KeyModifierMask::ALT + KeyModifierMask::CMD + Key::KEY_2), MENU_VIEW_USE_2_VIEWPORTS_ALT); - p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports", TTR("3 Viewports"), KeyModifierMask::CMD + Key::KEY_3), MENU_VIEW_USE_3_VIEWPORTS); - p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports_alt", TTR("3 Viewports (Alt)"), KeyModifierMask::ALT + KeyModifierMask::CMD + Key::KEY_3), MENU_VIEW_USE_3_VIEWPORTS_ALT); - p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/4_viewports", TTR("4 Viewports"), KeyModifierMask::CMD + Key::KEY_4), MENU_VIEW_USE_4_VIEWPORTS); + p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/1_viewport", TTR("1 Viewport"), KeyModifierMask::CMD_OR_CTRL + Key::KEY_1), MENU_VIEW_USE_1_VIEWPORT); + p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports", TTR("2 Viewports"), KeyModifierMask::CMD_OR_CTRL + Key::KEY_2), MENU_VIEW_USE_2_VIEWPORTS); + p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports_alt", TTR("2 Viewports (Alt)"), KeyModifierMask::ALT + KeyModifierMask::CMD_OR_CTRL + Key::KEY_2), MENU_VIEW_USE_2_VIEWPORTS_ALT); + p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports", TTR("3 Viewports"), KeyModifierMask::CMD_OR_CTRL + Key::KEY_3), MENU_VIEW_USE_3_VIEWPORTS); + p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports_alt", TTR("3 Viewports (Alt)"), KeyModifierMask::ALT + KeyModifierMask::CMD_OR_CTRL + Key::KEY_3), MENU_VIEW_USE_3_VIEWPORTS_ALT); + p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/4_viewports", TTR("4 Viewports"), KeyModifierMask::CMD_OR_CTRL + Key::KEY_4), MENU_VIEW_USE_4_VIEWPORTS); p->add_separator(); p->add_submenu_item(TTR("Gizmos"), "GizmosMenu"); @@ -8449,7 +8449,7 @@ void Node3DEditor::remove_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin) { Node3DEditorPlugin::Node3DEditorPlugin() { spatial_editor = memnew(Node3DEditor); spatial_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); - EditorNode::get_singleton()->get_main_control()->add_child(spatial_editor); + EditorNode::get_singleton()->get_main_screen_control()->add_child(spatial_editor); spatial_editor->hide(); } diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index dc6dfd81c2..c8bd4c1d05 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -150,7 +150,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } // Check for point creation. - if (mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && ((mb->is_command_pressed() && mode == MODE_EDIT) || mode == MODE_CREATE)) { + if (mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && ((mb->is_command_or_control_pressed() && mode == MODE_EDIT) || mode == MODE_CREATE)) { Ref<Curve2D> curve = node->get_curve(); undo_redo->create_action(TTR("Add Point to Curve")); @@ -537,7 +537,7 @@ Path2DEditor::Path2DEditor() { curve_edit->set_flat(true); curve_edit->set_toggle_mode(true); curve_edit->set_focus_mode(Control::FOCUS_NONE); - curve_edit->set_tooltip_text(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point")); + curve_edit->set_tooltip_text(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point")); curve_edit->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_EDIT)); base_hb->add_child(curve_edit); diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index 1029b06638..adfaf11264 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -597,7 +597,7 @@ Path3DEditorPlugin::Path3DEditorPlugin() { curve_edit->set_toggle_mode(true); curve_edit->hide(); curve_edit->set_focus_mode(Control::FOCUS_NONE); - curve_edit->set_tooltip_text(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point")); + curve_edit->set_tooltip_text(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point")); Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_edit); curve_create = memnew(Button); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index a652d1d12f..58a3a07c43 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -94,8 +94,8 @@ void Polygon2DEditor::_notification(int p_what) { [[fallthrough]]; } case NOTIFICATION_THEME_CHANGED: { - uv_edit_draw->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); - bone_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + uv_edit_draw->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); + bone_scroll->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -627,11 +627,11 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } if (uv_move_current == UV_MODE_EDIT_POINT) { - if (mb->is_shift_pressed() && mb->is_command_pressed()) { + if (mb->is_shift_pressed() && mb->is_command_or_control_pressed()) { uv_move_current = UV_MODE_SCALE; } else if (mb->is_shift_pressed()) { uv_move_current = UV_MODE_MOVE; - } else if (mb->is_command_pressed()) { + } else if (mb->is_command_or_control_pressed()) { uv_move_current = UV_MODE_ROTATE; } } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index ad114e022f..0a111aeb49 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -882,7 +882,7 @@ void ScriptEditor::_queue_close_tabs() { // Maybe there are unsaved changes. if (se->is_unsaved()) { _ask_close_current_unsaved_tab(se); - erase_tab_confirm->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &ScriptEditor::_queue_close_tabs), CONNECT_ONESHOT); + erase_tab_confirm->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &ScriptEditor::_queue_close_tabs), CONNECT_ONE_SHOT); break; } } @@ -3363,15 +3363,15 @@ void ScriptEditor::_update_selected_editor_menu() { EditorHelp *eh = Object::cast_to<EditorHelp>(tab_container->get_current_tab_control()); script_search_menu->get_popup()->clear(); if (eh) { - script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find..."), KeyModifierMask::CMD | Key::F), HELP_SEARCH_FIND); + script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find..."), KeyModifierMask::CMD_OR_CTRL | Key::F), HELP_SEARCH_FIND); script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_next", TTR("Find Next"), Key::F3), HELP_SEARCH_FIND_NEXT); script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_previous", TTR("Find Previous"), KeyModifierMask::SHIFT | Key::F3), HELP_SEARCH_FIND_PREVIOUS); script_search_menu->get_popup()->add_separator(); - script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_in_files", TTR("Find in Files"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F), SEARCH_IN_FILES); + script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_in_files", TTR("Find in Files"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::F), SEARCH_IN_FILES); script_search_menu->show(); } else { if (tab_container->get_tab_count() == 0) { - script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_in_files", TTR("Find in Files"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F), SEARCH_IN_FILES); + script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_in_files", TTR("Find in Files"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::F), SEARCH_IN_FILES); script_search_menu->show(); } else { script_search_menu->hide(); @@ -3757,8 +3757,8 @@ ScriptEditor::ScriptEditor() { ED_SHORTCUT("script_editor/window_move_up", TTR("Move Up"), KeyModifierMask::SHIFT | KeyModifierMask::ALT | Key::UP); ED_SHORTCUT("script_editor/window_move_down", TTR("Move Down"), KeyModifierMask::SHIFT | KeyModifierMask::ALT | Key::DOWN); // FIXME: These should be `Key::GREATER` and `Key::LESS` but those don't work. - ED_SHORTCUT("script_editor/next_script", TTR("Next Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::PERIOD); - ED_SHORTCUT("script_editor/prev_script", TTR("Previous Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::COMMA); + ED_SHORTCUT("script_editor/next_script", TTR("Next Script"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::PERIOD); + ED_SHORTCUT("script_editor/prev_script", TTR("Previous Script"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::COMMA); set_process_input(true); set_process_shortcut_input(true); @@ -3768,10 +3768,10 @@ ScriptEditor::ScriptEditor() { file_menu->set_shortcut_context(this); menu_hb->add_child(file_menu); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New Script..."), KeyModifierMask::CMD | Key::N), FILE_NEW); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new_textfile", TTR("New Text File..."), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::N), FILE_NEW_TEXTFILE); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New Script..."), KeyModifierMask::CMD_OR_CTRL | Key::N), FILE_NEW); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new_textfile", TTR("New Text File..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::N), FILE_NEW_TEXTFILE); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/open", TTR("Open...")), FILE_OPEN); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reopen_closed_script", TTR("Reopen Closed Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::T), FILE_REOPEN_CLOSED); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reopen_closed_script", TTR("Reopen Closed Script"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::T), FILE_REOPEN_CLOSED); file_menu->get_popup()->add_submenu_item(TTR("Open Recent"), "RecentScripts", FILE_OPEN_RECENT); recent_scripts = memnew(PopupMenu); @@ -3781,11 +3781,11 @@ ScriptEditor::ScriptEditor() { _update_recent_scripts(); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save", TTR("Save"), KeyModifierMask::ALT | KeyModifierMask::CMD | Key::S), FILE_SAVE); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save", TTR("Save"), KeyModifierMask::ALT | KeyModifierMask::CMD_OR_CTRL | Key::S), FILE_SAVE); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_as", TTR("Save As...")), FILE_SAVE_AS); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KeyModifierMask::SHIFT | KeyModifierMask::ALT | Key::S), FILE_SAVE_ALL); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Tool Script"), KeyModifierMask::CMD | KeyModifierMask::ALT | Key::R), FILE_TOOL_RELOAD_SOFT); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Tool Script"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::ALT | Key::R), FILE_TOOL_RELOAD_SOFT); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy_path", TTR("Copy Script Path")), FILE_COPY_PATH); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/show_in_file_system", TTR("Show in FileSystem")), SHOW_IN_FILE_SYSTEM); file_menu->get_popup()->add_separator(); @@ -3808,16 +3808,16 @@ ScriptEditor::ScriptEditor() { theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/save_theme_as", TTR("Save Theme As...")), THEME_SAVE_AS); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_file", TTR("Close"), KeyModifierMask::CMD | Key::W), FILE_CLOSE); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_file", TTR("Close"), KeyModifierMask::CMD_OR_CTRL | Key::W), FILE_CLOSE); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_all", TTR("Close All")), CLOSE_ALL); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_other_tabs", TTR("Close Other Tabs")), CLOSE_OTHER_TABS); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_docs", TTR("Close Docs")), CLOSE_DOCS); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/run_file", TTR("Run"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::X), FILE_RUN); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/run_file", TTR("Run"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::X), FILE_RUN); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/toggle_scripts_panel", TTR("Toggle Scripts Panel"), KeyModifierMask::CMD | Key::BACKSLASH), TOGGLE_SCRIPTS_PANEL); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/toggle_scripts_panel", TTR("Toggle Scripts Panel"), KeyModifierMask::CMD_OR_CTRL | Key::BACKSLASH), TOGGLE_SCRIPTS_PANEL); file_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptEditor::_menu_option)); file_menu->get_popup()->connect("about_to_popup", callable_mp(this, &ScriptEditor::_prepare_file_menu)); @@ -4049,7 +4049,7 @@ void ScriptEditorPlugin::edited_scene_changed() { ScriptEditorPlugin::ScriptEditorPlugin() { script_editor = memnew(ScriptEditor); - EditorNode::get_singleton()->get_main_control()->add_child(script_editor); + EditorNode::get_singleton()->get_main_screen_control()->add_child(script_editor); script_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); script_editor->hide(); @@ -4070,7 +4070,7 @@ ScriptEditorPlugin::ScriptEditorPlugin() { EDITOR_DEF("text_editor/external/exec_flags", "{file}"); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "text_editor/external/exec_flags", PROPERTY_HINT_PLACEHOLDER_TEXT, "Call flags with placeholders: {project}, {file}, {col}, {line}.")); - ED_SHORTCUT("script_editor/reopen_closed_script", TTR("Reopen Closed Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::T); + ED_SHORTCUT("script_editor/reopen_closed_script", TTR("Reopen Closed Script"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::T); ED_SHORTCUT("script_editor/clear_recent", TTR("Clear Recent Scripts")); } diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index fff956a05e..42dcfb8b1f 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -340,7 +340,9 @@ void ScriptTextEditor::set_edit_state(const Variant &p_state) { } if (editor_enabled) { +#ifndef ANDROID_ENABLED ensure_focus(); +#endif } } @@ -2070,58 +2072,58 @@ static ScriptEditorBase *create_editor(const Ref<Resource> &p_resource) { void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/move_up", TTR("Move Up"), KeyModifierMask::ALT | Key::UP); ED_SHORTCUT("script_text_editor/move_down", TTR("Move Down"), KeyModifierMask::ALT | Key::DOWN); - ED_SHORTCUT("script_text_editor/delete_line", TTR("Delete Line"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::K); + ED_SHORTCUT("script_text_editor/delete_line", TTR("Delete Line"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::K); // Leave these at zero, same can be accomplished with tab/shift-tab, including selection. // The next/previous in history shortcut in this case makes a lot more sense. ED_SHORTCUT("script_text_editor/indent_left", TTR("Indent Left"), Key::NONE); ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), Key::NONE); - ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KeyModifierMask::CMD | Key::K); + ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KeyModifierMask::CMD_OR_CTRL | Key::K); ED_SHORTCUT("script_text_editor/toggle_fold_line", TTR("Fold/Unfold Line"), KeyModifierMask::ALT | Key::F); ED_SHORTCUT("script_text_editor/fold_all_lines", TTR("Fold All Lines"), Key::NONE); ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), Key::NONE); - ED_SHORTCUT("script_text_editor/duplicate_selection", TTR("Duplicate Selection"), KeyModifierMask::SHIFT | KeyModifierMask::CMD | Key::D); - ED_SHORTCUT_OVERRIDE("script_text_editor/duplicate_selection", "macos", KeyModifierMask::SHIFT | KeyModifierMask::CMD | Key::C); - ED_SHORTCUT("script_text_editor/evaluate_selection", TTR("Evaluate Selection"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::E); - ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KeyModifierMask::CMD | KeyModifierMask::ALT | Key::T); - ED_SHORTCUT("script_text_editor/convert_indent_to_spaces", TTR("Convert Indent to Spaces"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::Y); - ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent to Tabs"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::I); - ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KeyModifierMask::CMD | Key::I); + ED_SHORTCUT("script_text_editor/duplicate_selection", TTR("Duplicate Selection"), KeyModifierMask::SHIFT | KeyModifierMask::CTRL | Key::D); + ED_SHORTCUT_OVERRIDE("script_text_editor/duplicate_selection", "macos", KeyModifierMask::SHIFT | KeyModifierMask::META | Key::C); + ED_SHORTCUT("script_text_editor/evaluate_selection", TTR("Evaluate Selection"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::E); + ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::ALT | Key::T); + ED_SHORTCUT("script_text_editor/convert_indent_to_spaces", TTR("Convert Indent to Spaces"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::Y); + ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent to Tabs"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::I); + ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KeyModifierMask::CMD_OR_CTRL | Key::I); - ED_SHORTCUT_AND_COMMAND("script_text_editor/find", TTR("Find..."), KeyModifierMask::CMD | Key::F); + ED_SHORTCUT_AND_COMMAND("script_text_editor/find", TTR("Find..."), KeyModifierMask::CMD_OR_CTRL | Key::F); ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), Key::F3); - ED_SHORTCUT_OVERRIDE("script_text_editor/find_next", "macos", KeyModifierMask::CMD | Key::G); + ED_SHORTCUT_OVERRIDE("script_text_editor/find_next", "macos", KeyModifierMask::META | Key::G); ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KeyModifierMask::SHIFT | Key::F3); - ED_SHORTCUT_OVERRIDE("script_text_editor/find_previous", "macos", KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G); + ED_SHORTCUT_OVERRIDE("script_text_editor/find_previous", "macos", KeyModifierMask::META | KeyModifierMask::SHIFT | Key::G); - ED_SHORTCUT_AND_COMMAND("script_text_editor/replace", TTR("Replace..."), KeyModifierMask::CMD | Key::R); - ED_SHORTCUT_OVERRIDE("script_text_editor/replace", "macos", KeyModifierMask::ALT | KeyModifierMask::CMD | Key::F); + ED_SHORTCUT_AND_COMMAND("script_text_editor/replace", TTR("Replace..."), KeyModifierMask::CTRL | Key::R); + ED_SHORTCUT_OVERRIDE("script_text_editor/replace", "macos", KeyModifierMask::ALT | KeyModifierMask::META | Key::F); - ED_SHORTCUT("script_text_editor/find_in_files", TTR("Find in Files..."), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F); - ED_SHORTCUT("script_text_editor/replace_in_files", TTR("Replace in Files..."), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::R); + ED_SHORTCUT("script_text_editor/find_in_files", TTR("Find in Files..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::F); + ED_SHORTCUT("script_text_editor/replace_in_files", TTR("Replace in Files..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::R); ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KeyModifierMask::ALT | Key::F1); ED_SHORTCUT_OVERRIDE("script_text_editor/contextual_help", "macos", KeyModifierMask::ALT | KeyModifierMask::SHIFT | Key::SPACE); - ED_SHORTCUT("script_text_editor/toggle_bookmark", TTR("Toggle Bookmark"), KeyModifierMask::CMD | KeyModifierMask::ALT | Key::B); - ED_SHORTCUT("script_text_editor/goto_next_bookmark", TTR("Go to Next Bookmark"), KeyModifierMask::CMD | Key::B); - ED_SHORTCUT("script_text_editor/goto_previous_bookmark", TTR("Go to Previous Bookmark"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::B); + ED_SHORTCUT("script_text_editor/toggle_bookmark", TTR("Toggle Bookmark"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::ALT | Key::B); + ED_SHORTCUT("script_text_editor/goto_next_bookmark", TTR("Go to Next Bookmark"), KeyModifierMask::CMD_OR_CTRL | Key::B); + ED_SHORTCUT("script_text_editor/goto_previous_bookmark", TTR("Go to Previous Bookmark"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::B); ED_SHORTCUT("script_text_editor/remove_all_bookmarks", TTR("Remove All Bookmarks"), Key::NONE); - ED_SHORTCUT("script_text_editor/goto_function", TTR("Go to Function..."), KeyModifierMask::ALT | KeyModifierMask::CMD | Key::F); - ED_SHORTCUT_OVERRIDE("script_text_editor/goto_function", "macos", KeyModifierMask::CTRL | KeyModifierMask::CMD | Key::J); + ED_SHORTCUT("script_text_editor/goto_function", TTR("Go to Function..."), KeyModifierMask::ALT | KeyModifierMask::CTRL | Key::F); + ED_SHORTCUT_OVERRIDE("script_text_editor/goto_function", "macos", KeyModifierMask::CTRL | KeyModifierMask::META | Key::J); - ED_SHORTCUT("script_text_editor/goto_line", TTR("Go to Line..."), KeyModifierMask::CMD | Key::L); + ED_SHORTCUT("script_text_editor/goto_line", TTR("Go to Line..."), KeyModifierMask::CMD_OR_CTRL | Key::L); ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), Key::F9); - ED_SHORTCUT_OVERRIDE("script_text_editor/toggle_breakpoint", "macos", KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::B); + ED_SHORTCUT_OVERRIDE("script_text_editor/toggle_breakpoint", "macos", KeyModifierMask::META | KeyModifierMask::SHIFT | Key::B); - ED_SHORTCUT("script_text_editor/remove_all_breakpoints", TTR("Remove All Breakpoints"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F9); - ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Go to Next Breakpoint"), KeyModifierMask::CMD | Key::PERIOD); - ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Go to Previous Breakpoint"), KeyModifierMask::CMD | Key::COMMA); + ED_SHORTCUT("script_text_editor/remove_all_breakpoints", TTR("Remove All Breakpoints"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::F9); + ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Go to Next Breakpoint"), KeyModifierMask::CMD_OR_CTRL | Key::PERIOD); + ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Go to Previous Breakpoint"), KeyModifierMask::CMD_OR_CTRL | Key::COMMA); ScriptEditor::register_create_script_editor_function(create_editor); } diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp index 3dc068a72a..dbad81d743 100644 --- a/editor/plugins/skeleton_2d_editor_plugin.cpp +++ b/editor/plugins/skeleton_2d_editor_plugin.cpp @@ -131,7 +131,7 @@ void Skeleton2DEditorPlugin::make_visible(bool p_visible) { Skeleton2DEditorPlugin::Skeleton2DEditorPlugin() { sprite_editor = memnew(Skeleton2DEditor); - EditorNode::get_singleton()->get_main_control()->add_child(sprite_editor); + EditorNode::get_singleton()->get_main_screen_control()->add_child(sprite_editor); make_visible(false); //sprite_editor->options->hide(); diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 15ae4ffcff..3c75ac6ca6 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -785,7 +785,7 @@ void Skeleton3DEditor::create_editors() { key_insert_all_button->set_focus_mode(FOCUS_NONE); key_insert_all_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys).bind(true)); key_insert_all_button->set_tooltip_text(TTR("Insert key of all bone poses.")); - key_insert_all_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_of_all_bones", TTR("Insert Key (All Bones)"), KeyModifierMask::CMD + Key::INSERT)); + key_insert_all_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_of_all_bones", TTR("Insert Key (All Bones)"), KeyModifierMask::CMD_OR_CTRL + Key::INSERT)); animation_hb->add_child(key_insert_all_button); // Bone tree. @@ -835,7 +835,7 @@ void Skeleton3DEditor::_notification(int p_what) { skeleton->connect("show_rest_only_changed", callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible)); #endif - get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Object::CONNECT_ONESHOT); + get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Object::CONNECT_ONE_SHOT); } break; case NOTIFICATION_READY: { // Will trigger NOTIFICATION_THEME_CHANGED, but won't cause any loops if called here. @@ -852,6 +852,20 @@ void Skeleton3DEditor::_notification(int p_what) { update_joint_tree(); } break; + case NOTIFICATION_PREDELETE: { + if (skeleton) { + select_bone(-1); // Requires that the joint_tree has not been deleted. +#ifdef TOOLS_ENABLED + skeleton->disconnect("show_rest_only_changed", callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible)); + skeleton->disconnect("bone_enabled_changed", callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed)); + skeleton->disconnect("pose_updated", callable_mp(this, &Skeleton3DEditor::_draw_gizmo)); + skeleton->disconnect("pose_updated", callable_mp(this, &Skeleton3DEditor::_update_properties)); + skeleton->set_transform_gizmo_visible(true); +#endif + handles_mesh_instance->get_parent()->remove_child(handles_mesh_instance); + } + edit_mode_toggled(false); + } break; } } @@ -1066,18 +1080,7 @@ void Skeleton3DEditor::select_bone(int p_idx) { } Skeleton3DEditor::~Skeleton3DEditor() { - if (skeleton) { - select_bone(-1); -#ifdef TOOLS_ENABLED - skeleton->disconnect("show_rest_only_changed", callable_mp(this, &Skeleton3DEditor::_update_gizmo_visible)); - skeleton->disconnect("bone_enabled_changed", callable_mp(this, &Skeleton3DEditor::_bone_enabled_changed)); - skeleton->disconnect("pose_updated", callable_mp(this, &Skeleton3DEditor::_draw_gizmo)); - skeleton->disconnect("pose_updated", callable_mp(this, &Skeleton3DEditor::_update_properties)); - skeleton->set_transform_gizmo_visible(true); -#endif - handles_mesh_instance->get_parent()->remove_child(handles_mesh_instance); - } - edit_mode_toggled(false); + singleton = nullptr; handles_mesh_instance->queue_delete(); @@ -1128,7 +1131,7 @@ Skeleton3DEditorPlugin::Skeleton3DEditorPlugin() { EditorPlugin::AfterGUIInput Skeleton3DEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) { Skeleton3DEditor *se = Skeleton3DEditor::get_singleton(); Node3DEditor *ne = Node3DEditor::get_singleton(); - if (se->is_edit_mode()) { + if (se && se->is_edit_mode()) { const Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { if (ne->get_tool_mode() != Node3DEditor::TOOL_MODE_SELECT) { diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp index 615fd5dba9..b78b70cd5c 100644 --- a/editor/plugins/sprite_2d_editor_plugin.cpp +++ b/editor/plugins/sprite_2d_editor_plugin.cpp @@ -604,7 +604,7 @@ void Sprite2DEditorPlugin::make_visible(bool p_visible) { Sprite2DEditorPlugin::Sprite2DEditorPlugin() { sprite_editor = memnew(Sprite2DEditor); - EditorNode::get_singleton()->get_main_control()->add_child(sprite_editor); + EditorNode::get_singleton()->get_main_screen_control()->add_child(sprite_editor); make_visible(false); //sprite_editor->options->hide(); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 9508835442..ae21aad337 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -428,7 +428,7 @@ void SpriteFramesEditor::_notification(int p_what) { split_sheet_zoom_out->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons"))); split_sheet_zoom_reset->set_icon(get_theme_icon(SNAME("ZoomReset"), SNAME("EditorIcons"))); split_sheet_zoom_in->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons"))); - split_sheet_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + split_sheet_scroll->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); } break; case NOTIFICATION_READY: { diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index f0e3619060..8e04391a94 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -823,7 +823,7 @@ void TextureRegionEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - edit_draw->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + edit_draw->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); } break; case NOTIFICATION_READY: { zoom_out->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons"))); diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index 1dce41e4c7..4d54001b94 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -40,6 +40,10 @@ #include "editor/editor_scale.h" #include "editor/editor_undo_redo_manager.h" +#ifdef DEBUG_ENABLED +#include "servers/navigation_server_3d.h" +#endif // DEBUG_ENABLED + void TileDataEditor::_tile_set_changed_plan_update() { _tile_set_changed_update_needed = true; call_deferred(SNAME("_tile_set_changed_deferred_update")); @@ -2674,7 +2678,9 @@ void TileDataNavigationEditor::_tile_set_changed() { void TileDataNavigationEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - polygon_editor->set_polygons_color(get_tree()->get_debug_navigation_color()); +#ifdef DEBUG_ENABLED + polygon_editor->set_polygons_color(NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color()); +#endif // DEBUG_ENABLED } break; } } @@ -2701,7 +2707,10 @@ void TileDataNavigationEditor::draw_over_tile(CanvasItem *p_canvas_item, Transfo return; } - Color color = p_canvas_item->get_tree()->get_debug_navigation_color(); + Color color = Color(0.5, 1.0, 1.0, 1.0); +#ifdef DEBUG_ENABLED + color = NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color(); +#endif // DEBUG_ENABLED 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); diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index ec406ef9ba..01bef9b52b 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -577,7 +577,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p _fix_invalid_tiles_in_tile_map_selection(); } break; case DRAG_TYPE_BUCKET: { - Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos)); + Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->local_to_map(drag_last_mouse_pos), tile_map->local_to_map(mpos)); for (int i = 0; i < line.size(); i++) { if (!drag_modified.has(line[i])) { HashMap<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing); @@ -624,7 +624,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p } } else if (tool_buttons_group->get_pressed_button() == select_tool_button) { drag_start_mouse_pos = mpos; - if (tile_map_selection.has(tile_map->world_to_map(drag_start_mouse_pos)) && !mb->is_shift_pressed()) { + if (tile_map_selection.has(tile_map->local_to_map(drag_start_mouse_pos)) && !mb->is_shift_pressed()) { // Move the selection _update_selection_pattern_from_tilemap_selection(); // Make sure the pattern is up to date before moving. drag_type = DRAG_TYPE_MOVE; @@ -673,7 +673,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p drag_type = DRAG_TYPE_BUCKET; drag_start_mouse_pos = mpos; drag_modified.clear(); - Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos)); + Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->local_to_map(drag_last_mouse_pos), tile_map->local_to_map(mpos)); for (int i = 0; i < line.size(); i++) { if (!drag_modified.has(line[i])) { HashMap<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing); @@ -752,14 +752,14 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over if (drag_type == DRAG_TYPE_PICK) { // Draw the area being picked. - Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(drag_last_mouse_pos) - tile_map->world_to_map(drag_start_mouse_pos)).abs(); + Rect2i rect = Rect2i(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(drag_last_mouse_pos) - tile_map->local_to_map(drag_start_mouse_pos)).abs(); rect.size += Vector2i(1, 1); for (int x = rect.position.x; x < rect.get_end().x; x++) { 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) { Transform2D tile_xform; - tile_xform.set_origin(tile_map->map_to_world(coords)); + tile_xform.set_origin(tile_map->map_to_local(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); } @@ -767,7 +767,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over } } else if (drag_type == DRAG_TYPE_SELECT) { // Draw the area being selected. - Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(drag_last_mouse_pos) - tile_map->world_to_map(drag_start_mouse_pos)).abs(); + Rect2i rect = Rect2i(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(drag_last_mouse_pos) - tile_map->local_to_map(drag_start_mouse_pos)).abs(); rect.size += Vector2i(1, 1); RBSet<Vector2i> to_draw; for (int x = rect.position.x; x < rect.get_end().x; x++) { @@ -789,8 +789,8 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over for (const Vector2i &E : tile_map_selection) { top_left = top_left.min(E); } - Vector2i offset = drag_start_mouse_pos - tile_map->map_to_world(top_left); - offset = tile_map->world_to_map(drag_last_mouse_pos - offset) - tile_map->world_to_map(drag_start_mouse_pos - offset); + Vector2i offset = drag_start_mouse_pos - tile_map->map_to_local(top_left); + offset = tile_map->local_to_map(drag_last_mouse_pos - offset) - tile_map->local_to_map(drag_start_mouse_pos - offset); TypedArray<Vector2i> selection_used_cells = selection_pattern->get_used_cells(); for (int i = 0; i < selection_used_cells.size(); i++) { @@ -803,7 +803,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over Vector2 mouse_offset = (Vector2(tile_map_clipboard->get_size()) / 2.0 - Vector2(0.5, 0.5)) * tile_set->get_tile_size(); TypedArray<Vector2i> clipboard_used_cells = tile_map_clipboard->get_used_cells(); for (int i = 0; i < clipboard_used_cells.size(); i++) { - Vector2i coords = tile_map->map_pattern(tile_map->world_to_map(drag_last_mouse_pos - mouse_offset), clipboard_used_cells[i], tile_map_clipboard); + Vector2i coords = tile_map->map_pattern(tile_map->local_to_map(drag_last_mouse_pos - mouse_offset), clipboard_used_cells[i], tile_map_clipboard); preview[coords] = TileMapCell(tile_map_clipboard->get_cell_source_id(clipboard_used_cells[i]), tile_map_clipboard->get_cell_atlas_coords(clipboard_used_cells[i]), tile_map_clipboard->get_cell_alternative_tile(clipboard_used_cells[i])); } } else if (!picker_button->is_pressed() && !(drag_type == DRAG_TYPE_NONE && Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT))) { @@ -824,11 +824,11 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over } } else if (drag_type == DRAG_TYPE_RECT) { // Preview for a rect pattern. - preview = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(drag_last_mouse_pos), drag_erasing); + preview = _draw_rect(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(drag_last_mouse_pos), drag_erasing); expand_grid = true; } else if (tool_buttons_group->get_pressed_button() == bucket_tool_button && drag_type == DRAG_TYPE_NONE) { // Preview for a fill pattern. - preview = _draw_bucket_fill(tile_map->world_to_map(drag_last_mouse_pos), bucket_contiguous_checkbox->is_pressed(), erase_button->is_pressed()); + preview = _draw_bucket_fill(tile_map->local_to_map(drag_last_mouse_pos), bucket_contiguous_checkbox->is_pressed(), erase_button->is_pressed()); } // Expand the grid if needed @@ -861,7 +861,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f); Transform2D tile_xform; - tile_xform.set_origin(tile_map->map_to_world(Vector2(x, y))); + tile_xform.set_origin(tile_map->map_to_local(Vector2(x, y))); tile_xform.set_scale(tile_shape_size); Color color = grid_color; color.a = color.a * opacity; @@ -874,7 +874,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Draw the preview. for (const KeyValue<Vector2i, TileMapCell> &E : preview) { Transform2D tile_xform; - tile_xform.set_origin(tile_map->map_to_world(E.key)); + tile_xform.set_origin(tile_map->map_to_local(E.key)); tile_xform.set_scale(tile_set->get_tile_size()); if (!(drag_erasing || erase_button->is_pressed()) && random_tile_toggle->is_pressed()) { tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0, 0.5), true); @@ -899,9 +899,9 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over bool transpose = tile_data->get_transpose(); if (transpose) { - dest_rect.position = (tile_map->map_to_world(E.key) - Vector2(dest_rect.size.y, dest_rect.size.x) / 2 - tile_offset); + dest_rect.position = (tile_map->map_to_local(E.key) - Vector2(dest_rect.size.y, dest_rect.size.x) / 2 - tile_offset); } else { - dest_rect.position = (tile_map->map_to_world(E.key) - dest_rect.size / 2 - tile_offset); + dest_rect.position = (tile_map->map_to_local(E.key) - dest_rect.size / 2 - tile_offset); } dest_rect = xform.xform(dest_rect); @@ -1012,7 +1012,7 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_st // Paint the tiles on the tile map. if (!p_erase && random_tile_toggle->is_pressed()) { // Paint a random tile. - Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(p_from_mouse_pos), tile_map->world_to_map(p_to_mouse_pos)); + Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->local_to_map(p_from_mouse_pos), tile_map->local_to_map(p_to_mouse_pos)); for (int i = 0; i < line.size(); i++) { output.insert(line[i], _pick_random_tile(pattern)); } @@ -1020,9 +1020,9 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_st // Paint the pattern. // If we paint several tiles, we virtually move the mouse as if it was in the center of the "brush" Vector2 mouse_offset = (Vector2(pattern->get_size()) / 2.0 - Vector2(0.5, 0.5)) * tile_set->get_tile_size(); - Vector2i last_hovered_cell = tile_map->world_to_map(p_from_mouse_pos - mouse_offset); - Vector2i new_hovered_cell = tile_map->world_to_map(p_to_mouse_pos - mouse_offset); - Vector2i drag_start_cell = tile_map->world_to_map(p_start_drag_mouse_pos - mouse_offset); + Vector2i last_hovered_cell = tile_map->local_to_map(p_from_mouse_pos - mouse_offset); + Vector2i new_hovered_cell = tile_map->local_to_map(p_to_mouse_pos - mouse_offset); + Vector2i drag_start_cell = tile_map->local_to_map(p_start_drag_mouse_pos - mouse_offset); TypedArray<Vector2i> used_cells = pattern->get_used_cells(); Vector2i offset = Vector2i(Math::posmod(drag_start_cell.x, pattern->get_size().x), Math::posmod(drag_start_cell.y, pattern->get_size().y)); // Note: no posmodv for Vector2i for now. Meh.s @@ -1172,7 +1172,7 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vecto TypedArray<Vector2i> to_check; if (source_cell.source_id == TileSet::INVALID_SOURCE) { Rect2i rect = tile_map->get_used_rect(); - if (rect.has_no_area()) { + if (!rect.has_area()) { rect = Rect2i(p_coords, Vector2i(1, 1)); } for (int x = boundaries.position.x; x < boundaries.get_end().x; x++) { @@ -1241,7 +1241,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() { if (!Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CTRL)) { tile_map_selection.clear(); } - Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos) - tile_map->world_to_map(drag_start_mouse_pos)).abs(); + Rect2i rect = Rect2i(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos) - tile_map->local_to_map(drag_start_mouse_pos)).abs(); for (int x = rect.position.x; x <= rect.get_end().x; x++) { for (int y = rect.position.y; y <= rect.get_end().y; y++) { Vector2i coords = Vector2i(x, y); @@ -1287,8 +1287,8 @@ void TileMapEditorTilesPlugin::_stop_dragging() { } // Get the offset from the mouse. - Vector2i offset = drag_start_mouse_pos - tile_map->map_to_world(top_left); - offset = tile_map->world_to_map(mpos - offset) - tile_map->world_to_map(drag_start_mouse_pos - offset); + Vector2i offset = drag_start_mouse_pos - tile_map->map_to_local(top_left); + offset = tile_map->local_to_map(mpos - offset) - tile_map->local_to_map(drag_start_mouse_pos - offset); TypedArray<Vector2i> selection_used_cells = selection_pattern->get_used_cells(); @@ -1334,7 +1334,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() { } } break; case DRAG_TYPE_PICK: { - Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos) - tile_map->world_to_map(drag_start_mouse_pos)).abs(); + Rect2i rect = Rect2i(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos) - tile_map->local_to_map(drag_start_mouse_pos)).abs(); rect.size += Vector2i(1, 1); int picked_source = -1; @@ -1359,11 +1359,11 @@ void TileMapEditorTilesPlugin::_stop_dragging() { for (int i = 0; i < sources_list->get_item_count(); i++) { if (int(sources_list->get_item_metadata(i)) == picked_source) { sources_list->set_current(i); + TilesEditorPlugin::get_singleton()->set_sources_lists_current(i); break; } } sources_list->ensure_current_is_visible(); - TilesEditorPlugin::get_singleton()->set_sources_lists_current(picked_source); } Ref<TileMapPattern> new_selection_pattern = tile_map->get_pattern(tile_map_layer, coords_array); @@ -1394,7 +1394,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() { undo_redo->commit_action(); } break; case DRAG_TYPE_RECT: { - HashMap<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos), drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos), drag_erasing); undo_redo->create_action(TTR("Paint tiles")); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) { @@ -1418,7 +1418,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() { undo_redo->create_action(TTR("Paste tiles")); TypedArray<Vector2i> used_cells = tile_map_clipboard->get_used_cells(); for (int i = 0; i < used_cells.size(); i++) { - Vector2i coords = tile_map->map_pattern(tile_map->world_to_map(mpos - mouse_offset), used_cells[i], tile_map_clipboard); + Vector2i coords = tile_map->map_pattern(tile_map->local_to_map(mpos - mouse_offset), used_cells[i], tile_map_clipboard); undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, coords, tile_map_clipboard->get_cell_source_id(used_cells[i]), tile_map_clipboard->get_cell_atlas_coords(used_cells[i]), tile_map_clipboard->get_cell_alternative_tile(used_cells[i])); undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, coords, tile_map->get_cell_source_id(tile_map_layer, coords), tile_map->get_cell_atlas_coords(tile_map_layer, coords), tile_map->get_cell_alternative_tile(tile_map_layer, coords)); } @@ -2020,9 +2020,9 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { ->connect("mouse_exited", callable_mp(this, &TileMapEditorTilesPlugin::_mouse_exited_viewport)); // --- Shortcuts --- - ED_SHORTCUT("tiles_editor/cut", TTR("Cut"), KeyModifierMask::CMD | Key::X); - ED_SHORTCUT("tiles_editor/copy", TTR("Copy"), KeyModifierMask::CMD | Key::C); - ED_SHORTCUT("tiles_editor/paste", TTR("Paste"), KeyModifierMask::CMD | Key::V); + ED_SHORTCUT("tiles_editor/cut", TTR("Cut"), KeyModifierMask::CMD_OR_CTRL | Key::X); + ED_SHORTCUT("tiles_editor/copy", TTR("Copy"), KeyModifierMask::CMD_OR_CTRL | Key::C); + ED_SHORTCUT("tiles_editor/paste", TTR("Paste"), KeyModifierMask::CMD_OR_CTRL | Key::V); ED_SHORTCUT("tiles_editor/cancel", TTR("Cancel"), Key::ESCAPE); ED_SHORTCUT("tiles_editor/delete", TTR("Delete"), Key::KEY_DELETE); @@ -2558,7 +2558,7 @@ RBSet<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i TypedArray<Vector2i> to_check; if (source_cell.source_id == TileSet::INVALID_SOURCE) { Rect2i rect = tile_map->get_used_rect(); - if (rect.has_no_area()) { + if (!rect.has_area()) { rect = Rect2i(p_coords, Vector2i(1, 1)); } for (int x = boundaries.position.x; x < boundaries.get_end().x; x++) { @@ -2640,7 +2640,7 @@ void TileMapEditorTerrainsPlugin::_stop_dragging() { switch (drag_type) { case DRAG_TYPE_PICK: { - Vector2i coords = tile_map->world_to_map(mpos); + Vector2i coords = tile_map->local_to_map(mpos); TileMapCell cell = tile_map->get_cell(tile_map_layer, coords); TileData *tile_data = nullptr; @@ -2714,7 +2714,7 @@ void TileMapEditorTerrainsPlugin::_stop_dragging() { undo_redo->commit_action(false); } break; case DRAG_TYPE_LINE: { - HashMap<Vector2i, TileMapCell> to_draw = _draw_line(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos), drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_line(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos), drag_erasing); undo_redo->create_action(TTR("Paint terrain")); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) { @@ -2726,7 +2726,7 @@ void TileMapEditorTerrainsPlugin::_stop_dragging() { undo_redo->commit_action(); } break; case DRAG_TYPE_RECT: { - HashMap<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos), drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos), drag_erasing); undo_redo->create_action(TTR("Paint terrain")); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) { @@ -2836,7 +2836,7 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> switch (drag_type) { case DRAG_TYPE_PAINT: { if (selected_terrain_set >= 0) { - HashMap<Vector2i, TileMapCell> to_draw = _draw_line(tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos), drag_erasing); + HashMap<Vector2i, TileMapCell> to_draw = _draw_line(tile_map->local_to_map(drag_last_mouse_pos), tile_map->local_to_map(mpos), drag_erasing); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { if (!drag_modified.has(E.key)) { drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key); @@ -2880,7 +2880,7 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> drag_start_mouse_pos = mpos; drag_modified.clear(); - Vector2i cell = tile_map->world_to_map(mpos); + Vector2i cell = tile_map->local_to_map(mpos); HashMap<Vector2i, TileMapCell> to_draw = _draw_line(cell, cell, drag_erasing); for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) { drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key); @@ -2907,7 +2907,7 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> drag_type = DRAG_TYPE_BUCKET; drag_start_mouse_pos = mpos; drag_modified.clear(); - Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(drag_last_mouse_pos), tile_map->world_to_map(mpos)); + Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->local_to_map(drag_last_mouse_pos), tile_map->local_to_map(mpos)); for (int i = 0; i < line.size(); i++) { if (!drag_modified.has(line[i])) { HashMap<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing); @@ -2971,10 +2971,10 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o if (drag_type == DRAG_TYPE_PICK) { // Draw the area being picked. - Vector2i coords = tile_map->world_to_map(drag_last_mouse_pos); + Vector2i coords = tile_map->local_to_map(drag_last_mouse_pos); if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) { Transform2D tile_xform; - tile_xform.set_origin(tile_map->map_to_world(coords)); + tile_xform.set_origin(tile_map->map_to_local(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); } @@ -2982,15 +2982,15 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o bool expand_grid = false; if (tool_buttons_group->get_pressed_button() == paint_tool_button && drag_type == DRAG_TYPE_NONE) { // Preview for a single tile. - preview.insert(tile_map->world_to_map(drag_last_mouse_pos)); + preview.insert(tile_map->local_to_map(drag_last_mouse_pos)); expand_grid = true; } else if (tool_buttons_group->get_pressed_button() == line_tool_button || drag_type == DRAG_TYPE_LINE) { if (drag_type == DRAG_TYPE_NONE) { // Preview for a single tile. - preview.insert(tile_map->world_to_map(drag_last_mouse_pos)); + preview.insert(tile_map->local_to_map(drag_last_mouse_pos)); } else if (drag_type == DRAG_TYPE_LINE) { // Preview for a line. - Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(drag_last_mouse_pos)); + Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(drag_last_mouse_pos)); for (int i = 0; i < line.size(); i++) { preview.insert(line[i]); } @@ -2999,8 +2999,8 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o } else if (drag_type == DRAG_TYPE_RECT) { // Preview for a rect. Rect2i rect; - rect.set_position(tile_map->world_to_map(drag_start_mouse_pos)); - rect.set_end(tile_map->world_to_map(drag_last_mouse_pos)); + rect.set_position(tile_map->local_to_map(drag_start_mouse_pos)); + rect.set_end(tile_map->local_to_map(drag_last_mouse_pos)); rect = rect.abs(); HashMap<Vector2i, TileSet::TerrainsPattern> to_draw; @@ -3012,7 +3012,7 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o expand_grid = true; } else if (tool_buttons_group->get_pressed_button() == bucket_tool_button && drag_type == DRAG_TYPE_NONE) { // Preview for a fill. - preview = _get_cells_for_bucket_fill(tile_map->world_to_map(drag_last_mouse_pos), bucket_contiguous_checkbox->is_pressed()); + preview = _get_cells_for_bucket_fill(tile_map->local_to_map(drag_last_mouse_pos), bucket_contiguous_checkbox->is_pressed()); } // Expand the grid if needed @@ -3045,7 +3045,7 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f); Transform2D tile_xform; - tile_xform.set_origin(tile_map->map_to_world(Vector2(x, y))); + tile_xform.set_origin(tile_map->map_to_local(Vector2(x, y))); tile_xform.set_scale(tile_shape_size); Color color = grid_color; color.a = color.a * opacity; @@ -3058,7 +3058,7 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o // Draw the preview. for (const Vector2i &E : preview) { Transform2D tile_xform; - tile_xform.set_origin(tile_map->map_to_world(E)); + tile_xform.set_origin(tile_map->map_to_local(E)); tile_xform.set_scale(tile_set->get_tile_size()); if (drag_erasing || erase_button->is_pressed()) { tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(0.0, 0.0, 0.0, 0.5), true); @@ -3838,7 +3838,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { // Draw the scaled tile. Transform2D tile_xform; - tile_xform.set_origin(tile_map->map_to_world(coords)); + tile_xform.set_origin(tile_map->map_to_local(coords)); tile_xform.set_scale(tile_shape_size); tile_set->draw_tile_shape(p_overlay, xform * tile_xform, color, true, warning_pattern_texture); } @@ -3848,7 +3848,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { Vector2 icon_size; icon_size[min_axis] = tile_set->get_tile_size()[min_axis] / 3; icon_size[(min_axis + 1) % 2] = (icon_size[min_axis] * missing_tile_texture->get_size()[(min_axis + 1) % 2] / missing_tile_texture->get_size()[min_axis]); - Rect2 rect = Rect2(xform.xform(tile_map->map_to_world(coords)) - (icon_size * xform.get_scale() / 2), icon_size * xform.get_scale()); + Rect2 rect = Rect2(xform.xform(tile_map->map_to_local(coords)) - (icon_size * xform.get_scale() / 2), icon_size * xform.get_scale()); p_overlay->draw_texture_rect(missing_tile_texture, rect); } } @@ -3861,10 +3861,10 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { // Determine the drawn area. Size2 screen_size = p_overlay->get_size(); Rect2i screen_rect; - screen_rect.position = tile_map->world_to_map(xform_inv.xform(Vector2())); - screen_rect.expand_to(tile_map->world_to_map(xform_inv.xform(Vector2(0, screen_size.height)))); - screen_rect.expand_to(tile_map->world_to_map(xform_inv.xform(Vector2(screen_size.width, 0)))); - screen_rect.expand_to(tile_map->world_to_map(xform_inv.xform(screen_size))); + screen_rect.position = tile_map->local_to_map(xform_inv.xform(Vector2())); + screen_rect.expand_to(tile_map->local_to_map(xform_inv.xform(Vector2(0, screen_size.height)))); + screen_rect.expand_to(tile_map->local_to_map(xform_inv.xform(Vector2(screen_size.width, 0)))); + screen_rect.expand_to(tile_map->local_to_map(xform_inv.xform(screen_size))); screen_rect = screen_rect.grow(1); Rect2i tilemap_used_rect = tile_map->get_used_rect(); @@ -3897,7 +3897,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f); Transform2D tile_xform; - tile_xform.set_origin(tile_map->map_to_world(Vector2(x, y))); + tile_xform.set_origin(tile_map->map_to_local(Vector2(x, y))); tile_xform.set_scale(tile_shape_size); Color color = grid_color; color.a = color.a * opacity; @@ -3910,7 +3910,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { /*Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); for (int x = displayed_rect.position.x; x < (displayed_rect.position.x + displayed_rect.size.x); x++) { for (int y = displayed_rect.position.y; y < (displayed_rect.position.y + displayed_rect.size.y); y++) { - p_overlay->draw_string(font, xform.xform(tile_map->map_to_world(Vector2(x, y))) + Vector2i(-tile_shape_size.x / 2, 0), vformat("%s", Vector2(x, y))); + p_overlay->draw_string(font, xform.xform(tile_map->map_to_local(Vector2(x, y))) + Vector2i(-tile_shape_size.x / 2, 0), vformat("%s", Vector2(x, y))); } }*/ diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp index b5134f6893..17115519e2 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.cpp +++ b/editor/plugins/tiles/tiles_editor_plugin.cpp @@ -91,10 +91,10 @@ void TilesEditorPlugin::_thread() { TypedArray<Vector2i> used_cells = tile_map->get_used_cells(0); Rect2 encompassing_rect = Rect2(); - encompassing_rect.set_position(tile_map->map_to_world(used_cells[0])); + encompassing_rect.set_position(tile_map->map_to_local(used_cells[0])); for (int i = 0; i < used_cells.size(); i++) { Vector2i cell = used_cells[i]; - Vector2 world_pos = tile_map->map_to_world(cell); + Vector2 world_pos = tile_map->map_to_local(cell); encompassing_rect.expand_to(world_pos); // Texture. @@ -116,7 +116,7 @@ void TilesEditorPlugin::_thread() { // Add the viewport at the last moment to avoid rendering too early. EditorNode::get_singleton()->add_child(viewport); - RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_preview_frame_started), Object::CONNECT_ONESHOT); + RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_preview_frame_started), Object::CONNECT_ONE_SHOT); pattern_preview_done.wait(); diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index fba760d57f..761140b2d5 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -1319,7 +1319,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { commit_message->connect(SNAME("gui_input"), callable_mp(this, &VersionControlEditorPlugin::_commit_message_gui_input)); commit_area->add_child(commit_message); - ED_SHORTCUT("version_control/commit", TTR("Commit"), KeyModifierMask::CMD | Key::ENTER); + ED_SHORTCUT("version_control/commit", TTR("Commit"), KeyModifierMask::CMD_OR_CTRL | Key::ENTER); commit_button = memnew(Button); commit_button->set_text(TTR("Commit Changes")); diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp index 1c9afa8be8..4cc60c4c3c 100644 --- a/editor/progress_dialog.cpp +++ b/editor/progress_dialog.cpp @@ -176,7 +176,7 @@ void ProgressDialog::add_task(const String &p_task, const String &p_label, int p } else { cancel_hb->hide(); } - cancel_hb->raise(); + cancel_hb->move_to_front(); cancelled = false; _popup(); if (p_can_cancel) { @@ -207,7 +207,9 @@ bool ProgressDialog::task_step(const String &p_task, const String &p_state, int DisplayServer::get_singleton()->process_events(); } +#ifndef ANDROID_ENABLED Main::iteration(); // this will not work on a lot of platforms, so it's only meant for the editor +#endif return cancelled; } diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index 9c717a0518..39b30b31fb 100644 --- a/editor/project_converter_3_to_4.cpp +++ b/editor/project_converter_3_to_4.cpp @@ -91,6 +91,8 @@ static const char *enum_renames[][2] = { { "BUTTON_XBUTTON2", "MOUSE_BUTTON_XBUTTON2" }, // Globals { "CLEAR_MODE_ONLY_NEXT_FRAME", "CLEAR_MODE_ONCE" }, // SubViewport { "COMPRESS_PVRTC4", "COMPRESS_PVRTC1_4" }, // Image + { "CONNECT_ONESHOT", "CONNECT_ONE_SHOT" }, // Object + { "CONTAINER_PROPERTY_EDITOR_BOTTOM", "CONTAINER_INSPECTOR_BOTTOM" }, // EditorPlugin { "CUBEMAP_BACK", "CUBEMAP_LAYER_BACK" }, // RenderingServer { "CUBEMAP_BOTTOM", "CUBEMAP_LAYER_BOTTOM" }, // RenderingServer { "CUBEMAP_FRONT", "CUBEMAP_LAYER_FRONT" }, // RenderingServer @@ -131,6 +133,7 @@ static const char *enum_renames[][2] = { { "MODE_STATIC", "FREEZE_MODE_STATIC" }, // RigidBody { "NOTIFICATION_APP_PAUSED", "NOTIFICATION_APPLICATION_PAUSED" }, // MainLoop { "NOTIFICATION_APP_RESUMED", "NOTIFICATION_APPLICATION_RESUMED" }, // MainLoop + { "NOTIFICATION_INSTANCED", "NOTIFICATION_SCENE_INSTANTIATED" }, // Node { "NOTIFICATION_PATH_CHANGED", "NOTIFICATION_PATH_RENAMED" }, //Node { "NOTIFICATION_WM_FOCUS_IN", "NOTIFICATION_APPLICATION_FOCUS_IN" }, // MainLoop { "NOTIFICATION_WM_FOCUS_OUT", "NOTIFICATION_APPLICATION_FOCUS_OUT" }, // MainLoop @@ -237,16 +240,18 @@ static const char *gdscript_function_renames[][2] = { { "can_instance", "can_instantiate" }, // PackedScene, Script { "canvas_light_set_scale", "canvas_light_set_texture_scale" }, // RenderingServer { "center_viewport_to_cursor", "center_viewport_to_caret" }, // TextEdit + { "change_scene", "change_scene_to_file" }, // SceneTree + { "change_scene_to", "change_scene_to_packed" }, // SceneTree { "clip_polygons_2d", "clip_polygons" }, // Geometry2D { "clip_polyline_with_polygon_2d", "clip_polyline_with_polygon" }, //Geometry2D { "commit_handle", "_commit_handle" }, // EditorNode3DGizmo { "convex_hull_2d", "convex_hull" }, // Geometry2D { "create_gizmo", "_create_gizmo" }, // EditorNode3DGizmoPlugin - { "cursor_get_blink_speed", "get_caret_blink_speed" }, // TextEdit + { "cursor_get_blink_speed", "get_caret_blink_interval" }, // TextEdit { "cursor_get_column", "get_caret_column" }, // TextEdit { "cursor_get_line", "get_caret_line" }, // TextEdit { "cursor_set_blink_enabled", "set_caret_blink_enabled" }, // TextEdit - { "cursor_set_blink_speed", "set_caret_blink_speed" }, // TextEdit + { "cursor_set_blink_speed", "set_caret_blink_interval" }, // TextEdit { "cursor_set_column", "set_caret_column" }, // TextEdit { "cursor_set_line", "set_caret_line" }, // TextEdit { "damped_spring_joint_create", "joint_make_damped_spring" }, // PhysicsServer2D @@ -287,7 +292,7 @@ static const char *gdscript_function_renames[][2] = { { "get_collision_layer_bit", "get_collision_layer_value" }, // CSGShape3D and a lot of others like GridMap { "get_collision_mask_bit", "get_collision_mask_value" }, // CSGShape3D and a lot of others like GridMap { "get_color_types", "get_color_type_list" }, // Theme - { "get_command", "is_command_pressed" }, // InputEventWithModifiers + { "get_command", "is_command_or_control_pressed" }, // InputEventWithModifiers { "get_constant_types", "get_constant_type_list" }, // Theme { "get_control", "is_ctrl_pressed" }, // InputEventWithModifiers { "get_cull_mask_bit", "get_cull_mask_value" }, // Camera3D @@ -295,7 +300,7 @@ static const char *gdscript_function_renames[][2] = { { "get_d", "get_distance" }, // LineShape2D { "get_drag_data", "_get_drag_data" }, // Control { "get_drag_data_fw", "_get_drag_data_fw" }, // ScriptEditor - { "get_editor_viewport", "get_viewport" }, // EditorPlugin + { "get_editor_viewport", "get_editor_main_screen" }, // EditorPlugin { "get_enabled_focus_mode", "get_focus_mode" }, // BaseButton { "get_endian_swap", "is_big_endian" }, // File { "get_error_string", "get_error_message" }, // JSON @@ -331,6 +336,7 @@ static const char *gdscript_function_renames[][2] = { { "get_network_peer", "get_multiplayer_peer" }, // Multiplayer API { "get_network_unique_id", "get_unique_id" }, // Multiplayer API { "get_ok", "get_ok_button" }, // AcceptDialog + { "get_oneshot", "get_one_shot" }, // AnimatedTexture { "get_option_visibility", "_get_option_visibility" }, // EditorImportPlugin { "get_parameter_default_value", "_get_parameter_default_value" }, // AnimationNode { "get_parameter_list", "_get_parameter_list" }, // AnimationNode @@ -474,7 +480,7 @@ static const char *gdscript_function_renames[][2] = { { "set_collision_layer_bit", "set_collision_layer_value" }, // CSGShape3D and a lot of others like GridMap { "set_collision_mask_bit", "set_collision_mask_value" }, // CSGShape3D and a lot of others like GridMap { "set_column_min_width", "set_column_custom_minimum_width" }, // Tree - { "set_command", "set_command_pressed" }, // InputEventWithModifiers + { "set_command", "set_meta_pressed" }, // InputEventWithModifiers { "set_control", "set_ctrl_pressed" }, // InputEventWithModifiers { "set_create_options", "_set_create_options" }, // EditorResourcePicker { "set_cull_mask_bit", "set_cull_mask_value" }, // Camera3D @@ -506,6 +512,7 @@ static const char *gdscript_function_renames[][2] = { { "set_mid_height", "set_height" }, // CapsuleMesh { "set_network_master", "set_multiplayer_authority" }, // Node { "set_network_peer", "set_multiplayer_peer" }, // Multiplayer API + { "set_oneshot", "set_one_shot" }, // AnimatedTexture { "set_pause_mode", "set_process_mode" }, // Node { "set_physical_scancode", "set_physical_keycode" }, // InputEventKey { "set_refuse_new_network_connections", "set_refuse_new_connections" }, // Multiplayer API @@ -547,6 +554,7 @@ static const char *gdscript_function_renames[][2] = { { "update_gizmo", "update_gizmos" }, // Node3D { "viewport_set_use_arvr", "viewport_set_use_xr" }, // RenderingServer { "warp_mouse_position", "warp_mouse" }, // Input + { "world_to_map", "local_to_map" }, // TileMap, GridMap { "set_shader_param", "set_shader_parameter" }, // ShaderMaterial { "get_shader_param", "get_shader_parameter" }, // ShaderMaterial { "set_uniform_name", "set_parameter_name" }, // ParameterRef @@ -575,6 +583,7 @@ static const char *gdscript_function_renames[][2] = { { "linear2db", "linear_to_db" }, { "rad2deg", "rad_to_deg" }, { "rand_range", "randf_range" }, + { "range_lerp", "remap" }, { "stepify", "snapped" }, { "str2var", "str_to_var" }, { "var2str", "var_to_str" }, @@ -663,15 +672,17 @@ static const char *csharp_function_renames[][2] = { { "CanInstance", "CanInstantiate" }, // PackedScene, Script { "CanvasLightSetScale", "CanvasLightSetTextureScale" }, // RenderingServer { "CenterViewportToCursor", "CenterViewportToCaret" }, // TextEdit + { "ChangeScene", "ChangeSceneToFile" }, // SceneTree + { "ChangeSceneTo", "ChangeSceneToPacked" }, // SceneTree { "ClipPolygons2d", "ClipPolygons" }, // Geometry2D { "ClipPolylineWithPolygon2d", "ClipPolylineWithPolygon" }, //Geometry2D { "CommitHandle", "_CommitHandle" }, // EditorNode3DGizmo { "ConvexHull2d", "ConvexHull" }, // Geometry2D - { "CursorGetBlinkSpeed", "GetCaretBlinkSpeed" }, // TextEdit + { "CursorGetBlinkSpeed", "GetCaretBlinkInterval" }, // TextEdit { "CursorGetColumn", "GetCaretColumn" }, // TextEdit { "CursorGetLine", "GetCaretLine" }, // TextEdit { "CursorSetBlinkEnabled", "SetCaretBlinkEnabled" }, // TextEdit - { "CursorSetBlinkSpeed", "SetCaretBlinkSpeed" }, // TextEdit + { "CursorSetBlinkSpeed", "SetCaretBlinkInterval" }, // TextEdit { "CursorSetColumn", "SetCaretColumn" }, // TextEdit { "CursorSetLine", "SetCaretLine" }, // TextEdit { "DampedSpringJointCreate", "JointMakeDampedSpring" }, // PhysicsServer2D @@ -750,6 +761,7 @@ static const char *csharp_function_renames[][2] = { { "GetNetworkMaster", "GetMultiplayerAuthority" }, // Node { "GetNetworkPeer", "GetMultiplayerPeer" }, // Multiplayer API { "GetNetworkUniqueId", "GetUniqueId" }, // Multiplayer API + { "GetOneshot", "GetOneShot" }, // AnimatedTexture { "GetOk", "GetOkButton" }, // AcceptDialog { "GetOptionVisibility", "_GetOptionVisibility" }, // EditorImportPlugin { "GetParameterDefaultValue", "_GetParameterDefaultValue" }, // AnimationNode @@ -916,6 +928,7 @@ static const char *csharp_function_renames[][2] = { { "SetMidHeight", "SetHeight" }, // CapsuleMesh { "SetNetworkMaster", "SetMultiplayerAuthority" }, // Node { "SetNetworkPeer", "SetMultiplayerPeer" }, // Multiplayer API + { "SetOneshot", "SetOneShot" }, // AnimatedTexture { "SetPhysicalScancode", "SetPhysicalKeycode" }, // InputEventKey { "SetRefuseNewNetworkConnections", "SetRefuseNewConnections" }, // Multiplayer API { "SetRegion", "SetRegionEnabled" }, // Sprite2D, Sprite broke AtlasTexture @@ -958,6 +971,7 @@ static const char *csharp_function_renames[][2] = { { "UpdateGizmo", "UpdateGizmos" }, // Node3D { "ViewportSetUseArvr", "ViewportSetUseXr" }, // RenderingServer { "WarpMousePosition", "WarpMouse" }, // Input + { "WorldToMap", "LocalToMap" }, // TileMap, GridMap { "SetShaderParam", "SetShaderParameter" }, // ShaderMaterial { "GetShaderParam", "GetShaderParameter" }, // ShaderMaterial { "SetUniformName", "SetParameterName" }, // ParameterRef @@ -984,6 +998,7 @@ static const char *csharp_function_renames[][2] = { { "Linear2Db", "LinearToDb" }, { "Rad2Deg", "RadToDeg" }, { "RandRange", "RandfRange" }, + { "RangeLerp", "Remap" }, { "Stepify", "Snapped" }, { "Str2Var", "StrToVar" }, { "Var2Str", "VarToStr" }, @@ -1023,9 +1038,12 @@ static const char *gdscript_properties_renames[][2] = { // { "filename", "scene_file_path" }, // Node { "as_normalmap", "as_normal_map" }, // NoiseTexture { "bbcode_text", "text" }, // RichTextLabel + { "bg", "panel" }, // Theme + { "bg_focus", "focus" }, // Theme + { "caret_blink_speed", "caret_blink_interval" }, // TextEdit, LineEdit { "caret_moving_by_right_click", "caret_move_on_right_click" }, // TextEdit { "caret_position", "caret_column" }, // LineEdit - { "check_vadjust", "check_v_adjust" }, // Theme + { "check_vadjust", "check_v_offset" }, // Theme { "close_h_ofs", "close_h_offset" }, // Theme { "close_v_ofs", "close_v_offset" }, // Theme { "commentfocus", "comment_focus" }, // Theme @@ -1043,6 +1061,9 @@ static const char *gdscript_properties_renames[][2] = { { "focus_neighbour_left", "focus_neighbor_left" }, // Control { "focus_neighbour_right", "focus_neighbor_right" }, // Control { "focus_neighbour_top", "focus_neighbor_top" }, // Control + { "file_icon_modulate", "file_icon_color" }, // Theme + { "files_disabled", "file_disabled_color" }, // Theme + { "folder_icon_modulate", "folder_icon_color" }, // Theme { "global_rate_scale", "playback_speed_scale" }, // AudioServer { "gravity_distance_scale", "gravity_point_distance_scale" }, // Area2D { "gravity_vec", "gravity_direction" }, // Area2D @@ -1057,7 +1078,12 @@ static const char *gdscript_properties_renames[][2] = { { "mid_height", "height" }, // CapsuleMesh { "offset_h", "drag_horizontal_offset" }, // Camera2D { "offset_v", "drag_vertical_offset" }, // Camera2D + { "off", "unchecked" }, // Theme + { "off_disabled", "unchecked_disabled" }, // Theme { "ofs", "offset" }, // Theme + { "on", "checked" }, // Theme + { "on_disabled", "checked_disabled" }, // Theme + { "oneshot", "one_shot" }, // AnimatedTexture { "out_of_range_mode", "max_polyphony" }, // AudioStreamPlayer3D { "pause_mode", "process_mode" }, // Node { "physical_scancode", "physical_keycode" }, // InputEventKey @@ -1108,6 +1134,7 @@ static const char *csharp_properties_renames[][2] = { // { "CastTo", "TargetPosition" }, // RayCast2D, RayCast3D // { "Doubleclick", "DoubleClick" }, // InputEventMouseButton // { "Group", "ButtonGroup" }, // BaseButton + // { "PercentVisible, "ShowPercentage}, // ProgressBar, conflicts with Label and RichTextLabel, but may be a worth it. // { "ProcessMode", "ProcessCallback" }, // AnimationTree, Camera2D // { "Scancode", "Keycode" }, // InputEventKey // { "Toplevel", "TopLevel" }, // Node @@ -1117,6 +1144,7 @@ static const char *csharp_properties_renames[][2] = { // { "Znear", "Near" }, // Camera3D { "AsNormalmap", "AsNormalMap" }, // NoiseTexture { "BbcodeText", "Text" }, // RichTextLabel + { "CaretBlinkSpeed", "CaretBlinkInterval" }, // TextEdit, LineEdit { "CaretMovingByRightClick", "CaretMoveOnRightClick" }, // TextEdit { "CaretPosition", "CaretColumn" }, // LineEdit { "CheckVadjust", "CheckVAdjust" }, // Theme @@ -1151,6 +1179,7 @@ static const char *csharp_properties_renames[][2] = { { "OffsetH", "DragHorizontalOffset" }, // Camera2D { "OffsetV", "DragVerticalOffset" }, // Camera2D { "Ofs", "Offset" }, // Theme + { "Oneshot", "OneShot" }, // AnimatedTexture { "OutOfRangeMode", "MaxPolyphony" }, // AudioStreamPlayer3D { "PauseMode", "ProcessMode" }, // Node { "PhysicalScancode", "PhysicalKeycode" }, // InputEventKey @@ -1241,7 +1270,7 @@ static const char *project_settings_renames[][2] = { { "network/limits/debugger_stdout/max_errors_per_second", "network/limits/debugger/max_errors_per_second" }, { "network/limits/debugger_stdout/max_messages_per_frame", "network/limits/debugger/max_queued_messages" }, { "network/limits/debugger_stdout/max_warnings_per_second", "network/limits/debugger/max_warnings_per_second" }, - { "network/ssl/certificates", "network/ssl/certificate_bundle_override" }, + { "network/ssl/certificates", "network/tls/certificate_bundle_override" }, { "physics/2d/thread_model", "physics/2d/run_on_thread" }, // TODO not sure { "rendering/environment/default_clear_color", "rendering/environment/defaults/default_clear_color" }, { "rendering/environment/default_environment", "rendering/environment/defaults/default_environment" }, @@ -1456,6 +1485,7 @@ static const char *class_renames[][2] = { { "StreamCubemap", "CompressedCubemap" }, { "StreamCubemapArray", "CompressedCubemapArray" }, { "StreamPeerGDNative", "StreamPeerExtension" }, + { "StreamPeerSSL", "StreamPeerTLS" }, { "StreamTexture", "CompressedTexture2D" }, { "StreamTexture2D", "CompressedTexture2D" }, { "StreamTexture2DArray", "CompressedTexture2DArray" }, @@ -1524,7 +1554,6 @@ static const char *class_renames[][2] = { { nullptr, nullptr }, }; -// TODO - this colors needs to be validated(not all are valid) static const char *color_renames[][2] = { { "aliceblue", "ALICE_BLUE" }, { "antiquewhite", "ANTIQUE_WHITE" }, @@ -1678,7 +1707,7 @@ static const char *color_renames[][2] = { class ProjectConverter3To4::RegExContainer { public: - // Custom GDScript + // Custom GDScript. RegEx reg_is_empty = RegEx("\\bempty\\("); RegEx reg_super = RegEx("([\t ])\\.([a-zA-Z_])"); RegEx reg_json_to = RegEx("\\bto_json\\b"); @@ -1695,7 +1724,7 @@ public: RegEx reg_os_fullscreen = RegEx("OS.window_fullscreen[= ]+([^#^\n]+)"); RegEx reg_instantiate = RegEx("\\.instance\\(([^\\)]*)\\)"); - // GDScript keywords + // GDScript keywords. RegEx keyword_gdscript_tool = RegEx("^tool"); RegEx keyword_gdscript_export_single = RegEx("^export"); RegEx keyword_gdscript_export_mutli = RegEx("([\t]+)export\\b"); @@ -1709,7 +1738,7 @@ public: RegEx keyword_gdscript_master = RegEx("^master func"); RegEx keyword_gdscript_mastersync = RegEx("^mastersync func"); - // CSharp keywords + // CSharp keywords. RegEx keyword_csharp_remote = RegEx("\\[Remote(Attribute)?(\\(\\))?\\]"); RegEx keyword_csharp_remotesync = RegEx("\\[(Remote)?Sync(Attribute)?(\\(\\))?\\]"); RegEx keyword_csharp_puppet = RegEx("\\[(Puppet|Slave)(Attribute)?(\\(\\))?\\]"); @@ -1717,11 +1746,11 @@ public: RegEx keyword_csharp_master = RegEx("\\[Master(Attribute)?(\\(\\))?\\]"); RegEx keyword_csharp_mastersync = RegEx("\\[MasterSync(Attribute)?(\\(\\))?\\]"); - // Colors + // Colors. LocalVector<RegEx *> color_regexes; LocalVector<String> color_renamed; - // Classes + // Classes. LocalVector<RegEx *> class_tscn_regexes; LocalVector<RegEx *> class_gd_regexes; LocalVector<RegEx *> class_shader_regexes; @@ -1736,7 +1765,7 @@ public: LocalVector<String> class_temp_gd_renames; LocalVector<String> class_temp_shader_renames; - // Common + // Common. LocalVector<RegEx *> enum_regexes; LocalVector<RegEx *> gdscript_function_regexes; LocalVector<RegEx *> project_settings_regexes; @@ -1749,58 +1778,58 @@ public: LocalVector<RegEx *> csharp_signal_regexes; RegExContainer() { - // Common + // Common. { - // Enum + // Enum. for (unsigned int current_index = 0; enum_renames[current_index][0]; current_index++) { enum_regexes.push_back(memnew(RegEx(String("\\b") + enum_renames[current_index][0] + "\\b"))); } - // GDScript functions + // GDScript functions. for (unsigned int current_index = 0; gdscript_function_renames[current_index][0]; current_index++) { gdscript_function_regexes.push_back(memnew(RegEx(String("\\b") + gdscript_function_renames[current_index][0] + "\\b"))); } - // Project Settings + // Project Settings. for (unsigned int current_index = 0; project_settings_renames[current_index][0]; current_index++) { project_settings_regexes.push_back(memnew(RegEx(String("\\b") + project_settings_renames[current_index][0] + "\\b"))); } - // GDScript properties + // GDScript properties. for (unsigned int current_index = 0; gdscript_properties_renames[current_index][0]; current_index++) { gdscript_properties_regexes.push_back(memnew(RegEx(String("\\b") + gdscript_properties_renames[current_index][0] + "\\b"))); } - // GDScript Signals + // GDScript Signals. for (unsigned int current_index = 0; gdscript_signals_renames[current_index][0]; current_index++) { gdscript_signals_regexes.push_back(memnew(RegEx(String("\\b") + gdscript_signals_renames[current_index][0] + "\\b"))); } - // Shaders + // Shaders. for (unsigned int current_index = 0; shaders_renames[current_index][0]; current_index++) { shaders_regexes.push_back(memnew(RegEx(String("\\b") + shaders_renames[current_index][0] + "\\b"))); } - // Builtin types + // Builtin types. for (unsigned int current_index = 0; builtin_types_renames[current_index][0]; current_index++) { builtin_types_regexes.push_back(memnew(RegEx(String("\\b") + builtin_types_renames[current_index][0] + "\\b"))); } - // CSharp function renames + // CSharp function renames. for (unsigned int current_index = 0; csharp_function_renames[current_index][0]; current_index++) { csharp_function_regexes.push_back(memnew(RegEx(String("\\b") + csharp_function_renames[current_index][0] + "\\b"))); } - // CSharp properties renames + // CSharp properties renames. for (unsigned int current_index = 0; csharp_properties_renames[current_index][0]; current_index++) { csharp_properties_regexes.push_back(memnew(RegEx(String("\\b") + csharp_properties_renames[current_index][0] + "\\b"))); } - // CSharp signals renames + // CSharp signals renames. for (unsigned int current_index = 0; csharp_signals_renames[current_index][0]; current_index++) { csharp_signal_regexes.push_back(memnew(RegEx(String("\\b") + csharp_signals_renames[current_index][0] + "\\b"))); } } - // Colors + // Colors. { for (unsigned int current_index = 0; color_renames[current_index][0]; current_index++) { color_regexes.push_back(memnew(RegEx(String("\\bColor.") + color_renames[current_index][0] + "\\b"))); color_renamed.push_back(String("Color.") + color_renames[current_index][1]); } } - // Classes + // Classes. { for (unsigned int current_index = 0; class_renames[current_index][0]; current_index++) { class_tscn_regexes.push_back(memnew(RegEx(String("\\b") + class_renames[current_index][0] + ".tscn\\b"))); @@ -1858,12 +1887,12 @@ public: } }; -ProjectConverter3To4::ProjectConverter3To4(int maximum_file_size_kb, int maximum_line_length) { - this->maximum_file_size = maximum_file_size_kb * 1024; - this->maximum_line_length = maximum_line_length; +ProjectConverter3To4::ProjectConverter3To4(int p_maximum_file_size_kb, int p_maximum_line_length) { + maximum_file_size = p_maximum_file_size_kb * 1024; + maximum_line_length = p_maximum_line_length; } -// Function responsible for converting project +// Function responsible for converting project. int ProjectConverter3To4::convert() { print_line("Starting conversion."); uint64_t conversion_start_time = Time::get_singleton()->get_ticks_msec(); @@ -1871,7 +1900,7 @@ int ProjectConverter3To4::convert() { RegExContainer reg_container = RegExContainer(); int cached_maximum_line_length = maximum_line_length; - maximum_line_length = 10000; // Use only for tests bigger value, to not break them + maximum_line_length = 10000; // Use only for tests bigger value, to not break them. ERR_FAIL_COND_V_MSG(!test_array_names(), ERROR_CODE, "Cannot start converting due to problems with data in arrays."); ERR_FAIL_COND_V_MSG(!test_conversion(reg_container), ERROR_CODE, "Cannot start converting due to problems with converting arrays."); @@ -1879,36 +1908,36 @@ int ProjectConverter3To4::convert() { maximum_line_length = cached_maximum_line_length; // Checking if folder contains valid Godot 3 project. - // Project should not be converted more than 1 times + // Project should not be converted more than once. { - String conventer_text = "; Project was converted by built-in tool to Godot 4.0"; + String converter_text = "; Project was converted by built-in tool to Godot 4.0"; - ERR_FAIL_COND_V_MSG(!FileAccess::exists("project.godot"), ERROR_CODE, "Current directory doesn't contains any Godot 3 project"); + ERR_FAIL_COND_V_MSG(!FileAccess::exists("project.godot"), ERROR_CODE, "Current working directory doesn't contain a \"project.godot\" file for a Godot 3 project."); Error err = OK; String project_godot_content = FileAccess::get_file_as_string("project.godot", &err); - ERR_FAIL_COND_V_MSG(err != OK, ERROR_CODE, "Failed to read content of \"project.godot\" file."); - ERR_FAIL_COND_V_MSG(project_godot_content.contains(conventer_text), ERROR_CODE, "Project already was converted with this tool."); + ERR_FAIL_COND_V_MSG(err != OK, ERROR_CODE, "Unable to read \"project.godot\"."); + ERR_FAIL_COND_V_MSG(project_godot_content.contains(converter_text), ERROR_CODE, "Project was already converted with this tool."); Ref<FileAccess> file = FileAccess::open("project.godot", FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(file.is_null(), ERROR_CODE, "Failed to open project.godot file."); + ERR_FAIL_COND_V_MSG(file.is_null(), ERROR_CODE, "Unable to open \"project.godot\"."); - file->store_string(conventer_text + "\n" + project_godot_content); + file->store_string(converter_text + "\n" + project_godot_content); } Vector<String> collected_files = check_for_files(); uint32_t converted_files = 0; - // Check file by file + // Check file by file. for (int i = 0; i < collected_files.size(); i++) { String file_name = collected_files[i]; Vector<String> lines; uint32_t ignored_lines = 0; { Ref<FileAccess> file = FileAccess::open(file_name, FileAccess::READ); - ERR_CONTINUE_MSG(file.is_null(), "Failed to read content of \"" + file_name + "\"."); + ERR_CONTINUE_MSG(file.is_null(), vformat("Unable to read content of \"%s\".", file_name)); while (!file->eof_reached()) { String line = file->get_line(); lines.append(line); @@ -1917,7 +1946,7 @@ int ProjectConverter3To4::convert() { String file_content_before = collect_string_from_vector(lines); uint64_t hash_before = file_content_before.hash(); uint64_t file_size = file_content_before.size(); - print_line("Trying to convert\t" + itos(i + 1) + "/" + itos(collected_files.size()) + " file - \"" + file_name.trim_prefix("res://") + "\" with size - " + itos(file_size / 1024) + " KB"); + print_line(vformat("Trying to convert\t%d/%d file - \"%s\" with size - %d KB", i + 1, collected_files.size(), file_name.trim_prefix("res://"), file_size / 1024)); Vector<String> reason; bool is_ignored = false; @@ -1929,15 +1958,15 @@ int ProjectConverter3To4::convert() { } if (file_size < uint64_t(maximum_file_size)) { - // TSCN must be the same work exactly same as .gd file because it may contains builtin script + // ".tscn" must work exactly the same as ".gd" files because they may contain built-in Scripts. if (file_name.ends_with(".gd")) { - rename_classes(lines, reg_container); // Using only specialized function + rename_classes(lines, reg_container); // Using only specialized function. rename_common(enum_renames, reg_container.enum_regexes, lines); - rename_colors(lines, reg_container); // Require to additional rename + rename_colors(lines, reg_container); // Require to additional rename. rename_common(gdscript_function_renames, reg_container.gdscript_function_regexes, lines); - rename_gdscript_functions(lines, reg_container, false); // Require to additional rename + rename_gdscript_functions(lines, reg_container, false); // Require to additional rename. rename_common(project_settings_renames, reg_container.project_settings_regexes, lines); rename_gdscript_keywords(lines, reg_container); @@ -1948,13 +1977,13 @@ int ProjectConverter3To4::convert() { custom_rename(lines, "\\.shader", ".gdshader"); } else if (file_name.ends_with(".tscn")) { - rename_classes(lines, reg_container); // Using only specialized function + rename_classes(lines, reg_container); // Using only specialized function. rename_common(enum_renames, reg_container.enum_regexes, lines); - rename_colors(lines, reg_container); // Require to additional rename + rename_colors(lines, reg_container); // Require to do additional renames. rename_common(gdscript_function_renames, reg_container.gdscript_function_regexes, lines); - rename_gdscript_functions(lines, reg_container, true); // Require to additional rename + rename_gdscript_functions(lines, reg_container, true); // Require to do additional renames. rename_common(project_settings_renames, reg_container.project_settings_regexes, lines); rename_gdscript_keywords(lines, reg_container); @@ -1964,8 +1993,8 @@ int ProjectConverter3To4::convert() { rename_common(builtin_types_renames, reg_container.builtin_types_regexes, lines); custom_rename(lines, "\\.shader", ".gdshader"); - } else if (file_name.ends_with(".cs")) { // TODO, C# should use different methods - rename_classes(lines, reg_container); // Using only specialized function + } else if (file_name.ends_with(".cs")) { // TODO, C# should use different methods. + rename_classes(lines, reg_container); // Using only specialized function. rename_common(csharp_function_renames, reg_container.csharp_function_regexes, lines); rename_common(builtin_types_renames, reg_container.builtin_types_regexes, lines); rename_common(csharp_properties_renames, reg_container.csharp_properties_regexes, lines); @@ -1976,7 +2005,7 @@ int ProjectConverter3To4::convert() { } else if (file_name.ends_with(".gdshader") || file_name.ends_with(".shader")) { rename_common(shaders_renames, reg_container.shaders_regexes, lines); } else if (file_name.ends_with("tres")) { - rename_classes(lines, reg_container); // Using only specialized function + rename_classes(lines, reg_container); // Using only specialized function. rename_common(shaders_renames, reg_container.shaders_regexes, lines); rename_common(builtin_types_renames, reg_container.builtin_types_regexes, lines); @@ -1998,41 +2027,40 @@ int ProjectConverter3To4::convert() { } } } else { - reason.append(" ERROR: File has exceeded the maximum size allowed - " + itos(maximum_file_size / 1024) + " KB"); + reason.append(vformat(" ERROR: File has exceeded the maximum size allowed - %d KB", maximum_file_size / 1024)); is_ignored = true; } uint64_t end_time = Time::get_singleton()->get_ticks_msec(); if (is_ignored) { - String end_message = " Checking file took " + itos(end_time - start_time) + " ms."; + String end_message = vformat(" Checking file took %d ms.", end_time - start_time); print_line(end_message); } else { String file_content_after = collect_string_from_vector(lines); uint64_t hash_after = file_content_after.hash64(); - // Don't need to save file without any changes - // Save if this is a shader, because it was renamed + // Don't need to save file without any changes. + // Save if this is a shader, because it was renamed. if (hash_before != hash_after || file_name.ends_with(".gdshader")) { converted_files++; Ref<FileAccess> file = FileAccess::open(file_name, FileAccess::WRITE); - ERR_CONTINUE_MSG(file.is_null(), "Failed to open \"" + file_name + "\" to save data to file."); + ERR_CONTINUE_MSG(file.is_null(), vformat("Unable to apply changes to \"%s\", no writing access.", file_name)); file->store_string(file_content_after); - reason.append(" File was changed, conversion took " + itos(end_time - start_time) + " ms."); + reason.append(vformat(" File was changed, conversion took %d ms.", end_time - start_time)); } else { - reason.append(" File was not changed, checking took " + itos(end_time - start_time) + " ms."); + reason.append(vformat(" File was left unchanged, checking took %d ms.", end_time - start_time)); } if (ignored_lines != 0) { - reason.append(" Ignored " + itos(ignored_lines) + " lines, because their length exceeds maximum allowed characters - " + itos(maximum_line_length)); + reason.append(vformat(" Ignored %d lines, because their length exceeds maximum allowed characters - %d.", ignored_lines, maximum_line_length)); } } for (int k = 0; k < reason.size(); k++) { print_line(reason[k]); } } - - print_line("Conversion ended - all files(" + itos(collected_files.size()) + "), converted files(" + itos(converted_files) + "), not converted files(" + itos(collected_files.size() - converted_files) + ")."); + print_line(vformat("Conversion ended - all files(%d), converted files: (%d), not converted files: (%d).", collected_files.size(), converted_files, collected_files.size() - converted_files)); uint64_t conversion_end_time = Time::get_singleton()->get_ticks_msec(); - print_line("Conversion of all files took " + itos(conversion_end_time - conversion_start_time) + " ms."); + print_line(vformat("Conversion of all files took %10.3f seconds.", (conversion_end_time - conversion_start_time) / 1000.0)); return 0; }; @@ -2044,7 +2072,7 @@ int ProjectConverter3To4::validate_conversion() { RegExContainer reg_container = RegExContainer(); int cached_maximum_line_length = maximum_line_length; - maximum_line_length = 10000; // Use only for tests bigger value, to not break them + maximum_line_length = 10000; // To avoid breaking the tests, only use this for the their larger value. ERR_FAIL_COND_V_MSG(!test_array_names(), ERROR_CODE, "Cannot start converting due to problems with data in arrays."); ERR_FAIL_COND_V_MSG(!test_conversion(reg_container), ERROR_CODE, "Cannot start converting due to problems with converting arrays."); @@ -2052,7 +2080,7 @@ int ProjectConverter3To4::validate_conversion() { maximum_line_length = cached_maximum_line_length; // Checking if folder contains valid Godot 3 project. - // Project should not be converted more than 1 times + // Project should not be converted more than once. { String conventer_text = "; Project was converted by built-in tool to Godot 4.0"; @@ -2069,7 +2097,7 @@ int ProjectConverter3To4::validate_conversion() { uint32_t converted_files = 0; - // Check file by file + // Check file by file. for (int i = 0; i < collected_files.size(); i++) { String file_name = collected_files[i]; Vector<String> lines; @@ -2077,14 +2105,14 @@ int ProjectConverter3To4::validate_conversion() { uint64_t file_size = 0; { Ref<FileAccess> file = FileAccess::open(file_name, FileAccess::READ); - ERR_CONTINUE_MSG(file.is_null(), "Failed to read content of \"" + file_name + "\"."); + ERR_CONTINUE_MSG(file.is_null(), vformat("Unable to read content of \"%s\".", file_name)); while (!file->eof_reached()) { String line = file->get_line(); file_size += line.size(); lines.append(line); } } - print_line("Checking for conversion - " + itos(i + 1) + "/" + itos(collected_files.size()) + " file - \"" + file_name.trim_prefix("res://") + "\" with size - " + itos(file_size / 1024) + " KB"); + print_line(vformat("Checking for conversion - %d/%d file - \"%s\" with size - %d KB"), i + 1, collected_files.size(), file_name.trim_prefix("res://"), file_size / 1024); Vector<String> changed_elements; Vector<String> reason; @@ -2092,7 +2120,7 @@ int ProjectConverter3To4::validate_conversion() { uint64_t start_time = Time::get_singleton()->get_ticks_msec(); if (file_name.ends_with(".shader")) { - reason.append("\tFile extension will be renamed from `shader` to `gdshader`."); + reason.append("\tFile extension will be renamed from \"shader\" to \"gdshader\"."); } if (file_size < uint64_t(maximum_file_size)) { @@ -2154,7 +2182,7 @@ int ProjectConverter3To4::validate_conversion() { } else if (file_name.ends_with(".csproj")) { // TODO } else { - ERR_PRINT(file_name + " is not supported!"); + ERR_PRINT(vformat("\"%s\", is not supported!", file_name)); continue; } @@ -2164,14 +2192,14 @@ int ProjectConverter3To4::validate_conversion() { } } } else { - reason.append("\tERROR: File has exceeded the maximum size allowed - " + itos(maximum_file_size / 1024) + " KB"); + reason.append(vformat("\tERROR: File has exceeded the maximum size allowed - %d KB.", maximum_file_size / 1024)); is_ignored = true; } uint64_t end_time = Time::get_singleton()->get_ticks_msec(); - String end_message = " Checking file took " + itos(end_time - start_time) + " ms."; + String end_message = vformat(" Checking file took %10.3f ms.", (end_time - start_time) / 1000.0); if (ignored_lines != 0) { - end_message += " Ignored " + itos(ignored_lines) + " lines, because their length exceeds maximum allowed characters - " + itos(maximum_line_length); + end_message += vformat(" Ignored %d lines, because their length exceeds maximum allowed characters - %d.", ignored_lines, maximum_line_length); } print_line(end_message); @@ -2188,13 +2216,13 @@ int ProjectConverter3To4::validate_conversion() { } } - print_line("Checking for valid conversion ended - all files(" + itos(collected_files.size()) + "), files which would be converted(" + itos(converted_files) + "), files which would not be converted(" + itos(collected_files.size() - converted_files) + ")."); + print_line(vformat("Checking for valid conversion ended - all files(%d), files which would be converted(%d), files which would not be converted(%d).", collected_files.size(), converted_files, collected_files.size() - converted_files)); uint64_t conversion_end_time = Time::get_singleton()->get_ticks_msec(); - print_line("Conversion of all files took " + itos(conversion_end_time - conversion_start_time) + " ms."); + print_line(vformat("Conversion of all files took %10.3f seconds.", (conversion_end_time - conversion_start_time) / 1000.0)); return 0; } -// Collect files which will be checked, it will not touch txt, mp4, wav etc. files +// Collect files which will be checked, excluding ".txt", ".mp4", ".wav" etc. files. Vector<String> ProjectConverter3To4::check_for_files() { Vector<String> collected_files = Vector<String>(); @@ -2204,7 +2232,7 @@ Vector<String> ProjectConverter3To4::check_for_files() { core_bind::Directory dir = core_bind::Directory(); while (!directories_to_check.is_empty()) { String path = directories_to_check.get(directories_to_check.size() - 1); // Is there any pop_back function? - directories_to_check.resize(directories_to_check.size() - 1); // Remove last element + directories_to_check.resize(directories_to_check.size() - 1); // Remove last element. if (dir.open(path) == OK) { dir.set_include_hidden(true); dir.list_dir_begin(); @@ -2241,10 +2269,7 @@ bool ProjectConverter3To4::test_conversion_gdscript_builtin(String name, String Vector<String> got = name.split("\n"); (this->*func)(got, reg_container, builtin_script); String got_str = collect_string_from_vector(got); - if (expected != got_str) { - ERR_PRINT("Failed to convert " + what + " `" + name + "` to `" + expected + "`, got instead `" + got_str + "`"); - return false; - } + ERR_FAIL_COND_V_MSG(expected != got_str, false, vformat("Failed to convert %s \"%s\" to \"%s\", got instead \"%s\"", what, name, expected, got_str)); return true; } @@ -2253,10 +2278,7 @@ bool ProjectConverter3To4::test_conversion_with_regex(String name, String expect Vector<String> got = name.split("\n"); (this->*func)(got, reg_container); String got_str = collect_string_from_vector(got); - if (expected != got_str) { - ERR_PRINT("Failed to convert " + what + " `" + name + "` to `" + expected + "`, got instead `" + got_str + "`"); - return false; - } + ERR_FAIL_COND_V_MSG(expected != got_str, false, vformat("Failed to convert %s \"%s\" to \"%s\", got instead \"%s\"", what, name, expected, got_str)); return true; } @@ -2265,187 +2287,185 @@ bool ProjectConverter3To4::test_conversion_basic(String name, String expected, c Vector<String> got = name.split("\n"); rename_common(array, regex_cache, got); String got_str = collect_string_from_vector(got); - if (expected != got_str) { - ERR_PRINT("Failed to convert " + what + " `" + name + "` to `" + expected + "`, got instead `" + got_str + "`"); - return false; - } + ERR_FAIL_COND_V_MSG(expected != got_str, false, vformat("Failed to convert %s \"%s\" to \"%s\", got instead \"%s\"", what, name, expected, got_str)); + return true; } -// Validate if conversions are proper +// Validate if conversions are proper. bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { bool valid = true; - valid = valid & test_conversion_basic("TYPE_REAL", "TYPE_FLOAT", enum_renames, reg_container.enum_regexes, "enum"); + valid = valid && test_conversion_basic("TYPE_REAL", "TYPE_FLOAT", enum_renames, reg_container.enum_regexes, "enum"); - valid = valid & test_conversion_basic("can_instance", "can_instantiate", gdscript_function_renames, reg_container.gdscript_function_regexes, "gdscript function"); + valid = valid && test_conversion_basic("can_instance", "can_instantiate", gdscript_function_renames, reg_container.gdscript_function_regexes, "gdscript function"); - valid = valid & test_conversion_basic("CanInstance", "CanInstantiate", csharp_function_renames, reg_container.csharp_function_regexes, "csharp function"); + valid = valid && test_conversion_basic("CanInstance", "CanInstantiate", csharp_function_renames, reg_container.csharp_function_regexes, "csharp function"); - valid = valid & test_conversion_basic("translation", "position", gdscript_properties_renames, reg_container.gdscript_properties_regexes, "gdscript property"); + valid = valid && test_conversion_basic("translation", "position", gdscript_properties_renames, reg_container.gdscript_properties_regexes, "gdscript property"); - valid = valid & test_conversion_basic("Translation", "Position", csharp_properties_renames, reg_container.csharp_properties_regexes, "csharp property"); + valid = valid && test_conversion_basic("Translation", "Position", csharp_properties_renames, reg_container.csharp_properties_regexes, "csharp property"); - valid = valid & test_conversion_basic("NORMALMAP", "NORMAL_MAP", shaders_renames, reg_container.shaders_regexes, "shader"); + valid = valid && test_conversion_basic("NORMALMAP", "NORMAL_MAP", shaders_renames, reg_container.shaders_regexes, "shader"); - valid = valid & test_conversion_basic("text_entered", "text_submitted", gdscript_signals_renames, reg_container.gdscript_signals_regexes, "gdscript signal"); + valid = valid && test_conversion_basic("text_entered", "text_submitted", gdscript_signals_renames, reg_container.gdscript_signals_regexes, "gdscript signal"); - valid = valid & test_conversion_basic("TextEntered", "TextSubmitted", csharp_signals_renames, reg_container.csharp_signal_regexes, "csharp signal"); + valid = valid && test_conversion_basic("TextEntered", "TextSubmitted", csharp_signals_renames, reg_container.csharp_signal_regexes, "csharp signal"); - valid = valid & test_conversion_basic("audio/channel_disable_threshold_db", "audio/buses/channel_disable_threshold_db", project_settings_renames, reg_container.project_settings_regexes, "project setting"); + valid = valid && test_conversion_basic("audio/channel_disable_threshold_db", "audio/buses/channel_disable_threshold_db", project_settings_renames, reg_container.project_settings_regexes, "project setting"); - valid = valid & test_conversion_basic("Transform", "Transform3D", builtin_types_renames, reg_container.builtin_types_regexes, "builtin type"); + valid = valid && test_conversion_basic("Transform", "Transform3D", builtin_types_renames, reg_container.builtin_types_regexes, "builtin type"); - // Custom Renames + // Custom Renames. - valid = valid & test_conversion_with_regex("(Connect(A,B,C,D,E,F,G) != OK):", "(Connect(A,new Callable(B,C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename csharp", reg_container); - valid = valid & test_conversion_with_regex("(Disconnect(A,B,C) != OK):", "(Disconnect(A,new Callable(B,C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename csharp", reg_container); - valid = valid & test_conversion_with_regex("(IsConnected(A,B,C) != OK):", "(IsConnected(A,new Callable(B,C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename", reg_container); + valid = valid && test_conversion_with_regex("(Connect(A,B,C,D,E,F,G) != OK):", "(Connect(A,new Callable(B,C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename csharp", reg_container); + valid = valid && test_conversion_with_regex("(Disconnect(A,B,C) != OK):", "(Disconnect(A,new Callable(B,C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename csharp", reg_container); + valid = valid && test_conversion_with_regex("(IsConnected(A,B,C) != OK):", "(IsConnected(A,new Callable(B,C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename", reg_container); - valid = valid & test_conversion_with_regex("[Remote]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); - valid = valid & test_conversion_with_regex("[RemoteSync]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); - valid = valid & test_conversion_with_regex("[Sync]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); - valid = valid & test_conversion_with_regex("[Slave]", "[RPC]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); - valid = valid & test_conversion_with_regex("[Puppet]", "[RPC]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); - valid = valid & test_conversion_with_regex("[PuppetSync]", "[RPC(CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); - valid = valid & test_conversion_with_regex("[Master]", "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using Multiplayer.GetRemoteSenderId()\n[RPC]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); - valid = valid & test_conversion_with_regex("[MasterSync]", "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using Multiplayer.GetRemoteSenderId()\n[RPC(CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); - - valid = valid & test_conversion_gdscript_builtin("OS.window_fullscreen = Settings.fullscreen", "ProjectSettings.set(\"display/window/size/fullscreen\", Settings.fullscreen)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("OS.window_fullscreen = Settings.fullscreen", "ProjectSettings.set(\\\"display/window/size/fullscreen\\\", Settings.fullscreen)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, true); - valid = valid & test_conversion_gdscript_builtin("OS.get_window_safe_area()", "DisplayServer.get_display_safe_area()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("\tvar aa = roman(r.move_and_slide( a, b, c, d, e, f )) # Roman", "\tr.set_velocity(a)\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tr.move_and_slide()\n\tvar aa = roman(r.velocity) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("\tvar aa = roman(r.move_and_slide_with_snap( a, g, b, c, d, e, f )) # Roman", "\tr.set_velocity(a)\n\t# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `g`\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tr.move_and_slide()\n\tvar aa = roman(r.velocity) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_with_regex("[Remote]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); + valid = valid && test_conversion_with_regex("[RemoteSync]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); + valid = valid && test_conversion_with_regex("[Sync]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); + valid = valid && test_conversion_with_regex("[Slave]", "[RPC]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); + valid = valid && test_conversion_with_regex("[Puppet]", "[RPC]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); + valid = valid && test_conversion_with_regex("[PuppetSync]", "[RPC(CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); + valid = valid && test_conversion_with_regex("[Master]", "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using Multiplayer.GetRemoteSenderId()\n[RPC]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); + valid = valid && test_conversion_with_regex("[MasterSync]", "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using Multiplayer.GetRemoteSenderId()\n[RPC(CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); + + valid = valid && test_conversion_gdscript_builtin("OS.window_fullscreen = Settings.fullscreen", "ProjectSettings.set(\"display/window/size/fullscreen\", Settings.fullscreen)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("OS.window_fullscreen = Settings.fullscreen", "ProjectSettings.set(\\\"display/window/size/fullscreen\\\", Settings.fullscreen)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, true); + valid = valid && test_conversion_gdscript_builtin("OS.get_window_safe_area()", "DisplayServer.get_display_safe_area()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("\tvar aa = roman(r.move_and_slide( a, b, c, d, e, f )) # Roman", "\tr.set_velocity(a)\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tr.move_and_slide()\n\tvar aa = roman(r.velocity) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("\tvar aa = roman(r.move_and_slide_with_snap( a, g, b, c, d, e, f )) # Roman", "\tr.set_velocity(a)\n\t# TODOConverter40 looks that snap in Godot 4.0 is float, not vector like in Godot 3 - previous value `g`\n\tr.set_up_direction(b)\n\tr.set_floor_stop_on_slope_enabled(c)\n\tr.set_max_slides(d)\n\tr.set_floor_max_angle(e)\n\t# TODOConverter40 infinite_inertia were removed in Godot 4.0 - previous value `f`\n\tr.move_and_slide()\n\tvar aa = roman(r.velocity) # Roman", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("list_dir_begin( a , b )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("list_dir_begin( a )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("list_dir_begin( )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("list_dir_begin( a , b )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("list_dir_begin( a )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("list_dir_begin( )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("sort_custom( a , b )", "sort_custom(Callable(a,b))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("func c(var a, var b)", "func c(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("sort_custom( a , b )", "sort_custom(Callable(a,b))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("func c(var a, var b)", "func c(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("draw_line(1, 2, 3, 4, 5)", "draw_line(1,2,3,4)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("draw_line(1, 2, 3, 4, 5)", "draw_line(1,2,3,4)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("\timage.lock()", "\tfalse # image.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("\timage.unlock()", "\tfalse # image.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("\troman.image.unlock()", "\tfalse # roman.image.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("\tmtx.lock()", "\tmtx.lock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("\tmutex.unlock()", "\tmutex.unlock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("\timage.lock()", "\tfalse # image.lock() # TODOConverter40, Image no longer requires locking, `false` helps to not break one line if/else, so it can freely be removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("\timage.unlock()", "\tfalse # image.unlock() # TODOConverter40, Image no longer requires locking, `false` helps to not break one line if/else, so it can freely be removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("\troman.image.unlock()", "\tfalse # roman.image.unlock() # TODOConverter40, Image no longer requires locking, `false` helps to not break one line if/else, so it can freely be removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("\tmtx.lock()", "\tmtx.lock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("\tmutex.unlock()", "\tmutex.unlock()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_with_regex("extends CSGBox", "extends CSGBox3D", &ProjectConverter3To4::rename_classes, "classes", reg_container); - valid = valid & test_conversion_with_regex("CSGBox", "CSGBox3D", &ProjectConverter3To4::rename_classes, "classes", reg_container); - valid = valid & test_conversion_with_regex("Spatial", "Node3D", &ProjectConverter3To4::rename_classes, "classes", reg_container); - valid = valid & test_conversion_with_regex("Spatial.tscn", "Spatial.tscn", &ProjectConverter3To4::rename_classes, "classes", reg_container); - valid = valid & test_conversion_with_regex("Spatial.gd", "Spatial.gd", &ProjectConverter3To4::rename_classes, "classes", reg_container); - valid = valid & test_conversion_with_regex("Spatial.shader", "Spatial.shader", &ProjectConverter3To4::rename_classes, "classes", reg_container); - valid = valid & test_conversion_with_regex("Spatial.other", "Node3D.other", &ProjectConverter3To4::rename_classes, "classes", reg_container); - - valid = valid & test_conversion_with_regex("\nonready", "\n@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("onready", "@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex(" onready", " onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\nexport", "\n@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\texport", "\t@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\texport_dialog", "\texport_dialog", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("export", "@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex(" export", " export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("tool", "@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\n tool", "\n tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\n\ntool", "\n\n@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\n\nremote func", "\n\n@rpc(any_peer) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\n\nremotesync func", "\n\n@rpc(any_peer, call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\n\nsync func", "\n\n@rpc(any_peer, call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\n\nslave func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\n\npuppet func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\n\npuppetsync func", "\n\n@rpc(call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\n\nmaster func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid & test_conversion_with_regex("\n\nmastersync func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc(call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - - valid = valid & test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function\n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , ", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function \n set(mod_value):\n mod_value # TODOConverter40 Non existent set function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("get_node(@", "get_node(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("yield(this, \"timeout\")", "await this.timeout", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("yield(this, \\\"timeout\\\")", "await this.timeout", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, true); - - valid = valid & test_conversion_gdscript_builtin(" Transform.xform(Vector3(a,b,c)) ", " Transform * Vector3(a,b,c) ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin(" Transform.xform_inv(Vector3(a,b,c)) ", " Vector3(a,b,c) * Transform ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("export(float) var lifetime = 3.0", "export var lifetime: float = 3.0", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro'", "export var _font_name = 'AnonymousPro' # (String, 'AnonymousPro', 'CourierPrime')", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); // TODO, this is only a workaround - valid = valid & test_conversion_gdscript_builtin("export(PackedScene) var mob_scene", "export var mob_scene: PackedScene", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("var d = parse_json(roman(sfs))", "var test_json_conv = JSON.new()\ntest_json_conv.parse(roman(sfs))\nvar d = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("to_json( AA ) szon", "JSON.new().stringify( AA ) szon", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("s to_json", "s JSON.new().stringify", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("AF to_json2", "AF to_json2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("var rr = JSON.parse(a)", "var test_json_conv = JSON.new()\ntest_json_conv.parse(a)\nvar rr = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("empty()", "is_empty()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin(".empty", ".empty", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin(").roman(", ").roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("\t.roman(", "\tsuper.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin(" .roman(", " super.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin(".1", ".1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin(" .1", " .1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("'.'", "'.'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("'.a'", "'.a'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("\t._input(_event)", "\tsuper._input(_event)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("(connect(A,B,C) != OK):", "(connect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("(connect(A,B,C,D) != OK):", "(connect(A,Callable(B,C).bind(D)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("(connect(A,B,C,[D]) != OK):", "(connect(A,Callable(B,C).bind(D)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("(connect(A,B,C,[D,E]) != OK):", "(connect(A,Callable(B,C).bind(D,E)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("(connect(A,B,C,[D,E],F) != OK):", "(connect(A,Callable(B,C).bind(D,E),F) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("(connect(A,B,C,D,E) != OK):", "(connect(A,Callable(B,C).bind(D),E) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("(start(A,B) != OK):", "(start(Callable(A,B)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("func start(A,B):", "func start(A,B):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("(start(A,B,C,D,E,F,G) != OK):", "(start(Callable(A,B).bind(C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("disconnect(A,B,C) != OK):", "disconnect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("is_connected(A,B,C) != OK):", "is_connected(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("is_connected(A,B,C))", "is_connected(A,Callable(B,C)))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("(tween_method(A,B,C,D,E).foo())", "(tween_method(Callable(A,B),C,D,E).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("(tween_method(A,B,C,D,E,[F,G]).foo())", "(tween_method(Callable(A,B).bind(F,G),C,D,E).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("(tween_callback(A,B).foo())", "(tween_callback(Callable(A,B)).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("(tween_callback(A,B,[C,D]).foo())", "(tween_callback(Callable(A,B).bind(C,D)).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("func _init(", "func _init(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("func _init(p_x:int)->void:", "func _init(p_x:int):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("q_PackedDataContainer._iter_init(variable1)", "q_PackedDataContainer._iter_init(variable1)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("assert(speed < 20, str(randi()%10))", "assert(speed < 20) #,str(randi()%10))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("assert(speed < 2)", "assert(speed < 2)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("assert(false, \"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", "assert(false) #,\"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("create_from_image(aa, bb)", "create_from_image(aa) #,bb", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("q_ImageTexture.create_from_image(variable1, variable2)", "q_ImageTexture.create_from_image(variable1) #,variable2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("set_cell_item(a, b, c, d ,e) # AA", "set_cell_item( Vector3(a,b,c) ,d,e) # AA", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("set_cell_item(a, b)", "set_cell_item(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("get_cell_item_orientation(a, b,c)", "get_cell_item_orientation(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("get_cell_item(a, b,c)", "get_cell_item(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("map_to_world(a, b,c)", "map_to_world(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("PackedStringArray(req_godot).join('.')", "'.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("=PackedStringArray(req_godot).join('.')", "='.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_gdscript_builtin("apply_force(position, impulse)", "apply_force(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("apply_impulse(position, impulse)", "apply_impulse(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("draw_rect(a,b,c,d,e).abc", "draw_rect(a,b,c,d).abc# e) TODOGODOT4 Antialiasing argument is missing", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("get_focus_owner()", "get_viewport().gui_get_focus_owner()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("button.pressed = 1", "button.button_pressed = 1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("button.pressed=1", "button.button_pressed=1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid & test_conversion_gdscript_builtin("button.pressed SF", "button.pressed SF", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - - valid = valid & test_conversion_with_regex("AAA Color.white AF", "AAA Color.WHITE AF", &ProjectConverter3To4::rename_colors, "custom rename", reg_container); + valid = valid && test_conversion_with_regex("extends CSGBox", "extends CSGBox3D", &ProjectConverter3To4::rename_classes, "classes", reg_container); + valid = valid && test_conversion_with_regex("CSGBox", "CSGBox3D", &ProjectConverter3To4::rename_classes, "classes", reg_container); + valid = valid && test_conversion_with_regex("Spatial", "Node3D", &ProjectConverter3To4::rename_classes, "classes", reg_container); + valid = valid && test_conversion_with_regex("Spatial.tscn", "Spatial.tscn", &ProjectConverter3To4::rename_classes, "classes", reg_container); + valid = valid && test_conversion_with_regex("Spatial.gd", "Spatial.gd", &ProjectConverter3To4::rename_classes, "classes", reg_container); + valid = valid && test_conversion_with_regex("Spatial.shader", "Spatial.shader", &ProjectConverter3To4::rename_classes, "classes", reg_container); + valid = valid && test_conversion_with_regex("Spatial.other", "Node3D.other", &ProjectConverter3To4::rename_classes, "classes", reg_container); + + valid = valid && test_conversion_with_regex("\nonready", "\n@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("onready", "@onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex(" onready", " onready", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\nexport", "\n@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\texport", "\t@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\texport_dialog", "\texport_dialog", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("export", "@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex(" export", " export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("tool", "@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\n tool", "\n tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\n\ntool", "\n\n@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\n\nremote func", "\n\n@rpc(any_peer) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\n\nremotesync func", "\n\n@rpc(any_peer, call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\n\nsync func", "\n\n@rpc(any_peer, call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\n\nslave func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\n\npuppet func", "\n\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\n\npuppetsync func", "\n\n@rpc(call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\n\nmaster func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\n\nmastersync func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc(call_local) func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); + + valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function\n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , ", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Non existent get function \n set(mod_value):\n mod_value # TODOConverter40 Copy here content of set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget , get_function", "var size : Vector2 = Vector2() :\n get:\n return size # TODOConverter40 Copy here content of get_function \n set(mod_value):\n mod_value # TODOConverter40 Non existent set function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("get_node(@", "get_node(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("yield(this, \"timeout\")", "await this.timeout", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("yield(this, \\\"timeout\\\")", "await this.timeout", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, true); + + valid = valid && test_conversion_gdscript_builtin(" Transform.xform(Vector3(a,b,c)) ", " Transform * Vector3(a,b,c) ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin(" Transform.xform_inv(Vector3(a,b,c)) ", " Vector3(a,b,c) * Transform ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("export(float) var lifetime = 3.0", "export var lifetime: float = 3.0", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro'", "export var _font_name = 'AnonymousPro' # (String, 'AnonymousPro', 'CourierPrime')", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); // TODO, this is only a workaround + valid = valid && test_conversion_gdscript_builtin("export(PackedScene) var mob_scene", "export var mob_scene: PackedScene", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("var d = parse_json(roman(sfs))", "var test_json_conv = JSON.new()\ntest_json_conv.parse(roman(sfs))\nvar d = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("to_json( AA ) szon", "JSON.new().stringify( AA ) szon", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("s to_json", "s JSON.new().stringify", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("AF to_json2", "AF to_json2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("var rr = JSON.parse(a)", "var test_json_conv = JSON.new()\ntest_json_conv.parse(a)\nvar rr = test_json_conv.get_data()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("empty()", "is_empty()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin(".empty", ".empty", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin(").roman(", ").roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("\t.roman(", "\tsuper.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin(" .roman(", " super.roman(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin(".1", ".1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin(" .1", " .1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("'.'", "'.'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("'.a'", "'.a'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("\t._input(_event)", "\tsuper._input(_event)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C) != OK):", "(connect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,D) != OK):", "(connect(A,Callable(B,C).bind(D)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,[D]) != OK):", "(connect(A,Callable(B,C).bind(D)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,[D,E]) != OK):", "(connect(A,Callable(B,C).bind(D,E)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,[D,E],F) != OK):", "(connect(A,Callable(B,C).bind(D,E),F) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,D,E) != OK):", "(connect(A,Callable(B,C).bind(D),E) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("(start(A,B) != OK):", "(start(Callable(A,B)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("func start(A,B):", "func start(A,B):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(start(A,B,C,D,E,F,G) != OK):", "(start(Callable(A,B).bind(C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("disconnect(A,B,C) != OK):", "disconnect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("is_connected(A,B,C) != OK):", "is_connected(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("is_connected(A,B,C))", "is_connected(A,Callable(B,C)))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("(tween_method(A,B,C,D,E).foo())", "(tween_method(Callable(A,B),C,D,E).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(tween_method(A,B,C,D,E,[F,G]).foo())", "(tween_method(Callable(A,B).bind(F,G),C,D,E).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(tween_callback(A,B).foo())", "(tween_callback(Callable(A,B)).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(tween_callback(A,B,[C,D]).foo())", "(tween_callback(Callable(A,B).bind(C,D)).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("func _init(", "func _init(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("func _init(p_x:int)->void:", "func _init(p_x:int):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("q_PackedDataContainer._iter_init(variable1)", "q_PackedDataContainer._iter_init(variable1)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("assert(speed < 20, str(randi()%10))", "assert(speed < 20) #,str(randi()%10))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("assert(speed < 2)", "assert(speed < 2)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("assert(false, \"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", "assert(false) #,\"Missing type --\" + str(argument.type) + \"--, needs to be added to project\")", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("create_from_image(aa, bb)", "create_from_image(aa) #,bb", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("q_ImageTexture.create_from_image(variable1, variable2)", "q_ImageTexture.create_from_image(variable1) #,variable2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("set_cell_item(a, b, c, d ,e) # AA", "set_cell_item( Vector3(a,b,c) ,d,e) # AA", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("set_cell_item(a, b)", "set_cell_item(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("get_cell_item_orientation(a, b,c)", "get_cell_item_orientation(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("get_cell_item(a, b,c)", "get_cell_item(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("map_to_world(a, b,c)", "map_to_local(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("PackedStringArray(req_godot).join('.')", "'.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("=PackedStringArray(req_godot).join('.')", "='.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_gdscript_builtin("apply_force(position, impulse)", "apply_force(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("apply_impulse(position, impulse)", "apply_impulse(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("draw_rect(a,b,c,d,e).abc", "draw_rect(a,b,c,d).abc# e) TODOGODOT4 Antialiasing argument is missing", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("get_focus_owner()", "get_viewport().gui_get_focus_owner()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("button.pressed = 1", "button.button_pressed = 1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("button.pressed=1", "button.button_pressed=1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("button.pressed SF", "button.pressed SF", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + + valid = valid && test_conversion_with_regex("AAA Color.white AF", "AAA Color.WHITE AF", &ProjectConverter3To4::rename_colors, "custom rename", reg_container); // Custom rule conversion { @@ -2457,9 +2477,9 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { custom_rename(got, from, to); String got_str = collect_string_from_vector(got); if (got_str != expected) { - ERR_PRINT("Failed to convert custom rename `" + name + "` to `" + expected + "`, got instead `" + got_str + "`"); + ERR_PRINT(vformat("Failed to convert custom rename \"%s\" to \"%s\", got \"%s\", instead.", name, expected, got_str)); } - valid = valid & (got_str == expected); + valid = valid && (got_str == expected); } // get_object_of_execution @@ -2468,36 +2488,36 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { String expected = "kieliszek."; String got = get_object_of_execution(base); if (got != expected) { - ERR_PRINT("Failed to get proper data from get_object_of_execution `" + base + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")"); + ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); } - valid = valid & (got == expected); + valid = valid && (got == expected); } { String base = "r."; String expected = "r."; String got = get_object_of_execution(base); if (got != expected) { - ERR_PRINT("Failed to get proper data from get_object_of_execution `" + base + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")"); + ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); } - valid = valid & (got == expected); + valid = valid && (got == expected); } { String base = "mortadela("; String expected = ""; String got = get_object_of_execution(base); if (got != expected) { - ERR_PRINT("Failed to get proper data from get_object_of_execution `" + base + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")"); + ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); } - valid = valid & (got == expected); + valid = valid && (got == expected); } { String base = "var node = $world/ukraine/lviv."; String expected = "$world/ukraine/lviv."; String got = get_object_of_execution(base); if (got != expected) { - ERR_PRINT("Failed to get proper data from get_object_of_execution `" + base + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")"); + ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); } - valid = valid & (got == expected); + valid = valid && (got == expected); } } // get_starting_space @@ -2506,9 +2526,9 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { String expected = "\t\t\t"; String got = get_starting_space(base); if (got != expected) { - ERR_PRINT("Failed to get proper data from get_starting_space `" + base + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")"); + ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size())); } - valid = valid & (got == expected); + valid = valid && (got == expected); } // Parse Arguments { @@ -2520,9 +2540,9 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { got += part + "|||"; } if (got != expected) { - ERR_PRINT("Failed to get proper data from parse_arguments `" + line + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")"); + ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size())); } - valid = valid & (got == expected); + valid = valid && (got == expected); } { String line = "(a , b , c)"; @@ -2533,9 +2553,9 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { got += part + "|||"; } if (got != expected) { - ERR_PRINT("Failed to get proper data from parse_arguments `" + line + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")"); + ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size())); } - valid = valid & (got == expected); + valid = valid && (got == expected); } { String line = "(a , \"b,\" , c)"; @@ -2546,9 +2566,9 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { got += part + "|||"; } if (got != expected) { - ERR_PRINT("Failed to get proper data from parse_arguments `" + line + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")"); + ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size())); } - valid = valid & (got == expected); + valid = valid && (got == expected); } { String line = "(a , \"(,),,,,\" , c)"; @@ -2559,35 +2579,35 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { got += part + "|||"; } if (got != expected) { - ERR_PRINT("Failed to get proper data from parse_arguments `" + line + "` should return `" + expected + "`(" + itos(expected.size()) + "), got instead `" + got + "`(" + itos(got.size()) + ")"); + ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size())); } - valid = valid & (got == expected); + valid = valid && (got == expected); } return valid; } -// Validate in all arrays if names don't do cyclic renames `Node` -> `Node2D` | `Node2D` -> `2DNode` +// Validate in all arrays if names don't do cyclic renames "Node" -> "Node2D" | "Node2D" -> "2DNode" bool ProjectConverter3To4::test_array_names() { bool valid = true; Vector<String> names = Vector<String>(); - // Validate if all classes are valid + // Validate if all classes are valid. { for (unsigned int current_index = 0; class_renames[current_index][0]; current_index++) { const String old_class = class_renames[current_index][0]; const String new_class = class_renames[current_index][1]; - // Light2D, Texture, Viewport are special classes(probably virtual ones) + // Light2D, Texture, Viewport are special classes(probably virtual ones). if (ClassDB::class_exists(StringName(old_class)) && old_class != "Light2D" && old_class != "Texture" && old_class != "Viewport") { - ERR_PRINT(String("Class `") + old_class + "` exists in Godot 4.0, so cannot be renamed to something else."); - valid = false; // This probably should be only a warning, but not 100% sure - this would need to be added to CI + ERR_PRINT(vformat("Class \"%s\" exists in Godot 4.0, so it cannot be renamed to something else.", old_class)); + valid = false; // This probably should be only a warning, but not 100% sure - this would need to be added to CI. } - // Callable is special class, to which normal classes may be renamed + // Callable is special class, to which normal classes may be renamed. if (!ClassDB::class_exists(StringName(new_class)) && new_class != "Callable") { - ERR_PRINT(String("Class `") + new_class + "` doesn't exists in Godot 4.0, so cannot be used in conversion."); - valid = false; // This probably should be only a warning, but not 100% sure - this would need to be added to CI + ERR_PRINT(vformat("Class \"%s\" does not exist in Godot 4.0, so it cannot be used in the conversion.", old_class)); + valid = false; // This probably should be only a warning, but not 100% sure - this would need to be added to CI. } } } @@ -2595,9 +2615,9 @@ bool ProjectConverter3To4::test_array_names() { { HashSet<String> all_functions; - // List of excluded functions from builtin types and global namespace, because currently it is not possible to get list of functions from them - // This will be available when https://github.com/godotengine/godot/pull/49053 or similar will be included into Godot - static const char *builtin_types_excluded_functions[] = { "dict_to_inst", "inst_to_dict", "bytes_to_var", "bytes_to_var_with_objects", "db_to_linear", "deg_to_rad", "linear_to_db", "rad_to_deg", "randf_range", "snapped", "str_to_var", "var_to_str", "var_to_bytes", "var_to_bytes_with_objects", "move_toward", "uri_encode", "uri_decode", "remove_at", "get_rotation_quaternion", "clamp", "grow_side", "is_absolute_path", "is_valid_int", "lerp", "to_ascii_buffer", "to_utf8_buffer", "to_utf32_buffer", "snapped", nullptr }; + // List of excluded functions from builtin types and global namespace, because currently it is not possible to get list of functions from them. + // This will be available when https://github.com/godotengine/godot/pull/49053 or similar will be included into Godot. + static const char *builtin_types_excluded_functions[] = { "dict_to_inst", "inst_to_dict", "bytes_to_var", "bytes_to_var_with_objects", "db_to_linear", "deg_to_rad", "linear_to_db", "rad_to_deg", "randf_range", "snapped", "str_to_var", "var_to_str", "var_to_bytes", "var_to_bytes_with_objects", "move_toward", "uri_encode", "uri_decode", "remove_at", "get_rotation_quaternion", "clamp", "grow_side", "is_absolute_path", "is_valid_int", "lerp", "to_ascii_buffer", "to_utf8_buffer", "to_utf32_buffer", "snapped", "remap", nullptr }; for (int current_index = 0; builtin_types_excluded_functions[current_index]; current_index++) { all_functions.insert(builtin_types_excluded_functions[current_index]); } @@ -2626,82 +2646,79 @@ bool ProjectConverter3To4::test_array_names() { int current_element = 0; while (gdscript_function_renames[current_element][0] != nullptr) { + String name_3_x = gdscript_function_renames[current_element][0]; + String name_4_0 = gdscript_function_renames[current_element][1]; if (!all_functions.has(gdscript_function_renames[current_element][1])) { - ERR_PRINT(String("Missing gdscript function in pair (") + gdscript_function_renames[current_element][0] + " - ===> " + gdscript_function_renames[current_element][1] + " <===)"); + ERR_PRINT(vformat("Missing GDScript function in pair (%s - ===> %s <===)", name_3_x, name_4_0)); valid = false; } current_element++; } } if (!valid) { - ERR_PRINT("Found function which is used in converter, but cannot be found in Godot 4. Rename this element to new name or remove entire rule about it if is obsolete."); + ERR_PRINT("Found function which is used in the converter, but it cannot be found in Godot 4. Rename this element or remove its entry if it's obsolete."); } - valid = valid & test_single_array(enum_renames); - valid = valid & test_single_array(class_renames, true); - valid = valid & test_single_array(gdscript_function_renames, true); - valid = valid & test_single_array(csharp_function_renames, true); - valid = valid & test_single_array(gdscript_properties_renames, true); - valid = valid & test_single_array(csharp_properties_renames); - valid = valid & test_single_array(shaders_renames, true); - valid = valid & test_single_array(gdscript_signals_renames); - valid = valid & test_single_array(project_settings_renames); - valid = valid & test_single_array(builtin_types_renames); - valid = valid & test_single_array(color_renames); + valid = valid && test_single_array(enum_renames); + valid = valid && test_single_array(class_renames, true); + valid = valid && test_single_array(gdscript_function_renames, true); + valid = valid && test_single_array(csharp_function_renames, true); + valid = valid && test_single_array(gdscript_properties_renames, true); + valid = valid && test_single_array(csharp_properties_renames); + valid = valid && test_single_array(shaders_renames, true); + valid = valid && test_single_array(gdscript_signals_renames); + valid = valid && test_single_array(project_settings_renames); + valid = valid && test_single_array(builtin_types_renames); + valid = valid && test_single_array(color_renames); return valid; } -// Validate in one array if names don't do cyclic renames `Node` -> `Node2D` | `Node2D` -> `2DNode` -// Also checks if in name contains spaces at the end or beginning -bool ProjectConverter3To4::test_single_array(const char *array[][2], bool ignore_second_check) { +// Validates the array to prevent cyclic renames, such as `Node` -> `Node2D`, then `Node2D` -> `2DNode`. +// Also checks if names contain leading or trailing spaces. +bool ProjectConverter3To4::test_single_array(const char *p_array[][2], bool p_ignore_4_0_name) { bool valid = true; Vector<String> names = Vector<String>(); - for (unsigned int current_index = 0; array[current_index][0]; current_index++) { - if (String(array[current_index][0]).begins_with(" ") || String(array[current_index][0]).ends_with(" ")) { - { - ERR_PRINT(String("Entry \"") + array[current_index][0] + "\" ends or stars with space."); - valid = false; - } + for (unsigned int current_index = 0; p_array[current_index][0]; current_index++) { + String name_3_x = p_array[current_index][0]; + String name_4_0 = p_array[current_index][1]; + if (name_3_x != name_3_x.strip_edges()) { + ERR_PRINT(vformat("Invalid Entry \"%s\" contains leading or trailing spaces.", name_3_x)); + valid = false; } - if (names.has(array[current_index][0])) { - ERR_PRINT(String("Found duplicated things, pair ( -> ") + array[current_index][0] + " , " + array[current_index][1] + ")"); + if (names.has(name_3_x)) { + ERR_PRINT(vformat("Found duplicated entry, pair ( -> %s , %s)", name_3_x, name_4_0)); valid = false; } - names.append(array[current_index][0]); + names.append(name_3_x); - if (String(array[current_index][1]).begins_with(" ") || String(array[current_index][1]).ends_with(" ")) { - { - ERR_PRINT(String("Entry \"") + array[current_index][1] + "\" ends or stars with space."); - valid = false; - } + if (name_4_0 != name_4_0.strip_edges()) { + ERR_PRINT(vformat("Invalid Entry \"%s\" contains leading or trailing spaces.", name_3_x)); + valid = false; } - if (names.has(array[current_index][1])) { - ERR_PRINT(String("Found duplicated things, pair (") + array[current_index][0] + " , ->" + array[current_index][1] + ")"); + if (names.has(name_4_0)) { + ERR_PRINT(vformat("Found duplicated entry, pair ( -> %s , %s)", name_3_x, name_4_0)); valid = false; } - if (!ignore_second_check) { - names.append(array[current_index][1]); + if (!p_ignore_4_0_name) { + names.append(name_4_0); } } return valid; }; -// Returns arguments from given function execution, this cannot be really done as regex +// Returns arguments from given function execution, this cannot be really done as regex. // `abc(d,e(f,g),h)` -> [d], [e(f,g)], [h] Vector<String> ProjectConverter3To4::parse_arguments(const String &line) { Vector<String> parts; int string_size = line.length(); - int start_part = 0; // Index of beginning of start par + int start_part = 0; // Index of beginning of start part. int parts_counter = 0; char32_t previous_character = '\0'; - bool is_inside_string = false; // if true, it ignore this 3 characters ( , ) inside string + bool is_inside_string = false; // If true, it ignores these 3 characters ( , ) inside string. - if (line.count("(") != line.count(")")) { - ERR_PRINT("Converter internal bug: substring should have equal number of open and close parenthess in line - `" + line + "`"); - return parts; - } + ERR_FAIL_COND_V_MSG(line.count("(") != line.count(")"), parts, vformat("Converter internal bug: substring should have equal number of open and close parentheses in line - \"%s\".", line)); for (int current_index = 0; current_index < string_size; current_index++) { char32_t character = line.get(current_index); @@ -2762,9 +2779,9 @@ Vector<String> ProjectConverter3To4::parse_arguments(const String &line) { return clean_parts; } -// Finds latest parenthess owned by function +// Finds latest parenthesis owned by function. // `function(abc(a,b),DD)):` finds this parenthess `function(abc(a,b),DD => ) <= ):` -int ProjectConverter3To4::get_end_parenthess(const String &line) const { +int ProjectConverter3To4::get_end_parenthesis(const String &line) const { int current_state = 0; for (int current_index = 0; line.length() > current_index; current_index++) { char32_t character = line.get(current_index); @@ -2781,8 +2798,8 @@ int ProjectConverter3To4::get_end_parenthess(const String &line) const { return -1; } -// Connects arguments from vector to one string -// Needed when after processing e.g. 2 arguments, later arguments are not changed in any way +// Merges multiple arguments into a single String. +// Needed when after processing e.g. 2 arguments, later arguments are not changed in any way. String ProjectConverter3To4::connect_arguments(const Vector<String> &arguments, int from, int to) const { if (to == -1) { to = arguments.size(); @@ -2802,7 +2819,7 @@ String ProjectConverter3To4::connect_arguments(const Vector<String> &arguments, return value; } -// Return spaces or tabs which starts line e.g. `\t\tmove_this` will return `\t\t` +// Returns the indentation (spaces and tabs) at the start of the line e.g. `\t\tmove_this` returns `\t\t`. String ProjectConverter3To4::get_starting_space(const String &line) const { String empty_space; int current_character = 0; @@ -2834,9 +2851,8 @@ String ProjectConverter3To4::get_starting_space(const String &line) const { return empty_space; } -// Return object which execute specific function -// e.g. in `var roman = kieliszek.funkcja()` to this function is passed everything before function which we want to check -// so it is `var roman = kieliszek.` and this function return `kieliszek.` +// Returns the object that’s executing the function in the line. +// e.g. Passing the line "var roman = kieliszek.funkcja()" to this function returns "kieliszek". String ProjectConverter3To4::get_object_of_execution(const String &line) const { int end = line.size() - 1; // Last one is \0 int variable_start = end - 1; @@ -2854,10 +2870,10 @@ String ProjectConverter3To4::get_object_of_execution(const String &line) const { if (start == 0) { break; } else if (is_nodepath_sep) { - // Freeze variable_start, try to fetch more chars since this might be node path literal + // Freeze variable_start, try to fetch more chars since this might be a Node path literal. is_possibly_nodepath = true; } else if (is_nodepath_start) { - // Found $, this is a node path literal + // Found $, this is a Node path literal. is_valid_nodepath = true; break; } @@ -2867,8 +2883,8 @@ String ProjectConverter3To4::get_object_of_execution(const String &line) const { start--; continue; } else { - // Abandon all hope, this is neither a variable nor a node path literal - variable_start++; // Found invalid character, needs to be ignored + // Abandon all hope, this is neither a variable nor a Node path literal. + variable_start++; // Found invalid character, needs to be ignored. break; } } @@ -2917,7 +2933,7 @@ void ProjectConverter3To4::rename_classes(Vector<String> &lines, const RegExCont for (unsigned int current_index = 0; class_renames[current_index][0]; current_index++) { if (line.contains(class_renames[current_index][0])) { bool found_ignored_items = false; - // Renaming Spatial.tscn to TEMP_RENAMED_CLASS.tscn + // Renaming Spatial.tscn to TEMP_RENAMED_CLASS.tscn. if (line.contains(String(class_renames[current_index][0]) + ".")) { found_ignored_items = true; line = reg_container.class_tscn_regexes[current_index]->sub(line, "TEMP_RENAMED_CLASS.tscn", true); @@ -2925,10 +2941,10 @@ void ProjectConverter3To4::rename_classes(Vector<String> &lines, const RegExCont line = reg_container.class_shader_regexes[current_index]->sub(line, "TEMP_RENAMED_CLASS.shader", true); } - // Causal renaming Spatial -> Node3D + // Causal renaming Spatial -> Node3D. line = reg_container.class_regexes[current_index]->sub(line, class_renames[current_index][1], true); - // Restore Spatial.tscn from TEMP_RENAMED_CLASS.tscn + // Restore Spatial.tscn from TEMP_RENAMED_CLASS.tscn. if (found_ignored_items) { line = reg_container.class_temp_tscn.sub(line, reg_container.class_temp_tscn_renames[current_index], true); line = reg_container.class_temp_gd.sub(line, reg_container.class_temp_gd_renames[current_index], true); @@ -2951,7 +2967,7 @@ Vector<String> ProjectConverter3To4::check_for_rename_classes(Vector<String> &li if (line.contains(class_renames[current_index][0])) { String old_line = line; bool found_ignored_items = false; - // Renaming Spatial.tscn to TEMP_RENAMED_CLASS.tscn + // Renaming Spatial.tscn to TEMP_RENAMED_CLASS.tscn. if (line.contains(String(class_renames[current_index][0]) + ".")) { found_ignored_items = true; line = reg_container.class_tscn_regexes[current_index]->sub(line, "TEMP_RENAMED_CLASS.tscn", true); @@ -2959,13 +2975,13 @@ Vector<String> ProjectConverter3To4::check_for_rename_classes(Vector<String> &li line = reg_container.class_shader_regexes[current_index]->sub(line, "TEMP_RENAMED_CLASS.shader", true); } - // Causal renaming Spatial -> Node3D + // Causal renaming Spatial -> Node3D. TypedArray<RegExMatch> reg_match = reg_container.class_regexes[current_index]->search_all(line); if (reg_match.size() > 0) { found_renames.append(line_formatter(current_line, class_renames[current_index][0], class_renames[current_index][1], old_line)); } - // Restore Spatial.tscn from TEMP_RENAMED_CLASS.tscn + // Restore Spatial.tscn from TEMP_RENAMED_CLASS.tscn. if (found_ignored_items) { line = reg_container.class_temp_tscn.sub(line, reg_container.class_temp_tscn_renames[current_index], true); line = reg_container.class_temp_gd.sub(line, reg_container.class_temp_gd_renames[current_index], true); @@ -3005,13 +3021,14 @@ Vector<String> ProjectConverter3To4::check_for_rename_gdscript_functions(Vector< return found_renames; } -// TODO, this function should run only on all .gd files and also on lines in tscn files which +// TODO, this function should run only on all ".gd" files and also on lines in ".tscn" files which are parts of built-in Scripts. void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContainer ®_container, bool builtin) { - // In this and other functions, reg.sub are used only after checking line with str.contains function which is sometimes few times faster with bigger line lengths + // In this and other functions, reg.sub() is used only after checking lines with str.contains(). + // With longer lines, doing so can sometimes be significantly faster. if ((line.contains(".lock") || line.contains(".unlock")) && !line.contains("mtx") && !line.contains("mutex") && !line.contains("Mutex")) { - line = reg_container.reg_image_lock.sub(line, "false # $1.lock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true); - line = reg_container.reg_image_unlock.sub(line, "false # $1.unlock() # TODOConverter40, image no longer require locking, `false` helps to not broke one line if/else, so can be freely removed", true); + line = reg_container.reg_image_lock.sub(line, "false # $1.lock() # TODOConverter40, Image no longer requires locking, `false` helps to not break one line if/else, so it can freely be removed", true); + line = reg_container.reg_image_unlock.sub(line, "false # $1.unlock() # TODOConverter40, Image no longer requires locking, `false` helps to not break one line if/else, so it can freely be removed", true); } // PackedStringArray(req_godot).join('.') -> '.'.join(PackedStringArray(req_godot)) PoolStringArray @@ -3090,7 +3107,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- r.move_and_slide( a, b, c, d, e ) -> r.set_velocity(a) ... r.move_and_slide() KinematicBody if (line.contains(("move_and_slide("))) { int start = line.find("move_and_slide("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { String base_obj = get_object_of_execution(line.substr(0, start)); String starting_space = get_starting_space(line); @@ -3136,7 +3153,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- r.move_and_slide_with_snap( a, b, c, d, e ) -> r.set_velocity(a) ... r.move_and_slide() KinematicBody if (line.contains("move_and_slide_with_snap(")) { int start = line.find("move_and_slide_with_snap("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { String base_obj = get_object_of_execution(line.substr(0, start)); String starting_space = get_starting_space(line); @@ -3187,7 +3204,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- sort_custom( a , b ) -> sort_custom(Callable( a , b )) Object if (line.contains("sort_custom(")) { int start = line.find("sort_custom("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 2) { @@ -3199,7 +3216,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- list_dir_begin( ) -> list_dir_begin() Object if (line.contains("list_dir_begin(")) { int start = line.find("list_dir_begin("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { line = line.substr(0, start) + "list_dir_begin() " + line.substr(end + start) + "# TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547"; } @@ -3208,7 +3225,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- draw_line(1,2,3,4,5) -> draw_line(1,2,3,4) CanvasItem if (line.contains("draw_line(")) { int start = line.find("draw_line("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 5) { @@ -3221,7 +3238,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (line.contains("func ") && line.contains("var ")) { int start = line.find("func "); start = line.substr(start).find("(") + start; - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); @@ -3239,7 +3256,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- yield(this, \"timeout\") -> await this.timeout GDScript if (line.contains("yield(")) { int start = line.find("yield("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 2) { @@ -3255,7 +3272,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- parse_json( AA ) -> TODO Object if (line.contains("parse_json(")) { int start = line.find("parse_json("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); line = line.substr(0, start) + "JSON.new().stringify(" + connect_arguments(parts, 0) + ")" + line.substr(end + start); @@ -3265,7 +3282,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- .xform(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform if (line.contains(".xform(")) { int start = line.find(".xform("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 1) { @@ -3277,7 +3294,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- .xform_inv(Vector3(a,b,c)) -> * Vector3(a,b,c) Transform if (line.contains(".xform_inv(")) { int start = line.find(".xform_inv("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { String object_exec = get_object_of_execution(line.substr(0, start)); if (line.contains(object_exec + ".xform")) { @@ -3295,7 +3312,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai int start = line.find("connect("); // Protection from disconnect if (start == 0 || line.get(start - 1) != 's') { - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { @@ -3309,7 +3326,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- disconnect(a,b,c) -> disconnect(a,Callable(b,c)) Object if (line.contains("disconnect(")) { int start = line.find("disconnect("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { @@ -3320,7 +3337,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- is_connected(a,b,c) -> is_connected(a,Callable(b,c)) Object if (line.contains("is_connected(")) { int start = line.find("is_connected("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { @@ -3332,7 +3349,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- "(tween_method(A,B,C,D,E,[F,G]) != OK):", "(tween_method(Callable(A,B).bind(F,G),C,D,E) Object if (line.contains("tween_method(")) { int start = line.find("tween_method("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 5) { @@ -3345,7 +3362,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- "(tween_callback(A,B,[C,D]) != OK):", "(connect(Callable(A,B).bind(C,D)) Object if (line.contains("tween_callback(")) { int start = line.find("tween_callback("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 2) { @@ -3359,7 +3376,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // -- start(a,b,c,d) -> start(Callable(a,b).bind(c),d) Thread if (line.contains("start(")) { int start = line.find("start("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; // Protection from 'func start' if (!line.begins_with("func ")) { if (end > -1) { @@ -3386,7 +3403,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // assert(speed < 20, str(randi()%10)) -> assert(speed < 20) #,str(randi()%10)) GDScript - GDScript bug constant message if (line.contains("assert(")) { int start = line.find("assert("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 2) { @@ -3397,7 +3414,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // create_from_image(aa, bb) -> create_from_image(aa) #, bb ImageTexture if (line.contains("create_from_image(")) { int start = line.find("create_from_image("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 2) { @@ -3408,7 +3425,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // set_cell_item(a, b, c, d ,e) -> set_cell_item(Vector3(a, b, c), d ,e) if (line.contains("set_cell_item(")) { int start = line.find("set_cell_item("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() > 2) { @@ -3419,7 +3436,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // get_cell_item(a, b, c) -> get_cell_item(Vector3i(a, b, c)) if (line.contains("get_cell_item(")) { int start = line.find("get_cell_item("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { @@ -3430,7 +3447,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // get_cell_item_orientation(a, b, c) -> get_cell_item_orientation(Vector3i(a, b, c)) if (line.contains("get_cell_item_orientation(")) { int start = line.find("get_cell_item_orientation("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { @@ -3441,7 +3458,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // apply_impulse(A, B) -> apply_impulse(B, A) if (line.contains("apply_impulse(")) { int start = line.find("apply_impulse("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 2) { @@ -3452,7 +3469,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // apply_force(A, B) -> apply_force(B, A) if (line.contains("apply_force(")) { int start = line.find("apply_force("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 2) { @@ -3460,21 +3477,23 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai } } } - // map_to_world(a, b, c) -> map_to_world(Vector3i(a, b, c)) + // map_to_world(a, b, c) -> map_to_local(Vector3i(a, b, c)) if (line.contains("map_to_world(")) { int start = line.find("map_to_world("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { - line = line.substr(0, start) + "map_to_world(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + line = line.substr(0, start) + "map_to_local(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + } else if (parts.size() == 1) { + line = line.substr(0, start) + "map_to_local(" + parts[0] + ")" + line.substr(end + start); } } } // OS.get_window_safe_area() -> DisplayServer.get_display_safe_area() if (line.contains("OS.get_window_safe_area(")) { int start = line.find("OS.get_window_safe_area("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 0) { @@ -3485,7 +3504,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai // draw_rect(a,b,c,d,e) -> draw_rect(a,b,c,d)#e) TODOGODOT4 Antialiasing argument is missing if (line.contains("draw_rect(")) { int start = line.find("draw_rect("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 5) { @@ -3538,7 +3557,7 @@ void ProjectConverter3To4::process_csharp_line(String &line, const RegExContaine int start = line.find("Connect("); // Protection from disconnect if (start == 0 || line.get(start - 1) != 's') { - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() >= 3) { @@ -3550,7 +3569,7 @@ void ProjectConverter3To4::process_csharp_line(String &line, const RegExContaine // -- Disconnect(a,b,c) -> Disconnect(a,Callable(b,c)) Object if (line.contains("Disconnect(")) { int start = line.find("Disconnect("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { @@ -3561,7 +3580,7 @@ void ProjectConverter3To4::process_csharp_line(String &line, const RegExContaine // -- IsConnected(a,b,c) -> IsConnected(a,Callable(b,c)) Object if (line.contains("IsConnected(")) { int start = line.find("IsConnected("); - int end = get_end_parenthess(line.substr(start)) + 1; + int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { @@ -3838,7 +3857,7 @@ Vector<String> ProjectConverter3To4::check_for_custom_rename(Vector<String> &lin if (uint64_t(line.length()) <= maximum_line_length) { TypedArray<RegExMatch> reg_match = reg.search_all(line); if (reg_match.size() > 0) { - found_renames.append(line_formatter(current_line, from.replace("\\.", "."), to, line)); // Without replacing it will print "\.shader" instead ".shader" + found_renames.append(line_formatter(current_line, from.replace("\\.", "."), to, line)); // Without replacing it will print "\.shader" instead ".shader". } } current_line++; @@ -3892,19 +3911,28 @@ String ProjectConverter3To4::line_formatter(int current_line, String from, Strin if (line.size() > 400) { line = line.substr(0, 397) + "..."; } - return String("Line (") + itos(current_line) + ") " + from.replace("\r", "").replace("\n", "") + " -> " + to.replace("\r", "").replace("\n", "") + " - LINE \"\"\" " + line.replace("\r", "").replace("\n", "").strip_edges() + " \"\"\""; + + from = from.strip_escapes(); + to = to.strip_escapes(); + line = line.replace("\r", "").replace("\n", "").strip_edges(); + + return vformat("Line(%d), %s -> %s - LINE \"\"\" %s \"\"\"", current_line, from, to, line); } // Prints only full lines e.g.: // Line (1) - FULL LINES - """yield(get_tree().create_timer(3), 'timeout')""" =====> """ await get_tree().create_timer(3).timeout """ -String ProjectConverter3To4::simple_line_formatter(int current_line, String old_line, String line) { +String ProjectConverter3To4::simple_line_formatter(int current_line, String old_line, String new_line) { if (old_line.size() > 1000) { old_line = old_line.substr(0, 997) + "..."; } - if (line.size() > 1000) { - line = line.substr(0, 997) + "..."; + if (new_line.size() > 1000) { + new_line = new_line.substr(0, 997) + "..."; } - return String("Line (") + itos(current_line) + ") - FULL LINES - \"\"\"" + old_line.replace("\r", "").replace("\n", "").strip_edges() + "\"\"\" =====> \"\"\" " + line.replace("\r", "").replace("\n", "").strip_edges() + " \"\"\""; + + old_line = old_line.replace("\r", "").replace("\n", "").strip_edges(); + new_line = new_line.replace("\r", "").replace("\n", "").strip_edges(); + + return vformat("Line (%d) - FULL LINES - \"\"\" %s \"\"\" =====> \"\"\" %s \"\"\"", current_line, old_line, new_line); } // Collects string from vector strings @@ -3920,14 +3948,14 @@ String ProjectConverter3To4::collect_string_from_vector(Vector<String> &vector) return string; } -#else // No regex. +#else // No RegEx. int ProjectConverter3To4::convert() { - ERR_FAIL_V_MSG(ERROR_CODE, "Can't run converter for Godot 3.x projects as RegEx module is disabled."); + ERR_FAIL_V_MSG(ERROR_CODE, "Can't run converter for Godot 3.x projects, because RegEx module is disabled."); } int ProjectConverter3To4::validate_conversion() { - ERR_FAIL_V_MSG(ERROR_CODE, "Can't validate conversion for Godot 3.x projects as RegEx module is disabled."); + ERR_FAIL_V_MSG(ERROR_CODE, "Can't validate conversion for Godot 3.x projects, because RegEx module is disabled."); } #endif // MODULE_REGEX_ENABLED diff --git a/editor/project_converter_3_to_4.h b/editor/project_converter_3_to_4.h index fc6d66c9a8..2cecb9da79 100644 --- a/editor/project_converter_3_to_4.h +++ b/editor/project_converter_3_to_4.h @@ -76,7 +76,7 @@ private: Vector<String> check_for_files(); Vector<String> parse_arguments(const String &line); - int get_end_parenthess(const String &line) const; + int get_end_parenthesis(const String &line) const; String connect_arguments(const Vector<String> &line, int from, int to = -1) const; String get_starting_space(const String &line) const; String get_object_of_execution(const String &line) const; diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index ed8c7b14c8..544e8c9323 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -35,7 +35,7 @@ #include "core/io/dir_access.h" #include "core/io/file_access.h" #include "core/io/resource_saver.h" -#include "core/io/stream_peer_ssl.h" +#include "core/io/stream_peer_tls.h" #include "core/io/zip_io.h" #include "core/os/keyboard.h" #include "core/os/os.h" @@ -1901,11 +1901,13 @@ void ProjectManager::_notification(int p_what) { filter_option->select(default_sorting); _project_list->set_order_option(default_sorting); +#ifndef ANDROID_ENABLED if (_project_list->get_project_count() >= 1) { // Focus on the search box immediately to allow the user // to search without having to reach for their mouse search_box->grab_focus(); } +#endif if (asset_library) { // Removes extra border margins. @@ -1991,7 +1993,7 @@ void ProjectManager::shortcut_input(const Ref<InputEvent> &p_ev) { // This is handled by the platform implementation on macOS, // so only define the shortcut on other platforms #ifndef MACOS_ENABLED - if (k->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::Q)) { + if (k->get_keycode_with_modifiers() == (KeyModifierMask::META | Key::Q)) { _dim_window(); get_tree()->quit(); } @@ -2049,7 +2051,7 @@ void ProjectManager::shortcut_input(const Ref<InputEvent> &p_ev) { } break; case Key::F: { - if (k->is_command_pressed()) { + if (k->is_command_or_control_pressed()) { this->search_box->grab_focus(); } else { keycode_handled = false; @@ -2443,6 +2445,7 @@ void ProjectManager::_on_order_option_changed(int p_idx) { } void ProjectManager::_on_tab_changed(int p_tab) { +#ifndef ANDROID_ENABLED if (p_tab == 0) { // Projects // Automatically grab focus when the user moves from the Templates tab // back to the Projects tab. @@ -2451,6 +2454,7 @@ void ProjectManager::_on_tab_changed(int p_tab) { // The Templates tab's search field is focused on display in the asset // library editor plugin code. +#endif } void ProjectManager::_on_search_term_changed(const String &p_term) { @@ -2602,7 +2606,7 @@ ProjectManager::ProjectManager() { } PanelContainer *pc = memnew(PanelContainer); - pc->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + pc->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); pc->set_v_size_flags(Control::SIZE_EXPAND_FILL); search_tree_vb->add_child(pc); @@ -2624,21 +2628,21 @@ ProjectManager::ProjectManager() { create_btn = memnew(Button); create_btn->set_text(TTR("New Project")); create_btn->add_theme_constant_override("h_separation", btn_h_separation); - create_btn->set_shortcut(ED_SHORTCUT("project_manager/new_project", TTR("New Project"), KeyModifierMask::CMD | Key::N)); + create_btn->set_shortcut(ED_SHORTCUT("project_manager/new_project", TTR("New Project"), KeyModifierMask::CMD_OR_CTRL | Key::N)); create_btn->connect("pressed", callable_mp(this, &ProjectManager::_new_project)); tree_vb->add_child(create_btn); import_btn = memnew(Button); import_btn->set_text(TTR("Import")); import_btn->add_theme_constant_override("h_separation", btn_h_separation); - import_btn->set_shortcut(ED_SHORTCUT("project_manager/import_project", TTR("Import Project"), KeyModifierMask::CMD | Key::I)); + import_btn->set_shortcut(ED_SHORTCUT("project_manager/import_project", TTR("Import Project"), KeyModifierMask::CMD_OR_CTRL | Key::I)); import_btn->connect("pressed", callable_mp(this, &ProjectManager::_import_project)); tree_vb->add_child(import_btn); scan_btn = memnew(Button); scan_btn->set_text(TTR("Scan")); scan_btn->add_theme_constant_override("h_separation", btn_h_separation); - scan_btn->set_shortcut(ED_SHORTCUT("project_manager/scan_projects", TTR("Scan Projects"), KeyModifierMask::CMD | Key::S)); + scan_btn->set_shortcut(ED_SHORTCUT("project_manager/scan_projects", TTR("Scan Projects"), KeyModifierMask::CMD_OR_CTRL | Key::S)); scan_btn->connect("pressed", callable_mp(this, &ProjectManager::_scan_projects)); tree_vb->add_child(scan_btn); @@ -2647,14 +2651,14 @@ ProjectManager::ProjectManager() { open_btn = memnew(Button); open_btn->set_text(TTR("Edit")); open_btn->add_theme_constant_override("h_separation", btn_h_separation); - open_btn->set_shortcut(ED_SHORTCUT("project_manager/edit_project", TTR("Edit Project"), KeyModifierMask::CMD | Key::E)); + open_btn->set_shortcut(ED_SHORTCUT("project_manager/edit_project", TTR("Edit Project"), KeyModifierMask::CMD_OR_CTRL | Key::E)); open_btn->connect("pressed", callable_mp(this, &ProjectManager::_open_selected_projects_ask)); tree_vb->add_child(open_btn); run_btn = memnew(Button); run_btn->set_text(TTR("Run")); run_btn->add_theme_constant_override("h_separation", btn_h_separation); - run_btn->set_shortcut(ED_SHORTCUT("project_manager/run_project", TTR("Run Project"), KeyModifierMask::CMD | Key::R)); + run_btn->set_shortcut(ED_SHORTCUT("project_manager/run_project", TTR("Run Project"), KeyModifierMask::CMD_OR_CTRL | Key::R)); run_btn->connect("pressed", callable_mp(this, &ProjectManager::_run_project)); tree_vb->add_child(run_btn); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 581315d512..2da49f11cc 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -239,7 +239,7 @@ void ProjectSettingsEditor::shortcut_input(const Ref<InputEvent> &p_event) { handled = true; } - if (k->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::F)) { + if (k->is_match(InputEventKey::create_reference(KeyModifierMask::CMD_OR_CTRL | Key::F))) { search_box->grab_focus(); search_box->select_all(); handled = true; @@ -521,7 +521,7 @@ void ProjectSettingsEditor::_update_action_map_editor() { void ProjectSettingsEditor::_update_theme() { search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); restart_close_button->set_icon(get_theme_icon(SNAME("Close"), SNAME("EditorIcons"))); - restart_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + restart_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); restart_icon->set_texture(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); restart_label->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor"))); diff --git a/editor/scene_create_dialog.cpp b/editor/scene_create_dialog.cpp index 9b8684b7b8..573e57ca04 100644 --- a/editor/scene_create_dialog.cpp +++ b/editor/scene_create_dialog.cpp @@ -53,7 +53,7 @@ void SceneCreateDialog::_notification(int p_what) { node_type_3d->set_icon(get_theme_icon(SNAME("Node3D"), SNAME("EditorIcons"))); node_type_gui->set_icon(get_theme_icon(SNAME("Control"), SNAME("EditorIcons"))); node_type_other->add_theme_icon_override(SNAME("icon"), get_theme_icon(SNAME("Node"), SNAME("EditorIcons"))); - status_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + status_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); } break; } } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index e2265f2f83..488a651c29 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1255,16 +1255,14 @@ void SceneTreeDock::_notification(int p_what) { // create_root_dialog HBoxContainer *top_row = memnew(HBoxContainer); - top_row->set_name("NodeShortcutsTopRow"); top_row->set_h_size_flags(SIZE_EXPAND_FILL); Label *l = memnew(Label(TTR("Create Root Node:"))); l->set_theme_type_variation("HeaderSmall"); top_row->add_child(l); top_row->add_spacer(); - Button *node_shortcuts_toggle = memnew(Button); + node_shortcuts_toggle = memnew(Button); node_shortcuts_toggle->set_flat(true); - node_shortcuts_toggle->set_name("NodeShortcutsToggle"); node_shortcuts_toggle->set_icon(get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons"))); node_shortcuts_toggle->set_toggle_mode(true); node_shortcuts_toggle->set_tooltip_text(TTR("Switch to Favorite Nodes")); @@ -1276,18 +1274,15 @@ void SceneTreeDock::_notification(int p_what) { create_root_dialog->add_child(top_row); ScrollContainer *scroll_container = memnew(ScrollContainer); - scroll_container->set_name("NodeShortcutsScrollContainer"); create_root_dialog->add_child(scroll_container); scroll_container->set_v_size_flags(SIZE_EXPAND_FILL); scroll_container->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); VBoxContainer *node_shortcuts = memnew(VBoxContainer); - node_shortcuts->set_name("NodeShortcuts"); scroll_container->add_child(node_shortcuts); node_shortcuts->set_h_size_flags(SIZE_EXPAND_FILL); - VBoxContainer *beginner_node_shortcuts = memnew(VBoxContainer); - beginner_node_shortcuts->set_name("BeginnerNodeShortcuts"); + beginner_node_shortcuts = memnew(VBoxContainer); node_shortcuts->add_child(beginner_node_shortcuts); button_2d = memnew(Button); @@ -1308,8 +1303,7 @@ void SceneTreeDock::_notification(int p_what) { button_ui->set_icon(get_theme_icon(SNAME("Control"), SNAME("EditorIcons"))); button_ui->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_USER_INTERFACE, false)); - VBoxContainer *favorite_node_shortcuts = memnew(VBoxContainer); - favorite_node_shortcuts->set_name("FavoriteNodeShortcuts"); + favorite_node_shortcuts = memnew(VBoxContainer); node_shortcuts->add_child(favorite_node_shortcuts); button_custom = memnew(Button); @@ -3227,25 +3221,11 @@ void SceneTreeDock::_local_tree_selected() { } void SceneTreeDock::_update_create_root_dialog() { - BaseButton *toggle = Object::cast_to<BaseButton>(create_root_dialog->get_node(String("NodeShortcutsTopRow/NodeShortcutsToggle"))); - Node *node_shortcuts = create_root_dialog->get_node(String("NodeShortcutsScrollContainer/NodeShortcuts")); - - if (!toggle || !node_shortcuts) { - return; - } - - Control *beginner_nodes = Object::cast_to<Control>(node_shortcuts->get_node(String("BeginnerNodeShortcuts"))); - Control *favorite_nodes = Object::cast_to<Control>(node_shortcuts->get_node(String("FavoriteNodeShortcuts"))); - - if (!beginner_nodes || !favorite_nodes) { - return; - } - - EditorSettings::get_singleton()->set_setting("_use_favorites_root_selection", toggle->is_pressed()); + EditorSettings::get_singleton()->set_setting("_use_favorites_root_selection", node_shortcuts_toggle->is_pressed()); EditorSettings::get_singleton()->save(); - if (toggle->is_pressed()) { - for (int i = 0; i < favorite_nodes->get_child_count(); i++) { - favorite_nodes->get_child(i)->queue_delete(); + if (node_shortcuts_toggle->is_pressed()) { + for (int i = 0; i < favorite_node_shortcuts->get_child_count(); i++) { + favorite_node_shortcuts->get_child(i)->queue_delete(); } Ref<FileAccess> f = FileAccess::open(EditorPaths::get_singleton()->get_project_settings_dir().path_join("favorites.Node"), FileAccess::READ); @@ -3255,7 +3235,7 @@ void SceneTreeDock::_update_create_root_dialog() { if (!l.is_empty()) { Button *button = memnew(Button); - favorite_nodes->add_child(button); + favorite_node_shortcuts->add_child(button); button->set_text(l); button->set_clip_text(true); String name = l.get_slicec(' ', 0); @@ -3268,14 +3248,14 @@ void SceneTreeDock::_update_create_root_dialog() { } } - if (!favorite_nodes->is_visible_in_tree()) { - favorite_nodes->show(); - beginner_nodes->hide(); + if (!favorite_node_shortcuts->is_visible_in_tree()) { + favorite_node_shortcuts->show(); + beginner_node_shortcuts->hide(); } } else { - if (!beginner_nodes->is_visible_in_tree()) { - beginner_nodes->show(); - favorite_nodes->hide(); + if (!beginner_node_shortcuts->is_visible_in_tree()) { + beginner_node_shortcuts->show(); + favorite_node_shortcuts->hide(); } button_clipboard->set_visible(!node_clipboard.is_empty()); } @@ -3422,24 +3402,24 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec ED_SHORTCUT("scene_tree/batch_rename", TTR("Batch Rename"), KeyModifierMask::SHIFT | Key::F2); ED_SHORTCUT_OVERRIDE("scene_tree/batch_rename", "macos", KeyModifierMask::SHIFT | Key::ENTER); - ED_SHORTCUT("scene_tree/add_child_node", TTR("Add Child Node"), KeyModifierMask::CMD | Key::A); - ED_SHORTCUT("scene_tree/instance_scene", TTR("Instantiate Child Scene"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::A); + ED_SHORTCUT("scene_tree/add_child_node", TTR("Add Child Node"), KeyModifierMask::CMD_OR_CTRL | Key::A); + ED_SHORTCUT("scene_tree/instance_scene", TTR("Instantiate Child Scene"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::A); ED_SHORTCUT("scene_tree/expand_collapse_all", TTR("Expand/Collapse Branch")); - ED_SHORTCUT("scene_tree/cut_node", TTR("Cut"), KeyModifierMask::CMD | Key::X); - ED_SHORTCUT("scene_tree/copy_node", TTR("Copy"), KeyModifierMask::CMD | Key::C); - ED_SHORTCUT("scene_tree/paste_node", TTR("Paste"), KeyModifierMask::CMD | Key::V); + ED_SHORTCUT("scene_tree/cut_node", TTR("Cut"), KeyModifierMask::CMD_OR_CTRL | Key::X); + ED_SHORTCUT("scene_tree/copy_node", TTR("Copy"), KeyModifierMask::CMD_OR_CTRL | Key::C); + ED_SHORTCUT("scene_tree/paste_node", TTR("Paste"), KeyModifierMask::CMD_OR_CTRL | Key::V); ED_SHORTCUT("scene_tree/change_node_type", TTR("Change Type")); ED_SHORTCUT("scene_tree/attach_script", TTR("Attach Script")); ED_SHORTCUT("scene_tree/extend_script", TTR("Extend Script")); ED_SHORTCUT("scene_tree/detach_script", TTR("Detach Script")); - ED_SHORTCUT("scene_tree/move_up", TTR("Move Up"), KeyModifierMask::CMD | Key::UP); - ED_SHORTCUT("scene_tree/move_down", TTR("Move Down"), KeyModifierMask::CMD | Key::DOWN); - ED_SHORTCUT("scene_tree/duplicate", TTR("Duplicate"), KeyModifierMask::CMD | Key::D); + ED_SHORTCUT("scene_tree/move_up", TTR("Move Up"), KeyModifierMask::CMD_OR_CTRL | Key::UP); + ED_SHORTCUT("scene_tree/move_down", TTR("Move Down"), KeyModifierMask::CMD_OR_CTRL | Key::DOWN); + ED_SHORTCUT("scene_tree/duplicate", TTR("Duplicate"), KeyModifierMask::CMD_OR_CTRL | Key::D); ED_SHORTCUT("scene_tree/reparent", TTR("Reparent")); ED_SHORTCUT("scene_tree/reparent_to_new_node", TTR("Reparent to New Node")); ED_SHORTCUT("scene_tree/make_root", TTR("Make Scene Root")); ED_SHORTCUT("scene_tree/save_branch_as_scene", TTR("Save Branch as Scene")); - ED_SHORTCUT("scene_tree/copy_node_path", TTR("Copy Node Path"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::C); + ED_SHORTCUT("scene_tree/copy_node_path", TTR("Copy Node Path"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::C); ED_SHORTCUT("scene_tree/delete_no_confirm", TTR("Delete (No Confirm)"), KeyModifierMask::SHIFT | Key::KEY_DELETE); ED_SHORTCUT("scene_tree/delete", TTR("Delete"), Key::KEY_DELETE); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index e15865036b..dc228e1c93 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -119,6 +119,10 @@ class SceneTreeDock : public VBoxContainer { Button *button_detach_script = nullptr; MenuButton *button_tree_menu = nullptr; + Button *node_shortcuts_toggle = nullptr; + VBoxContainer *beginner_node_shortcuts = nullptr; + VBoxContainer *favorite_node_shortcuts = nullptr; + Button *button_2d = nullptr; Button *button_3d = nullptr; Button *button_ui = nullptr; diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index c120468ecb..50bb6496e1 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -387,17 +387,18 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { Ref<Script> script = p_node->get_script(); if (!script.is_null()) { String additional_notes; + Color button_color = Color(1, 1, 1); // Can't set tooltip after adding button, need to do it before. if (script->is_tool()) { additional_notes += "\n" + TTR("This script is currently running in the editor."); + button_color = get_theme_color(SNAME("accent_color"), SNAME("Editor")); } - item->add_button(0, get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), BUTTON_SCRIPT, false, TTR("Open Script:") + " " + script->get_path() + additional_notes); if (EditorNode::get_singleton()->get_object_custom_type_base(p_node) == script) { - item->set_button_color(0, item->get_button_count(0) - 1, Color(1, 1, 1, 0.5)); - } - if (script->is_tool()) { - item->set_button_color(0, item->get_button_count(0) - 1, get_theme_color(SNAME("accent_color"), SNAME("Editor"))); + additional_notes += "\n" + TTR("This script is a custom type."); + button_color.a = 0.5; } + item->add_button(0, get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), BUTTON_SCRIPT, false, TTR("Open Script:") + " " + script->get_path() + additional_notes); + item->set_button_color(0, item->get_button_count(0) - 1, button_color); } if (p_node->is_class("CanvasItem")) { diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index 7d065b4920..f57dfe4827 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -134,7 +134,7 @@ void ScriptCreateDialog::_notification(int p_what) { path_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); parent_browse_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); parent_search_button->set_icon(get_theme_icon(SNAME("ClassList"), SNAME("EditorIcons"))); - status_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + status_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); } break; } } @@ -202,7 +202,7 @@ bool ScriptCreateDialog::_validate_parent(const String &p_string) { } } - return ClassDB::class_exists(p_string) || ScriptServer::is_global_class(p_string); + return EditorNode::get_editor_data().is_type_recognized(p_string); } bool ScriptCreateDialog::_validate_class(const String &p_string) { @@ -372,7 +372,15 @@ void ScriptCreateDialog::_create_new() { const ScriptLanguage::ScriptTemplate sinfo = _get_current_template(); - scr = ScriptServer::get_language(language_menu->get_selected())->make_template(sinfo.content, cname_param, parent_name->get_text()); + String parent_class = parent_name->get_text(); + if (!ClassDB::class_exists(parent_class) && !ScriptServer::is_global_class(parent_class)) { + // If base is a custom type, replace with script path instead. + const EditorData::CustomType *type = EditorNode::get_editor_data().get_custom_type_by_name(parent_class); + ERR_FAIL_NULL(type); + parent_class = "\"" + type->script->get_path() + "\""; + } + + scr = ScriptServer::get_language(language_menu->get_selected())->make_template(sinfo.content, cname_param, parent_class); if (has_named_classes) { String cname = class_name->get_text(); diff --git a/editor/shader_create_dialog.cpp b/editor/shader_create_dialog.cpp index 522fd7c645..ae533b5b75 100644 --- a/editor/shader_create_dialog.cpp +++ b/editor/shader_create_dialog.cpp @@ -89,7 +89,7 @@ void ShaderCreateDialog::_update_theme() { } path_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); - status_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + status_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); } void ShaderCreateDialog::_update_language_info() { |