diff options
Diffstat (limited to 'editor')
-rw-r--r-- | editor/editor_node.cpp | 8 | ||||
-rw-r--r-- | editor/export/editor_export.cpp | 11 | ||||
-rw-r--r-- | editor/export/editor_export_platform.cpp | 49 | ||||
-rw-r--r-- | editor/export/editor_export_platform.h | 2 | ||||
-rw-r--r-- | editor/export/editor_export_plugin.cpp | 10 | ||||
-rw-r--r-- | editor/export/editor_export_plugin.h | 18 | ||||
-rw-r--r-- | editor/export/editor_export_preset.cpp | 96 | ||||
-rw-r--r-- | editor/export/editor_export_preset.h | 21 | ||||
-rw-r--r-- | editor/export/project_export.cpp | 132 | ||||
-rw-r--r-- | editor/export/project_export.h | 10 | ||||
-rw-r--r-- | editor/icons/BoneMapHumanBody.svg | 27 | ||||
-rw-r--r-- | editor/icons/BoneMapHumanFace.svg | 2 | ||||
-rw-r--r-- | editor/icons/BoneMapHumanLeftHand.svg | 2 | ||||
-rw-r--r-- | editor/icons/BoneMapHumanRightHand.svg | 2 | ||||
-rw-r--r-- | editor/plugins/dedicated_server_export_plugin.cpp | 139 | ||||
-rw-r--r-- | editor/plugins/dedicated_server_export_plugin.h | 58 | ||||
-rw-r--r-- | editor/plugins/skeleton_3d_editor_plugin.cpp | 140 |
17 files changed, 598 insertions, 129 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index c344812065..c7ea7dc7cf 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -125,6 +125,7 @@ #include "editor/plugins/asset_library_editor_plugin.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/debugger_editor_plugin.h" +#include "editor/plugins/dedicated_server_export_plugin.h" #include "editor/plugins/editor_preview_plugins.h" #include "editor/plugins/editor_resource_conversion_plugin.h" #include "editor/plugins/gdextension_export_plugin.h" @@ -5440,7 +5441,7 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { _scene_tab_closed(scene_tabs->get_hovered_tab()); } } else { - if ((mb->get_button_index() == MouseButton::LEFT && mb->is_double_click()) || (mb->get_button_index() == MouseButton::MIDDLE && mb->is_pressed())) { + if (mb->get_button_index() == MouseButton::LEFT && mb->is_double_click()) { _menu_option_confirm(FILE_NEW_SCENE, true); } } @@ -7878,6 +7879,11 @@ EditorNode::EditorNode() { EditorExport::get_singleton()->add_export_plugin(gdextension_export_plugin); + Ref<DedicatedServerExportPlugin> dedicated_server_export_plugin; + dedicated_server_export_plugin.instantiate(); + + EditorExport::get_singleton()->add_export_plugin(dedicated_server_export_plugin); + Ref<PackedSceneEditorTranslationParserPlugin> packed_scene_translation_parser_plugin; packed_scene_translation_parser_plugin.instantiate(); EditorTranslationParser::get_singleton()->add_parser(packed_scene_translation_parser_plugin, EditorTranslationParser::STANDARD); diff --git a/editor/export/editor_export.cpp b/editor/export/editor_export.cpp index 1d147cc5b9..4900ced2e4 100644 --- a/editor/export/editor_export.cpp +++ b/editor/export/editor_export.cpp @@ -45,6 +45,7 @@ void EditorExport::_save() { config->set_value(section, "name", preset->get_name()); config->set_value(section, "platform", preset->get_platform()->get_name()); config->set_value(section, "runnable", preset->is_runnable()); + config->set_value(section, "dedicated_server", preset->is_dedicated_server()); config->set_value(section, "custom_features", preset->get_custom_features()); bool save_files = false; @@ -64,6 +65,11 @@ void EditorExport::_save() { config->set_value(section, "export_filter", "exclude"); save_files = true; } break; + case EditorExportPreset::EXPORT_CUSTOMIZED: { + config->set_value(section, "export_filter", "customized"); + config->set_value(section, "customized_files", preset->get_customized_files()); + save_files = false; + }; } if (save_files) { @@ -213,6 +219,7 @@ void EditorExport::load_config() { preset->set_name(config->get_value(section, "name")); preset->set_runnable(config->get_value(section, "runnable")); + preset->set_dedicated_server(config->get_value(section, "dedicated_server", false)); if (config->has_section_key(section, "custom_features")) { preset->set_custom_features(config->get_value(section, "custom_features")); @@ -233,6 +240,10 @@ void EditorExport::load_config() { } else if (export_filter == "exclude") { preset->set_export_filter(EditorExportPreset::EXCLUDE_SELECTED_RESOURCES); get_files = true; + } else if (export_filter == "customized") { + preset->set_export_filter(EditorExportPreset::EXPORT_CUSTOMIZED); + preset->set_customized_files(config->get_value(section, "customized_files", Dictionary())); + get_files = false; } if (get_files) { diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index 8da52e20f7..9f79eecfb7 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -343,6 +343,24 @@ void EditorExportPlatform::_export_find_resources(EditorFileSystemDirectory *p_d } } +void EditorExportPlatform::_export_find_customized_resources(const Ref<EditorExportPreset> &p_preset, EditorFileSystemDirectory *p_dir, EditorExportPreset::FileExportMode p_mode, HashSet<String> &p_paths) { + for (int i = 0; i < p_dir->get_subdir_count(); i++) { + EditorFileSystemDirectory *subdir = p_dir->get_subdir(i); + _export_find_customized_resources(p_preset, subdir, p_preset->get_file_export_mode(subdir->get_path(), p_mode), p_paths); + } + + for (int i = 0; i < p_dir->get_file_count(); i++) { + if (p_dir->get_file_type(i) == "TextFile") { + continue; + } + String path = p_dir->get_file_path(i); + EditorExportPreset::FileExportMode file_mode = p_preset->get_file_export_mode(path, p_mode); + if (file_mode != EditorExportPreset::MODE_FILE_REMOVE) { + p_paths.insert(path); + } + } +} + void EditorExportPlatform::_export_find_dependencies(const String &p_path, HashSet<String> &p_paths) { if (p_paths.has(p_path)) { return; @@ -639,10 +657,20 @@ bool EditorExportPlatform::_export_customize_object(Object *p_object, LocalVecto return changed; } +bool EditorExportPlatform::_is_editable_ancestor(Node *p_root, Node *p_node) { + while (p_node != nullptr && p_node != p_root) { + if (p_root->is_editable_instance(p_node)) { + return true; + } + p_node = p_node->get_owner(); + } + return false; +} + bool EditorExportPlatform::_export_customize_scene_resources(Node *p_root, Node *p_node, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins) { bool changed = false; - if (p_node == p_root || p_node->get_owner() == p_root) { + if (p_root == p_node || p_node->get_owner() == p_root || _is_editable_ancestor(p_root, p_node)) { if (_export_customize_object(p_node, customize_resources_plugins)) { changed = true; } @@ -757,10 +785,10 @@ String EditorExportPlatform::_export_customize(const String &p_path, LocalVector break; } } + } - if (_export_customize_object(res.ptr(), customize_resources_plugins)) { - modified = true; - } + if (_export_customize_object(res.ptr(), customize_resources_plugins)) { + modified = true; } if (modified || p_force_save) { @@ -796,6 +824,8 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & for (int i = 0; i < files.size(); i++) { paths.erase(files[i]); } + } else if (p_preset->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED) { + _export_find_customized_resources(p_preset, EditorFileSystem::get_singleton()->get_filesystem(), p_preset->get_file_export_mode("res://"), paths); } else { bool scenes_only = p_preset->get_export_filter() == EditorExportPreset::EXPORT_SELECTED_SCENES; @@ -939,14 +969,14 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & LocalVector<Ref<EditorExportPlugin>> customize_scenes_plugins; for (int i = 0; i < export_plugins.size(); i++) { - if (export_plugins[i]->_begin_customize_resources(Ref<EditorExportPlatform>(this), features_psa)) { + if (export_plugins.write[i]->_begin_customize_resources(Ref<EditorExportPlatform>(this), features_psa)) { customize_resources_plugins.push_back(export_plugins[i]); custom_resources_hash = hash_murmur3_one_64(export_plugins[i]->_get_name().hash64(), custom_resources_hash); uint64_t hash = export_plugins[i]->_get_customization_configuration_hash(); custom_resources_hash = hash_murmur3_one_64(hash, custom_resources_hash); } - if (export_plugins[i]->_begin_customize_scenes(Ref<EditorExportPlatform>(this), features_psa)) { + if (export_plugins.write[i]->_begin_customize_scenes(Ref<EditorExportPlatform>(this), features_psa)) { customize_scenes_plugins.push_back(export_plugins[i]); custom_resources_hash = hash_murmur3_one_64(export_plugins[i]->_get_name().hash64(), custom_resources_hash); @@ -1218,6 +1248,9 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } } } + for (int i = 0; i < export_plugins.size(); i++) { + custom_list.append_array(export_plugins[i]->_get_export_features(Ref<EditorExportPlatform>(this), p_debug)); + } ProjectSettings::CustomMap custom_map; if (path_remaps.size()) { @@ -1294,7 +1327,9 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } else { // Use default text server data. String icu_data_file = EditorPaths::get_singleton()->get_cache_dir().path_join("tmp_icu_data"); - TS->save_support_data(icu_data_file); + if (!TS->save_support_data(icu_data_file)) { + return ERR_INVALID_DATA; + } Vector<uint8_t> array = FileAccess::get_file_as_bytes(icu_data_file); err = p_func(p_udata, ts_data, array, idx, total, enc_in_filters, enc_ex_filters, key); DirAccess::remove_file_or_error(icu_data_file); diff --git a/editor/export/editor_export_platform.h b/editor/export/editor_export_platform.h index 1fb35759ac..3b4e92c9bd 100644 --- a/editor/export/editor_export_platform.h +++ b/editor/export/editor_export_platform.h @@ -91,6 +91,7 @@ private: Vector<ExportMessage> messages; void _export_find_resources(EditorFileSystemDirectory *p_dir, HashSet<String> &p_paths); + void _export_find_customized_resources(const Ref<EditorExportPreset> &p_preset, EditorFileSystemDirectory *p_dir, EditorExportPreset::FileExportMode p_mode, HashSet<String> &p_paths); void _export_find_dependencies(const String &p_path, HashSet<String> &p_paths); static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); @@ -112,6 +113,7 @@ private: bool _export_customize_array(Array &array, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins); bool _export_customize_object(Object *p_object, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins); bool _export_customize_scene_resources(Node *p_root, Node *p_node, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins); + bool _is_editable_ancestor(Node *p_root, Node *p_node); String _export_customize(const String &p_path, LocalVector<Ref<EditorExportPlugin>> &customize_resources_plugins, LocalVector<Ref<EditorExportPlugin>> &customize_scenes_plugins, HashMap<String, FileExportCache> &export_cache, const String &export_base_path, bool p_force_save); diff --git a/editor/export/editor_export_plugin.cpp b/editor/export/editor_export_plugin.cpp index dfd4520eec..0add55820f 100644 --- a/editor/export/editor_export_plugin.cpp +++ b/editor/export/editor_export_plugin.cpp @@ -141,7 +141,7 @@ void EditorExportPlugin::_export_end_script() { // Customization -bool EditorExportPlugin::_begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) const { +bool EditorExportPlugin::_begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) { bool ret = false; GDVIRTUAL_CALL(_begin_customize_resources, p_platform, p_features, ret); return ret; @@ -153,7 +153,7 @@ Ref<Resource> EditorExportPlugin::_customize_resource(const Ref<Resource> &p_res return ret; } -bool EditorExportPlugin::_begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) const { +bool EditorExportPlugin::_begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) { bool ret = false; GDVIRTUAL_CALL(_begin_customize_scenes, p_platform, p_features, ret); return ret; @@ -185,6 +185,12 @@ String EditorExportPlugin::_get_name() const { return ret; } +PackedStringArray EditorExportPlugin::_get_export_features(const Ref<EditorExportPlatform> &p_platform, bool p_debug) const { + PackedStringArray ret; + GDVIRTUAL_CALL(_get_export_features, p_platform, p_debug, ret); + return ret; +} + void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) { } diff --git a/editor/export/editor_export_plugin.h b/editor/export/editor_export_plugin.h index 5ac0a70c3e..fad647a67b 100644 --- a/editor/export/editor_export_plugin.h +++ b/editor/export/editor_export_plugin.h @@ -120,18 +120,22 @@ protected: GDVIRTUAL0(_end_customize_scenes) GDVIRTUAL0(_end_customize_resources) + GDVIRTUAL2RC(PackedStringArray, _get_export_features, const Ref<EditorExportPlatform> &, bool); + GDVIRTUAL0RC(String, _get_name) - bool _begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) const; // Return true if this plugin does property export customization - Ref<Resource> _customize_resource(const Ref<Resource> &p_resource, const String &p_path); // If nothing is returned, it means do not touch (nothing changed). If something is returned (either the same or a different resource) it means changes are made. + virtual bool _begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features); // Return true if this plugin does property export customization + virtual Ref<Resource> _customize_resource(const Ref<Resource> &p_resource, const String &p_path); // If nothing is returned, it means do not touch (nothing changed). If something is returned (either the same or a different resource) it means changes are made. + + virtual bool _begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features); // Return true if this plugin does property export customization + virtual Node *_customize_scene(Node *p_root, const String &p_path); // Return true if a change was made - bool _begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) const; // Return true if this plugin does property export customization - Node *_customize_scene(Node *p_root, const String &p_path); // Return true if a change was made + virtual uint64_t _get_customization_configuration_hash() const; // Hash used for caching customized resources and scenes. - uint64_t _get_customization_configuration_hash() const; // Hash used for caching customized resources and scenes. + virtual void _end_customize_scenes(); + virtual void _end_customize_resources(); - void _end_customize_scenes(); - void _end_customize_resources(); + virtual PackedStringArray _get_export_features(const Ref<EditorExportPlatform> &p_export_platform, bool p_debug) const; virtual String _get_name() const; diff --git a/editor/export/editor_export_preset.cpp b/editor/export/editor_export_preset.cpp index c6365806b3..6beef623bc 100644 --- a/editor/export/editor_export_preset.cpp +++ b/editor/export/editor_export_preset.cpp @@ -64,15 +64,29 @@ Ref<EditorExportPlatform> EditorExportPreset::get_platform() const { return platform; } -void EditorExportPreset::update_files_to_export() { - Vector<String> to_remove; - for (const String &E : selected_files) { - if (!FileAccess::exists(E)) { - to_remove.push_back(E); +void EditorExportPreset::update_files() { + { + Vector<String> to_remove; + for (const String &E : selected_files) { + if (!FileAccess::exists(E)) { + to_remove.push_back(E); + } + } + for (int i = 0; i < to_remove.size(); ++i) { + selected_files.erase(to_remove[i]); } } - for (int i = 0; i < to_remove.size(); ++i) { - selected_files.erase(to_remove[i]); + + { + Vector<String> to_remove; + for (const KeyValue<String, FileExportMode> &E : customized_files) { + if (!FileAccess::exists(E.key) && !DirAccess::exists(E.key)) { + to_remove.push_back(E.key); + } + } + for (int i = 0; i < to_remove.size(); ++i) { + customized_files.erase(to_remove[i]); + } } } @@ -84,6 +98,48 @@ Vector<String> EditorExportPreset::get_files_to_export() const { return files; } +Dictionary EditorExportPreset::get_customized_files() const { + Dictionary files; + for (const KeyValue<String, FileExportMode> &E : customized_files) { + String mode; + switch (E.value) { + case MODE_FILE_NOT_CUSTOMIZED: { + continue; + } break; + case MODE_FILE_STRIP: { + mode = "strip"; + } break; + case MODE_FILE_KEEP: { + mode = "keep"; + } break; + case MODE_FILE_REMOVE: { + mode = "remove"; + } + } + files[E.key] = mode; + } + return files; +} + +int EditorExportPreset::get_customized_files_count() const { + return customized_files.size(); +} + +void EditorExportPreset::set_customized_files(const Dictionary &p_files) { + for (const Variant *key = p_files.next(nullptr); key; key = p_files.next(key)) { + EditorExportPreset::FileExportMode mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED; + String value = p_files[*key]; + if (value == "strip") { + mode = EditorExportPreset::MODE_FILE_STRIP; + } else if (value == "keep") { + mode = EditorExportPreset::MODE_FILE_KEEP; + } else if (value == "remove") { + mode = EditorExportPreset::MODE_FILE_REMOVE; + } + set_file_export_mode(*key, mode); + } +} + void EditorExportPreset::set_name(const String &p_name) { name = p_name; EditorExport::singleton->save_presets(); @@ -102,6 +158,15 @@ bool EditorExportPreset::is_runnable() const { return runnable; } +void EditorExportPreset::set_dedicated_server(bool p_enable) { + dedicated_server = p_enable; + EditorExport::singleton->save_presets(); +} + +bool EditorExportPreset::is_dedicated_server() const { + return dedicated_server; +} + void EditorExportPreset::set_export_filter(ExportFilter p_filter) { export_filter = p_filter; EditorExport::singleton->save_presets(); @@ -158,6 +223,23 @@ bool EditorExportPreset::has_export_file(const String &p_path) { return selected_files.has(p_path); } +void EditorExportPreset::set_file_export_mode(const String &p_path, EditorExportPreset::FileExportMode p_mode) { + if (p_mode == FileExportMode::MODE_FILE_NOT_CUSTOMIZED) { + customized_files.erase(p_path); + } else { + customized_files.insert(p_path, p_mode); + } + EditorExport::singleton->save_presets(); +} + +EditorExportPreset::FileExportMode EditorExportPreset::get_file_export_mode(const String &p_path, EditorExportPreset::FileExportMode p_default) const { + HashMap<String, FileExportMode>::ConstIterator i = customized_files.find(p_path); + if (i) { + return i->value; + } + return p_default; +} + void EditorExportPreset::set_custom_features(const String &p_custom_features) { custom_features = p_custom_features; EditorExport::singleton->save_presets(); diff --git a/editor/export/editor_export_preset.h b/editor/export/editor_export_preset.h index de208f410e..db139d8860 100644 --- a/editor/export/editor_export_preset.h +++ b/editor/export/editor_export_preset.h @@ -44,6 +44,14 @@ public: EXPORT_SELECTED_SCENES, EXPORT_SELECTED_RESOURCES, EXCLUDE_SELECTED_RESOURCES, + EXPORT_CUSTOMIZED, + }; + + enum FileExportMode { + MODE_FILE_NOT_CUSTOMIZED, + MODE_FILE_STRIP, + MODE_FILE_KEEP, + MODE_FILE_REMOVE, }; private: @@ -55,7 +63,9 @@ private: String exporter; HashSet<String> selected_files; + HashMap<String, FileExportMode> customized_files; bool runnable = false; + bool dedicated_server = false; friend class EditorExport; friend class EditorExportPlatform; @@ -85,20 +95,29 @@ public: bool has(const StringName &p_property) const { return values.has(p_property); } - void update_files_to_export(); + void update_files(); Vector<String> get_files_to_export() const; + Dictionary get_customized_files() const; + int get_customized_files_count() const; + void set_customized_files(const Dictionary &p_files); void add_export_file(const String &p_path); void remove_export_file(const String &p_path); bool has_export_file(const String &p_path); + void set_file_export_mode(const String &p_path, FileExportMode p_mode); + FileExportMode get_file_export_mode(const String &p_path, FileExportMode p_default = MODE_FILE_NOT_CUSTOMIZED) const; + void set_name(const String &p_name); String get_name() const; void set_runnable(bool p_enable); bool is_runnable() const; + void set_dedicated_server(bool p_enable); + bool is_dedicated_server() const; + void set_export_filter(ExportFilter p_filter); ExportFilter get_export_filter() const; diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index 2caebc6f04..52c192164f 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -45,6 +45,7 @@ #include "scene/gui/link_button.h" #include "scene/gui/menu_button.h" #include "scene/gui/option_button.h" +#include "scene/gui/popup_menu.h" #include "scene/gui/split_container.h" #include "scene/gui/texture_rect.h" #include "scene/gui/tree.h" @@ -165,7 +166,7 @@ void ProjectExportDialog::_update_presets() { if (preset->is_runnable()) { preset_name += " (" + TTR("Runnable") + ")"; } - preset->update_files_to_export(); + preset->update_files(); presets->add_item(preset_name, preset->get_platform()->get_logo()); } @@ -244,6 +245,7 @@ void ProjectExportDialog::_edit_preset(int p_index) { export_filter->select(current->get_export_filter()); include_filters->set_text(current->get_include_filter()); exclude_filters->set_text(current->get_exclude_filter()); + server_strip_message->set_visible(current->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED); _fill_resource_tree(); @@ -570,6 +572,7 @@ void ProjectExportDialog::_duplicate_preset() { if (make_runnable) { preset->set_runnable(make_runnable); } + preset->set_dedicated_server(current->is_dedicated_server()); preset->set_export_filter(current->get_export_filter()); preset->set_include_filter(current->get_include_filter()); preset->set_exclude_filter(current->get_exclude_filter()); @@ -692,7 +695,16 @@ void ProjectExportDialog::_export_type_changed(int p_which) { return; } - current->set_export_filter(EditorExportPreset::ExportFilter(p_which)); + EditorExportPreset::ExportFilter filter_type = (EditorExportPreset::ExportFilter)p_which; + current->set_export_filter(filter_type); + current->set_dedicated_server(filter_type == EditorExportPreset::EXPORT_CUSTOMIZED); + server_strip_message->set_visible(filter_type == EditorExportPreset::EXPORT_CUSTOMIZED); + + // Default to stripping everything when first switching to server build. + if (filter_type == EditorExportPreset::EXPORT_CUSTOMIZED && current->get_customized_files_count() == 0) { + current->set_file_export_mode("res://", EditorExportPreset::MODE_FILE_STRIP); + } + updating = true; _fill_resource_tree(); updating = false; @@ -728,25 +740,53 @@ void ProjectExportDialog::_fill_resource_tree() { return; } + TreeItem *root = include_files->create_item(); + + if (f == EditorExportPreset::EXPORT_CUSTOMIZED) { + include_files->set_columns(2); + include_files->set_column_expand(1, false); + include_files->set_column_custom_minimum_width(1, 250 * EDSCALE); + } else { + include_files->set_columns(1); + } + include_label->show(); include_margin->show(); - TreeItem *root = include_files->create_item(); + _fill_tree(EditorFileSystem::get_singleton()->get_filesystem(), root, current, f); +} - _fill_tree(EditorFileSystem::get_singleton()->get_filesystem(), root, current, f == EditorExportPreset::EXPORT_SELECTED_SCENES); +void ProjectExportDialog::_setup_item_for_file_mode(TreeItem *p_item, EditorExportPreset::FileExportMode p_mode) { + if (p_mode == EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED) { + p_item->set_checked(0, false); + p_item->set_cell_mode(1, TreeItem::CELL_MODE_STRING); + p_item->set_text(1, ""); + p_item->set_editable(1, false); + p_item->set_selectable(1, false); + } else { + p_item->set_checked(0, true); + p_item->set_cell_mode(1, TreeItem::CELL_MODE_CUSTOM); + p_item->set_text(1, file_mode_popup->get_item_text(file_mode_popup->get_item_index(p_mode))); + p_item->set_editable(1, true); + p_item->set_selectable(1, true); + } } -bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> ¤t, bool p_only_scenes) { +bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> ¤t, EditorExportPreset::ExportFilter p_export_filter) { p_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); p_item->set_icon(0, presets->get_theme_icon(SNAME("folder"), SNAME("FileDialog"))); p_item->set_text(0, p_dir->get_name() + "/"); p_item->set_editable(0, true); p_item->set_metadata(0, p_dir->get_path()); + if (p_export_filter == EditorExportPreset::EXPORT_CUSTOMIZED) { + _setup_item_for_file_mode(p_item, current->get_file_export_mode(p_dir->get_path())); + } + bool used = false; for (int i = 0; i < p_dir->get_subdir_count(); i++) { TreeItem *subdir = include_files->create_item(p_item); - if (_fill_tree(p_dir->get_subdir(i), subdir, current, p_only_scenes)) { + if (_fill_tree(p_dir->get_subdir(i), subdir, current, p_export_filter)) { used = true; } else { memdelete(subdir); @@ -755,7 +795,7 @@ bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem for (int i = 0; i < p_dir->get_file_count(); i++) { String type = p_dir->get_file_type(i); - if (p_only_scenes && type != "PackedScene") { + if (p_export_filter == EditorExportPreset::EXPORT_SELECTED_SCENES && type != "PackedScene") { continue; } if (type == "TextFile") { @@ -770,9 +810,14 @@ bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem file->set_icon(0, EditorNode::get_singleton()->get_class_icon(type)); file->set_editable(0, true); - file->set_checked(0, current->has_export_file(path)); file->set_metadata(0, path); - file->propagate_check(0); + + if (p_export_filter == EditorExportPreset::EXPORT_CUSTOMIZED) { + _setup_item_for_file_mode(file, current->get_file_export_mode(path)); + } else { + file->set_checked(0, current->has_export_file(path)); + file->propagate_check(0); + } used = true; } @@ -794,7 +839,19 @@ void ProjectExportDialog::_tree_changed() { return; } - item->propagate_check(0); + if (current->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED) { + EditorExportPreset::FileExportMode file_mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED; + String path = item->get_metadata(0); + + if (item->is_checked(0)) { + file_mode = current->get_file_export_mode(path, EditorExportPreset::MODE_FILE_STRIP); + } + + _setup_item_for_file_mode(item, file_mode); + current->set_file_export_mode(path, file_mode); + } else { + item->propagate_check(0); + } } void ProjectExportDialog::_check_propagated_to_item(Object *p_obj, int column) { @@ -814,6 +871,30 @@ void ProjectExportDialog::_check_propagated_to_item(Object *p_obj, int column) { } } +void ProjectExportDialog::_tree_popup_edited(bool p_arrow_clicked) { + Rect2 bounds = include_files->get_custom_popup_rect(); + bounds.position += get_global_canvas_transform().get_origin(); + bounds.size *= get_global_canvas_transform().get_scale(); + if (!is_embedding_subwindows()) { + bounds.position += get_position(); + } + file_mode_popup->popup(bounds); +} + +void ProjectExportDialog::_set_file_export_mode(int p_id) { + Ref<EditorExportPreset> current = get_current_preset(); + if (current.is_null()) { + return; + } + + TreeItem *item = include_files->get_edited(); + String path = item->get_metadata(0); + + current->set_file_export_mode(path, (EditorExportPreset::FileExportMode)p_id); + + item->set_text(1, file_mode_popup->get_item_text(file_mode_popup->get_item_index(p_id))); +} + void ProjectExportDialog::_export_pck_zip() { Ref<EditorExportPreset> current = get_current_preset(); ERR_FAIL_COND(current.is_null()); @@ -1068,6 +1149,7 @@ ProjectExportDialog::ProjectExportDialog() { export_filter->add_item(TTR("Export selected scenes (and dependencies)")); export_filter->add_item(TTR("Export selected resources (and dependencies)")); export_filter->add_item(TTR("Export all resources in the project except resources checked below")); + export_filter->add_item(TTR("Export as dedicated server")); resources_vb->add_margin_child(TTR("Export Mode:"), export_filter); export_filter->connect("item_selected", callable_mp(this, &ProjectExportDialog::_export_type_changed)); @@ -1082,6 +1164,36 @@ ProjectExportDialog::ProjectExportDialog() { include_margin->add_child(include_files); include_files->connect("item_edited", callable_mp(this, &ProjectExportDialog::_tree_changed)); include_files->connect("check_propagated_to_item", callable_mp(this, &ProjectExportDialog::_check_propagated_to_item)); + include_files->connect("custom_popup_edited", callable_mp(this, &ProjectExportDialog::_tree_popup_edited)); + + server_strip_message = memnew(Label); + server_strip_message->set_visible(false); + server_strip_message->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); + resources_vb->add_child(server_strip_message); + + { + List<StringName> resource_names; + ClassDB::get_inheriters_from_class("Resource", &resource_names); + + PackedStringArray strippable; + for (StringName resource_name : resource_names) { + if (ClassDB::has_method(resource_name, "create_placeholder", true)) { + strippable.push_back(resource_name); + } + } + strippable.sort(); + + String message = TTR("\"Strip Visuals\" will replace the following resources with placeholders:") + " "; + message += String(", ").join(strippable); + server_strip_message->set_text(message); + } + + file_mode_popup = memnew(PopupMenu); + add_child(file_mode_popup); + file_mode_popup->add_item(TTR("Strip Visuals"), EditorExportPreset::MODE_FILE_STRIP); + file_mode_popup->add_item(TTR("Keep"), EditorExportPreset::MODE_FILE_KEEP); + file_mode_popup->add_item(TTR("Remove"), EditorExportPreset::MODE_FILE_REMOVE); + file_mode_popup->connect("id_pressed", callable_mp(this, &ProjectExportDialog::_set_file_export_mode)); include_filters = memnew(LineEdit); resources_vb->add_margin_child( diff --git a/editor/export/project_export.h b/editor/export/project_export.h index d392dba2a4..63f8fc4a2e 100644 --- a/editor/export/project_export.h +++ b/editor/export/project_export.h @@ -31,11 +31,11 @@ #ifndef PROJECT_EXPORT_H #define PROJECT_EXPORT_H +#include "editor/export/editor_export_preset.h" #include "scene/gui/dialogs.h" class CheckBox; class CheckButton; -class EditorExportPreset; class EditorFileDialog; class EditorFileSystemDirectory; class EditorInspector; @@ -43,6 +43,7 @@ class EditorPropertyPath; class ItemList; class MenuButton; class OptionButton; +class PopupMenu; class RichTextLabel; class TabContainer; class Tree; @@ -75,6 +76,8 @@ private: LineEdit *include_filters = nullptr; LineEdit *exclude_filters = nullptr; Tree *include_files = nullptr; + Label *server_strip_message = nullptr; + PopupMenu *file_mode_popup = nullptr; Label *include_label = nullptr; MarginContainer *include_margin = nullptr; @@ -113,9 +116,12 @@ private: void _export_type_changed(int p_which); void _filter_changed(const String &p_filter); void _fill_resource_tree(); - bool _fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> ¤t, bool p_only_scenes); + void _setup_item_for_file_mode(TreeItem *p_item, EditorExportPreset::FileExportMode p_mode); + bool _fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> ¤t, EditorExportPreset::ExportFilter p_export_filter); void _tree_changed(); void _check_propagated_to_item(Object *p_obj, int column); + void _tree_popup_edited(bool p_arrow_clicked); + void _set_file_export_mode(int p_id); 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; diff --git a/editor/icons/BoneMapHumanBody.svg b/editor/icons/BoneMapHumanBody.svg index 8674157aaa..818ee63069 100644 --- a/editor/icons/BoneMapHumanBody.svg +++ b/editor/icons/BoneMapHumanBody.svg @@ -1,26 +1 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" - y="0px" width="1024px" height="1024px" viewBox="0 0 1024 1024" enable-background="new 0 0 1024 1024" xml:space="preserve"> -<path fill="#3F3F3F" d="M0,0h1024v1024H0V0z"/> -<path fill="#B2B2B2" d="M512,536.162c7,35,11.645,66.898,14,114c2,40,4,51,2,66c-7.384,55.369,6.77,183.898,8.666,206.667 - c2,24-7.653,24.241-10.666,46.333c-2.449,17.958,79,18.439,65-9c-25-49-2-84,4-221c0.521-11.921-8.967-47.874-2-94 - c11.086-73.414,8.42-107.242,6.5-145.662c-1.245-31.973-1-56.963-9-138.963c-0.976-10.002,5.915-79.268,11.954-79.088 - c42,1.25,97.313-5.009,118.145-14.68c28.901,3.73,97.81-12.047,127.887-16.126c14.541,9.407,16.673,3.335,37.515,9.019 - c5.5,1.5,17.336-1.443,12-5c-7.409-4.937-20.75-8.25-23-12c10.75-2.5,22.365-9.578,36-13.166c9.5-2.5,18.866-11.748,15.5-12.334l0,0 - c-11.5-2-26.03,4.547-37.5,6.5c-15.724,2.678-25.238,3.24-33.334,5.167c-1.227,0.292-3.103,0.763-5.791,0.958 - c0,0-0.02,0.16-0.053,0.437c-36.818,0.994-80.322-9.724-130.31-5.569c-34.026-3.925-94.181-5.16-113.513-5.493 - c-13.911-0.239-59.293-2.583-71.75-0.5c-0.668-4.083-1.5-9.75,0.949-16.468c14.881-7.246,19.188-17.796,27.301-34.694 - c0.922,4.424,6.252,4.929,12.459-14.231c5.661-17.478,2.323-22.254-2.313-22.525c0.172-2.056,0.279-4.105,0.313-6.142 - C573.746,76.562,566,42.163,512,42.163s-61.746,34.399-60.959,82.44c0.034,2.037,0.142,4.086,0.313,6.142 - c-4.637,0.271-7.975,5.047-2.313,22.525c6.207,19.16,11.537,18.655,12.459,14.231c8.112,16.898,12.42,27.448,27.301,34.694 - c2.449,6.718,1.617,12.385,0.949,16.468c-12.457-2.083-57.839,0.261-71.75,0.5c-19.332,0.333-79.486,1.568-113.513,5.493 - c-49.987-4.155-93.491,6.563-130.31,5.569c-0.033-0.277-0.053-0.437-0.053-0.437c-2.688-0.195-4.564-0.666-5.791-0.958 - c-8.096-1.927-17.61-2.489-33.334-5.167c-11.47-1.953-26-8.5-37.5-6.5l0,0c-3.366,0.586,6,9.834,15.5,12.334 - c13.635,3.588,25.25,10.666,36,13.166c-2.25,3.75-15.591,7.063-23,12c-5.336,3.557,6.5,6.5,12,5 - c20.842-5.684,22.974,0.388,37.515-9.019c30.077,4.079,98.985,19.857,127.887,16.126c20.832,9.671,76.145,15.93,118.145,14.68 - c6.039-0.18,12.93,69.085,11.954,79.088c-8,82-7.755,106.99-9,138.963c-1.92,38.419-4.586,72.248,6.5,145.662 - c6.967,46.126-2.521,82.079-2,94c6,137,29,172,4,221c-14,27.439,67.449,26.958,65,9c-3.013-22.092-12.666-22.333-10.666-46.333 - c1.896-22.769,16.05-151.298,8.666-206.667c-2-15,0-26,2-66C500.356,603.061,505,571.162,512,536.162z"/> -</svg> +<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_1451_455)"><path d="M0 0H256V256H0V0Z" fill="#3F3F3F"/><path d="M128 134.04C129.75 142.79 130.911 150.765 131.5 162.54C132 172.54 132.5 175.29 132 179.04C130.154 192.883 133.692 225.015 134.166 230.707C134.666 236.707 132.253 236.767 131.5 242.29C130.888 246.78 151.25 246.9 147.75 240.04C141.5 227.79 147.25 219.04 148.75 184.79C148.88 181.81 146.508 172.822 148.25 161.29C151.021 142.937 150.355 134.48 149.875 124.875C149.564 116.882 149.625 110.634 147.625 90.134C147.381 87.6335 149.104 70.317 150.613 70.362C161.113 70.6745 174.942 69.1098 180.15 66.692C187.375 67.6245 204.602 63.6803 212.121 62.6605C215.757 65.0123 216.29 63.4943 221.5 64.9153C222.875 65.2903 225.834 64.5545 224.5 63.6653C222.648 62.431 219.313 61.6028 218.75 60.6653C221.438 60.0403 224.341 58.2708 227.75 57.3738C230.125 56.7488 232.467 54.4368 231.625 54.2903C228.75 53.7903 225.118 55.427 222.25 55.9153C218.319 56.5848 215.941 56.7253 213.917 57.207C213.61 57.28 213.141 57.3978 212.469 57.4465C212.469 57.4465 212.464 57.4865 212.456 57.5558C203.251 57.8043 192.375 55.1248 179.878 56.1635C171.372 55.1823 156.333 54.8735 151.5 54.7903C148.022 54.7305 136.677 54.1445 133.562 54.6653C133.395 53.6445 133.187 52.2278 133.8 50.5483C137.52 48.7368 138.597 46.0993 140.625 41.8748C140.855 42.9808 142.188 43.107 143.74 38.317C145.155 33.9475 144.32 32.7535 143.161 32.6858C143.204 32.1718 143.231 31.6595 143.24 31.1503C143.436 19.1403 141.5 10.5405 128 10.5405C114.5 10.5405 112.563 19.1403 112.76 31.1505C112.769 31.6598 112.796 32.172 112.838 32.686C111.679 32.7538 110.845 33.9478 112.26 38.3173C113.812 43.1073 115.144 42.981 115.375 41.875C117.403 46.0995 118.48 48.737 122.2 50.5485C122.812 52.228 122.604 53.6448 122.437 54.6655C119.323 54.1448 107.978 54.7308 104.5 54.7905C99.6669 54.8738 84.6284 55.1825 76.1217 56.1638C63.6249 55.125 52.7489 57.8045 43.5442 57.556C43.5359 57.4868 43.5309 57.4468 43.5309 57.4468C42.8589 57.398 42.3899 57.2803 42.0832 57.2073C40.0592 56.7255 37.6807 56.585 33.7497 55.9155C30.8822 55.4273 27.2497 53.7905 24.3747 54.2905C23.5332 54.437 25.8747 56.749 28.2497 57.374C31.6584 58.271 34.5622 60.0405 37.2497 60.6655C36.6872 61.603 33.3519 62.4313 31.4997 63.6655C30.1657 64.5548 33.1247 65.2905 34.4997 64.9155C39.7102 63.4945 40.2432 65.0125 43.8784 62.6608C51.3977 63.6805 68.6247 67.625 75.8502 66.6923C81.0582 69.11 94.8864 70.6748 105.386 70.3623C106.896 70.3173 108.619 87.6335 108.375 90.1343C106.375 110.634 106.436 116.882 106.125 124.875C105.645 134.48 104.978 142.937 107.75 161.291C109.492 172.822 107.12 181.81 107.25 184.791C108.75 219.041 114.5 227.791 108.25 240.041C104.75 246.9 125.112 246.78 124.5 242.291C123.747 236.768 121.333 236.707 121.833 230.707C122.307 225.015 125.846 192.883 124 179.041C123.5 175.291 124 172.541 124.5 162.541C125.089 150.765 126.25 142.79 128 134.04Z" fill="#B2B2B2"/></g><defs><clipPath id="clip0_1451_455"><rect width="256" height="256" fill="white"/></clipPath></defs></svg> diff --git a/editor/icons/BoneMapHumanFace.svg b/editor/icons/BoneMapHumanFace.svg index 6cb21140bc..e38c5cb790 100644 --- a/editor/icons/BoneMapHumanFace.svg +++ b/editor/icons/BoneMapHumanFace.svg @@ -1 +1 @@ -<svg enable-background="new 0 0 1024 1024" height="1024" viewBox="0 0 1024 1024" width="1024" xmlns="http://www.w3.org/2000/svg"><path d="m0 0h1024v1024h-1024z" fill="#3f3f3f"/><path d="m788.105 552.967c17.995-57.892 31.896-124.566 30.875-198.071-3.758-270.403-249.846-251.479-295.568-244.947-359.868 51.409-219.047 452.358-220.453 496.426-4.899 153.499 83.686 170.991 161.665 215.554 2.646 1.512 7.259 1.786 13.313 1.111 7.223 25.179 11.762 59.035 9.548 75.638-3.266 24.495 209.021 24.495 209.021 0 0-62.883 12.233-124.363 33.827-188.89 7.143-2.284 16.054-7.601 25.963-16.95 13.681-12.908 34.839-21.774 45.726-63.145 15.615-59.338 3.869-76.074-13.917-76.726z" fill="#b2b2b2"/></svg> +<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_1451_458)"><path d="M0 0H256V256H0V0Z" fill="#3F3F3F"/><path d="M197.026 138.242C201.525 123.769 205 107.1 204.745 88.724C203.805 21.1232 142.283 25.8542 130.853 27.4872C40.8859 40.3395 76.0912 140.577 75.7397 151.594C74.5149 189.968 96.6612 194.342 116.156 205.482C116.817 205.86 117.971 205.929 119.484 205.76C121.29 212.055 122.425 220.519 121.871 224.669C121.055 230.793 174.126 230.793 174.126 224.669C174.126 208.949 177.185 193.579 182.583 177.447C184.369 176.876 186.597 175.547 189.074 173.21C192.494 169.983 197.784 167.766 200.505 157.423C204.409 142.589 201.473 138.405 197.026 138.242Z" fill="#B2B2B2"/></g><defs><clipPath id="clip0_1451_458"><rect width="256" height="256" fill="white"/></clipPath></defs></svg> diff --git a/editor/icons/BoneMapHumanLeftHand.svg b/editor/icons/BoneMapHumanLeftHand.svg index 08c68bb4be..a9861f818c 100644 --- a/editor/icons/BoneMapHumanLeftHand.svg +++ b/editor/icons/BoneMapHumanLeftHand.svg @@ -1 +1 @@ -<svg enable-background="new 0 0 1024 1024" height="1024" viewBox="0 0 1024 1024" width="1024" xmlns="http://www.w3.org/2000/svg"><path d="m0 0h1024v1024h-1024z" fill="#3f3f3f"/><path d="m703.906 786.098c7.046-66.929 28.135-153.363 18.529-260.192-1.143-12.71-4.5-48.282-4.46-82.732.025-21.174-2.111-48.505-1.975-64.174.167-19.333-.428-41.584-.625-55.755-1.052-75.44-13.225-85.827-30.813-85.827-17.246 0-26.77 14.266-27.062 84.582-.061 14.42.5 51 .5 58.5 0 17.508-.333 34.167 0 53.5.447 25.955-4.279 68-9 68-3.902 0-8.099-39.299-9.575-76.999-.756-19.326-3.219-58.336-2.6-70.102 1.759-33.413.474-58.914 1.537-90.165 3.183-93.607-13.016-111.729-34.695-111.729-21.973 0-35.979 57.688-34.849 114.224.128 6.394-1.165 50.739.188 89.859.754 21.811-1.07 49.627-1.683 69.67-1.095 35.768-5.755 63.896-8.869 63.896-2.641 0-4.135-32.584-5.456-65.706-.859-21.557-4.468-58.477-3.664-83.616 1.886-59.012-1.139-110.226-1.063-121.501.635-94.955-14.66-123.101-36.052-123.101-21.476 0-37.188 30.192-36.6 123.343.067 10.53-2.62 99.926-1.759 121.816.865 21.992-2.773 65.062-3.517 84.818-1.299 34.521-6.49 63.947-9.124 63.947-3.281 0-10.794-25.638-11.724-60.965-.587-22.275 1.231-50.99.624-70.688-1.257-40.707-3.175-64.631-3.877-99.708-1.945-97.182-16.352-106.289-38.142-106.289-17.957 0-32.453 28.673-32.657 115.03-.065 27.702-2.429 62.626-.315 94.329.805 12.081-.622 42.512-1.875 73.894-.799 20.007-1.102 47.501-1.137 63.775-.17 78.595-26.712 133.424-36.555 131.308-30.333-6.521-51.648-43.918-71.219-117.307-10.551-39.566-36.667-71.149-69.9-77.813-25.9-5.193-19.783 46.161-1.319 125.293 8.65 37.068 27.909 86.227 39.566 122.655 31.653 98.917 125.574 188.563 160.903 228.546 17.146 19.403 236.894 19.403 264.59 0 11.525-8.07 43.087-101.557 45.724-126.616z" fill="#b2b2b2"/></svg> +<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_1451_461)"><path d="M0 0H256V256H0V0Z" fill="#3F3F3F"/><path d="M175.976 196.525C177.738 179.792 183.01 158.184 180.609 131.477C180.323 128.299 179.484 119.406 179.494 110.794C179.5 105.5 178.966 98.6674 179 94.7501C179.042 89.9169 178.893 84.3541 178.844 80.8114C178.581 61.9514 175.537 59.3546 171.14 59.3546C166.829 59.3546 164.448 62.9211 164.375 80.5001C164.36 84.1051 164.5 93.2501 164.5 95.1251C164.5 99.5021 164.417 103.667 164.5 108.5C164.612 114.989 163.43 125.5 162.25 125.5C161.274 125.5 160.225 115.675 159.856 106.25C159.667 101.419 159.051 91.6664 159.206 88.7249C159.646 80.3716 159.325 73.9964 159.59 66.1836C160.386 42.7819 156.336 38.2514 150.917 38.2514C145.423 38.2514 141.922 52.6734 142.204 66.8074C142.236 68.4059 141.913 79.4921 142.251 89.2721C142.44 94.7249 141.984 101.679 141.831 106.69C141.557 115.632 140.392 122.664 139.613 122.664C138.953 122.664 138.58 114.518 138.249 106.237C138.035 100.848 137.132 91.6179 137.333 85.3331C137.805 70.5801 137.049 57.7766 137.068 54.9579C137.226 31.2191 133.403 24.1826 128.055 24.1826C122.686 24.1826 118.758 31.7306 118.905 55.0184C118.921 57.6509 118.25 79.9999 118.465 85.4724C118.681 90.9704 117.772 101.738 117.586 106.677C117.261 115.307 115.963 122.664 115.305 122.664C114.484 122.664 112.606 116.254 112.374 107.422C112.227 101.854 112.681 94.6749 112.53 89.7504C112.215 79.5736 111.736 73.5926 111.56 64.8234C111.074 40.5279 107.472 38.2511 102.025 38.2511C97.5357 38.2511 93.9117 45.4194 93.8607 67.0086C93.8445 73.9341 93.2535 82.6651 93.782 90.5909C93.9832 93.6111 93.6265 101.219 93.3132 109.064C93.1135 114.066 93.0377 120.94 93.029 125.008C92.9865 144.657 86.351 158.364 83.8902 157.835C76.307 156.205 70.9782 146.856 66.0855 128.508C63.4477 118.617 56.9187 110.721 48.6105 109.055C42.1355 107.757 43.6647 120.595 48.2807 140.378C50.4432 149.645 55.258 161.935 58.1722 171.042C66.0855 195.771 89.5657 218.183 98.398 228.179C102.684 233.029 157.621 233.029 164.545 228.179C167.427 226.161 175.317 202.789 175.976 196.525Z" fill="#B2B2B2"/></g><defs><clipPath id="clip0_1451_461"><rect width="256" height="256" fill="white"/></clipPath></defs></svg> diff --git a/editor/icons/BoneMapHumanRightHand.svg b/editor/icons/BoneMapHumanRightHand.svg index 4e40af35d8..e92898152f 100644 --- a/editor/icons/BoneMapHumanRightHand.svg +++ b/editor/icons/BoneMapHumanRightHand.svg @@ -1 +1 @@ -<svg enable-background="new 0 0 1024 1024" height="1024" viewBox="0 0 1024 1024" width="1024" xmlns="http://www.w3.org/2000/svg"><path d="m0 0h1024v1024h-1024z" fill="#3f3f3f"/><path d="m320.094 786.098c-7.046-66.929-28.135-153.363-18.529-260.192 1.143-12.71 4.5-48.282 4.46-82.732-.025-21.174 2.111-48.505 1.975-64.174-.167-19.333.428-41.584.625-55.755 1.052-75.44 13.225-85.827 30.813-85.827 17.246 0 26.77 14.266 27.062 84.582.061 14.42-.5 51-.5 58.5 0 17.508.333 34.167 0 53.5-.447 25.955 4.279 68 9 68 3.902 0 8.099-39.299 9.575-76.999.756-19.326 3.219-58.336 2.6-70.102-1.759-33.413-.474-58.914-1.537-90.165-3.183-93.607 13.016-111.729 34.695-111.729 21.973 0 35.979 57.688 34.849 114.224-.128 6.394 1.165 50.739-.188 89.859-.754 21.811 1.07 49.627 1.683 69.67 1.095 35.768 5.755 63.896 8.869 63.896 2.641 0 4.135-32.584 5.456-65.706.859-21.557 4.468-58.477 3.664-83.616-1.886-59.012 1.139-110.226 1.063-121.501-.635-94.955 14.66-123.101 36.052-123.101 21.476 0 37.188 30.192 36.6 123.343-.067 10.53 2.62 99.926 1.759 121.816-.865 21.992 2.773 65.062 3.517 84.818 1.299 34.521 6.49 63.947 9.124 63.947 3.281 0 10.794-25.638 11.724-60.965.587-22.275-1.231-50.99-.624-70.688 1.257-40.707 3.176-64.631 3.877-99.708 1.945-97.182 16.352-106.289 38.142-106.289 17.957 0 32.453 28.673 32.657 115.03.065 27.702 2.429 62.626.314 94.329-.805 12.081.622 42.512 1.875 73.894.799 20.007 1.102 47.501 1.137 63.775.171 78.595 26.713 133.424 36.556 131.308 30.333-6.521 51.648-43.918 71.219-117.307 10.551-39.566 36.667-71.149 69.9-77.813 25.9-5.193 19.783 46.161 1.318 125.293-8.649 37.068-27.909 86.227-39.566 122.655-31.652 98.917-125.573 188.563-160.902 228.546-17.146 19.403-236.894 19.403-264.59 0-11.525-8.07-43.087-101.557-45.724-126.616z" fill="#b2b2b2"/></svg> +<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_1451_464)"><path d="M0 0H256V256H0V0Z" fill="#3F3F3F"/><path d="M80.0233 196.525C78.2618 179.792 72.9896 158.184 75.3911 131.477C75.6768 128.299 76.5161 119.406 76.5061 110.794C76.4998 105.5 77.0338 98.6674 76.9998 94.7501C76.9581 89.9169 77.1068 84.3541 77.1561 80.8114C77.4191 61.9514 80.4623 59.3546 84.8593 59.3546C89.1708 59.3546 91.5518 62.9211 91.6248 80.5001C91.6401 84.1051 91.4998 93.2501 91.4998 95.1251C91.4998 99.5021 91.5831 103.667 91.4998 108.5C91.3881 114.989 92.5696 125.5 93.7498 125.5C94.7253 125.5 95.7746 115.675 96.1436 106.25C96.3326 101.419 96.9483 91.6664 96.7935 88.7249C96.3538 80.3716 96.6751 73.9964 96.4093 66.1836C95.6136 42.7819 99.6633 38.2514 105.083 38.2514C110.576 38.2514 114.078 52.6734 113.795 66.8074C113.763 68.4059 114.087 79.4921 113.748 89.2721C113.56 94.7249 114.016 101.679 114.169 106.69C114.443 115.632 115.608 122.664 116.386 122.664C117.047 122.664 117.42 114.518 117.75 106.237C117.965 100.848 118.867 91.6179 118.666 85.3331C118.195 70.5801 118.951 57.7766 118.932 54.9579C118.773 31.2191 122.597 24.1826 127.945 24.1826C133.314 24.1826 137.242 31.7306 137.095 55.0184C137.078 57.6509 137.75 79.9999 137.535 85.4724C137.319 90.9704 138.228 101.738 138.414 106.677C138.739 115.307 140.037 122.664 140.695 122.664C141.515 122.664 143.394 116.254 143.626 107.422C143.773 101.854 143.318 94.6749 143.47 89.7504C143.784 79.5736 144.264 73.5926 144.439 64.8234C144.926 40.5279 148.527 38.2511 153.975 38.2511C158.464 38.2511 162.088 45.4194 162.139 67.0086C162.155 73.9341 162.746 82.6651 162.218 90.5909C162.016 93.6111 162.373 101.219 162.686 109.064C162.886 114.066 162.962 120.94 162.971 125.008C163.013 144.657 169.649 158.364 172.11 157.835C179.693 156.205 185.022 146.856 189.914 128.508C192.552 118.617 199.081 110.721 207.389 109.055C213.864 107.757 212.335 120.595 207.719 140.378C205.557 149.645 200.742 161.935 197.827 171.042C189.914 195.771 166.434 218.183 157.602 228.179C153.315 233.029 98.3783 233.029 91.4543 228.179C88.5731 226.161 80.6826 202.789 80.0233 196.525Z" fill="#B2B2B2"/></g><defs><clipPath id="clip0_1451_464"><rect width="256" height="256" fill="white"/></clipPath></defs></svg> diff --git a/editor/plugins/dedicated_server_export_plugin.cpp b/editor/plugins/dedicated_server_export_plugin.cpp new file mode 100644 index 0000000000..013706034e --- /dev/null +++ b/editor/plugins/dedicated_server_export_plugin.cpp @@ -0,0 +1,139 @@ +/**************************************************************************/ +/* dedicated_server_export_plugin.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "dedicated_server_export_plugin.h" + +EditorExportPreset::FileExportMode DedicatedServerExportPlugin::_get_export_mode_for_path(const String &p_path) { + Ref<EditorExportPreset> preset = get_export_preset(); + ERR_FAIL_COND_V(preset.is_null(), EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED); + + EditorExportPreset::FileExportMode mode = preset->get_file_export_mode(p_path); + if (mode != EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED) { + return mode; + } + + String path = p_path; + if (path.begins_with("res://")) { + path = path.substr(6); + } + + Vector<String> parts = path.split("/"); + + while (parts.size() > 0) { + parts.resize(parts.size() - 1); + + String test_path = "res://"; + if (parts.size() > 0) { + test_path += String("/").join(parts) + "/"; + } + + mode = preset->get_file_export_mode(test_path); + if (mode != EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED) { + break; + } + } + + return mode; +} + +PackedStringArray DedicatedServerExportPlugin::_get_export_features(const Ref<EditorExportPlatform> &p_platform, bool p_debug) const { + PackedStringArray ret; + + Ref<EditorExportPreset> preset = get_export_preset(); + ERR_FAIL_COND_V(preset.is_null(), ret); + + if (preset->is_dedicated_server()) { + ret.append("dedicated_server"); + } + return ret; +} + +uint64_t DedicatedServerExportPlugin::_get_customization_configuration_hash() const { + Ref<EditorExportPreset> preset = get_export_preset(); + ERR_FAIL_COND_V(preset.is_null(), 0); + + if (preset->get_export_filter() != EditorExportPreset::EXPORT_CUSTOMIZED) { + return 0; + } + + return preset->get_customized_files().hash(); +} + +bool DedicatedServerExportPlugin::_begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) { + Ref<EditorExportPreset> preset = get_export_preset(); + ERR_FAIL_COND_V(preset.is_null(), false); + + current_export_mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED; + + return preset->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED; +} + +bool DedicatedServerExportPlugin::_begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) { + Ref<EditorExportPreset> preset = get_export_preset(); + ERR_FAIL_COND_V(preset.is_null(), false); + + current_export_mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED; + + return preset->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED; +} + +Node *DedicatedServerExportPlugin::_customize_scene(Node *p_root, const String &p_path) { + // Simply set the export mode based on the scene path. All the real + // customization happens in _customize_resource(). + current_export_mode = _get_export_mode_for_path(p_path); + return nullptr; +} + +Ref<Resource> DedicatedServerExportPlugin::_customize_resource(const Ref<Resource> &p_resource, const String &p_path) { + // If the resource has a path, we use that to get our export mode. But if it + // doesn't, we assume that this resource is embedded in the last resource with + // a path. + if (p_path != "") { + current_export_mode = _get_export_mode_for_path(p_path); + } + + if (p_resource.is_valid() && current_export_mode == EditorExportPreset::MODE_FILE_STRIP && p_resource->has_method("create_placeholder")) { + Callable::CallError err; + Ref<Resource> result = const_cast<Resource *>(p_resource.ptr())->callp("create_placeholder", nullptr, 0, err); + if (err.error == Callable::CallError::CALL_OK) { + return result; + } + } + + return Ref<Resource>(); +} + +void DedicatedServerExportPlugin::_end_customize_scenes() { + current_export_mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED; +} + +void DedicatedServerExportPlugin::_end_customize_resources() { + current_export_mode = EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED; +} diff --git a/editor/plugins/dedicated_server_export_plugin.h b/editor/plugins/dedicated_server_export_plugin.h new file mode 100644 index 0000000000..cb014ae52d --- /dev/null +++ b/editor/plugins/dedicated_server_export_plugin.h @@ -0,0 +1,58 @@ +/**************************************************************************/ +/* dedicated_server_export_plugin.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DEDICATED_SERVER_EXPORT_PLUGIN_H +#define DEDICATED_SERVER_EXPORT_PLUGIN_H + +#include "editor/export/editor_export.h" + +class DedicatedServerExportPlugin : public EditorExportPlugin { +private: + EditorExportPreset::FileExportMode current_export_mode; + + EditorExportPreset::FileExportMode _get_export_mode_for_path(const String &p_path); + +protected: + String _get_name() const override { return "DedicatedServer"; } + + PackedStringArray _get_export_features(const Ref<EditorExportPlatform> &p_platform, bool p_debug) const override; + uint64_t _get_customization_configuration_hash() const override; + + bool _begin_customize_scenes(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) override; + bool _begin_customize_resources(const Ref<EditorExportPlatform> &p_platform, const Vector<String> &p_features) override; + + Node *_customize_scene(Node *p_root, const String &p_path) override; + Ref<Resource> _customize_resource(const Ref<Resource> &p_resource, const String &p_path) override; + + void _end_customize_scenes() override; + void _end_customize_resources() override; +}; + +#endif // DEDICATED_SERVER_EXPORT_PLUGIN_H diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 3ee9823f3a..782e365138 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -266,15 +266,15 @@ void Skeleton3DEditor::reset_pose(const bool p_all_bones) { if (!skeleton) { return; } - const int bone_len = skeleton->get_bone_count(); - if (!bone_len) { + const int bone_count = skeleton->get_bone_count(); + if (!bone_count) { return; } EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); ur->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS); if (p_all_bones) { - for (int i = 0; i < bone_len; i++) { + for (int i = 0; i < bone_count; i++) { ur->add_undo_method(skeleton, "set_bone_pose_position", i, skeleton->get_bone_pose_position(i)); ur->add_undo_method(skeleton, "set_bone_pose_rotation", i, skeleton->get_bone_pose_rotation(i)); ur->add_undo_method(skeleton, "set_bone_pose_scale", i, skeleton->get_bone_pose_scale(i)); @@ -333,15 +333,15 @@ void Skeleton3DEditor::pose_to_rest(const bool p_all_bones) { if (!skeleton) { return; } - const int bone_len = skeleton->get_bone_count(); - if (!bone_len) { + const int bone_count = skeleton->get_bone_count(); + if (!bone_count) { return; } EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); ur->create_action(TTR("Set Bone Rest"), UndoRedo::MERGE_ENDS); if (p_all_bones) { - for (int i = 0; i < bone_len; i++) { + for (int i = 0; i < bone_count; i++) { ur->add_do_method(skeleton, "set_bone_rest", i, skeleton->get_bone_pose(i)); ur->add_undo_method(skeleton, "set_bone_rest", i, skeleton->get_bone_rest(i)); } @@ -362,57 +362,56 @@ void Skeleton3DEditor::create_physical_skeleton() { ERR_FAIL_COND(!get_tree()); Node *owner = get_tree()->get_edited_scene_root(); - const int bc = skeleton->get_bone_count(); + const int bone_count = skeleton->get_bone_count(); - if (!bc) { + if (!bone_count) { + EditorNode::get_singleton()->show_warning(vformat(TTR("Cannot create a physical skeleton for a Skeleton3D node with no bones."))); return; } Vector<BoneInfo> bones_infos; - bones_infos.resize(bc); + bones_infos.resize(bone_count); - if (bc > 0) { - ur->create_action(TTR("Create physical bones"), UndoRedo::MERGE_ALL); - for (int bone_id = 0; bc > bone_id; ++bone_id) { - const int parent = skeleton->get_bone_parent(bone_id); + ur->create_action(TTR("Create physical bones"), UndoRedo::MERGE_ALL); + for (int bone_id = 0; bone_count > bone_id; ++bone_id) { + const int parent = skeleton->get_bone_parent(bone_id); - if (parent < 0) { - bones_infos.write[bone_id].relative_rest = skeleton->get_bone_rest(bone_id); - } else { - const int parent_parent = skeleton->get_bone_parent(parent); - - bones_infos.write[bone_id].relative_rest = bones_infos[parent].relative_rest * skeleton->get_bone_rest(bone_id); - - // Create physical bone on parent. - if (!bones_infos[parent].physical_bone) { - PhysicalBone3D *physical_bone = create_physical_bone(parent, bone_id, bones_infos); - if (physical_bone && physical_bone->get_child(0)) { - CollisionShape3D *collision_shape = Object::cast_to<CollisionShape3D>(physical_bone->get_child(0)); - if (collision_shape) { - bones_infos.write[parent].physical_bone = physical_bone; - - ur->add_do_method(skeleton, "add_child", physical_bone); - ur->add_do_method(physical_bone, "set_owner", owner); - ur->add_do_method(collision_shape, "set_owner", owner); - ur->add_do_property(physical_bone, "bone_name", skeleton->get_bone_name(parent)); - - // Create joint between parent of parent. - if (parent_parent != -1) { - ur->add_do_method(physical_bone, "set_joint_type", PhysicalBone3D::JOINT_TYPE_PIN); - } + if (parent < 0) { + bones_infos.write[bone_id].relative_rest = skeleton->get_bone_rest(bone_id); + } else { + const int parent_parent = skeleton->get_bone_parent(parent); + + bones_infos.write[bone_id].relative_rest = bones_infos[parent].relative_rest * skeleton->get_bone_rest(bone_id); + + // Create physical bone on parent. + if (!bones_infos[parent].physical_bone) { + PhysicalBone3D *physical_bone = create_physical_bone(parent, bone_id, bones_infos); + if (physical_bone && physical_bone->get_child(0)) { + CollisionShape3D *collision_shape = Object::cast_to<CollisionShape3D>(physical_bone->get_child(0)); + if (collision_shape) { + bones_infos.write[parent].physical_bone = physical_bone; + + ur->add_do_method(skeleton, "add_child", physical_bone); + ur->add_do_method(physical_bone, "set_owner", owner); + ur->add_do_method(collision_shape, "set_owner", owner); + ur->add_do_property(physical_bone, "bone_name", skeleton->get_bone_name(parent)); + + // Create joint between parent of parent. + if (parent_parent != -1) { + ur->add_do_method(physical_bone, "set_joint_type", PhysicalBone3D::JOINT_TYPE_PIN); + } - ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, physical_bone); - ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, collision_shape); + ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, physical_bone); + ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, collision_shape); - ur->add_do_reference(physical_bone); - ur->add_undo_method(skeleton, "remove_child", physical_bone); - } + ur->add_do_reference(physical_bone); + ur->add_undo_method(skeleton, "remove_child", physical_bone); } } } } - ur->commit_action(); } + ur->commit_action(); } PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_child_id, const Vector<BoneInfo> &bones_infos) { @@ -457,6 +456,11 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi } void Skeleton3DEditor::export_skeleton_profile() { + if (!skeleton->get_bone_count()) { + EditorNode::get_singleton()->show_warning(vformat(TTR("Cannot export a SkeletonProfile for a Skeleton3D node with no bones."))); + return; + } + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); file_dialog->set_title(TTR("Export Skeleton Profile As...")); @@ -481,9 +485,9 @@ void Skeleton3DEditor::_file_selected(const String &p_file) { Vector2 position_max; Vector2 position_min; - int len = skeleton->get_bone_count(); - sp->set_bone_size(len); - for (int i = 0; i < len; i++) { + const int bone_count = skeleton->get_bone_count(); + sp->set_bone_size(bone_count); + for (int i = 0; i < bone_count; i++) { sp->set_bone_name(i, skeleton->get_bone_name(i)); int parent = skeleton->get_bone_parent(i); if (parent >= 0) { @@ -509,7 +513,7 @@ void Skeleton3DEditor::_file_selected(const String &p_file) { Vector2 center = Vector2((position_max.x + position_min.x) * 0.5, (position_max.y + position_min.y) * 0.5); float nrm = MAX(bound.x, bound.y); if (nrm > 0) { - for (int i = 0; i < len; i++) { + for (int i = 0; i < bone_count; i++) { handle_positions.write[i] = (handle_positions[i] - center) / nrm * 0.9; sp->set_handle_offset(i, Vector2(0.5 + handle_positions[i].x, 0.5 - handle_positions[i].y)); } @@ -980,25 +984,31 @@ void Skeleton3DEditor::_draw_gizmo() { } void Skeleton3DEditor::_draw_handles() { - handles_mesh_instance->show(); + const int bone_count = skeleton->get_bone_count(); - const int bone_len = skeleton->get_bone_count(); handles_mesh->clear_surfaces(); - handles_mesh->surface_begin(Mesh::PRIMITIVE_POINTS); - for (int i = 0; i < bone_len; i++) { - Color c; - if (i == selected_bone) { - c = Color(1, 1, 0); - } else { - c = Color(0.1, 0.25, 0.8); + if (bone_count) { + handles_mesh_instance->show(); + + handles_mesh->surface_begin(Mesh::PRIMITIVE_POINTS); + + for (int i = 0; i < bone_count; i++) { + Color c; + if (i == selected_bone) { + c = Color(1, 1, 0); + } else { + c = Color(0.1, 0.25, 0.8); + } + Vector3 point = skeleton->get_bone_global_pose(i).origin; + handles_mesh->surface_set_color(c); + handles_mesh->surface_add_vertex(point); } - Vector3 point = skeleton->get_bone_global_pose(i).origin; - handles_mesh->surface_set_color(c); - handles_mesh->surface_add_vertex(point); + handles_mesh->surface_end(); + handles_mesh->surface_set_material(0, handle_material); + } else { + handles_mesh_instance->hide(); } - handles_mesh->surface_end(); - handles_mesh->surface_set_material(0, handle_material); } TreeItem *Skeleton3DEditor::_find(TreeItem *p_node, const NodePath &p_path) { @@ -1253,8 +1263,8 @@ int Skeleton3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gi Transform3D gt = skeleton->get_global_transform(); int closest_idx = -1; real_t closest_dist = 1e10; - const int bone_len = skeleton->get_bone_count(); - for (int i = 0; i < bone_len; i++) { + const int bone_count = skeleton->get_bone_count(); + for (int i = 0; i < bone_count; i++) { Vector3 joint_pos_3d = gt.xform(skeleton->get_bone_global_pose(i).origin); Vector2 joint_pos_2d = p_camera->unproject_position(joint_pos_3d); real_t dist_3d = ray_from.distance_to(joint_pos_3d); @@ -1349,6 +1359,10 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_gizmo->get_node_3d()); p_gizmo->clear(); + if (!skeleton->get_bone_count()) { + return; + } + int selected = -1; Skeleton3DEditor *se = Skeleton3DEditor::get_singleton(); if (se) { |