diff options
Diffstat (limited to 'editor')
30 files changed, 357 insertions, 308 deletions
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index db780b3665..ef33b82390 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -47,7 +47,7 @@ EditorFileSystem *EditorFileSystem::singleton = nullptr; //the name is the version, to keep compatibility with different versions of Godot -#define CACHE_FILE_NAME "filesystem_cache7" +#define CACHE_FILE_NAME "filesystem_cache8" void EditorFileSystemDirectory::sort_files() { files.sort_custom<FileInfoSort>(); @@ -169,6 +169,11 @@ StringName EditorFileSystemDirectory::get_file_type(int p_idx) const { return files[p_idx]->type; } +StringName EditorFileSystemDirectory::get_file_resource_script_class(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, files.size(), ""); + return files[p_idx]->resource_script_class; +} + String EditorFileSystemDirectory::get_name() { return name; } @@ -266,6 +271,10 @@ void EditorFileSystem::_scan_filesystem() { FileCache fc; fc.type = split[1]; + if (fc.type.find("/") != -1) { + fc.type = fc.type.get_slice("/", 0); + fc.resource_script_class = fc.type.get_slice("/", 1); + } fc.uid = split[2].to_int(); fc.modification_time = split[3].to_int(); fc.import_modification_time = split[4].to_int(); @@ -854,6 +863,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAc if (fc && fc->modification_time == mt && fc->import_modification_time == import_mt && !_test_for_reimport(path, true)) { fi->type = fc->type; + fi->resource_script_class = fc->resource_script_class; fi->uid = fc->uid; fi->deps = fc->deps; fi->modified_time = fc->modification_time; @@ -875,6 +885,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAc if (fc->type.is_empty()) { fi->type = ResourceLoader::get_resource_type(path); + fi->resource_script_class = ResourceLoader::get_resource_script_class(path); fi->import_group_file = ResourceLoader::get_import_group_file(path); //there is also the chance that file type changed due to reimport, must probably check this somehow here (or kind of note it for next time in another file?) //note: I think this should not happen any longer.. @@ -904,6 +915,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAc if (fc && fc->modification_time == mt) { //not imported, so just update type if changed fi->type = fc->type; + fi->resource_script_class = fc->resource_script_class; fi->uid = fc->uid; fi->modified_time = fc->modification_time; fi->deps = fc->deps; @@ -915,6 +927,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAc } else { //new or modified time fi->type = ResourceLoader::get_resource_type(path); + fi->resource_script_class = ResourceLoader::get_resource_script_class(path); if (fi->type == "" && textfile_extensions.has(ext)) { fi->type = "TextFile"; } @@ -1029,6 +1042,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const fi->modified_time = FileAccess::get_modified_time(path); fi->import_modified_time = 0; fi->type = ResourceLoader::get_resource_type(path); + fi->resource_script_class = ResourceLoader::get_resource_script_class(path); if (fi->type == "" && textfile_extensions.has(ext)) { fi->type = "TextFile"; } @@ -1285,7 +1299,12 @@ void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir, if (!p_dir->files[i]->import_group_file.is_empty()) { group_file_cache.insert(p_dir->files[i]->import_group_file); } - String s = p_dir->files[i]->file + "::" + p_dir->files[i]->type + "::" + itos(p_dir->files[i]->uid) + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->import_group_file + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends + "<>" + p_dir->files[i]->script_class_icon_path; + + String type = p_dir->files[i]->type; + if (p_dir->files[i]->resource_script_class) { + type += "/" + String(p_dir->files[i]->resource_script_class); + } + String s = p_dir->files[i]->file + "::" + type + "::" + itos(p_dir->files[i]->uid) + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->import_group_file + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends + "<>" + p_dir->files[i]->script_class_icon_path; s += "::"; for (int j = 0; j < p_dir->files[i]->deps.size(); j++) { if (j > 0) { @@ -1617,6 +1636,8 @@ void EditorFileSystem::update_file(const String &p_file) { if (type.is_empty() && textfile_extensions.has(p_file.get_extension())) { type = "TextFile"; } + String script_class = ResourceLoader::get_resource_script_class(p_file); + ResourceUID::ID uid = ResourceLoader::get_resource_uid(p_file); if (cpos == -1) { @@ -1650,6 +1671,7 @@ void EditorFileSystem::update_file(const String &p_file) { } fs->files[cpos]->type = type; + fs->files[cpos]->resource_script_class = script_class; fs->files[cpos]->uid = uid; fs->files[cpos]->script_class_name = _get_global_script_class(type, p_file, &fs->files[cpos]->script_class_extends, &fs->files[cpos]->script_class_icon_path); fs->files[cpos]->import_group_file = ResourceLoader::get_import_group_file(p_file); diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 03b1fb4a49..2490bd31b3 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -54,6 +54,7 @@ class EditorFileSystemDirectory : public Object { struct FileInfo { String file; StringName type; + StringName resource_script_class; // If any resource has script with a global class name, its found here. ResourceUID::ID uid = ResourceUID::INVALID_ID; uint64_t modified_time = 0; uint64_t import_modified_time = 0; @@ -61,6 +62,7 @@ class EditorFileSystemDirectory : public Object { String import_group_file; Vector<String> deps; bool verified = false; //used for checking changes + // These are for script resources only. String script_class_name; String script_class_extends; String script_class_icon_path; @@ -90,6 +92,7 @@ public: String get_file(int p_idx) const; String get_file_path(int p_idx) const; StringName get_file_type(int p_idx) const; + StringName get_file_resource_script_class(int p_idx) const; Vector<String> get_file_deps(int p_idx) const; bool get_file_import_is_valid(int p_idx) const; uint64_t get_file_modified_time(int p_idx) const; @@ -189,6 +192,7 @@ class EditorFileSystem : public Node { /* Used for reading the filesystem cache file */ struct FileCache { String type; + String resource_script_class; ResourceUID::ID uid = ResourceUID::INVALID_ID; uint64_t modification_time = 0; uint64_t import_modification_time = 0; diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 035bd96f4d..4753761f05 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -2181,8 +2181,7 @@ void EditorInspectorArray::_notification(int p_what) { odd_style->set_bg_color(color.darkened(-0.08)); even_style->set_bg_color(color.darkened(0.08)); - for (int i = 0; i < (int)array_elements.size(); i++) { - ArrayElement &ae = array_elements[i]; + for (ArrayElement &ae : array_elements) { if (ae.move_texture_rect) { ae.move_texture_rect->set_texture(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons"))); } @@ -3283,6 +3282,11 @@ void EditorInspector::update_tree() { ped->parse_end(object); _parse_added_editors(main_vbox, nullptr, ped); } + + if (_is_main_editor_inspector()) { + // Updating inspector might invalidate some editing owners. + EditorNode::get_singleton()->hide_unused_editors(); + } } void EditorInspector::update_property(const String &p_prop) { @@ -3307,6 +3311,9 @@ void EditorInspector::_clear() { sections.clear(); pending.clear(); restart_request_props.clear(); + if (_is_main_editor_inspector()) { + EditorNode::get_singleton()->hide_unused_editors(this); + } } Object *EditorInspector::get_edited_object() { @@ -3641,6 +3648,10 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo } } +bool EditorInspector::_is_main_editor_inspector() const { + return InspectorDock::get_singleton() && InspectorDock::get_inspector_singleton() == this; +} + void EditorInspector::_property_changed(const String &p_path, const Variant &p_value, const String &p_name, bool p_changing, bool p_update_all) { // The "changing" variable must be true for properties that trigger events as typing occurs, // like "text_changed" signal. E.g. text property of Label, Button, RichTextLabel, etc. diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 699a88e657..1690302e6e 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -502,6 +502,7 @@ class EditorInspector : public ScrollContainer { bool restrict_to_basic = false; void _edit_set(const String &p_name, const Variant &p_value, bool p_refresh_all, const String &p_changed_field); + bool _is_main_editor_inspector() const; void _property_changed(const String &p_path, const Variant &p_value, const String &p_name = "", bool p_changing = false, bool p_update_all = false); void _multiple_properties_changed(Vector<String> p_paths, Array p_values, bool p_changing = false); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index b0278030f9..05e0c6750e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2078,51 +2078,55 @@ bool EditorNode::_is_class_editor_disabled_by_feature_profile(const StringName & return false; } -void EditorNode::edit_item(Object *p_object) { +void EditorNode::edit_item(Object *p_object, Object *p_editing_owner) { + ERR_FAIL_NULL(p_editing_owner); + if (p_object && _is_class_editor_disabled_by_feature_profile(p_object->get_class())) { return; } - Vector<EditorPlugin *> top_plugins = editor_plugins_over->get_plugins_list(); Vector<EditorPlugin *> item_plugins; if (p_object) { item_plugins = editor_data.get_subeditors(p_object); } if (!item_plugins.is_empty()) { - bool same = true; - if (item_plugins.size() == top_plugins.size()) { - for (int i = 0; i < item_plugins.size(); i++) { - if (item_plugins[i] != top_plugins[i]) { - same = false; - } + ObjectID owner_id = p_editing_owner->get_instance_id(); + + for (EditorPlugin *plugin : active_plugins[owner_id]) { + if (!item_plugins.has(plugin)) { + plugin->make_visible(false); + plugin->edit(nullptr); } - } else { - same = false; } - if (!same) { - _display_top_editors(false); - _set_top_editors(item_plugins); + for (EditorPlugin *plugin : item_plugins) { + for (KeyValue<ObjectID, HashSet<EditorPlugin *>> &kv : active_plugins) { + if (kv.key != owner_id) { + EditorPropertyResource *epres = Object::cast_to<EditorPropertyResource>(ObjectDB::get_instance(kv.key)); + if (epres && kv.value.has(plugin)) { + // If it's resource property editing the same resource type, fold it. + epres->fold_resource(); + } + kv.value.erase(plugin); + } + } + active_plugins[owner_id].insert(plugin); + plugin->edit(p_object); + plugin->make_visible(true); } - _set_editing_top_editors(p_object); - _display_top_editors(true); - } else if (!top_plugins.is_empty()) { - hide_top_editors(); + } else { + hide_unused_editors(p_editing_owner); } } -void EditorNode::edit_item_resource(Ref<Resource> p_resource) { - edit_item(p_resource.ptr()); -} - void EditorNode::push_item(Object *p_object, const String &p_property, bool p_inspector_only) { if (!p_object) { InspectorDock::get_inspector_singleton()->edit(nullptr); NodeDock::get_singleton()->set_node(nullptr); SceneTreeDock::get_singleton()->set_selected(nullptr); InspectorDock::get_singleton()->update(nullptr); - _display_top_editors(false); + hide_unused_editors(); return; } @@ -2150,22 +2154,34 @@ void EditorNode::_save_default_environment() { } } -void EditorNode::hide_top_editors() { - _display_top_editors(false); - - editor_plugins_over->clear(); -} - -void EditorNode::_display_top_editors(bool p_display) { - editor_plugins_over->make_visible(p_display); -} - -void EditorNode::_set_top_editors(Vector<EditorPlugin *> p_editor_plugins_over) { - editor_plugins_over->set_plugins_list(p_editor_plugins_over); -} +void EditorNode::hide_unused_editors(const Object *p_editing_owner) { + if (p_editing_owner) { + const ObjectID id = p_editing_owner->get_instance_id(); + for (EditorPlugin *plugin : active_plugins[id]) { + plugin->make_visible(false); + plugin->edit(nullptr); + editor_plugins_over->remove_plugin(plugin); + } + active_plugins.erase(id); + } else { + // If no editing owner is provided, this method will go over all owners and check if they are valid. + // This is to sweep properties that were removed from the inspector. + List<ObjectID> to_remove; + for (KeyValue<ObjectID, HashSet<EditorPlugin *>> &kv : active_plugins) { + if (!ObjectDB::get_instance(kv.key)) { + to_remove.push_back(kv.key); + for (EditorPlugin *plugin : kv.value) { + plugin->make_visible(false); + plugin->edit(nullptr); + editor_plugins_over->remove_plugin(plugin); + } + } + } -void EditorNode::_set_editing_top_editors(Object *p_current_object) { - editor_plugins_over->edit(p_current_object); + for (const ObjectID &id : to_remove) { + active_plugins.erase(id); + } + } } static bool overrides_external_editor(Object *p_object) { @@ -2199,7 +2215,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) { NodeDock::get_singleton()->set_node(nullptr); InspectorDock::get_singleton()->update(nullptr); - _display_top_editors(false); + hide_unused_editors(); return; } @@ -2327,6 +2343,9 @@ void EditorNode::_edit_current(bool p_skip_foreign) { InspectorDock::get_inspector_singleton()->set_use_folding(!disable_folding); } + Object *editor_owner = is_node ? (Object *)SceneTreeDock::get_singleton() : is_resource ? (Object *)InspectorDock::get_inspector_singleton() + : (Object *)this; + // Take care of the main editor plugin. if (!inspector_only) { @@ -2343,6 +2362,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) { } } + ObjectID editor_owner_id = editor_owner->get_instance_id(); if (main_plugin && !skip_main_plugin) { // Special case if use of external editor is true. Resource *current_res = Object::cast_to<Resource>(current_obj); @@ -2353,15 +2373,22 @@ void EditorNode::_edit_current(bool p_skip_foreign) { } else if (main_plugin != editor_plugin_screen && (!ScriptEditor::get_singleton() || !ScriptEditor::get_singleton()->is_visible_in_tree() || ScriptEditor::get_singleton()->can_take_away_focus())) { + // Unedit previous plugin. + editor_plugin_screen->edit(nullptr); + active_plugins[editor_owner_id].erase(editor_plugin_screen); // Update screen main_plugin. editor_select(plugin_index); main_plugin->edit(current_obj); } else { editor_plugin_screen->edit(current_obj); } + is_main_screen_editing = true; + } else if (!main_plugin && editor_plugin_screen && is_main_screen_editing) { + editor_plugin_screen->edit(nullptr); + is_main_screen_editing = false; } - edit_item(current_obj); + edit_item(current_obj, editor_owner); } InspectorDock::get_singleton()->update(current_obj); @@ -3712,11 +3739,12 @@ void EditorNode::set_current_scene(int p_idx) { call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); // Do after everything else is done setting up. } -void EditorNode::setup_color_picker(ColorPicker *picker) { +void EditorNode::setup_color_picker(ColorPicker *p_picker) { + p_picker->set_editor_settings(EditorSettings::get_singleton()); int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode"); int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape"); - picker->set_color_mode((ColorPicker::ColorModeType)default_color_mode); - picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape); + p_picker->set_color_mode((ColorPicker::ColorModeType)default_color_mode); + p_picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape); } bool EditorNode::is_scene_open(const String &p_path) { @@ -6916,7 +6944,7 @@ EditorNode::EditorNode() { _reset_play_buttons(); - ED_SHORTCUT_AND_COMMAND("editor/run_specific_scene", TTR("Run Specific Scene"), KeyModifierMask::META | KeyModifierMask::SHIFT | Key::F5); + ED_SHORTCUT_AND_COMMAND("editor/run_specific_scene", TTR("Run Specific Scene"), KeyModifierMask::CTRL | KeyModifierMask::SHIFT | Key::F5); ED_SHORTCUT_OVERRIDE("editor/run_specific_scene", "macos", KeyModifierMask::META | KeyModifierMask::SHIFT | Key::R); play_custom_scene_button->set_shortcut(ED_GET_SHORTCUT("editor/run_specific_scene")); diff --git a/editor/editor_node.h b/editor/editor_node.h index fb2544c141..ef4ea34da2 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -68,6 +68,7 @@ class EditorLayoutsDialog; class EditorLog; class EditorPluginList; class EditorQuickOpen; +class EditorPropertyResource; class EditorResourcePreview; class EditorResourceConversionPlugin; class EditorRun; @@ -293,6 +294,8 @@ private: bool _initializing_plugins = false; HashMap<String, EditorPlugin *> addon_name_to_plugin; LocalVector<String> pending_addons; + HashMap<ObjectID, HashSet<EditorPlugin *>> active_plugins; + bool is_main_screen_editing = false; PanelContainer *scene_root_parent = nullptr; Control *theme_base = nullptr; @@ -592,10 +595,6 @@ private: void _inherit_request(String p_file); void _instantiate_request(const Vector<String> &p_files); - void _display_top_editors(bool p_display); - void _set_top_editors(Vector<EditorPlugin *> p_editor_plugins_over); - void _set_editing_top_editors(Object *p_current_object); - void _quick_opened(); void _quick_run(); void _open_command_palette(); @@ -796,9 +795,8 @@ public: void show_about() { _menu_option_confirm(HELP_ABOUT, false); } void push_item(Object *p_object, const String &p_property = "", bool p_inspector_only = false); - void edit_item(Object *p_object); - void edit_item_resource(Ref<Resource> p_resource); - void hide_top_editors(); + void edit_item(Object *p_object, Object *p_editing_owner); + void hide_unused_editors(const Object *p_editing_owner = nullptr); void select_editor_by_name(const String &p_name); @@ -824,7 +822,7 @@ public: void set_current_scene(int p_idx); - void setup_color_picker(ColorPicker *picker); + void setup_color_picker(ColorPicker *p_picker); void request_instantiate_scene(const String &p_path); void request_instantiate_scenes(const Vector<String> &p_files); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 46f52ec4af..a69214f903 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -3905,40 +3905,7 @@ void EditorPropertyResource::_open_editor_pressed() { Ref<Resource> res = get_edited_object()->get(get_edited_property()); if (res.is_valid()) { // May clear the editor so do it deferred. - callable_mp(EditorNode::get_singleton(), &EditorNode::edit_item_resource).bind(res).call_deferred(); - } -} - -void EditorPropertyResource::_fold_other_editors(Object *p_self) { - if (this == p_self) { - return; - } - - Ref<Resource> res = get_edited_object()->get(get_edited_property()); - if (!res.is_valid()) { - return; - } - - bool use_editor = false; - for (int i = 0; i < EditorNode::get_editor_data().get_editor_plugin_count(); i++) { - EditorPlugin *ep = EditorNode::get_editor_data().get_editor_plugin(i); - if (ep->handles(res.ptr())) { - use_editor = true; - break; - } - } - if (!use_editor) { - return; - } - - opened_editor = false; - - bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); - if (unfolded) { - // Refold. - resource_picker->set_toggle_pressed(false); - get_edited_object()->editor_set_section_unfold(get_edited_property(), false); - update_property(); + callable_mp(EditorNode::get_singleton(), &EditorNode::edit_item).bind(res.ptr(), this).call_deferred(); } } @@ -4091,20 +4058,17 @@ void EditorPropertyResource::update_property() { sub_inspector_vbox->add_child(sub_inspector); resource_picker->set_toggle_pressed(true); - bool use_editor = false; + Array editor_list; for (int i = 0; i < EditorNode::get_editor_data().get_editor_plugin_count(); i++) { EditorPlugin *ep = EditorNode::get_editor_data().get_editor_plugin(i); if (ep->handles(res.ptr())) { - use_editor = true; + editor_list.push_back(ep); } } - if (use_editor) { - // Open editor directly and hide other such editors which are currently open. + if (!editor_list.is_empty()) { + // Open editor directly. _open_editor_pressed(); - if (is_inside_tree()) { - get_tree()->call_deferred(SNAME("call_group"), "_editor_resource_properties", "_fold_other_editors", this); - } opened_editor = true; } @@ -4123,7 +4087,7 @@ void EditorPropertyResource::update_property() { sub_inspector_vbox = nullptr; if (opened_editor) { - EditorNode::get_singleton()->hide_top_editors(); + EditorNode::get_singleton()->hide_unused_editors(); opened_editor = false; } @@ -4157,6 +4121,15 @@ void EditorPropertyResource::set_use_sub_inspector(bool p_enable) { use_sub_inspector = p_enable; } +void EditorPropertyResource::fold_resource() { + bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); + if (unfolded) { + resource_picker->set_toggle_pressed(false); + get_edited_object()->editor_set_section_unfold(get_edited_property(), false); + update_property(); + } +} + void EditorPropertyResource::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: @@ -4168,14 +4141,8 @@ void EditorPropertyResource::_notification(int p_what) { } } -void EditorPropertyResource::_bind_methods() { - ClassDB::bind_method(D_METHOD("_fold_other_editors"), &EditorPropertyResource::_fold_other_editors); -} - EditorPropertyResource::EditorPropertyResource() { use_sub_inspector = bool(EDITOR_GET("interface/inspector/open_resources_in_current_inspector")); - - add_to_group("_editor_resource_properties"); } ////////////// DEFAULT PLUGIN ////////////////////// diff --git a/editor/editor_properties.h b/editor/editor_properties.h index a255af30ee..ea9203cbf4 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -834,13 +834,11 @@ class EditorPropertyResource : public EditorProperty { void _sub_inspector_object_id_selected(int p_id); void _open_editor_pressed(); - void _fold_other_editors(Object *p_self); void _update_property_bg(); void _update_preferred_shader(); protected: virtual void _set_read_only(bool p_read_only) override; - static void _bind_methods(); void _notification(int p_what); public: @@ -852,6 +850,7 @@ public: void expand_revertable() override; void set_use_sub_inspector(bool p_enable); + void fold_resource(); EditorPropertyResource(); }; diff --git a/editor/editor_quick_open.cpp b/editor/editor_quick_open.cpp index d516610908..b90edb8f90 100644 --- a/editor/editor_quick_open.cpp +++ b/editor/editor_quick_open.cpp @@ -69,17 +69,9 @@ void EditorQuickOpen::_build_search_cache(EditorFileSystemDirectory *p_efsd) { for (int i = 0; i < p_efsd->get_file_count(); i++) { String file = p_efsd->get_file_path(i); String engine_type = p_efsd->get_file_type(i); - // TODO: Fix lack of caching for resource's script's global class name (if applicable). - String script_type; - if (_load_resources) { - Ref<Resource> res = ResourceLoader::load(file); - if (res.is_valid()) { - Ref<Script> scr = res->get_script(); - if (scr.is_valid()) { - script_type = scr->get_language()->get_global_class_name(file); - } - } - } + + String script_type = p_efsd->get_file_resource_script_class(i); + String actual_type = script_type.is_empty() ? engine_type : script_type; // Iterate all possible base types. for (String &parent_type : base_types) { diff --git a/editor/editor_quick_open.h b/editor/editor_quick_open.h index 0503eec835..4b63a226c2 100644 --- a/editor/editor_quick_open.h +++ b/editor/editor_quick_open.h @@ -43,7 +43,6 @@ class EditorQuickOpen : public ConfirmationDialog { Tree *search_options = nullptr; String base_type; bool allow_multi_select = false; - bool _load_resources = false; // Prohibitively slow for now. Vector<String> files; OAHashMap<String, Ref<Texture2D>> icons; diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index a1c913aadd..cb71a2457b 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -42,12 +42,6 @@ #include "editor/plugins/script_editor_plugin.h" #include "editor/scene_tree_dock.h" -HashMap<StringName, List<StringName>> EditorResourcePicker::allowed_types_cache; - -void EditorResourcePicker::clear_caches() { - allowed_types_cache.clear(); -} - void EditorResourcePicker::_update_resource() { String resource_path; if (edited_resource.is_valid() && edited_resource->get_path().is_resource_file()) { @@ -464,7 +458,7 @@ void EditorResourcePicker::set_create_options(Object *p_menu_node) { if (!base_type.is_empty()) { int idx = 0; - HashSet<String> allowed_types; + HashSet<StringName> allowed_types; _get_allowed_types(false, &allowed_types); Vector<EditorData::CustomType> custom_resources; @@ -472,7 +466,7 @@ void EditorResourcePicker::set_create_options(Object *p_menu_node) { custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"]; } - for (const String &E : allowed_types) { + for (const StringName &E : allowed_types) { const String &t = E; bool is_custom_resource = false; @@ -561,53 +555,44 @@ String EditorResourcePicker::_get_resource_type(const Ref<Resource> &p_resource) return res_type; } -void EditorResourcePicker::_get_allowed_types(bool p_with_convert, HashSet<String> *p_vector) const { - Vector<String> allowed_types = base_type.split(","); - int size = allowed_types.size(); +static void _add_allowed_type(const StringName &p_type, HashSet<StringName> *p_vector) { + if (p_vector->has(p_type)) { + // Already added + return; + } - List<StringName> global_classes; - ScriptServer::get_global_class_list(&global_classes); + if (ClassDB::class_exists(p_type)) { + // Engine class, - for (int i = 0; i < size; i++) { - String base = allowed_types[i].strip_edges(); - if (!ClassDB::is_virtual(base)) { - p_vector->insert(base); + if (!ClassDB::is_virtual(p_type)) { + p_vector->insert(p_type); } - // If we hit a familiar base type, take all the data from cache. - if (allowed_types_cache.has(base)) { - List<StringName> allowed_subtypes = allowed_types_cache[base]; - for (const StringName &subtype_name : allowed_subtypes) { - if (!ClassDB::is_virtual(subtype_name)) { - p_vector->insert(subtype_name); - } - } - } else { - List<StringName> allowed_subtypes; + List<StringName> inheriters; + ClassDB::get_inheriters_from_class(p_type, &inheriters); + for (const StringName &S : inheriters) { + _add_allowed_type(S, p_vector); + } + } else { + // Script class. + p_vector->insert(p_type); + } - List<StringName> inheriters; - if (!ScriptServer::is_global_class(base)) { - ClassDB::get_inheriters_from_class(base, &inheriters); - } - for (const StringName &subtype_name : inheriters) { - if (!ClassDB::is_virtual(subtype_name)) { - p_vector->insert(subtype_name); - } - allowed_subtypes.push_back(subtype_name); - } + List<StringName> inheriters; + ScriptServer::get_inheriters_list(p_type, &inheriters); + for (const StringName &S : inheriters) { + _add_allowed_type(S, p_vector); + } +} - for (const StringName &subtype_name : global_classes) { - if (EditorNode::get_editor_data().script_class_is_parent(subtype_name, base)) { - if (!ClassDB::is_virtual(subtype_name)) { - p_vector->insert(subtype_name); - } - allowed_subtypes.push_back(subtype_name); - } - } +void EditorResourcePicker::_get_allowed_types(bool p_with_convert, HashSet<StringName> *p_vector) const { + Vector<String> allowed_types = base_type.split(","); + int size = allowed_types.size(); - // Store the subtypes of the base type in the cache for future use. - allowed_types_cache[base] = allowed_subtypes; - } + for (int i = 0; i < size; i++) { + String base = allowed_types[i].strip_edges(); + + _add_allowed_type(base, p_vector); if (p_with_convert) { if (base == "BaseMaterial3D") { @@ -619,14 +604,6 @@ void EditorResourcePicker::_get_allowed_types(bool p_with_convert, HashSet<Strin } } } - - if (EditorNode::get_editor_data().get_custom_types().has("Resource")) { - Vector<EditorData::CustomType> custom_resources = EditorNode::get_editor_data().get_custom_types()["Resource"]; - - for (int i = 0; i < custom_resources.size(); i++) { - p_vector->insert(custom_resources[i].name); - } - } } bool EditorResourcePicker::_is_drop_valid(const Dictionary &p_drag_data) const { @@ -654,7 +631,7 @@ bool EditorResourcePicker::_is_drop_valid(const Dictionary &p_drag_data) const { } } - HashSet<String> allowed_types; + HashSet<StringName> allowed_types; _get_allowed_types(true, &allowed_types); if (res.is_valid()) { @@ -673,9 +650,9 @@ bool EditorResourcePicker::_is_drop_valid(const Dictionary &p_drag_data) const { return false; } -bool EditorResourcePicker::_is_type_valid(const String p_type_name, HashSet<String> p_allowed_types) const { - for (const String &E : p_allowed_types) { - String at = E.strip_edges(); +bool EditorResourcePicker::_is_type_valid(const String p_type_name, HashSet<StringName> p_allowed_types) const { + for (const StringName &E : p_allowed_types) { + String at = E; if (p_type_name == at || ClassDB::is_parent_class(p_type_name, at) || EditorNode::get_editor_data().script_class_is_parent(p_type_name, at)) { return true; } @@ -721,15 +698,15 @@ void EditorResourcePicker::drop_data_fw(const Point2 &p_point, const Variant &p_ } if (dropped_resource.is_valid()) { - HashSet<String> allowed_types; + HashSet<StringName> allowed_types; _get_allowed_types(false, &allowed_types); String res_type = _get_resource_type(dropped_resource); // If the accepted dropped resource is from the extended list, it requires conversion. if (!_is_type_valid(res_type, allowed_types)) { - for (const String &E : allowed_types) { - String at = E.strip_edges(); + for (const StringName &E : allowed_types) { + String at = E; if (at == "BaseMaterial3D" && Ref<Texture2D>(dropped_resource).is_valid()) { // Use existing resource if possible and only replace its data. @@ -832,7 +809,7 @@ void EditorResourcePicker::set_base_type(const String &p_base_type) { // There is a possibility that the new base type is conflicting with the existing value. // Keep the value, but warn the user that there is a potential mistake. if (!base_type.is_empty() && edited_resource.is_valid()) { - HashSet<String> allowed_types; + HashSet<StringName> allowed_types; _get_allowed_types(true, &allowed_types); StringName custom_class; @@ -846,10 +823,6 @@ void EditorResourcePicker::set_base_type(const String &p_base_type) { String class_str = (custom_class == StringName() ? edited_resource->get_class() : vformat("%s (%s)", custom_class, edited_resource->get_class())); WARN_PRINT(vformat("Value mismatch between the new base type of this EditorResourcePicker, '%s', and the type of the value it already has, '%s'.", base_type, class_str)); } - } else { - // Call the method to build the cache immediately. - HashSet<String> allowed_types; - _get_allowed_types(false, &allowed_types); } } @@ -858,7 +831,7 @@ String EditorResourcePicker::get_base_type() const { } Vector<String> EditorResourcePicker::get_allowed_types() const { - HashSet<String> allowed_types; + HashSet<StringName> allowed_types; _get_allowed_types(false, &allowed_types); Vector<String> types; @@ -866,7 +839,7 @@ Vector<String> EditorResourcePicker::get_allowed_types() const { int i = 0; String *w = types.ptrw(); - for (const String &E : allowed_types) { + for (const StringName &E : allowed_types) { w[i] = E; i++; } @@ -882,7 +855,7 @@ void EditorResourcePicker::set_edited_resource(Ref<Resource> p_resource) { } if (!base_type.is_empty()) { - HashSet<String> allowed_types; + HashSet<StringName> allowed_types; _get_allowed_types(true, &allowed_types); StringName custom_class; diff --git a/editor/editor_resource_picker.h b/editor/editor_resource_picker.h index 8641cb6e84..a302e24957 100644 --- a/editor/editor_resource_picker.h +++ b/editor/editor_resource_picker.h @@ -42,8 +42,6 @@ class EditorQuickOpen; class EditorResourcePicker : public HBoxContainer { GDCLASS(EditorResourcePicker, HBoxContainer); - static HashMap<StringName, List<StringName>> allowed_types_cache; - String base_type; Ref<Resource> edited_resource; @@ -92,9 +90,9 @@ class EditorResourcePicker : public HBoxContainer { void _button_input(const Ref<InputEvent> &p_event); String _get_resource_type(const Ref<Resource> &p_resource) const; - void _get_allowed_types(bool p_with_convert, HashSet<String> *p_vector) const; + void _get_allowed_types(bool p_with_convert, HashSet<StringName> *p_vector) const; bool _is_drop_valid(const Dictionary &p_drag_data) const; - bool _is_type_valid(const String p_type_name, HashSet<String> p_allowed_types) const; + bool _is_type_valid(const String p_type_name, HashSet<StringName> p_allowed_types) const; 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; @@ -118,8 +116,6 @@ protected: GDVIRTUAL1R(bool, _handle_menu_selected, int) public: - static void clear_caches(); - void set_base_type(const String &p_base_type); String get_base_type() const; Vector<String> get_allowed_types() const; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 8ca98e6f76..4879790b74 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -473,6 +473,12 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { /* Filesystem */ + // External Programs + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/external_programs/raster_image_editor", "", "") + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/external_programs/vector_image_editor", "", "") + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/external_programs/audio_editor", "", "") + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/external_programs/3d_model_editor", "", "") + // Directories EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/directories/autoscan_project_path", "", "") const String fs_dir_default_project_path = OS::get_singleton()->has_environment("HOME") ? OS::get_singleton()->get_environment("HOME") : OS::get_singleton()->get_system_dir(OS::SYSTEM_DIR_DOCUMENTS); diff --git a/editor/editor_toaster.cpp b/editor/editor_toaster.cpp index 558423df78..43f2c4e74e 100644 --- a/editor/editor_toaster.cpp +++ b/editor/editor_toaster.cpp @@ -230,10 +230,10 @@ void EditorToaster::_auto_hide_or_free_toasts() { } // Delete the control right away (removed as child) as it might cause issues otherwise when iterative over the vbox_container children. - for (unsigned int i = 0; i < to_delete.size(); i++) { - vbox_container->remove_child(to_delete[i]); - to_delete[i]->queue_free(); - toasts.erase(to_delete[i]); + for (Control *c : to_delete) { + vbox_container->remove_child(c); + c->queue_free(); + toasts.erase(c); } if (toasts.is_empty()) { diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index cacd181ad8..8da52e20f7 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -503,8 +503,8 @@ bool EditorExportPlatform::_export_customize_dictionary(Dictionary &dict, LocalV case Variant::OBJECT: { Ref<Resource> res = v; if (res.is_valid()) { - for (uint32_t j = 0; j < customize_resources_plugins.size(); j++) { - Ref<Resource> new_res = customize_resources_plugins[j]->_customize_resource(res, ""); + for (Ref<EditorExportPlugin> &plugin : customize_resources_plugins) { + Ref<Resource> new_res = plugin->_customize_resource(res, ""); if (new_res.is_valid()) { changed = true; if (new_res != res) { @@ -550,8 +550,8 @@ bool EditorExportPlatform::_export_customize_array(Array &arr, LocalVector<Ref<E case Variant::OBJECT: { Ref<Resource> res = v; if (res.is_valid()) { - for (uint32_t j = 0; j < customize_resources_plugins.size(); j++) { - Ref<Resource> new_res = customize_resources_plugins[j]->_customize_resource(res, ""); + for (Ref<EditorExportPlugin> &plugin : customize_resources_plugins) { + Ref<Resource> new_res = plugin->_customize_resource(res, ""); if (new_res.is_valid()) { changed = true; if (new_res != res) { @@ -597,8 +597,8 @@ bool EditorExportPlatform::_export_customize_object(Object *p_object, LocalVecto case Variant::OBJECT: { Ref<Resource> res = p_object->get(E.name); if (res.is_valid()) { - for (uint32_t j = 0; j < customize_resources_plugins.size(); j++) { - Ref<Resource> new_res = customize_resources_plugins[j]->_customize_resource(res, ""); + for (Ref<EditorExportPlugin> &plugin : customize_resources_plugins) { + Ref<Resource> new_res = plugin->_customize_resource(res, ""); if (new_res.is_valid()) { changed = true; if (new_res != res) { @@ -715,16 +715,16 @@ String EditorExportPlatform::_export_customize(const String &p_path, LocalVector ERR_FAIL_COND_V(ps.is_null(), p_path); Node *node = ps->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE); // Make sure the child scene root gets the correct inheritance chain. ERR_FAIL_COND_V(node == nullptr, p_path); - if (customize_scenes_plugins.size()) { - for (uint32_t i = 0; i < customize_scenes_plugins.size(); i++) { - Node *customized = customize_scenes_plugins[i]->_customize_scene(node, p_path); + if (!customize_scenes_plugins.is_empty()) { + for (Ref<EditorExportPlugin> &plugin : customize_scenes_plugins) { + Node *customized = plugin->_customize_scene(node, p_path); if (customized != nullptr) { node = customized; modified = true; } } } - if (customize_resources_plugins.size()) { + if (!customize_resources_plugins.is_empty()) { if (_export_customize_scene_resources(node, node, customize_resources_plugins)) { modified = true; } @@ -746,9 +746,9 @@ String EditorExportPlatform::_export_customize(const String &p_path, LocalVector Ref<Resource> res = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_IGNORE); ERR_FAIL_COND_V(res.is_null(), p_path); - if (customize_resources_plugins.size()) { - for (uint32_t i = 0; i < customize_resources_plugins.size(); i++) { - Ref<Resource> new_res = customize_resources_plugins[i]->_customize_resource(res, p_path); + if (!customize_resources_plugins.is_empty()) { + for (Ref<EditorExportPlugin> &plugin : customize_resources_plugins) { + Ref<Resource> new_res = plugin->_customize_resource(res, p_path); if (new_res.is_valid()) { modified = true; if (new_res != res) { @@ -960,7 +960,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & bool convert_text_to_binary = GLOBAL_GET("editor/export/convert_text_resources_to_binary"); - if (convert_text_to_binary || customize_resources_plugins.size() || customize_scenes_plugins.size()) { + if (convert_text_to_binary || !customize_resources_plugins.is_empty() || !customize_scenes_plugins.is_empty()) { // See if we have something to open Ref<FileAccess> f = FileAccess::open(export_base_path.path_join("file_cache"), FileAccess::READ); if (f.is_valid()) { @@ -1179,7 +1179,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & idx++; } - if (convert_text_to_binary || customize_resources_plugins.size() || customize_scenes_plugins.size()) { + if (convert_text_to_binary || !customize_resources_plugins.is_empty() || !customize_scenes_plugins.is_empty()) { // End scene customization String fcache = export_base_path.path_join("file_cache"); @@ -1196,12 +1196,12 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & ERR_PRINT("Error opening export file cache: " + fcache); } - for (uint32_t i = 0; i < customize_resources_plugins.size(); i++) { - customize_resources_plugins[i]->_end_customize_resources(); + for (Ref<EditorExportPlugin> &plugin : customize_resources_plugins) { + plugin->_end_customize_resources(); } - for (uint32_t i = 0; i < customize_scenes_plugins.size(); i++) { - customize_scenes_plugins[i]->_end_customize_scenes(); + for (Ref<EditorExportPlugin> &plugin : customize_scenes_plugins) { + plugin->_end_customize_scenes(); } } //save config! diff --git a/editor/export/editor_export_plugin.cpp b/editor/export/editor_export_plugin.cpp index 784dbc116a..dfd4520eec 100644 --- a/editor/export/editor_export_plugin.cpp +++ b/editor/export/editor_export_plugin.cpp @@ -227,8 +227,6 @@ void EditorExportPlugin::_bind_methods() { } EditorExportPlugin::EditorExportPlugin() { - GLOBAL_DEF("editor/export/convert_text_resources_to_binary", false); - EDITOR_DEF("export/ssh/ssh", ""); EDITOR_DEF("export/ssh/scp", ""); } diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index f1ea8e8e65..f41792af7f 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1819,6 +1819,43 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected OS::get_singleton()->shell_open(String("file://") + dir); } break; + case FILE_OPEN_EXTERNAL: { + String fpath = path; + if (path == "Favorites") { + fpath = p_selected[0]; + } + + String file = ProjectSettings::get_singleton()->globalize_path(fpath); + + String resource_type = ResourceLoader::get_resource_type(fpath); + String external_program; + + if (resource_type == "CompressedTexture2D" || resource_type == "Image") { + if (file.get_extension() == "svg" || file.get_extension() == "svgz") { + external_program = EDITOR_GET("filesystem/external_programs/vector_image_editor"); + } else { + external_program = EDITOR_GET("filesystem/external_programs/raster_image_editor"); + } + } else if (ClassDB::is_parent_class(resource_type, "AudioStream")) { + external_program = EDITOR_GET("filesystem/external_programs/audio_editor"); + } else if (resource_type == "PackedScene") { + // Ignore non-model scenes. + if (file.get_extension() != "tscn" && file.get_extension() != "scn" && file.get_extension() != "res") { + external_program = EDITOR_GET("filesystem/external_programs/3d_model_editor"); + } + } else if (ClassDB::is_parent_class(resource_type, "Script")) { + external_program = EDITOR_GET("text_editor/external/exec_path"); + } + + if (external_program.is_empty()) { + OS::get_singleton()->shell_open(file); + } else { + List<String> args; + args.push_back(file); + OS::get_singleton()->create_process(external_program, args); + } + } break; + case FILE_OPEN: { // Open folders. TreeItem *selected = tree->get_root(); @@ -2606,9 +2643,13 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str } String fpath = p_paths[0]; - String item_text = fpath.ends_with("/") ? TTR("Open in File Manager") : TTR("Show in File Manager"); + bool is_directory = fpath.ends_with("/"); + String item_text = is_directory ? TTR("Open in File Manager") : TTR("Show in File Manager"); p_popup->add_icon_shortcut(get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), ED_GET_SHORTCUT("filesystem_dock/show_in_explorer"), FILE_SHOW_IN_EXPLORER); p_popup->set_item_text(p_popup->get_item_index(FILE_SHOW_IN_EXPLORER), item_text); + if (!is_directory) { + p_popup->add_icon_item(get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), TTR("Open in External Program"), FILE_OPEN_EXTERNAL); + } path = fpath; } } @@ -2714,6 +2755,7 @@ void FileSystemDock::_file_list_empty_clicked(const Vector2 &p_pos, MouseButton file_list_popup->add_icon_item(get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")), TTR("New TextFile..."), FILE_NEW_TEXTFILE); file_list_popup->add_separator(); file_list_popup->add_icon_shortcut(get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), ED_GET_SHORTCUT("filesystem_dock/show_in_explorer"), FILE_SHOW_IN_EXPLORER); + file_list_popup->set_position(files->get_screen_position() + p_pos); file_list_popup->reset_size(); file_list_popup->popup(); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 2304d8f8ad..3f12b73043 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -94,6 +94,7 @@ private: FILE_NEW_SCRIPT, FILE_NEW_SCENE, FILE_SHOW_IN_EXPLORER, + FILE_OPEN_EXTERNAL, FILE_COPY_PATH, FILE_COPY_UID, FILE_NEW_RESOURCE, diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index b28373e308..52482ecb16 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -189,8 +189,7 @@ void InspectorDock::_menu_option_confirm(int p_option, bool p_confirmed) { int history_id = EditorUndoRedoManager::get_singleton()->get_history_for_object(current).id; EditorUndoRedoManager::get_singleton()->clear_history(true, history_id); - EditorNode::get_singleton()->get_editor_plugins_over()->edit(nullptr); - EditorNode::get_singleton()->get_editor_plugins_over()->edit(current); + EditorNode::get_singleton()->edit_item(current, inspector); } } break; diff --git a/editor/multi_node_edit.cpp b/editor/multi_node_edit.cpp index 2a55ac949f..4f0db70681 100644 --- a/editor/multi_node_edit.cpp +++ b/editor/multi_node_edit.cpp @@ -48,6 +48,8 @@ bool MultiNodeEdit::_set_impl(const StringName &p_name, const Variant &p_value, if (name == "scripts") { // Script set is intercepted at object level (check Variant Object::get()), so use a different name. name = "script"; + } else if (name.begins_with("Metadata/")) { + name = name.replace_first("Metadata/", "metadata/"); } Node *node_path_target = nullptr; @@ -98,6 +100,8 @@ 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. name = "script"; + } else if (name.begins_with("Metadata/")) { + name = name.replace_first("Metadata/", "metadata/"); } for (const NodePath &E : nodes) { @@ -137,14 +141,18 @@ void MultiNodeEdit::_get_property_list(List<PropertyInfo> *p_list) const { List<PropertyInfo> plist; n->get_property_list(&plist, true); - for (const PropertyInfo &F : plist) { + for (PropertyInfo F : plist) { if (F.name == "script") { continue; // Added later manually, since this is intercepted before being set (check Variant Object::get()). + } else if (F.name.begins_with("metadata/")) { + F.name = F.name.replace_first("metadata/", "Metadata/"); // Trick to not get actual metadata edited from MultiNodeEdit. } + if (!usage.has(F.name)) { PLData pld; pld.uses = 0; pld.info = F; + pld.info.name = F.name; usage[F.name] = pld; data_list.push_back(usage.getptr(F.name)); } diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index a675495429..c0972d201e 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -1237,7 +1237,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() { if (playback.is_valid()) { playing = playback->is_playing(); current = playback->get_current_node(); - blend_from = playback->get_blend_from_node(); + blend_from = playback->get_fading_from_node(); travel_path = playback->get_travel_path(); } @@ -1695,7 +1695,7 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) { tp = playback->get_travel_path(); is_playing = playback->is_playing(); current_node = playback->get_current_node(); - blend_from_node = playback->get_blend_from_node(); + blend_from_node = playback->get_fading_from_node(); play_pos = playback->get_current_play_pos(); current_length = playback->get_current_length(); } diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp index c913a9b0ab..3d94dd13a7 100644 --- a/editor/plugins/bone_map_editor_plugin.cpp +++ b/editor/plugins/bone_map_editor_plugin.cpp @@ -566,9 +566,9 @@ int BoneMapper::search_bone_by_name(Skeleton3D *p_skeleton, Vector<String> p_pic if (hit_list.size() > 0) { shortest = hit_list[0]; - for (uint32_t i = 0; i < hit_list.size(); i++) { - if (hit_list[i].length() < shortest.length()) { - shortest = hit_list[i]; // Prioritize parent. + for (const String &hit : hit_list) { + if (hit.length() < shortest.length()) { + shortest = hit; // Prioritize parent. } } } @@ -592,9 +592,9 @@ int BoneMapper::search_bone_by_name(Skeleton3D *p_skeleton, Vector<String> p_pic if (hit_list.size() > 0) { shortest = hit_list[0]; - for (uint32_t i = 0; i < hit_list.size(); i++) { - if (hit_list[i].length() <= shortest.length()) { - shortest = hit_list[i]; // Prioritize parent. + for (const String &hit : hit_list) { + if (hit.length() <= shortest.length()) { + shortest = hit; // Prioritize parent. } } } diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index dea07ab50c..f1b7ed73b8 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2208,11 +2208,6 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (ED_IS_SHORTCUT("spatial_editor/focus_selection", p_event)) { _menu_option(VIEW_CENTER_TO_SELECTION); } - // Orthgonal mode doesn't work in freelook. - if (!freelook_active && ED_IS_SHORTCUT("spatial_editor/switch_perspective_orthogonal", p_event)) { - _menu_option(orthogonal ? VIEW_PERSPECTIVE : VIEW_ORTHOGONAL); - _update_name(); - } if (ED_IS_SHORTCUT("spatial_editor/align_transform_with_view", p_event)) { _menu_option(VIEW_ALIGN_TRANSFORM_WITH_VIEW); } @@ -3279,6 +3274,10 @@ void Node3DEditorViewport::_menu_option(int p_option) { _update_name(); } break; + case VIEW_SWITCH_PERSPECTIVE_ORTHOGONAL: { + _menu_option(orthogonal ? VIEW_PERSPECTIVE : VIEW_ORTHOGONAL); + + } break; case VIEW_AUTO_ORTHOGONAL: { int idx = view_menu->get_popup()->get_item_index(VIEW_AUTO_ORTHOGONAL); bool current = view_menu->get_popup()->is_item_checked(idx); @@ -4952,8 +4951,9 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/front_view"), VIEW_FRONT); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/rear_view"), VIEW_REAR); view_menu->get_popup()->add_separator(); - view_menu->get_popup()->add_radio_check_item(TTR("Perspective") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_PERSPECTIVE); - view_menu->get_popup()->add_radio_check_item(TTR("Orthogonal") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_ORTHOGONAL); + view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal"), VIEW_SWITCH_PERSPECTIVE_ORTHOGONAL); + view_menu->get_popup()->add_radio_check_item(TTR("Perspective"), VIEW_PERSPECTIVE); + view_menu->get_popup()->add_radio_check_item(TTR("Orthogonal"), VIEW_ORTHOGONAL); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE), true); view_menu->get_popup()->add_check_item(TTR("Auto Orthogonal Enabled"), VIEW_AUTO_ORTHOGONAL); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUTO_ORTHOGONAL), true); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index edc09f115a..a1fd9757d0 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -117,6 +117,7 @@ class Node3DEditorViewport : public Control { VIEW_PERSPECTIVE, VIEW_ENVIRONMENT, VIEW_ORTHOGONAL, + VIEW_SWITCH_PERSPECTIVE_ORTHOGONAL, VIEW_HALF_RESOLUTION, VIEW_AUDIO_LISTENER, VIEW_AUDIO_DOPPLER, diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 87d602ccf1..907bc81674 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -43,10 +43,10 @@ void ShaderEditorPlugin::_update_shader_list() { shader_list->clear(); - for (uint32_t i = 0; i < edited_shaders.size(); i++) { - Ref<Resource> shader = edited_shaders[i].shader; + for (EditedShader &edited_shader : edited_shaders) { + Ref<Resource> shader = edited_shader.shader; if (shader.is_null()) { - shader = edited_shaders[i].shader_inc; + shader = edited_shader.shader_inc; } String path = shader->get_path(); @@ -62,8 +62,8 @@ void ShaderEditorPlugin::_update_shader_list() { } bool unsaved = false; - if (edited_shaders[i].shader_editor) { - unsaved = edited_shaders[i].shader_editor->is_unsaved(); + if (edited_shader.shader_editor) { + unsaved = edited_shader.shader_editor->is_unsaved(); } // TODO: Handle visual shaders too. @@ -86,7 +86,7 @@ void ShaderEditorPlugin::_update_shader_list() { } for (int i = FILE_SAVE; i < FILE_MAX; i++) { - file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(i), edited_shaders.size() == 0); + file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(i), edited_shaders.is_empty()); } _update_shader_list_status(); @@ -117,6 +117,10 @@ void ShaderEditorPlugin::_move_shader_tab(int p_from, int p_to) { } void ShaderEditorPlugin::edit(Object *p_object) { + if (!p_object) { + return; + } + EditedShader es; ShaderInclude *si = Object::cast_to<ShaderInclude>(p_object); @@ -175,36 +179,36 @@ void ShaderEditorPlugin::selected_notify() { } TextShaderEditor *ShaderEditorPlugin::get_shader_editor(const Ref<Shader> &p_for_shader) { - for (uint32_t i = 0; i < edited_shaders.size(); i++) { - if (edited_shaders[i].shader == p_for_shader) { - return edited_shaders[i].shader_editor; + for (EditedShader &edited_shader : edited_shaders) { + if (edited_shader.shader == p_for_shader) { + return edited_shader.shader_editor; } } return nullptr; } VisualShaderEditor *ShaderEditorPlugin::get_visual_shader_editor(const Ref<Shader> &p_for_shader) { - for (uint32_t i = 0; i < edited_shaders.size(); i++) { - if (edited_shaders[i].shader == p_for_shader) { - return edited_shaders[i].visual_shader_editor; + for (EditedShader &edited_shader : edited_shaders) { + if (edited_shader.shader == p_for_shader) { + return edited_shader.visual_shader_editor; } } return nullptr; } void ShaderEditorPlugin::save_external_data() { - for (uint32_t i = 0; i < edited_shaders.size(); i++) { - if (edited_shaders[i].shader_editor) { - edited_shaders[i].shader_editor->save_external_data(); + for (EditedShader &edited_shader : edited_shaders) { + if (edited_shader.shader_editor) { + edited_shader.shader_editor->save_external_data(); } } _update_shader_list(); } void ShaderEditorPlugin::apply_changes() { - for (uint32_t i = 0; i < edited_shaders.size(); i++) { - if (edited_shaders[i].shader_editor) { - edited_shaders[i].shader_editor->apply_shaders(); + for (EditedShader &edited_shader : edited_shaders) { + if (edited_shader.shader_editor) { + edited_shader.shader_editor->apply_shaders(); } } } @@ -234,8 +238,8 @@ void ShaderEditorPlugin::_close_shader(int p_index) { void ShaderEditorPlugin::_resource_saved(Object *obj) { // May have been renamed on save. - for (uint32_t i = 0; i < edited_shaders.size(); i++) { - if (edited_shaders[i].shader.ptr() == obj) { + for (EditedShader &edited_shader : edited_shaders) { + if (edited_shader.shader.ptr() == obj) { _update_shader_list(); return; } diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index 81aa9bf272..1a4223e9e6 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -169,8 +169,7 @@ void GenericTilePolygonEditor::_base_control_draw() { } // Draw the polygons. - for (unsigned int i = 0; i < polygons.size(); i++) { - const Vector<Vector2> &polygon = polygons[i]; + for (const Vector<Vector2> &polygon : polygons) { Color color = polygon_color; if (!in_creation_polygon.is_empty()) { color = color.darkened(0.3); @@ -285,8 +284,8 @@ void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) { undo_redo->add_do_method(base_control, "queue_redraw"); undo_redo->add_do_method(this, "emit_signal", "polygons_changed"); undo_redo->add_undo_method(this, "clear_polygons"); - for (unsigned int i = 0; i < polygons.size(); i++) { - undo_redo->add_undo_method(this, "add_polygon", polygons[i]); + for (const PackedVector2Array &poly : polygons) { + undo_redo->add_undo_method(this, "add_polygon", poly); } undo_redo->add_undo_method(base_control, "queue_redraw"); undo_redo->add_undo_method(this, "emit_signal", "polygons_changed"); @@ -298,8 +297,8 @@ void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) { undo_redo->add_do_method(base_control, "queue_redraw"); undo_redo->add_do_method(this, "emit_signal", "polygons_changed"); undo_redo->add_undo_method(this, "clear_polygons"); - for (unsigned int i = 0; i < polygons.size(); i++) { - undo_redo->add_undo_method(this, "add_polygon", polygons[i]); + for (const PackedVector2Array &polygon : polygons) { + undo_redo->add_undo_method(this, "add_polygon", polygon); } undo_redo->add_undo_method(base_control, "queue_redraw"); undo_redo->add_undo_method(this, "emit_signal", "polygons_changed"); @@ -327,8 +326,8 @@ void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) { } for (unsigned int i = 0; i < polygons.size(); i++) { Vector<Point2> new_polygon; - for (int point_index = 0; point_index < polygons[i].size(); point_index++) { - Vector2 point = polygons[i][point_index]; + for (const Vector2 &vec : polygons[i]) { + Vector2 point = vec; switch (p_item_pressed) { case ROTATE_RIGHT: { point = Vector2(-point.y, point.x); @@ -351,8 +350,8 @@ void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) { } undo_redo->add_do_method(base_control, "queue_redraw"); undo_redo->add_do_method(this, "emit_signal", "polygons_changed"); - for (unsigned int i = 0; i < polygons.size(); i++) { - undo_redo->add_undo_method(this, "set_polygon", polygons[i]); + for (const PackedVector2Array &polygon : polygons) { + undo_redo->add_undo_method(this, "set_polygon", polygon); } undo_redo->add_undo_method(base_control, "queue_redraw"); undo_redo->add_undo_method(this, "emit_signal", "polygons_changed"); diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index 885d41b8da..2394130ad6 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -922,7 +922,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Get the tile modulation. Color modulate = tile_data->get_modulate(); - Color self_modulate = tile_map->get_self_modulate(); + Color self_modulate = tile_map->get_modulate_in_tree() * tile_map->get_self_modulate(); modulate *= self_modulate; modulate *= tile_map->get_layer_modulate(tile_map_layer); @@ -3088,8 +3088,8 @@ void TileMapEditorTerrainsPlugin::_update_terrains_cache() { per_terrain_terrains_patterns.resize(tile_set->get_terrain_sets_count()); for (int i = 0; i < tile_set->get_terrain_sets_count(); i++) { per_terrain_terrains_patterns[i].resize(tile_set->get_terrains_count(i)); - for (int j = 0; j < (int)per_terrain_terrains_patterns[i].size(); j++) { - per_terrain_terrains_patterns[i][j].clear(); + for (RBSet<TileSet::TerrainsPattern> &pattern : per_terrain_terrains_patterns[i]) { + pattern.clear(); } } @@ -3519,8 +3519,8 @@ void TileMapEditor::_update_bottom_panel() { // Update the visibility of controls. missing_tileset_label->set_visible(!tile_set.is_valid()); - for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) { - tabs_data[tab_index].panel->hide(); + for (TileMapEditorPlugin::TabData &tab_data : tabs_data) { + tab_data.panel->hide(); } if (tile_set.is_valid()) { tabs_data[tabs_bar->get_current_tab()].panel->show(); @@ -3609,15 +3609,15 @@ void TileMapEditor::_tab_changed(int p_tab_id) { tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer); // Update toolbar. - for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) { - tabs_data[tab_index].toolbar->hide(); + for (TileMapEditorPlugin::TabData &tab_data : tabs_data) { + tab_data.toolbar->hide(); } tabs_data[p_tab_id].toolbar->show(); // Update visible panel. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); - for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) { - tabs_data[tab_index].panel->hide(); + for (TileMapEditorPlugin::TabData &tab_data : tabs_data) { + tab_data.panel->hide(); } if (tile_map && tile_map->get_tileset().is_valid()) { tabs_data[tabs_bar->get_current_tab()].panel->show(); @@ -3994,10 +3994,10 @@ TileMapEditor::TileMapEditor() { tile_map_toolbar->add_child(tabs_bar); // Tabs toolbars. - for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) { - tabs_data[tab_index].toolbar->hide(); - if (!tabs_data[tab_index].toolbar->get_parent()) { - tile_map_toolbar->add_child(tabs_data[tab_index].toolbar); + for (TileMapEditorPlugin::TabData &tab_data : tabs_data) { + tab_data.toolbar->hide(); + if (!tab_data.toolbar->get_parent()) { + tile_map_toolbar->add_child(tab_data.toolbar); } } diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index b5dca26c63..5f61d10f9d 100644 --- a/editor/project_converter_3_to_4.cpp +++ b/editor/project_converter_3_to_4.cpp @@ -1977,8 +1977,8 @@ public: } } ~RegExContainer() { - for (unsigned int i = 0; i < color_regexes.size(); i++) { - memdelete(color_regexes[i]); + for (RegEx *regex : color_regexes) { + memdelete(regex); } for (unsigned int i = 0; i < class_tscn_regexes.size(); i++) { memdelete(class_tscn_regexes[i]); @@ -1986,38 +1986,38 @@ public: memdelete(class_shader_regexes[i]); memdelete(class_regexes[i]); } - for (unsigned int i = 0; i < enum_regexes.size(); i++) { - memdelete(enum_regexes[i]); + for (RegEx *regex : enum_regexes) { + memdelete(regex); } - for (unsigned int i = 0; i < gdscript_function_regexes.size(); i++) { - memdelete(gdscript_function_regexes[i]); + for (RegEx *regex : gdscript_function_regexes) { + memdelete(regex); } - for (unsigned int i = 0; i < project_settings_regexes.size(); i++) { - memdelete(project_settings_regexes[i]); + for (RegEx *regex : project_settings_regexes) { + memdelete(regex); } - for (unsigned int i = 0; i < input_map_regexes.size(); i++) { - memdelete(input_map_regexes[i]); + for (RegEx *regex : input_map_regexes) { + memdelete(regex); } - for (unsigned int i = 0; i < gdscript_properties_regexes.size(); i++) { - memdelete(gdscript_properties_regexes[i]); + for (RegEx *regex : gdscript_properties_regexes) { + memdelete(regex); } - for (unsigned int i = 0; i < gdscript_signals_regexes.size(); i++) { - memdelete(gdscript_signals_regexes[i]); + for (RegEx *regex : gdscript_signals_regexes) { + memdelete(regex); } - for (unsigned int i = 0; i < shaders_regexes.size(); i++) { - memdelete(shaders_regexes[i]); + for (RegEx *regex : shaders_regexes) { + memdelete(regex); } - for (unsigned int i = 0; i < builtin_types_regexes.size(); i++) { - memdelete(builtin_types_regexes[i]); + for (RegEx *regex : builtin_types_regexes) { + memdelete(regex); } - for (unsigned int i = 0; i < csharp_function_regexes.size(); i++) { - memdelete(csharp_function_regexes[i]); + for (RegEx *regex : csharp_function_regexes) { + memdelete(regex); } - for (unsigned int i = 0; i < csharp_properties_regexes.size(); i++) { - memdelete(csharp_properties_regexes[i]); + for (RegEx *regex : csharp_properties_regexes) { + memdelete(regex); } - for (unsigned int i = 0; i < csharp_signal_regexes.size(); i++) { - memdelete(csharp_signal_regexes[i]); + for (RegEx *regex : csharp_signal_regexes) { + memdelete(regex); } } }; diff --git a/editor/register_editor_types.cpp b/editor/register_editor_types.cpp index 5f6b5aa42f..061baaff7e 100644 --- a/editor/register_editor_types.cpp +++ b/editor/register_editor_types.cpp @@ -219,6 +219,4 @@ void unregister_editor_types() { if (EditorPaths::get_singleton()) { EditorPaths::free(); } - - EditorResourcePicker::clear_caches(); } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 733f140a56..c1dd9e2f6a 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1428,6 +1428,9 @@ void SceneTreeDock::_script_open_request(const Ref<Script> &p_script) { void SceneTreeDock::_push_item(Object *p_object) { EditorNode::get_singleton()->push_item(p_object); + if (p_object == nullptr) { + EditorNode::get_singleton()->hide_unused_editors(this); + } } void SceneTreeDock::_handle_select(Node *p_node) { @@ -2061,7 +2064,7 @@ void SceneTreeDock::_delete_confirm(bool p_cut) { return; } - EditorNode::get_singleton()->get_editor_plugins_over()->make_visible(false); + EditorNode::get_singleton()->hide_unused_editors(this); EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); undo_redo->create_action(p_cut ? TTR("Cut Node(s)") : TTR("Remove Node(s)"), UndoRedo::MERGE_DISABLE, remove_list.front()->get()); |