diff options
Diffstat (limited to 'editor')
38 files changed, 375 insertions, 226 deletions
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 1985c91f31..e8490e8729 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -63,8 +63,6 @@ public: ClassDB::bind_method("_dont_undo_redo", &AnimationTrackKeyEdit::_dont_undo_redo); } - //PopupDialog *ke_dialog; - void _fix_node_path(Variant &value) { NodePath np = value; @@ -1215,7 +1213,8 @@ void AnimationTrackEdit::_notification(int p_what) { if (has_focus()) { Color accent = get_color("accent_color", "Editor"); accent.a *= 0.7; - draw_rect(Rect2(Point2(), get_size()), accent, false); + // Offside so the horizontal sides aren't cutoff. + draw_rect(Rect2(Point2(1, 0), get_size() - Size2(1, 0)), accent, false); } Ref<Font> font = get_font("font", "Label"); @@ -2187,6 +2186,9 @@ Variant AnimationTrackEdit::get_drag_data(const Point2 &p_point) { Dictionary drag_data; drag_data["type"] = "animation_track"; + String base_path = animation->track_get_path(track); + base_path = base_path.get_slice(":", 0); // Remove sub-path. + drag_data["group"] = base_path; drag_data["index"] = track; ToolButton *tb = memnew(ToolButton); @@ -2207,8 +2209,18 @@ bool AnimationTrackEdit::can_drop_data(const Point2 &p_point, const Variant &p_d } String type = d["type"]; - if (type != "animation_track") + if (type != "animation_track") { return false; + } + + // Don't allow moving tracks outside their groups. + if (get_editor()->is_grouping_tracks()) { + String base_path = animation->track_get_path(track); + base_path = base_path.get_slice(":", 0); // Remove sub-path. + if (d["group"] != base_path) { + return false; + } + } if (p_point.y < get_size().height / 2) { dropping_at = -1; @@ -2229,8 +2241,18 @@ void AnimationTrackEdit::drop_data(const Point2 &p_point, const Variant &p_data) } String type = d["type"]; - if (type != "animation_track") + if (type != "animation_track") { return; + } + + // Don't allow moving tracks outside their groups. + if (get_editor()->is_grouping_tracks()) { + String base_path = animation->track_get_path(track); + base_path = base_path.get_slice(":", 0); // Remove sub-path. + if (d["group"] != base_path) { + return; + } + } int from_track = d["index"]; @@ -2685,6 +2707,13 @@ void AnimationTrackEditor::_track_remove_request(int p_track) { } } +void AnimationTrackEditor::_track_grab_focus(int p_track) { + + // Don't steal focus if not working with the track editor. + if (Object::cast_to<AnimationTrackEdit>(get_focus_owner())) + track_edits[p_track]->grab_focus(); +} + void AnimationTrackEditor::set_anim_pos(float p_pos) { timeline->set_play_position(p_pos); @@ -3449,14 +3478,14 @@ void AnimationTrackEditor::_update_tracks() { if (use_grouping) { String base_path = animation->track_get_path(i); - base_path = base_path.get_slice(":", 0); // remove subpath + base_path = base_path.get_slice(":", 0); // Remove sub-path. if (!group_sort.has(base_path)) { AnimationTrackEditGroup *g = memnew(AnimationTrackEditGroup); Ref<Texture> icon = get_icon("Node", "EditorIcons"); String name = base_path; String tooltip; - if (root) { + if (root && root->has_node(base_path)) { Node *n = root->get_node(base_path); if (n) { if (has_icon(n->get_class(), "EditorIcons")) { @@ -3666,17 +3695,18 @@ void AnimationTrackEditor::_update_length(double p_new_len) { } void AnimationTrackEditor::_dropped_track(int p_from_track, int p_to_track) { - if (p_to_track >= track_edits.size()) { - p_to_track = track_edits.size() - 1; - } - - if (p_from_track == p_to_track) + if (p_from_track == p_to_track || p_from_track == p_to_track - 1) { return; + } _clear_selection(); undo_redo->create_action(TTR("Rearrange Tracks")); - undo_redo->add_do_method(animation.ptr(), "track_swap", p_from_track, p_to_track); - undo_redo->add_undo_method(animation.ptr(), "track_swap", p_to_track, p_from_track); + undo_redo->add_do_method(animation.ptr(), "track_move_to", p_from_track, p_to_track); + // Take into account that the position of the tracks that come after the one removed will change. + int to_track_real = p_to_track > p_from_track ? p_to_track - 1 : p_to_track; + undo_redo->add_undo_method(animation.ptr(), "track_move_to", to_track_real, p_to_track > p_from_track ? p_from_track : p_from_track + 1); + undo_redo->add_do_method(this, "_track_grab_focus", to_track_real); + undo_redo->add_undo_method(this, "_track_grab_focus", p_from_track); undo_redo->commit_action(); } @@ -4878,10 +4908,20 @@ void AnimationTrackEditor::_cleanup_animation(Ref<Animation> p_animation) { } void AnimationTrackEditor::_view_group_toggle() { + _update_tracks(); view_group->set_icon(get_icon(view_group->is_pressed() ? "AnimationTrackList" : "AnimationTrackGroup", "EditorIcons")); } +bool AnimationTrackEditor::is_grouping_tracks() { + + if (!view_group) { + return false; + } + + return !view_group->is_pressed(); +} + void AnimationTrackEditor::_selection_changed() { if (selected_filter->is_pressed()) { @@ -4928,6 +4968,7 @@ void AnimationTrackEditor::_bind_methods() { ClassDB::bind_method("_animation_update", &AnimationTrackEditor::_animation_update); ClassDB::bind_method("_timeline_changed", &AnimationTrackEditor::_timeline_changed); ClassDB::bind_method("_track_remove_request", &AnimationTrackEditor::_track_remove_request); + ClassDB::bind_method("_track_grab_focus", &AnimationTrackEditor::_track_grab_focus); ClassDB::bind_method("_name_limit_changed", &AnimationTrackEditor::_name_limit_changed); ClassDB::bind_method("_update_scroll", &AnimationTrackEditor::_update_scroll); ClassDB::bind_method("_update_tracks", &AnimationTrackEditor::_update_tracks); @@ -5026,7 +5067,6 @@ AnimationTrackEditor::AnimationTrackEditor() { scroll->set_enable_v_scroll(true); track_vbox->add_constant_override("separation", 0); - //timeline_vbox->add_child(memnew(HSeparator)); HBoxContainer *bottom_hb = memnew(HBoxContainer); add_child(bottom_hb); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index a69659642c..c64f663b3b 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -325,6 +325,7 @@ class AnimationTrackEditor : public VBoxContainer { void _name_limit_changed(); void _timeline_changed(float p_new_pos, bool p_drag); void _track_remove_request(int p_track); + void _track_grab_focus(int p_track); UndoRedo *undo_redo; @@ -513,6 +514,7 @@ public: float get_moving_selection_offset() const; bool is_snap_enabled(); float snap_time(float p_value); + bool is_grouping_tracks(); MenuButton *get_edit_menu(); AnimationTrackEditor(); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index ac42f15f7f..604a050fcd 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -38,7 +38,7 @@ #include "editor_settings.h" #include "scene/gui/box_container.h" -void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) { +void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const String &p_select_type) { type_list.clear(); ClassDB::get_class_list(&type_list); @@ -93,14 +93,7 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) { if (saved_size != Rect2()) { popup(saved_size); } else { - - Size2 popup_size = Size2(900, 700) * editor_get_scale(); - Size2 window_size = get_viewport_rect().size; - - popup_size.x = MIN(window_size.x * 0.8, popup_size.x); - popup_size.y = MIN(window_size.y * 0.8, popup_size.y); - - popup_centered(popup_size); + popup_centered_clamped(Size2(900, 700) * EDSCALE, 0.8); } if (p_dont_clear) { @@ -116,6 +109,7 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) { is_replace_mode = p_replace_mode; if (p_replace_mode) { + select_type(p_select_type); set_title(vformat(TTR("Change %s Type"), base_type)); get_ok()->set_text(TTR("Change")); } else { @@ -258,6 +252,27 @@ bool CreateDialog::_is_class_disabled_by_feature_profile(const StringName &p_cla return false; } +void CreateDialog::select_type(const String &p_type) { + TreeItem *to_select; + if (search_options_types.has(p_type)) { + to_select = search_options_types[p_type]; + } else { + to_select = search_options->get_root(); + } + + // uncollapse from selected type to top level + // TODO: should this be in tree? + TreeItem *cur = to_select; + while (cur) { + cur->set_collapsed(false); + cur = cur->get_parent(); + } + + to_select->select(0); + + search_options->scroll_to_item(to_select); +} + void CreateDialog::_update_search() { search_options->clear(); @@ -269,7 +284,7 @@ void CreateDialog::_update_search() { _parse_fs(EditorFileSystem::get_singleton()->get_filesystem()); */ - HashMap<String, TreeItem *> types; + search_options_types.clear(); TreeItem *root = search_options->create_item(); EditorData &ed = EditorNode::get_editor_data(); @@ -307,7 +322,7 @@ void CreateDialog::_update_search() { } if (search_box->get_text() == "") { - add_type(type, types, root, &to_select); + add_type(type, search_options_types, root, &to_select); } else { bool found = false; @@ -323,7 +338,7 @@ void CreateDialog::_update_search() { } if (found) - add_type(I->get(), types, root, &to_select); + add_type(I->get(), search_options_types, root, &to_select); } if (EditorNode::get_editor_data().get_custom_types().has(type) && ClassDB::is_parent_class(type, base_type)) { @@ -337,12 +352,12 @@ void CreateDialog::_update_search() { if (!show) continue; - if (!types.has(type)) - add_type(type, types, root, &to_select); + if (!search_options_types.has(type)) + add_type(type, search_options_types, root, &to_select); TreeItem *ti; - if (types.has(type)) - ti = types[type]; + if (search_options_types.has(type)) + ti = search_options_types[type]; else ti = search_options->get_root(); diff --git a/editor/create_dialog.h b/editor/create_dialog.h index d859f7cbe4..03c4b25f5c 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -53,6 +53,7 @@ class CreateDialog : public ConfirmationDialog { Button *favorite; LineEdit *search_box; Tree *search_options; + HashMap<String, TreeItem *> search_options_types; bool is_replace_mode; String base_type; String preferred_search_result_type; @@ -82,6 +83,8 @@ class CreateDialog : public ConfirmationDialog { void add_type(const String &p_type, HashMap<String, TreeItem *> &p_types, TreeItem *p_root, TreeItem **to_select); + void select_type(const String &p_type); + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); @@ -104,7 +107,7 @@ public: void set_preferred_search_result_type(const String &p_preferred_type); String get_preferred_search_result_type(); - void popup_create(bool p_dont_clear, bool p_replace_mode = false); + void popup_create(bool p_dont_clear, bool p_replace_mode = false, const String &p_select_type = "Node"); CreateDialog(); }; diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index e0c90808a0..a7975c86c5 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -73,7 +73,7 @@ bool EditorAutoloadSettings::_autoload_name_is_valid(const String &p_name, Strin if (ClassDB::class_exists(p_name)) { if (r_error) - *r_error = TTR("Invalid name. Must not collide with an existing engine class name."); + *r_error = TTR("Invalid name.") + "\n" + TTR("Must not collide with an existing engine class name."); return false; } @@ -81,7 +81,7 @@ bool EditorAutoloadSettings::_autoload_name_is_valid(const String &p_name, Strin for (int i = 0; i < Variant::VARIANT_MAX; i++) { if (Variant::get_type_name(Variant::Type(i)) == p_name) { if (r_error) - *r_error = TTR("Invalid name. Must not collide with an existing buit-in type name."); + *r_error = TTR("Invalid name.") + "\n" + TTR("Must not collide with an existing buit-in type name."); return false; } @@ -90,20 +90,33 @@ bool EditorAutoloadSettings::_autoload_name_is_valid(const String &p_name, Strin for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) { if (GlobalConstants::get_global_constant_name(i) == p_name) { if (r_error) - *r_error = TTR("Invalid name. Must not collide with an existing global constant name."); + *r_error = TTR("Invalid name.") + "\n" + TTR("Must not collide with an existing global constant name."); return false; } } + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + List<String> keywords; + ScriptServer::get_language(i)->get_reserved_words(&keywords); + for (List<String>::Element *E = keywords.front(); E; E = E->next()) { + if (E->get() == p_name) { + if (r_error) + *r_error = TTR("Invalid name.") + "\n" + TTR("Keyword cannot be used as an autoload name."); + + return false; + } + } + } + return true; } void EditorAutoloadSettings::_autoload_add() { - autoload_add(autoload_add_name->get_text(), autoload_add_path->get_line_edit()->get_text()); + if (autoload_add(autoload_add_name->get_text(), autoload_add_path->get_line_edit()->get_text())) + autoload_add_path->get_line_edit()->set_text(""); - autoload_add_path->get_line_edit()->set_text(""); autoload_add_name->set_text(""); } @@ -294,6 +307,7 @@ void EditorAutoloadSettings::_autoload_open(const String &fpath) { } ProjectSettingsEditor::get_singleton()->hide(); } + void EditorAutoloadSettings::_autoload_file_callback(const String &p_path) { autoload_add_name->set_text(p_path.get_file().get_basename()); @@ -626,25 +640,25 @@ void EditorAutoloadSettings::drop_data_fw(const Point2 &p_point, const Variant & undo_redo->commit_action(); } -void EditorAutoloadSettings::autoload_add(const String &p_name, const String &p_path) { +bool EditorAutoloadSettings::autoload_add(const String &p_name, const String &p_path) { String name = p_name; String error; if (!_autoload_name_is_valid(name, &error)) { EditorNode::get_singleton()->show_warning(error); - return; + return false; } String path = p_path; if (!FileAccess::exists(path)) { EditorNode::get_singleton()->show_warning(TTR("Invalid path.") + "\n" + TTR("File does not exist.")); - return; + return false; } if (!path.begins_with("res://")) { EditorNode::get_singleton()->show_warning(TTR("Invalid path.") + "\n" + TTR("Not in resource path.")); - return; + return false; } name = "autoload/" + name; @@ -668,6 +682,8 @@ void EditorAutoloadSettings::autoload_add(const String &p_name, const String &p_ undo_redo->add_undo_method(this, "emit_signal", autoload_changed); undo_redo->commit_action(); + + return true; } void EditorAutoloadSettings::autoload_remove(const String &p_name) { @@ -701,9 +717,10 @@ void EditorAutoloadSettings::_bind_methods() { ClassDB::bind_method("_autoload_selected", &EditorAutoloadSettings::_autoload_selected); ClassDB::bind_method("_autoload_edited", &EditorAutoloadSettings::_autoload_edited); ClassDB::bind_method("_autoload_button_pressed", &EditorAutoloadSettings::_autoload_button_pressed); - ClassDB::bind_method("_autoload_file_callback", &EditorAutoloadSettings::_autoload_file_callback); ClassDB::bind_method("_autoload_activated", &EditorAutoloadSettings::_autoload_activated); + ClassDB::bind_method("_autoload_text_entered", &EditorAutoloadSettings::_autoload_text_entered); ClassDB::bind_method("_autoload_open", &EditorAutoloadSettings::_autoload_open); + ClassDB::bind_method("_autoload_file_callback", &EditorAutoloadSettings::_autoload_file_callback); ClassDB::bind_method("get_drag_data_fw", &EditorAutoloadSettings::get_drag_data_fw); ClassDB::bind_method("can_drop_data_fw", &EditorAutoloadSettings::can_drop_data_fw); @@ -802,6 +819,7 @@ EditorAutoloadSettings::EditorAutoloadSettings() { autoload_add_name = memnew(LineEdit); autoload_add_name->set_h_size_flags(SIZE_EXPAND_FILL); + autoload_add_name->connect("text_entered", this, "_autoload_text_entered"); hbc->add_child(autoload_add_name); Button *add_autoload = memnew(Button); diff --git a/editor/editor_autoload_settings.h b/editor/editor_autoload_settings.h index 45added56b..76ce020d8a 100644 --- a/editor/editor_autoload_settings.h +++ b/editor/editor_autoload_settings.h @@ -84,6 +84,7 @@ class EditorAutoloadSettings : public VBoxContainer { void _autoload_edited(); void _autoload_button_pressed(Object *p_item, int p_column, int p_button); void _autoload_activated(); + void _autoload_text_entered(String) { _autoload_add(); } void _autoload_open(const String &fpath); void _autoload_file_callback(const String &p_path); Node *_create_autoload(const String &p_path); @@ -98,7 +99,7 @@ protected: public: void update_autoload(); - void autoload_add(const String &p_name, const String &p_path); + bool autoload_add(const String &p_name, const String &p_path); void autoload_remove(const String &p_name); EditorAutoloadSettings(); diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index df481e0855..37f148bdbb 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -693,6 +693,10 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } } + //add native icons to non-resource include list + _edit_filter_list(paths, String("*.icns"), false); + _edit_filter_list(paths, String("*.ico"), false); + _edit_filter_list(paths, p_preset->get_include_filter(), false); _edit_filter_list(paths, p_preset->get_exclude_filter(), true); diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 724b821267..3d198dec67 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -710,7 +710,6 @@ void EditorFileDialog::update_file_list() { } String cdir = dir_access->get_current_dir(); - bool skip_pp = access == ACCESS_RESOURCES && cdir == "res://"; dir_access->list_dir_begin(); @@ -733,7 +732,7 @@ void EditorFileDialog::update_file_list() { if (show_hidden || !ishidden) { if (!isdir) files.push_back(item); - else if (item != ".." || !skip_pp) + else dirs.push_back(item); } } @@ -764,8 +763,6 @@ void EditorFileDialog::update_file_list() { dirs.pop_front(); } - dirs.clear(); - List<String> patterns; // build filter if (filter->get_selected() == filter->get_item_count() - 1) { @@ -864,8 +861,6 @@ void EditorFileDialog::update_file_list() { break; } } - - files.clear(); } void EditorFileDialog::_filter_selected(int) { diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index 5b16b8f6d5..cddabbc4e4 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -228,7 +228,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { p_theme->set_font("doc", "EditorFonts", df_doc); p_theme->set_font("doc_title", "EditorFonts", df_doc_title); - MAKE_SOURCE_FONT(df_doc_code, int(EDITOR_DEF("text_editor/help/help_source_font_size", 14)) * EDSCALE); + MAKE_SOURCE_FONT(df_doc_code, int(EDITOR_GET("text_editor/help/help_source_font_size")) * EDSCALE); p_theme->set_font("doc_source", "EditorFonts", df_doc_code); // Ruler font diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 82e7a37f19..90604a36f1 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1921,6 +1921,12 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { file->popup_centered_ratio(); } break; + case FILE_QUICK_OPEN: { + + quick_open->popup_dialog("Resource", true); + quick_open->set_title(TTR("Quick Open...")); + + } break; case FILE_QUICK_OPEN_SCENE: { quick_open->popup_dialog("PackedScene", true); @@ -2454,14 +2460,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case SETTINGS_MANAGE_FEATURE_PROFILES: { - Size2 popup_size = Size2(900, 800) * editor_get_scale(); - Size2 window_size = get_viewport()->get_size(); - - popup_size.x = MIN(window_size.x * 0.8, popup_size.x); - popup_size.y = MIN(window_size.y * 0.8, popup_size.y); - - feature_profile_manager->popup_centered(popup_size); - + feature_profile_manager->popup_centered_clamped(Size2(900, 800) * EDSCALE, 0.8); } break; case SETTINGS_TOGGLE_FULLSCREEN: { @@ -5702,6 +5701,7 @@ EditorNode::EditorNode() { p->add_separator(); p->add_submenu_item(TTR("Open Recent"), "RecentScenes", FILE_OPEN_RECENT); p->add_separator(); + p->add_shortcut(ED_SHORTCUT("editor/quick_open", TTR("Quick Open..."), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_O), FILE_QUICK_OPEN); p->add_shortcut(ED_SHORTCUT("editor/quick_open_scene", TTR("Quick Open Scene..."), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_O), FILE_QUICK_OPEN_SCENE); p->add_shortcut(ED_SHORTCUT("editor/quick_open_script", TTR("Quick Open Script..."), KEY_MASK_ALT + KEY_MASK_CMD + KEY_O), FILE_QUICK_OPEN_SCRIPT); p->add_separator(); @@ -6242,7 +6242,6 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(TextureEditorPlugin(this))); add_editor_plugin(memnew(AudioStreamEditorPlugin(this))); add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); - add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); add_editor_plugin(memnew(SkeletonEditorPlugin(this))); add_editor_plugin(memnew(SkeletonIKEditorPlugin(this))); add_editor_plugin(memnew(PhysicalBonePlugin(this))); diff --git a/editor/editor_node.h b/editor/editor_node.h index cfe8bf9ec4..6e7b2b2443 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -146,6 +146,7 @@ private: FILE_SAVE_OPTIMIZED, FILE_OPEN_RECENT, FILE_OPEN_OLD_SCENE, + FILE_QUICK_OPEN, FILE_QUICK_OPEN_SCENE, FILE_QUICK_OPEN_SCRIPT, FILE_OPEN_PREV, diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 8af4ee8017..56fc1f87a5 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -400,6 +400,18 @@ void EditorPlugin::add_control_to_container(CustomControlContainer p_location, C EditorNode::get_singleton()->get_inspector_dock_addon_area()->add_child(p_control); } break; + case CONTAINER_PROJECT_SETTING_TAB_LEFT: { + + ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(p_control); + ProjectSettingsEditor::get_singleton()->get_tabs()->move_child(p_control, 0); + + } break; + case CONTAINER_PROJECT_SETTING_TAB_RIGHT: { + + ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(p_control); + ProjectSettingsEditor::get_singleton()->get_tabs()->move_child(p_control, 1); + + } break; } } @@ -450,6 +462,12 @@ void EditorPlugin::remove_control_from_container(CustomControlContainer p_locati EditorNode::get_singleton()->get_inspector_dock_addon_area()->remove_child(p_control); } break; + case CONTAINER_PROJECT_SETTING_TAB_LEFT: + case CONTAINER_PROJECT_SETTING_TAB_RIGHT: { + + ProjectSettingsEditor::get_singleton()->get_tabs()->remove_child(p_control); + + } break; } } @@ -863,6 +881,8 @@ void EditorPlugin::_bind_methods() { BIND_ENUM_CONSTANT(CONTAINER_CANVAS_EDITOR_SIDE_RIGHT); BIND_ENUM_CONSTANT(CONTAINER_CANVAS_EDITOR_BOTTOM); BIND_ENUM_CONSTANT(CONTAINER_PROPERTY_EDITOR_BOTTOM); + BIND_ENUM_CONSTANT(CONTAINER_PROJECT_SETTING_TAB_LEFT); + BIND_ENUM_CONSTANT(CONTAINER_PROJECT_SETTING_TAB_RIGHT); BIND_ENUM_CONSTANT(DOCK_SLOT_LEFT_UL); BIND_ENUM_CONSTANT(DOCK_SLOT_LEFT_BL); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 2fcc487377..ba4df35e66 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -137,7 +137,9 @@ public: CONTAINER_CANVAS_EDITOR_SIDE_LEFT, CONTAINER_CANVAS_EDITOR_SIDE_RIGHT, CONTAINER_CANVAS_EDITOR_BOTTOM, - CONTAINER_PROPERTY_EDITOR_BOTTOM + CONTAINER_PROPERTY_EDITOR_BOTTOM, + CONTAINER_PROJECT_SETTING_TAB_LEFT, + CONTAINER_PROJECT_SETTING_TAB_RIGHT, }; enum DockSlot { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 79dcbca7a2..c0dc231ea9 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -487,6 +487,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // Help _initial_set("text_editor/help/show_help_index", true); + _initial_set("text_editor/help_source_font_size", 14); + hints["text_editor/help/help_source_font_size"] = PropertyInfo(Variant::REAL, "text_editor/help/help_source_font_size", PROPERTY_HINT_RANGE, "10, 50, 1"); /* Editors */ diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 52ed94e428..194a131095 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -2160,6 +2160,18 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) { } } +void FileSystemDock::_tree_rmb_empty(const Vector2 &p_pos) { + // Right click is pressed in the empty space of the tree + path = "res://"; + tree_popup->clear(); + tree_popup->set_size(Size2(1, 1)); + tree_popup->add_item(TTR("New Folder..."), FILE_NEW_FOLDER); + tree_popup->add_item(TTR("New Script..."), FILE_NEW_SCRIPT); + tree_popup->add_item(TTR("New Resource..."), FILE_NEW_RESOURCE); + tree_popup->set_position(tree->get_global_position() + p_pos); + tree_popup->popup(); +} + void FileSystemDock::_tree_empty_selected() { tree->deselect_all(); } @@ -2353,6 +2365,7 @@ void FileSystemDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_file_list_rmb_option", "option"), &FileSystemDock::_file_list_rmb_option); ClassDB::bind_method(D_METHOD("_file_list_rmb_select"), &FileSystemDock::_file_list_rmb_select); ClassDB::bind_method(D_METHOD("_file_list_rmb_pressed"), &FileSystemDock::_file_list_rmb_pressed); + ClassDB::bind_method(D_METHOD("_tree_rmb_empty"), &FileSystemDock::_tree_rmb_empty); ClassDB::bind_method(D_METHOD("_file_deleted"), &FileSystemDock::_file_deleted); ClassDB::bind_method(D_METHOD("_folder_deleted"), &FileSystemDock::_folder_deleted); @@ -2485,6 +2498,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { tree->connect("item_activated", this, "_tree_activate_file"); tree->connect("multi_selected", this, "_tree_multi_selected"); tree->connect("item_rmb_selected", this, "_tree_rmb_select"); + tree->connect("empty_rmb", this, "_tree_rmb_empty"); tree->connect("nothing_selected", this, "_tree_empty_selected"); tree->connect("gui_input", this, "_tree_gui_input"); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 9d20544ac2..978235b328 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -236,6 +236,7 @@ private: void _file_and_folders_fill_popup(PopupMenu *p_popup, Vector<String> p_paths, bool p_display_path_dependent_options = true); void _tree_rmb_select(const Vector2 &p_pos); + void _tree_rmb_empty(const Vector2 &p_pos); void _file_list_rmb_select(int p_item, const Vector2 &p_pos); void _file_list_rmb_pressed(const Vector2 &p_pos); void _tree_empty_selected(); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 11af9fc2eb..e1ab5c62a7 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -367,28 +367,11 @@ FindInFilesDialog::FindInFilesDialog() { Label *filter_label = memnew(Label); filter_label->set_text(TTR("Filters:")); + filter_label->set_tooltip(TTR("Include the files with the following extensions. Add or remove them in ProjectSettings.")); gc->add_child(filter_label); - { - HBoxContainer *hbc = memnew(HBoxContainer); - - // TODO: Unhardcode this. - Vector<String> exts; - exts.push_back("gd"); - if (Engine::get_singleton()->has_singleton("GodotSharp")) - exts.push_back("cs"); - exts.push_back("shader"); - - for (int i = 0; i < exts.size(); ++i) { - CheckBox *cb = memnew(CheckBox); - cb->set_text(exts[i]); - cb->set_pressed(true); - hbc->add_child(cb); - _filters.push_back(cb); - } - - gc->add_child(hbc); - } + _filters_container = memnew(HBoxContainer); + gc->add_child(_filters_container); _find_button = add_button(TTR("Find..."), false, "find"); _find_button->set_disabled(true); @@ -424,11 +407,12 @@ String FindInFilesDialog::get_folder() const { } Set<String> FindInFilesDialog::get_filter() const { + // could check the _filters_preferences but it might not have been generated yet. Set<String> filters; - for (int i = 0; i < _filters.size(); ++i) { - CheckBox *cb = _filters[i]; + for (int i = 0; i < _filters_container->get_child_count(); ++i) { + CheckBox *cb = (CheckBox *)_filters_container->get_child(i); if (cb->is_pressed()) { - filters.insert(_filters[i]->get_text()); + filters.insert(cb->get_text()); } } return filters; @@ -440,6 +424,20 @@ void FindInFilesDialog::_notification(int p_what) { // Doesn't work more than once if not deferred... _search_text_line_edit->call_deferred("grab_focus"); _search_text_line_edit->select_all(); + // Extensions might have changed in the meantime, we clean them and instance them again. + for (int i = 0; i < _filters_container->get_child_count(); i++) { + _filters_container->get_child(i)->queue_delete(); + } + Array exts = ProjectSettings::get_singleton()->get("editor/search_in_file_extensions"); + for (int i = 0; i < exts.size(); ++i) { + CheckBox *cb = memnew(CheckBox); + cb->set_text(exts[i]); + if (!_filters_preferences.has(exts[i])) { + _filters_preferences[exts[i]] = true; + } + cb->set_pressed(_filters_preferences[exts[i]]); + _filters_container->add_child(cb); + } } } } @@ -449,6 +447,10 @@ void FindInFilesDialog::_on_folder_button_pressed() { } void FindInFilesDialog::custom_action(const String &p_action) { + for (int i = 0; i < _filters_container->get_child_count(); ++i) { + CheckBox *cb = (CheckBox *)_filters_container->get_child(i); + _filters_preferences[cb->get_text()] = cb->is_pressed(); + } if (p_action == "find") { emit_signal(SIGNAL_FIND_REQUESTED); hide(); diff --git a/editor/find_in_files.h b/editor/find_in_files.h index 220f8cc136..5f728a104b 100644 --- a/editor/find_in_files.h +++ b/editor/find_in_files.h @@ -31,6 +31,7 @@ #ifndef FIND_IN_FILES_H #define FIND_IN_FILES_H +#include "core/hash_map.h" #include "scene/gui/dialogs.h" // Performs the actual search @@ -88,6 +89,7 @@ private: class LineEdit; class CheckBox; class FileDialog; +class HBoxContainer; // Prompts search parameters class FindInFilesDialog : public AcceptDialog { @@ -120,12 +122,13 @@ private: LineEdit *_search_text_line_edit; LineEdit *_folder_line_edit; - Vector<CheckBox *> _filters; CheckBox *_match_case_checkbox; CheckBox *_whole_words_checkbox; Button *_find_button; Button *_replace_button; FileDialog *_folder_dialog; + HBoxContainer *_filters_container; + HashMap<String, bool> _filters_preferences; }; class Button; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 5ac7bc3bc8..5da731b0a0 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -1291,6 +1291,13 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p } String root_type = p_options["nodes/root_type"]; + root_type = root_type.split(" ")[0]; // full root_type is "ClassName (filename.gd)" for a script global class. + + Ref<Script> root_script = NULL; + if (ScriptServer::is_global_class(root_type)) { + root_script = ResourceLoader::load(ScriptServer::get_global_class_path(root_type)); + root_type = ScriptServer::get_global_class_base(root_type); + } if (root_type != "Spatial") { Node *base_node = Object::cast_to<Node>(ClassDB::instance(root_type)); @@ -1303,6 +1310,10 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p } } + if (root_script.is_valid()) { + scene->set_script(Variant(root_script)); + } + if (Object::cast_to<Spatial>(scene)) { float root_scale = p_options["nodes/root_scale"]; Object::cast_to<Spatial>(scene)->scale(Vector3(root_scale, root_scale, root_scale)); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index eabb781288..951e971615 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -703,7 +703,7 @@ void AnimationPlayerEditor::set_state(const Dictionary &p_state) { if (Object::cast_to<AnimationPlayer>(n) && EditorNode::get_singleton()->get_editor_selection()->is_selected(n)) { player = Object::cast_to<AnimationPlayer>(n); _update_player(); - show(); + editor->make_bottom_panel_item_visible(this); set_process(true); ensure_visibility(); @@ -1874,8 +1874,6 @@ void AnimationPlayerEditorPlugin::edit(Object *p_object) { if (!p_object) return; anim_editor->edit(Object::cast_to<AnimationPlayer>(p_object)); - // In case switching to a scene with an AnimationPlayer selected but with the animation editor closed. - button->set_pressed(true); } bool AnimationPlayerEditorPlugin::handles(Object *p_object) const { @@ -1898,7 +1896,7 @@ AnimationPlayerEditorPlugin::AnimationPlayerEditorPlugin(EditorNode *p_node) { editor = p_node; anim_editor = memnew(AnimationPlayerEditor(editor, this)); anim_editor->set_undo_redo(editor->get_undo_redo()); - button = editor->add_bottom_panel_item(TTR("Animation"), anim_editor); + editor->add_bottom_panel_item(TTR("Animation"), anim_editor); } AnimationPlayerEditorPlugin::~AnimationPlayerEditorPlugin() { diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h index 9b72ebac7e..b1026b5b9f 100644 --- a/editor/plugins/animation_player_editor_plugin.h +++ b/editor/plugins/animation_player_editor_plugin.h @@ -257,7 +257,6 @@ class AnimationPlayerEditorPlugin : public EditorPlugin { AnimationPlayerEditor *anim_editor; EditorNode *editor; - Button *button; protected: void _notification(int p_what); diff --git a/editor/plugins/particles_2d_editor_plugin.cpp b/editor/plugins/particles_2d_editor_plugin.cpp index 50bdf4512b..4c354b8002 100644 --- a/editor/plugins/particles_2d_editor_plugin.cpp +++ b/editor/plugins/particles_2d_editor_plugin.cpp @@ -93,7 +93,13 @@ void Particles2DEditorPlugin::_menu_callback(int p_idx) { cpu_particles->set_pause_mode(particles->get_pause_mode()); cpu_particles->set_z_index(particles->get_z_index()); - EditorNode::get_singleton()->get_scene_tree_dock()->replace_node(particles, cpu_particles, false); + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Convert from Particles2D")); + ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", particles, cpu_particles, true, false); + ur->add_do_reference(particles); + ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", cpu_particles, particles, false, false); + ur->add_undo_reference(this); + ur->commit_action(); } break; } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 38985a2b2c..839c9483d7 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -3055,7 +3055,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { members_overview->set_custom_minimum_size(Size2(0, 90) * EDSCALE); //need to give a bit of limit to avoid it from disappearing members_overview->set_v_size_flags(SIZE_EXPAND_FILL); members_overview->set_allow_rmb_select(true); - members_overview->set_drag_forwarding(this); help_overview = memnew(ItemList); overview_vbox->add_child(help_overview); diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp index 7642bfaf04..2deb2090e2 100644 --- a/editor/plugins/sprite_editor_plugin.cpp +++ b/editor/plugins/sprite_editor_plugin.cpp @@ -327,7 +327,14 @@ void SpriteEditor::_convert_to_mesh_2d_node() { MeshInstance2D *mesh_instance = memnew(MeshInstance2D); mesh_instance->set_mesh(mesh); - EditorNode::get_singleton()->get_scene_tree_dock()->replace_node(node, mesh_instance); + + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Convert to Mesh2D")); + ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", node, mesh_instance, true, false); + ur->add_do_reference(mesh_instance); + ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", mesh_instance, node, false, false); + ur->add_undo_reference(node); + ur->commit_action(); } void SpriteEditor::_convert_to_polygon_2d_node() { @@ -379,7 +386,13 @@ void SpriteEditor::_convert_to_polygon_2d_node() { polygon_2d_instance->set_polygon(polygon); polygon_2d_instance->set_polygons(polys); - EditorNode::get_singleton()->get_scene_tree_dock()->replace_node(node, polygon_2d_instance); + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Convert to Polygon2D")); + ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", node, polygon_2d_instance, true, false); + ur->add_do_reference(polygon_2d_instance); + ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", polygon_2d_instance, node, false, false); + ur->add_undo_reference(node); + ur->commit_action(); } void SpriteEditor::_create_collision_polygon_2d_node() { @@ -396,7 +409,12 @@ void SpriteEditor::_create_collision_polygon_2d_node() { CollisionPolygon2D *collision_polygon_2d_instance = memnew(CollisionPolygon2D); collision_polygon_2d_instance->set_polygon(outline); - _add_as_sibling_or_child(node, collision_polygon_2d_instance); + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Create CollisionPolygon2D Sibling")); + ur->add_do_method(this, "_add_as_sibling_or_child", node, collision_polygon_2d_instance); + ur->add_do_reference(collision_polygon_2d_instance); + ur->add_undo_method(node != this->get_tree()->get_edited_scene_root() ? node->get_parent() : this->get_tree()->get_edited_scene_root(), "remove_child", collision_polygon_2d_instance); + ur->commit_action(); } } @@ -425,15 +443,20 @@ void SpriteEditor::_create_light_occluder_2d_node() { LightOccluder2D *light_occluder_2d_instance = memnew(LightOccluder2D); light_occluder_2d_instance->set_occluder_polygon(polygon); - _add_as_sibling_or_child(node, light_occluder_2d_instance); + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Create LightOccluder2D Sibling")); + ur->add_do_method(this, "_add_as_sibling_or_child", node, light_occluder_2d_instance); + ur->add_do_reference(light_occluder_2d_instance); + ur->add_undo_method(node != this->get_tree()->get_edited_scene_root() ? node->get_parent() : this->get_tree()->get_edited_scene_root(), "remove_child", light_occluder_2d_instance); + ur->commit_action(); } } -void SpriteEditor::_add_as_sibling_or_child(Node2D *p_own_node, Node2D *p_new_node) { +void SpriteEditor::_add_as_sibling_or_child(Node *p_own_node, Node *p_new_node) { // Can't make sibling if own node is scene root if (p_own_node != this->get_tree()->get_edited_scene_root()) { p_own_node->get_parent()->add_child(p_new_node, true); - p_new_node->set_transform(p_own_node->get_transform()); + Object::cast_to<Node2D>(p_new_node)->set_transform(Object::cast_to<Node2D>(p_own_node)->get_transform()); } else { p_own_node->add_child(p_new_node, true); } @@ -534,6 +557,7 @@ void SpriteEditor::_bind_methods() { ClassDB::bind_method("_debug_uv_draw", &SpriteEditor::_debug_uv_draw); ClassDB::bind_method("_update_mesh_data", &SpriteEditor::_update_mesh_data); ClassDB::bind_method("_create_node", &SpriteEditor::_create_node); + ClassDB::bind_method("_add_as_sibling_or_child", &SpriteEditor::_add_as_sibling_or_child); } SpriteEditor::SpriteEditor() { diff --git a/editor/plugins/sprite_editor_plugin.h b/editor/plugins/sprite_editor_plugin.h index 460f5a5707..81be4a19e9 100644 --- a/editor/plugins/sprite_editor_plugin.h +++ b/editor/plugins/sprite_editor_plugin.h @@ -84,7 +84,7 @@ class SpriteEditor : public Control { void _create_collision_polygon_2d_node(); void _create_light_occluder_2d_node(); - void _add_as_sibling_or_child(Node2D *p_own_node, Node2D *p_new_node); + void _add_as_sibling_or_child(Node *p_own_node, Node *p_new_node); protected: void _node_removed(Node *p_node); diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 29a54f815d..772e47ac3a 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -760,7 +760,7 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p r.position += (r.size + Vector2(spacing, spacing)) * offset; } Size2 sc = p_xform.get_scale(); - + Size2 cell_size = node->get_cell_size(); Rect2 rect = Rect2(); rect.position = node->map_to_world(p_point) + node->get_cell_draw_offset(); @@ -770,62 +770,25 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p rect.size = r.size; } - if (rect.size.y > rect.size.x) { - if ((p_flip_h && (p_flip_v || p_transpose)) || (p_flip_v && !p_transpose)) - tile_ofs.y += rect.size.y - rect.size.x; - } else if (rect.size.y < rect.size.x) { - if ((p_flip_v && (p_flip_h || p_transpose)) || (p_flip_h && !p_transpose)) - tile_ofs.x += rect.size.x - rect.size.y; - } - if (p_transpose) { SWAP(tile_ofs.x, tile_ofs.y); + rect.position.x += cell_size.x / 2 - rect.size.y / 2; + rect.position.y += cell_size.y / 2 - rect.size.x / 2; + } else { + rect.position += cell_size / 2 - rect.size / 2; } + if (p_flip_h) { sc.x *= -1.0; tile_ofs.x *= -1.0; } + if (p_flip_v) { sc.y *= -1.0; tile_ofs.y *= -1.0; } - if (node->get_tile_origin() == TileMap::TILE_ORIGIN_TOP_LEFT) { - - rect.position += tile_ofs; - } else if (node->get_tile_origin() == TileMap::TILE_ORIGIN_BOTTOM_LEFT) { - Size2 cell_size = node->get_cell_size(); - - rect.position += tile_ofs; - - if (p_transpose) { - if (p_flip_h) - rect.position.x -= cell_size.x; - else - rect.position.x += cell_size.x; - } else { - if (p_flip_v) - rect.position.y -= cell_size.y; - else - rect.position.y += cell_size.y; - } - - } else if (node->get_tile_origin() == TileMap::TILE_ORIGIN_CENTER) { - Size2 cell_size = node->get_cell_size(); - - rect.position += tile_ofs; - - if (p_flip_h) - rect.position.x -= cell_size.x / 2; - else - rect.position.x += cell_size.x / 2; - - if (p_flip_v) - rect.position.y -= cell_size.y / 2; - else - rect.position.y += cell_size.y / 2; - } - + rect.position += tile_ofs; rect.position = p_xform.xform(rect.position); rect.size *= sc; diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 93c6614841..a00be3c0ce 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -372,6 +372,15 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { tool_editmode[EDITMODE_COLLISION]->set_pressed(true); edit_mode = EDITMODE_COLLISION; + tool_editmode[EDITMODE_REGION]->set_shortcut(ED_SHORTCUT("tileset_editor/editmode_region", TTR("Region Mode"), KEY_1)); + tool_editmode[EDITMODE_COLLISION]->set_shortcut(ED_SHORTCUT("tileset_editor/editmode_collision", TTR("Collision Mode"), KEY_2)); + tool_editmode[EDITMODE_OCCLUSION]->set_shortcut(ED_SHORTCUT("tileset_editor/editmode_occlusion", TTR("Occlusion Mode"), KEY_3)); + tool_editmode[EDITMODE_NAVIGATION]->set_shortcut(ED_SHORTCUT("tileset_editor/editmode_navigation", TTR("Navigation Mode"), KEY_4)); + tool_editmode[EDITMODE_BITMASK]->set_shortcut(ED_SHORTCUT("tileset_editor/editmode_bitmask", TTR("Bitmask Mode"), KEY_5)); + tool_editmode[EDITMODE_PRIORITY]->set_shortcut(ED_SHORTCUT("tileset_editor/editmode_priority", TTR("Priority Mode"), KEY_6)); + tool_editmode[EDITMODE_ICON]->set_shortcut(ED_SHORTCUT("tileset_editor/editmode_icon", TTR("Icon Mode"), KEY_7)); + tool_editmode[EDITMODE_Z_INDEX]->set_shortcut(ED_SHORTCUT("tileset_editor/editmode_z_index", TTR("Z Index Mode"), KEY_8)); + main_vb->add_child(tool_hb); separator_editmode = memnew(HSeparator); main_vb->add_child(separator_editmode); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 2c68633a3c..a1b903576e 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -31,6 +31,7 @@ #include "visual_shader_editor_plugin.h" #include "core/io/resource_loader.h" +#include "core/math/math_defs.h" #include "core/os/input.h" #include "core/os/keyboard.h" #include "core/project_settings.h" @@ -68,6 +69,7 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) { } } visual_shader = Ref<VisualShader>(p_visual_shader); + visual_shader->set_graph_offset(graph->get_scroll_ofs() / EDSCALE); } else { visual_shader.unref(); } @@ -1138,6 +1140,13 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx) { VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instance(add_options[p_idx].type)); ERR_FAIL_COND(!vsn); + VisualShaderNodeScalarConstant *constant = Object::cast_to<VisualShaderNodeScalarConstant>(vsn); + + if (constant) { + if ((int)add_options[p_idx].value != -1) + constant->set_constant(add_options[p_idx].value); + } + if (p_op_idx != -1) { VisualShaderNodeInput *input = Object::cast_to<VisualShaderNodeInput>(vsn); @@ -1987,6 +1996,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("ColorUniform", "Color", "Variables", "VisualShaderNodeColorUniform", TTR("Color uniform."), -1, VisualShaderNode::PORT_TYPE_COLOR)); // BOOLEAN + add_options.push_back(AddOption("If", "Conditional", "Functions", "VisualShaderNodeIf", TTR("Returns an associated vector if the provided scalars are equal, greater or less."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("Switch", "Conditional", "Functions", "VisualShaderNodeSwitch", TTR("Returns an associated vector if the provided boolean value is true or false."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("BooleanConstant", "Conditional", "Variables", "VisualShaderNodeBooleanConstant", TTR("Boolean constant."), -1, VisualShaderNode::PORT_TYPE_BOOLEAN)); @@ -2100,6 +2110,19 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("ScalarFunc", "Scalar", "Common", "VisualShaderNodeScalarFunc", TTR("Scalar function."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); add_options.push_back(AddOption("ScalarOp", "Scalar", "Common", "VisualShaderNodeScalarOp", TTR("Scalar operator."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + //CONSTANTS + + add_options.push_back(AddOption("E", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("E constant (2.718282). Represents the base of the natural logarithm."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, Math_E)); + add_options.push_back(AddOption("Epsilon", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Epsilon constant (0.00001). Smallest possible scalar number."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, CMP_EPSILON)); + add_options.push_back(AddOption("Phi", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Phi constant (1.618034). Golden ratio."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, 1.618034f)); + add_options.push_back(AddOption("Pi/4", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Pi/4 constant (0.785398) or 45 degrees."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, Math_PI / 4)); + add_options.push_back(AddOption("Pi/2", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Pi/2 constant (1.570796) or 90 degrees."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, Math_PI / 2)); + add_options.push_back(AddOption("Pi", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Pi constant (3.141593) or 180 degrees."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, Math_PI)); + add_options.push_back(AddOption("Tau", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Tau constant (6.283185) or 360 degrees."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, Math_TAU)); + add_options.push_back(AddOption("Sqrt2", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Sqrt2 constant (1.414214). Square root of 2."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, Math_SQRT2)); + + // FUNCTIONS + add_options.push_back(AddOption("Abs", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the absolute value of the parameter."), VisualShaderNodeScalarFunc::FUNC_ABS, VisualShaderNode::PORT_TYPE_SCALAR)); add_options.push_back(AddOption("ACos", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the arc-cosine of the parameter."), VisualShaderNodeScalarFunc::FUNC_ACOS, VisualShaderNode::PORT_TYPE_SCALAR)); add_options.push_back(AddOption("ACosH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("(GLES3 only) Returns the inverse hyperbolic cosine of the parameter."), VisualShaderNodeScalarFunc::FUNC_ACOSH, VisualShaderNode::PORT_TYPE_SCALAR)); diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index e851030ab4..1b009b61d5 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -101,8 +101,9 @@ class VisualShaderEditor : public VBoxContainer { int mode; int return_type; int func; + float value; - AddOption(const String &p_name = String(), const String &p_category = String(), const String &p_sub_category = String(), const String &p_type = String(), const String &p_description = String(), int p_sub_func = -1, int p_return_type = -1, int p_mode = -1, int p_func = -1) { + AddOption(const String &p_name = String(), const String &p_category = String(), const String &p_sub_category = String(), const String &p_type = String(), const String &p_description = String(), int p_sub_func = -1, int p_return_type = -1, int p_mode = -1, int p_func = -1, float p_value = -1) { name = p_name; type = p_type; category = p_category; @@ -112,9 +113,10 @@ class VisualShaderEditor : public VBoxContainer { return_type = p_return_type; mode = p_mode; func = p_func; + value = p_value; } - AddOption(const String &p_name, const String &p_category, const String &p_sub_category, const String &p_type, const String &p_description, const String &p_sub_func, int p_return_type = -1, int p_mode = -1, int p_func = -1) { + AddOption(const String &p_name, const String &p_category, const String &p_sub_category, const String &p_type, const String &p_description, const String &p_sub_func, int p_return_type = -1, int p_mode = -1, int p_func = -1, float p_value = -1) { name = p_name; type = p_type; category = p_category; @@ -124,6 +126,7 @@ class VisualShaderEditor : public VBoxContainer { return_type = p_return_type; mode = p_mode; func = p_func; + value = p_value; } }; diff --git a/editor/project_export.cpp b/editor/project_export.cpp index cc110f309c..ee78b240a4 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -88,14 +88,7 @@ void ProjectExportDialog::popup_export() { if (saved_size != Rect2()) { popup(saved_size); } else { - - Size2 popup_size = Size2(900, 700) * editor_get_scale(); - Size2 window_size = get_viewport_rect().size; - - popup_size.x = MIN(window_size.x * 0.8, popup_size.x); - popup_size.y = MIN(window_size.y * 0.8, popup_size.y); - - popup_centered(popup_size); + popup_centered_clamped(Size2(900, 700) * EDSCALE, 0.8); } } diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 6de4330493..b0baf954d2 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1627,40 +1627,28 @@ void ProjectManager::_show_project(const String &p_path) { OS::get_singleton()->shell_open(String("file://") + p_path); } -void ProjectManager::_scan_dir(DirAccess *da, float pos, float total, List<String> *r_projects) { - - List<String> subdirs; +void ProjectManager::_scan_dir(const String &path, List<String> *r_projects) { + DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + da->change_dir(path); da->list_dir_begin(); String n = da->get_next(); while (n != String()) { if (da->current_is_dir() && !n.begins_with(".")) { - subdirs.push_front(n); + _scan_dir(da->get_current_dir().plus_file(n), r_projects); } else if (n == "project.godot") { r_projects->push_back(da->get_current_dir()); } n = da->get_next(); } da->list_dir_end(); - int m = 0; - for (List<String>::Element *E = subdirs.front(); E; E = E->next()) { - - da->change_dir(E->get()); - - float slice = total / subdirs.size(); - _scan_dir(da, pos + slice * m, slice, r_projects); - da->change_dir(".."); - m++; - } + memdelete(da); } void ProjectManager::_scan_begin(const String &p_base) { print_line("Scanning projects at: " + p_base); List<String> projects; - DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - da->change_dir(p_base); - _scan_dir(da, 0, 1, &projects); - memdelete(da); + _scan_dir(p_base, &projects); print_line("Found " + itos(projects.size()) + " projects."); for (List<String>::Element *E = projects.front(); E; E = E->next()) { @@ -2166,6 +2154,19 @@ ProjectManager::ProjectManager() { Button *cancel = memnew(Button); cancel->set_text(TTR("Exit")); cancel->set_custom_minimum_size(Size2(100, 1) * EDSCALE); + +#ifndef OSX_ENABLED + // Pressing Command + Q quits the Project Manager + // This is handled by the platform implementation on macOS, + // so only define the shortcut on other platforms + InputEventKey *quit_key = memnew(InputEventKey); + quit_key->set_command(true); + quit_key->set_scancode(KEY_Q); + ShortCut *quit_shortcut = memnew(ShortCut); + quit_shortcut->set_shortcut(quit_key); + cancel->set_shortcut(quit_shortcut); +#endif + cc->add_child(cancel); cancel->connect("pressed", this, "_exit_dialog"); vb->add_child(cc); diff --git a/editor/project_manager.h b/editor/project_manager.h index 382e9fc8fb..fa878e75a6 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -106,7 +106,7 @@ class ProjectManager : public Control { void _on_project_created(const String &dir); void _on_projects_updated(); void _update_scroll_position(const String &dir); - void _scan_dir(DirAccess *da, float pos, float total, List<String> *r_projects); + void _scan_dir(const String &path, List<String> *r_projects); void _install_project(const String &p_zip_path, const String &p_title); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 71bddebcf5..872f8fcd2c 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -793,15 +793,9 @@ void ProjectSettingsEditor::popup_project_settings() { if (saved_size != Rect2()) { popup(saved_size); } else { - - Size2 popup_size = Size2(900, 700) * editor_get_scale(); - Size2 window_size = get_viewport_rect().size; - - popup_size.x = MIN(window_size.x * 0.8, popup_size.x); - popup_size.y = MIN(window_size.y * 0.8, popup_size.y); - - popup_centered(popup_size); + popup_centered_clamped(Size2(900, 700) * EDSCALE, 0.8); } + globals_editor->update_category_list(); _update_translations(); autoload_settings->update_autoload(); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 1f5300e351..ce2795f37b 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -31,6 +31,7 @@ #include "scene_tree_dock.h" #include "core/io/resource_saver.h" +#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/project_settings.h" @@ -347,7 +348,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (!profile_allow_editing) { break; } - create_dialog->popup_create(false, true); + create_dialog->popup_create(false, true, scene_tree->get_selected()->get_class()); } break; case TOOL_ATTACH_SCRIPT: { @@ -517,6 +518,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { editor_data->get_undo_redo().add_do_method(editor_selection, "clear"); Node *dupsingle = NULL; + List<Node *> editable_children; for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { @@ -529,6 +531,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { Map<const Node *, Node *> duplimap; Node *dup = node->duplicate_from_editor(duplimap); + if (EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node)) + editable_children.push_back(dup); + ERR_CONTINUE(!dup); if (selection.size() == 1) @@ -561,6 +566,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (dupsingle) editor->push_item(dupsingle); + for (List<Node *>::Element *E = editable_children.front(); E; E = E->next()) + _toggle_editable_children(E->get()); + } break; case TOOL_REPARENT: { @@ -796,7 +804,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { editable_instance_remove_dialog->popup_centered_minsize(); break; } - _toggle_editable_children(); + _toggle_editable_children(node); } } } break; @@ -1612,30 +1620,27 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) { _update_script_button(); } -void SceneTreeDock::_toggle_editable_children() { +void SceneTreeDock::_toggle_editable_children_from_selection() { + List<Node *> selection = editor_selection->get_selected_node_list(); List<Node *>::Element *e = selection.front(); - if (e) { - Node *node = e->get(); - if (node) { - bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node); - int editable_item_idx = menu->get_item_idx_from_text(TTR("Editable Children")); - int placeholder_item_idx = menu->get_item_idx_from_text(TTR("Load As Placeholder")); - editable = !editable; + if (e) { + _toggle_editable_children(e->get()); + } +} - EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node, editable); +void SceneTreeDock::_toggle_editable_children(Node *p_node) { - menu->set_item_checked(editable_item_idx, editable); - if (editable) { - node->set_scene_instance_load_placeholder(false); - menu->set_item_checked(placeholder_item_idx, false); - } + if (p_node) { + bool editable = !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); + EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(p_node, editable); + if (editable) + p_node->set_scene_instance_load_placeholder(false); - SpatialEditor::get_singleton()->update_all_gizmos(node); + SpatialEditor::get_singleton()->update_all_gizmos(p_node); - scene_tree->update_tree(); - } + scene_tree->update_tree(); } } @@ -1853,7 +1858,7 @@ void SceneTreeDock::_create() { scene_tree->get_scene_tree()->call_deferred("grab_focus"); } -void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties) { +void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties, bool p_remove_old) { Node *n = p_node; Node *newnode = p_by_node; @@ -1917,16 +1922,20 @@ void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_prop Node *c = newnode->get_child(i); c->call("set_transform", c->call("get_transform")); } - editor_data->get_undo_redo().clear_history(); + //p_remove_old was added to support undo + if (p_remove_old) + editor_data->get_undo_redo().clear_history(); newnode->set_name(newname); editor->push_item(newnode); - memdelete(n); + if (p_remove_old) { + memdelete(n); - while (to_erase.front()) { - memdelete(to_erase.front()->get()); - to_erase.pop_front(); + while (to_erase.front()) { + memdelete(to_erase.front()->get()); + to_erase.pop_front(); + } } } @@ -1942,13 +1951,7 @@ void SceneTreeDock::set_selected(Node *p_node, bool p_emit_selected) { void SceneTreeDock::import_subscene() { - Size2 popup_size = Size2(500, 800) * editor_get_scale(); - Size2 window_size = get_viewport_rect().size; - - popup_size.x = MIN(window_size.x * 0.8, popup_size.x); - popup_size.y = MIN(window_size.y * 0.8, popup_size.y); - - import_subscene_dialog->popup_centered(popup_size); + import_subscene_dialog->popup_centered_clamped(Size2(500, 800) * EDSCALE, 0.8); } void SceneTreeDock::_import_subscene() { @@ -2132,7 +2135,7 @@ void SceneTreeDock::_nodes_dragged(Array p_nodes, NodePath p_to, int p_type) { int to_pos = -1; _normalize_drop(to_node, to_pos, p_type); - _do_reparent(to_node, to_pos, nodes, true); + _do_reparent(to_node, to_pos, nodes, !Input::get_singleton()->is_key_pressed(KEY_SHIFT)); } void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) { @@ -2481,7 +2484,7 @@ void SceneTreeDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_input"), &SceneTreeDock::_input); ClassDB::bind_method(D_METHOD("_nodes_drag_begin"), &SceneTreeDock::_nodes_drag_begin); ClassDB::bind_method(D_METHOD("_delete_confirm"), &SceneTreeDock::_delete_confirm); - ClassDB::bind_method(D_METHOD("_toggle_editable_children"), &SceneTreeDock::_toggle_editable_children); + ClassDB::bind_method(D_METHOD("_toggle_editable_children_from_selection"), &SceneTreeDock::_toggle_editable_children_from_selection); ClassDB::bind_method(D_METHOD("_node_prerenamed"), &SceneTreeDock::_node_prerenamed); ClassDB::bind_method(D_METHOD("_import_subscene"), &SceneTreeDock::_import_subscene); ClassDB::bind_method(D_METHOD("_selection_changed"), &SceneTreeDock::_selection_changed); @@ -2501,6 +2504,7 @@ void SceneTreeDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_feature_profile_changed"), &SceneTreeDock::_feature_profile_changed); ClassDB::bind_method(D_METHOD("instance"), &SceneTreeDock::instance); + ClassDB::bind_method(D_METHOD("replace_node"), &SceneTreeDock::replace_node); ADD_SIGNAL(MethodInfo("remote_tree_selected")); } @@ -2649,7 +2653,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel editable_instance_remove_dialog = memnew(ConfirmationDialog); add_child(editable_instance_remove_dialog); - editable_instance_remove_dialog->connect("confirmed", this, "_toggle_editable_children"); + editable_instance_remove_dialog->connect("confirmed", this, "_toggle_editable_children_from_selection"); import_subscene_dialog = memnew(EditorSubScene); add_child(import_subscene_dialog); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index e66525d721..9f9e93f2df 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -172,7 +172,8 @@ class SceneTreeDock : public VBoxContainer { void _delete_confirm(); - void _toggle_editable_children(); + void _toggle_editable_children_from_selection(); + void _toggle_editable_children(Node *p_node); void _node_prerenamed(Node *p_node, const String &p_new_name); @@ -243,7 +244,7 @@ public: void show_tab_buttons(); void hide_tab_buttons(); - void replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties = true); + void replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties = true, bool p_remove_old = true); void open_script_dialog(Node *p_for_node); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index e3ad740005..5ca3448693 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -379,6 +379,12 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } if (!keep) { + if (editor_selection) { + Node *n = get_node(item->get_metadata(0)); + if (n) { + editor_selection->remove_node(n); + } + } memdelete(item); return false; } else { diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index a661c2cfc3..621ab039f4 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -262,7 +262,7 @@ void ScriptEditorDebugger::_scene_tree_folded(Object *obj) { return; ObjectID id = item->get_metadata(0); - if (item->is_collapsed()) { + if (unfold_cache.has(id)) { unfold_cache.erase(id); } else { unfold_cache.insert(id); diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index 68a1117364..b4643231d7 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -98,14 +98,7 @@ void EditorSettingsDialog::popup_edit_settings() { if (saved_size != Rect2()) { popup(saved_size); } else { - - Size2 popup_size = Size2(900, 700) * editor_get_scale(); - Size2 window_size = get_viewport_rect().size; - - popup_size.x = MIN(window_size.x * 0.8, popup_size.x); - popup_size.y = MIN(window_size.y * 0.8, popup_size.y); - - popup_centered(popup_size); + popup_centered_clamped(Size2(900, 700) * EDSCALE, 0.8); } _focus_current_search_box(); |