summaryrefslogtreecommitdiffstats
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/editor_node.cpp3
-rw-r--r--editor/export/editor_export_platform.cpp6
-rw-r--r--editor/export/project_export.cpp6
-rw-r--r--editor/filesystem_dock.cpp33
-rw-r--r--editor/filesystem_dock.h1
-rw-r--r--editor/gui/editor_dir_dialog.cpp15
-rw-r--r--editor/import/3d/editor_import_collada.cpp1
-rw-r--r--editor/import/3d/resource_importer_scene.cpp1
-rw-r--r--editor/import_dock.cpp24
-rw-r--r--editor/import_dock.h1
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp5
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp320
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.h25
-rw-r--r--editor/plugins/path_3d_editor_plugin.cpp14
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp9
-rw-r--r--editor/plugins/script_editor_plugin.cpp31
-rw-r--r--editor/plugins/script_editor_plugin.h2
-rw-r--r--editor/plugins/tiles/tile_map_layer_editor.cpp12
-rw-r--r--editor/plugins/tiles/tile_map_layer_editor.h1
-rw-r--r--editor/script_create_dialog.cpp1
-rw-r--r--editor/shader_globals_editor.cpp4
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;