diff options
Diffstat (limited to 'editor')
21 files changed, 286 insertions, 229 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 5b24fb1559..134733fa11 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -456,6 +456,9 @@ void EditorNode::_update_from_settings() { void EditorNode::_gdextensions_reloaded() { // In case the developer is inspecting an object that will be changed by the reload. InspectorDock::get_inspector_singleton()->update_tree(); + + // Regenerate documentation. + EditorHelp::generate_doc(); } void EditorNode::_select_default_main_screen_plugin() { diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index 33fdd7418e..aa44189782 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -510,6 +510,12 @@ HashSet<String> EditorExportPlatform::get_features(const Ref<EditorExportPreset> result.insert("template_release"); } +#ifdef REAL_T_IS_DOUBLE + result.insert("double"); +#else + result.insert("single"); +#endif // REAL_T_IS_DOUBLE + if (!p_preset->get_custom_features().is_empty()) { Vector<String> tmp_custom_list = p_preset->get_custom_features().split(","); diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index 038e357ce2..c995e590f1 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -419,6 +419,12 @@ void ProjectExportDialog::_update_feature_list() { feature_set.insert(E); } +#ifdef REAL_T_IS_DOUBLE + feature_set.insert("double"); +#else + feature_set.insert("single"); +#endif // REAL_T_IS_DOUBLE + custom_feature_display->clear(); String text; bool first = true; diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index b7deb6afa6..12c2408d0f 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -2394,6 +2394,12 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected } } break; + case FILE_SHOW_IN_FILESYSTEM: { + if (!p_selected.is_empty()) { + navigate_to_path(p_selected[0]); + } + } break; + case FILE_DEPENDENCIES: { // Checkout the file dependencies. if (!p_selected.is_empty()) { @@ -3286,8 +3292,33 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, const Vect if (p_paths.size() == 1) { const String &fpath = p_paths[0]; + bool added_separator = false; + + if (favorites_list.has(fpath)) { + TreeItem *favorites_item = tree->get_root()->get_first_child(); + TreeItem *cursor_item = tree->get_selected(); + bool is_item_in_favorites = false; + while (cursor_item != nullptr) { + if (cursor_item == favorites_item) { + is_item_in_favorites = true; + break; + } + + cursor_item = cursor_item->get_parent(); + } + + if (is_item_in_favorites) { + p_popup->add_separator(); + added_separator = true; + p_popup->add_icon_item(get_editor_theme_icon(SNAME("ShowInFileSystem")), TTR("Show in FileSystem"), FILE_SHOW_IN_FILESYSTEM); + } + } + #if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED) - p_popup->add_separator(); + if (!added_separator) { + p_popup->add_separator(); + added_separator = true; + } // Opening the system file manager is not supported on the Android and web editors. const bool is_directory = fpath.ends_with("/"); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 058886c91a..7449657c06 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -116,6 +116,7 @@ private: FILE_INSTANTIATE, FILE_ADD_FAVORITE, FILE_REMOVE_FAVORITE, + FILE_SHOW_IN_FILESYSTEM, FILE_DEPENDENCIES, FILE_OWNERS, FILE_MOVE, diff --git a/editor/gui/editor_dir_dialog.cpp b/editor/gui/editor_dir_dialog.cpp index 9d5464210b..08612f419c 100644 --- a/editor/gui/editor_dir_dialog.cpp +++ b/editor/gui/editor_dir_dialog.cpp @@ -117,23 +117,13 @@ void EditorDirDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { FileSystemDock::get_singleton()->connect("folder_color_changed", callable_mp(this, &EditorDirDialog::reload).bind("")); - EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &EditorDirDialog::reload).bind("")); reload(); - - if (!tree->is_connected("item_collapsed", callable_mp(this, &EditorDirDialog::_item_collapsed))) { - tree->connect("item_collapsed", callable_mp(this, &EditorDirDialog::_item_collapsed), CONNECT_DEFERRED); - } - - if (!EditorFileSystem::get_singleton()->is_connected("filesystem_changed", callable_mp(this, &EditorDirDialog::reload))) { - EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &EditorDirDialog::reload).bind("")); - } } break; case NOTIFICATION_EXIT_TREE: { - if (EditorFileSystem::get_singleton()->is_connected("filesystem_changed", callable_mp(this, &EditorDirDialog::reload))) { - EditorFileSystem::get_singleton()->disconnect("filesystem_changed", callable_mp(this, &EditorDirDialog::reload)); - } + EditorFileSystem::get_singleton()->disconnect("filesystem_changed", callable_mp(this, &EditorDirDialog::reload)); + FileSystemDock::get_singleton()->disconnect("folder_color_changed", callable_mp(this, &EditorDirDialog::reload)); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -229,6 +219,7 @@ EditorDirDialog::EditorDirDialog() { vb->add_child(tree); tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); tree->connect("item_activated", callable_mp(this, &EditorDirDialog::_item_activated)); + tree->connect("item_collapsed", callable_mp(this, &EditorDirDialog::_item_collapsed), CONNECT_DEFERRED); set_ok_button_text(TTR("Move")); diff --git a/editor/import/3d/editor_import_collada.cpp b/editor/import/3d/editor_import_collada.cpp index 4b91b1431a..04a3f23154 100644 --- a/editor/import/3d/editor_import_collada.cpp +++ b/editor/import/3d/editor_import_collada.cpp @@ -1556,6 +1556,7 @@ void ColladaImport::create_animation(int p_clip, bool p_import_value_tracks) { } animation->set_length(anim_length); + animation->set_step(snapshot_interval); bool tracks_found = false; diff --git a/editor/import/3d/resource_importer_scene.cpp b/editor/import/3d/resource_importer_scene.cpp index dce68a97ac..2560d43241 100644 --- a/editor/import/3d/resource_importer_scene.cpp +++ b/editor/import/3d/resource_importer_scene.cpp @@ -1908,6 +1908,7 @@ void ResourceImporterScene::_create_slices(AnimationPlayer *ap, Ref<Animation> a new_anim->set_loop_mode(loop_mode); new_anim->set_length(to - from); + new_anim->set_step(anim->get_step()); al->add_animation(name, new_anim); diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index 6f4a376496..fa503cc4df 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -200,7 +200,8 @@ void ImportDock::_update_options(const String &p_path, const Ref<ConfigFile> &p_ params->update(); _update_preset_menu(); - if (params->importer.is_valid() && params->paths.size() == 1 && params->importer->has_advanced_options()) { + bool was_imported = p_config.is_valid() && p_config->get_value("remap", "importer") != "skip" && p_config->get_value("remap", "importer") != "keep"; + if (was_imported && params->importer.is_valid() && params->paths.size() == 1 && params->importer->has_advanced_options()) { advanced->show(); advanced_spacer->show(); } else { @@ -508,6 +509,18 @@ static bool _find_owners(EditorFileSystemDirectory *efsd, const String &p_path) return false; } +void ImportDock::_reimport_pressed() { + _reimport_attempt(); + + if (params->importer.is_valid() && params->paths.size() == 1 && params->importer->has_advanced_options()) { + advanced->show(); + advanced_spacer->show(); + } else { + advanced->hide(); + advanced_spacer->hide(); + } +} + void ImportDock::_reimport_attempt() { bool used_in_resources = false; @@ -528,7 +541,7 @@ void ImportDock::_reimport_attempt() { ERR_CONTINUE(err != OK); String imported_with = config->get_value("remap", "importer"); - if (imported_with != importer_name) { + if (imported_with != importer_name && imported_with != "keep" && imported_with != "skip") { Ref<Resource> resource = ResourceLoader::load(params->paths[i]); if (resource.is_valid()) { need_cleanup.push_back(params->paths[i]); @@ -575,7 +588,10 @@ void ImportDock::_reimport_and_cleanup() { for (const String &path : need_cleanup) { Ref<Resource> old_res = old_resources[path]; - Ref<Resource> new_res = ResourceLoader::load(path); + Ref<Resource> new_res; + if (params->importer.is_valid()) { + new_res = ResourceLoader::load(path); + } for (int i = 0; i < EditorNode::get_editor_data().get_edited_scene_count(); i++) { Node *edited_scene_root = EditorNode::get_editor_data().get_edited_scene_root(i); @@ -782,7 +798,7 @@ ImportDock::ImportDock() { import = memnew(Button); import->set_text(TTR("Reimport")); import->set_disabled(true); - import->connect("pressed", callable_mp(this, &ImportDock::_reimport_attempt)); + import->connect("pressed", callable_mp(this, &ImportDock::_reimport_pressed)); if (!DisplayServer::get_singleton()->get_swap_cancel_ok()) { advanced_spacer = hb->add_spacer(); advanced = memnew(Button); diff --git a/editor/import_dock.h b/editor/import_dock.h index 78cd6a556c..c0a1dee7ca 100644 --- a/editor/import_dock.h +++ b/editor/import_dock.h @@ -76,6 +76,7 @@ class ImportDock : public VBoxContainer { void _property_edited(const StringName &p_prop); void _property_toggled(const StringName &p_prop, bool p_checked); void _set_dirty(bool p_dirty); + void _reimport_pressed(); void _reimport_attempt(); void _reimport_and_cleanup(); void _reimport(); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 43928b9c17..3399f265fc 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -548,8 +548,13 @@ void AnimationPlayerEditor::_animation_name_edited() { } break; case TOOL_NEW_ANIM: { + String current = animation->get_item_text(animation->get_selected()); + Ref<Animation> current_anim = player->get_animation(current); Ref<Animation> new_anim = Ref<Animation>(memnew(Animation)); new_anim->set_name(new_name); + if (current_anim.is_valid()) { + new_anim->set_step(current_anim->get_step()); + } String library_name; Ref<AnimationLibrary> al; library_name = library->get_item_metadata(library->get_selected()); diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp index d62eddeeea..0c922ea070 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp @@ -59,200 +59,159 @@ void MeshInstance3DEditor::edit(MeshInstance3D *p_mesh) { node = p_mesh; } -void MeshInstance3DEditor::_menu_option(int p_option) { - Ref<Mesh> mesh = node->get_mesh(); - if (mesh.is_null()) { - err_dialog->set_text(TTR("Mesh is empty!")); - err_dialog->popup_centered(); - return; - } - +Vector<Ref<Shape3D>> MeshInstance3DEditor::create_shape_from_mesh(Ref<Mesh> p_mesh, int p_option, bool p_verbose) { + Vector<Ref<Shape3D>> shapes; switch (p_option) { - case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: { - EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection(); - EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - - List<Node *> selection = editor_selection->get_selected_node_list(); - - if (selection.is_empty()) { - Ref<ConcavePolygonShape3D> shape = mesh->create_trimesh_shape(); - if (shape.is_null()) { - err_dialog->set_text(TTR("Couldn't create a Trimesh collision shape.")); - err_dialog->popup_centered(); - return; - } - - CollisionShape3D *cshape = memnew(CollisionShape3D); - cshape->set_shape(shape); - StaticBody3D *body = memnew(StaticBody3D); - body->add_child(cshape, true); - - Node *owner = get_tree()->get_edited_scene_root(); - - ur->create_action(TTR("Create Static Trimesh Body")); - ur->add_do_method(node, "add_child", body, true); - ur->add_do_method(body, "set_owner", owner); - ur->add_do_method(cshape, "set_owner", owner); - ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, body); - ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape); - ur->add_do_reference(body); - ur->add_undo_method(node, "remove_child", body); - ur->commit_action(); - return; - } + case SHAPE_TYPE_TRIMESH: { + shapes.push_back(p_mesh->create_trimesh_shape()); - ur->create_action(TTR("Create Static Trimesh Body")); - - for (Node *E : selection) { - MeshInstance3D *instance = Object::cast_to<MeshInstance3D>(E); - if (!instance) { - continue; - } - - Ref<Mesh> m = instance->get_mesh(); - if (m.is_null()) { - continue; - } - - Ref<ConcavePolygonShape3D> shape = m->create_trimesh_shape(); - if (shape.is_null()) { - continue; - } - - CollisionShape3D *cshape = memnew(CollisionShape3D); - cshape->set_shape(shape); - StaticBody3D *body = memnew(StaticBody3D); - body->add_child(cshape, true); - - Node *owner = get_tree()->get_edited_scene_root(); - - ur->add_do_method(instance, "add_child", body, true); - ur->add_do_method(body, "set_owner", owner); - ur->add_do_method(cshape, "set_owner", owner); - ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, body); - ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape); - ur->add_do_reference(body); - ur->add_undo_method(instance, "remove_child", body); + if (p_verbose && shapes.is_empty()) { + err_dialog->set_text(TTR("Couldn't create a Trimesh collision shape.")); + err_dialog->popup_centered(); } - - ur->commit_action(); - } break; - case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE: { - if (node == get_tree()->get_edited_scene_root()) { - err_dialog->set_text(TTR("This doesn't work on scene root!")); - err_dialog->popup_centered(); - return; - } + case SHAPE_TYPE_SINGLE_CONVEX: { + shapes.push_back(p_mesh->create_convex_shape(true, false)); - Ref<ConcavePolygonShape3D> shape = mesh->create_trimesh_shape(); - if (shape.is_null()) { - return; + if (p_verbose && shapes.is_empty()) { + err_dialog->set_text(TTR("Couldn't create a single collision shape.")); + err_dialog->popup_centered(); } - - CollisionShape3D *cshape = memnew(CollisionShape3D); - cshape->set_shape(shape); - cshape->set_transform(node->get_transform()); - - Node *owner = get_tree()->get_edited_scene_root(); - - EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - - ur->create_action(TTR("Create Trimesh Static Shape")); - - ur->add_do_method(node->get_parent(), "add_child", cshape, true); - ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1); - ur->add_do_method(cshape, "set_owner", owner); - ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape); - ur->add_do_reference(cshape); - ur->add_undo_method(node->get_parent(), "remove_child", cshape); - ur->commit_action(); } break; - case MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE: - case MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE: { - if (node == get_tree()->get_edited_scene_root()) { - err_dialog->set_text(TTR("Can't create a single convex collision shape for the scene root.")); + case SHAPE_TYPE_SIMPLIFIED_CONVEX: { + shapes.push_back(p_mesh->create_convex_shape(true, true)); + + if (p_verbose && shapes.is_empty()) { + err_dialog->set_text(TTR("Couldn't create a simplified collision shape.")); err_dialog->popup_centered(); - return; } + } break; - bool simplify = (p_option == MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE); + case SHAPE_TYPE_MULTIPLE_CONVEX: { + Ref<MeshConvexDecompositionSettings> settings; + settings.instantiate(); + settings->set_max_convex_hulls(32); + settings->set_max_concavity(0.001); - Ref<ConvexPolygonShape3D> shape = mesh->create_convex_shape(true, simplify); + shapes = p_mesh->convex_decompose(settings); - if (shape.is_null()) { - err_dialog->set_text(TTR("Couldn't create a single convex collision shape.")); + if (p_verbose && shapes.is_empty()) { + err_dialog->set_text(TTR("Couldn't create any collision shapes.")); err_dialog->popup_centered(); - return; } - EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); + } break; - if (simplify) { - ur->create_action(TTR("Create Simplified Convex Shape")); - } else { - ur->create_action(TTR("Create Single Convex Shape")); - } + default: + break; + } + return shapes; +} - CollisionShape3D *cshape = memnew(CollisionShape3D); - cshape->set_shape(shape); - cshape->set_transform(node->get_transform()); +void MeshInstance3DEditor::_create_collision_shape() { + int placement_option = shape_placement->get_selected(); + int shape_type_option = shape_type->get_selected(); - Node *owner = get_tree()->get_edited_scene_root(); + EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection(); + EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->add_do_method(node->get_parent(), "add_child", cshape, true); - ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1); - ur->add_do_method(cshape, "set_owner", owner); - ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape); - ur->add_do_reference(cshape); - ur->add_undo_method(node->get_parent(), "remove_child", cshape); + switch (shape_type_option) { + case SHAPE_TYPE_TRIMESH: { + ur->create_action(TTR(placement_option == SHAPE_PLACEMENT_SIBLING ? "Create Trimesh Collision Shape Sibling" : "Create Trimesh Static Body")); + } break; + case SHAPE_TYPE_SINGLE_CONVEX: { + ur->create_action(TTR(placement_option == SHAPE_PLACEMENT_SIBLING ? "Create Single Convex Collision Shape Sibling" : "Create Single Convex Static Body")); + } break; + case SHAPE_TYPE_SIMPLIFIED_CONVEX: { + ur->create_action(TTR(placement_option == SHAPE_PLACEMENT_SIBLING ? "Create Simplified Convex Collision Shape Sibling" : "Create Simplified Convex Static Body")); + } break; + case SHAPE_TYPE_MULTIPLE_CONVEX: { + ur->create_action(TTR(placement_option == SHAPE_PLACEMENT_SIBLING ? "Create Multiple Convex Collision Shape Siblings" : "Create Multiple Convex Static Body")); + } break; + default: + break; + } - ur->commit_action(); + List<Node *> selection = editor_selection->get_selected_node_list(); - } break; + bool verbose = false; + if (selection.is_empty()) { + selection.push_back(node); + verbose = true; + } - case MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES: { - if (node == get_tree()->get_edited_scene_root()) { - err_dialog->set_text(TTR("Can't create multiple convex collision shapes for the scene root.")); + for (Node *E : selection) { + if (placement_option == SHAPE_PLACEMENT_SIBLING && E == get_tree()->get_edited_scene_root()) { + if (verbose) { + err_dialog->set_text(TTR("Can't create a collision shape as sibling for the scene root.")); err_dialog->popup_centered(); - return; } + continue; + } - Ref<MeshConvexDecompositionSettings> settings = Ref<MeshConvexDecompositionSettings>(); - settings.instantiate(); - settings->set_max_convex_hulls(32); - settings->set_max_concavity(0.001); + MeshInstance3D *instance = Object::cast_to<MeshInstance3D>(E); + if (!instance) { + continue; + } - Vector<Ref<Shape3D>> shapes = mesh->convex_decompose(settings); + Ref<Mesh> m = instance->get_mesh(); + if (m.is_null()) { + continue; + } - if (!shapes.size()) { - err_dialog->set_text(TTR("Couldn't create any collision shapes.")); - err_dialog->popup_centered(); - return; - } - EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); + Vector<Ref<Shape3D>> shapes = create_shape_from_mesh(m, shape_type_option, verbose); + if (shapes.is_empty()) { + return; + } + + Node *owner = get_tree()->get_edited_scene_root(); + if (placement_option == SHAPE_PLACEMENT_STATIC_BODY_CHILD) { + StaticBody3D *body = memnew(StaticBody3D); - ur->create_action(TTR("Create Multiple Convex Shapes")); + ur->add_do_method(instance, "add_child", body, true); + ur->add_do_method(body, "set_owner", owner); + ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, body); - for (int i = 0; i < shapes.size(); i++) { + for (Ref<Shape3D> shape : shapes) { CollisionShape3D *cshape = memnew(CollisionShape3D); + cshape->set_shape(shape); + body->add_child(cshape, true); + ur->add_do_method(cshape, "set_owner", owner); + ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape); + } + ur->add_do_reference(body); + ur->add_undo_method(instance, "remove_child", body); + } else { + for (Ref<Shape3D> shape : shapes) { + CollisionShape3D *cshape = memnew(CollisionShape3D); + cshape->set_shape(shape); cshape->set_name("CollisionShape3D"); - - cshape->set_shape(shapes[i]); cshape->set_transform(node->get_transform()); - - Node *owner = get_tree()->get_edited_scene_root(); - - ur->add_do_method(node->get_parent(), "add_child", cshape); - ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1); + ur->add_do_method(E->get_parent(), "add_child", cshape); + ur->add_do_method(E->get_parent(), "move_child", cshape, E->get_index() + 1); ur->add_do_method(cshape, "set_owner", owner); ur->add_do_method(Node3DEditor::get_singleton(), SceneStringNames::get_singleton()->_request_gizmo, cshape); ur->add_do_reference(cshape); ur->add_undo_method(node->get_parent(), "remove_child", cshape); } - ur->commit_action(); + } + } + + ur->commit_action(); +} + +void MeshInstance3DEditor::_menu_option(int p_option) { + Ref<Mesh> mesh = node->get_mesh(); + if (mesh.is_null()) { + err_dialog->set_text(TTR("Mesh is empty!")); + err_dialog->popup_centered(); + return; + } + switch (p_option) { + case MENU_OPTION_CREATE_COLLISION_SHAPE: { + shape_dialog->popup_centered(); } break; case MENU_OPTION_CREATE_NAVMESH: { @@ -571,18 +530,7 @@ MeshInstance3DEditor::MeshInstance3DEditor() { options->set_switch_on_hover(true); Node3DEditor::get_singleton()->add_control_to_menu_panel(options); - options->get_popup()->add_item(TTR("Create Trimesh Static Body"), MENU_OPTION_CREATE_STATIC_TRIMESH_BODY); - options->get_popup()->set_item_tooltip(-1, TTR("Creates a StaticBody3D and assigns a polygon-based collision shape to it automatically.\nThis is the most accurate (but slowest) option for collision detection.")); - options->get_popup()->add_separator(); - options->get_popup()->add_item(TTR("Create Trimesh Collision Sibling"), MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE); - options->get_popup()->set_item_tooltip(-1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection.")); - options->get_popup()->add_item(TTR("Create Single Convex Collision Sibling"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE); - options->get_popup()->set_item_tooltip(-1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection.")); - options->get_popup()->add_item(TTR("Create Simplified Convex Collision Sibling"), MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE); - options->get_popup()->set_item_tooltip(-1, TTR("Creates a simplified convex collision shape.\nThis is similar to single collision shape, but can result in a simpler geometry in some cases, at the cost of accuracy.")); - options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES); - options->get_popup()->set_item_tooltip(-1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between a single convex collision and a polygon-based collision.")); - options->get_popup()->add_separator(); + options->get_popup()->add_item(TTR("Create Collision Shape..."), MENU_OPTION_CREATE_COLLISION_SHAPE); options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Create Outline Mesh..."), MENU_OPTION_CREATE_OUTLINE_MESH); @@ -613,6 +561,44 @@ MeshInstance3DEditor::MeshInstance3DEditor() { add_child(outline_dialog); outline_dialog->connect("confirmed", callable_mp(this, &MeshInstance3DEditor::_create_outline_mesh)); + shape_dialog = memnew(ConfirmationDialog); + shape_dialog->set_title(TTR("Create Collision Shape")); + shape_dialog->set_ok_button_text(TTR("Create")); + + VBoxContainer *shape_dialog_vbc = memnew(VBoxContainer); + shape_dialog->add_child(shape_dialog_vbc); + + Label *l = memnew(Label); + l->set_text(TTR("Collision Shape placement")); + shape_dialog_vbc->add_child(l); + + shape_placement = memnew(OptionButton); + shape_placement->set_h_size_flags(SIZE_EXPAND_FILL); + shape_placement->add_item(TTR("Sibling"), SHAPE_PLACEMENT_SIBLING); + shape_placement->set_item_tooltip(-1, TTR("Creates collision shapes as Sibling.")); + shape_placement->add_item(TTR("Static Body Child"), SHAPE_PLACEMENT_STATIC_BODY_CHILD); + shape_placement->set_item_tooltip(-1, TTR("Creates a StaticBody3D as child and assigns collision shapes to it.")); + shape_dialog_vbc->add_child(shape_placement); + + l = memnew(Label); + l->set_text(TTR("Collision Shape Type")); + shape_dialog_vbc->add_child(l); + + shape_type = memnew(OptionButton); + shape_type->set_h_size_flags(SIZE_EXPAND_FILL); + shape_type->add_item(TTR("Trimesh"), SHAPE_TYPE_TRIMESH); + shape_type->set_item_tooltip(-1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection.")); + shape_type->add_item(TTR("Single Convex"), SHAPE_TYPE_SINGLE_CONVEX); + shape_type->set_item_tooltip(-1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection.")); + shape_type->add_item(TTR("Simplified Convex"), SHAPE_TYPE_SIMPLIFIED_CONVEX); + shape_type->set_item_tooltip(-1, TTR("Creates a simplified convex collision shape.\nThis is similar to single collision shape, but can result in a simpler geometry in some cases, at the cost of accuracy.")); + shape_type->add_item(TTR("Multiple Convex"), SHAPE_TYPE_MULTIPLE_CONVEX); + shape_type->set_item_tooltip(-1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between a single convex collision and a polygon-based collision.")); + shape_dialog_vbc->add_child(shape_type); + + add_child(shape_dialog); + shape_dialog->connect("confirmed", callable_mp(this, &MeshInstance3DEditor::_create_collision_shape)); + err_dialog = memnew(AcceptDialog); add_child(err_dialog); diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h index eb984e240e..ce7d23239c 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.h +++ b/editor/plugins/mesh_instance_3d_editor_plugin.h @@ -33,6 +33,7 @@ #include "editor/editor_plugin.h" #include "scene/3d/mesh_instance_3d.h" +#include "scene/gui/option_button.h" class AcceptDialog; class ConfirmationDialog; @@ -43,11 +44,7 @@ class MeshInstance3DEditor : public Control { GDCLASS(MeshInstance3DEditor, Control); enum Menu { - MENU_OPTION_CREATE_STATIC_TRIMESH_BODY, - MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE, - MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE, - MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE, - MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES, + MENU_OPTION_CREATE_COLLISION_SHAPE, MENU_OPTION_CREATE_NAVMESH, MENU_OPTION_CREATE_OUTLINE_MESH, MENU_OPTION_CREATE_DEBUG_TANGENTS, @@ -56,6 +53,18 @@ class MeshInstance3DEditor : public Control { MENU_OPTION_DEBUG_UV2, }; + enum ShapePlacement { + SHAPE_PLACEMENT_SIBLING, + SHAPE_PLACEMENT_STATIC_BODY_CHILD, + }; + + enum ShapeType { + SHAPE_TYPE_TRIMESH, + SHAPE_TYPE_SINGLE_CONVEX, + SHAPE_TYPE_SIMPLIFIED_CONVEX, + SHAPE_TYPE_MULTIPLE_CONVEX, + }; + MeshInstance3D *node = nullptr; MenuButton *options = nullptr; @@ -63,12 +72,18 @@ class MeshInstance3DEditor : public Control { ConfirmationDialog *outline_dialog = nullptr; SpinBox *outline_size = nullptr; + ConfirmationDialog *shape_dialog = nullptr; + OptionButton *shape_type = nullptr; + OptionButton *shape_placement = nullptr; + AcceptDialog *err_dialog = nullptr; AcceptDialog *debug_uv_dialog = nullptr; Control *debug_uv = nullptr; Vector<Vector2> uv_lines; + void _create_collision_shape(); + Vector<Ref<Shape3D>> create_shape_from_mesh(Ref<Mesh> p_mesh, int p_option, bool p_verbose); void _menu_option(int p_option); void _create_outline_mesh(); diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index 1cffdb6454..4e317114a3 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -169,21 +169,17 @@ void Path3DGizmo::set_handle(int p_id, bool p_secondary, Camera3D *p_camera, con const Basis posture = c->get_point_baked_posture(idx); const Vector3 tangent = -posture.get_column(2); const Vector3 up = posture.get_column(1); - const Plane p_tilt = Plane(tangent, position); + const Plane tilt_plane_global = gt.xform(Plane(tangent, position)); Vector3 intersection; - if (p_tilt.intersects_ray(ray_from, ray_dir, &intersection)) { - Vector3 direction = intersection - position; - direction.normalize(); // FIXME: redundant? + if (tilt_plane_global.intersects_ray(ray_from, ray_dir, &intersection)) { + Vector3 direction = gi.xform(intersection) - position; real_t tilt_angle = up.signed_angle_to(direction, tangent); if (Node3DEditor::get_singleton()->is_snap_enabled()) { - real_t snap = Node3DEditor::get_singleton()->get_rotate_snap(); - - tilt_angle = Math::rad_to_deg(tilt_angle) + snap * 0.5; // Else it won't reach +180. - tilt_angle -= Math::fmod(tilt_angle, snap); - tilt_angle = Math::deg_to_rad(tilt_angle); + real_t snap_degrees = Node3DEditor::get_singleton()->get_rotate_snap(); + tilt_angle = Math::deg_to_rad(Math::snapped(Math::rad_to_deg(tilt_angle), snap_degrees)); } c->set_point_tilt(idx, tilt_angle); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 707cf13cad..24ec607f63 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -293,8 +293,7 @@ void Polygon2DEditor::_uv_edit_mode_select(int p_mode) { } void Polygon2DEditor::_uv_edit_popup_hide() { - EditorSettings::get_singleton()->set("interface/dialogs/uv_editor_bounds", Rect2(uv_edit->get_position(), uv_edit->get_size())); - + EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "uv_editor", Rect2(uv_edit->get_position(), uv_edit->get_size())); _cancel_editing(); } @@ -321,8 +320,9 @@ void Polygon2DEditor::_menu_option(int p_option) { undo_redo->commit_action(); } - if (EditorSettings::get_singleton()->has_setting("interface/dialogs/uv_editor_bounds")) { - uv_edit->popup(EDITOR_GET("interface/dialogs/uv_editor_bounds")); + const Rect2 bounds = EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "uv_editor", Rect2()); + if (bounds.has_area()) { + uv_edit->popup(bounds); } else { uv_edit->popup_centered_ratio(0.85); } @@ -1308,6 +1308,7 @@ Polygon2DEditor::Polygon2DEditor() { uv_edit = memnew(AcceptDialog); add_child(uv_edit); uv_edit->set_title(TTR("Polygon 2D UV Editor")); + uv_edit->connect("confirmed", callable_mp(this, &Polygon2DEditor::_uv_edit_popup_hide)); uv_edit->connect("canceled", callable_mp(this, &Polygon2DEditor::_uv_edit_popup_hide)); VBoxContainer *uv_main_vb = memnew(VBoxContainer); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index c832570fee..cc9e887448 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -863,19 +863,20 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { _save_editor_state(current); } memdelete(tselected); - if (idx >= tab_container->get_tab_count()) { - idx = tab_container->get_tab_count() - 1; - } - if (idx >= 0) { - if (history_pos >= 0) { - idx = tab_container->get_tab_idx_from_control(history[history_pos].control); - } - _go_to_tab(idx); - } else { - _update_selected_editor_menu(); - } if (script_close_queue.is_empty()) { + if (idx >= tab_container->get_tab_count()) { + idx = tab_container->get_tab_count() - 1; + } + if (idx >= 0) { + if (history_pos >= 0) { + idx = tab_container->get_tab_idx_from_control(history[history_pos].control); + } + _go_to_tab(idx); + } else { + _update_selected_editor_menu(); + } + _update_history_arrows(); _update_script_names(); _save_layout(); @@ -883,8 +884,8 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { } } -void ScriptEditor::_close_current_tab(bool p_save) { - _close_tab(tab_container->get_current_tab(), p_save); +void ScriptEditor::_close_current_tab(bool p_save, bool p_history_back) { + _close_tab(tab_container->get_current_tab(), p_save, p_history_back); } void ScriptEditor::_close_discard_current_tab(const String &p_str) { @@ -948,7 +949,7 @@ void ScriptEditor::_queue_close_tabs() { } } - _close_current_tab(false); + _close_current_tab(false, false); } _update_find_replace_bar(); } @@ -4153,7 +4154,7 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) { erase_tab_confirm = memnew(ConfirmationDialog); erase_tab_confirm->set_ok_button_text(TTR("Save")); erase_tab_confirm->add_button(TTR("Discard"), DisplayServer::get_singleton()->get_swap_cancel_ok(), "discard"); - erase_tab_confirm->connect("confirmed", callable_mp(this, &ScriptEditor::_close_current_tab).bind(true)); + erase_tab_confirm->connect("confirmed", callable_mp(this, &ScriptEditor::_close_current_tab).bind(true, true)); erase_tab_confirm->connect("custom_action", callable_mp(this, &ScriptEditor::_close_discard_current_tab)); add_child(erase_tab_confirm); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 0252e10b43..f87cb0958c 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -374,7 +374,7 @@ class ScriptEditor : public PanelContainer { void _close_tab(int p_idx, bool p_save = true, bool p_history_back = true); void _update_find_replace_bar(); - void _close_current_tab(bool p_save = true); + void _close_current_tab(bool p_save = true, bool p_history_back = true); void _close_discard_current_tab(const String &p_str); void _close_docs_tab(); void _close_other_tabs(); diff --git a/editor/plugins/tiles/tile_map_layer_editor.cpp b/editor/plugins/tiles/tile_map_layer_editor.cpp index e1a58a0998..f177245acc 100644 --- a/editor/plugins/tiles/tile_map_layer_editor.cpp +++ b/editor/plugins/tiles/tile_map_layer_editor.cpp @@ -1079,9 +1079,6 @@ HashMap<Vector2i, TileMapCell> TileMapLayerEditorTilesPlugin::_draw_line(Vector2 } // Get or create the pattern. - Ref<TileMapPattern> erase_pattern; - erase_pattern.instantiate(); - erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); Ref<TileMapPattern> pattern = p_erase ? erase_pattern : selection_pattern; HashMap<Vector2i, TileMapCell> output; @@ -1132,9 +1129,6 @@ HashMap<Vector2i, TileMapCell> TileMapLayerEditorTilesPlugin::_draw_rect(Vector2 rect.size += Vector2i(1, 1); // Get or create the pattern. - Ref<TileMapPattern> erase_pattern; - erase_pattern.instantiate(); - erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); Ref<TileMapPattern> pattern = p_erase ? erase_pattern : selection_pattern; HashMap<Vector2i, TileMapCell> err_output; @@ -1189,9 +1183,6 @@ HashMap<Vector2i, TileMapCell> TileMapLayerEditorTilesPlugin::_draw_bucket_fill( HashMap<Vector2i, TileMapCell> output; // Get or create the pattern. - Ref<TileMapPattern> erase_pattern; - erase_pattern.instantiate(); - erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); Ref<TileMapPattern> pattern = p_erase ? erase_pattern : selection_pattern; if (!pattern->is_empty()) { @@ -2200,6 +2191,9 @@ TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() { tile_map_clipboard.instantiate(); selection_pattern.instantiate(); + erase_pattern.instantiate(); + erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); + // --- Toolbar --- toolbar = memnew(HBoxContainer); diff --git a/editor/plugins/tiles/tile_map_layer_editor.h b/editor/plugins/tiles/tile_map_layer_editor.h index 2603261449..7d749be1ba 100644 --- a/editor/plugins/tiles/tile_map_layer_editor.h +++ b/editor/plugins/tiles/tile_map_layer_editor.h @@ -154,6 +154,7 @@ private: RBSet<Vector2i> tile_map_selection; Ref<TileMapPattern> tile_map_clipboard; Ref<TileMapPattern> selection_pattern; + Ref<TileMapPattern> erase_pattern; void _set_tile_map_selection(const TypedArray<Vector2i> &p_selection); TypedArray<Vector2i> _get_tile_map_selection() const; diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index cd043e165e..c12f95753f 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -883,6 +883,7 @@ ScriptCreateDialog::ScriptCreateDialog() { parent_name->connect("text_changed", callable_mp(this, &ScriptCreateDialog::_parent_name_changed)); parent_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); hb->add_child(parent_name); + register_text_enter(parent_name); parent_search_button = memnew(Button); parent_search_button->connect("pressed", callable_mp(this, &ScriptCreateDialog::_browse_class_in_tree)); hb->add_child(parent_search_button); diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp index 86a78d813e..216ccd71ab 100644 --- a/editor/shader_globals_editor.cpp +++ b/editor/shader_globals_editor.cpp @@ -219,7 +219,7 @@ protected: case RS::GLOBAL_VAR_TYPE_SAMPLER2DARRAY: { pinfo.type = Variant::OBJECT; pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE; - pinfo.hint_string = "Texture2DArray"; + pinfo.hint_string = "Texture2DArray,CompressedTexture2DArray"; } break; case RS::GLOBAL_VAR_TYPE_SAMPLER3D: { pinfo.type = Variant::OBJECT; @@ -229,7 +229,7 @@ protected: case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE: { pinfo.type = Variant::OBJECT; pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE; - pinfo.hint_string = "Cubemap"; + pinfo.hint_string = "Cubemap,CompressedCubemap"; } break; default: { } break; |
