From 4d0c21c131da07c766801d846929872dc8bd2a66 Mon Sep 17 00:00:00 2001 From: smix8 <52464204+smix8@users.noreply.github.com> Date: Mon, 27 Nov 2023 16:49:49 +0100 Subject: [PATCH] Make MeshLibrary export do recursive depth-search for MeshInstance3D nodes Makes MeshLibrary export do recursive depth-search for MeshInstance3D nodes. --- editor/editor_node.cpp | 7 +- editor/plugins/mesh_library_editor_plugin.cpp | 190 ++++++++---------- editor/plugins/mesh_library_editor_plugin.h | 2 + 3 files changed, 95 insertions(+), 104 deletions(-) diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 6711be3d069..20ceed0cb8f 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2026,8 +2026,11 @@ void EditorNode::_dialog_action(String p_file) { } break; case FILE_EXPORT_MESH_LIBRARY: { + bool merge_with_existing_library = file_export_lib_merge->is_pressed(); + bool apply_mesh_instance_transforms = file_export_lib_apply_xforms->is_pressed(); + Ref ml; - if (file_export_lib_merge->is_pressed() && FileAccess::exists(p_file)) { + if (merge_with_existing_library && FileAccess::exists(p_file)) { ml = ResourceLoader::load(p_file, "MeshLibrary"); if (ml.is_null()) { @@ -2040,7 +2043,7 @@ void EditorNode::_dialog_action(String p_file) { ml = Ref(memnew(MeshLibrary)); } - MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(), ml, true, file_export_lib_apply_xforms->is_pressed()); + MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(), ml, merge_with_existing_library, apply_mesh_instance_transforms); Error err = ResourceSaver::save(ml, p_file); if (err) { diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index e6f0e65e409..4e457141740 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -78,108 +78,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref p_library, HashMap mesh_instances; for (int i = 0; i < p_scene->get_child_count(); i++) { - Node *child = p_scene->get_child(i); - - if (!Object::cast_to(child)) { - if (child->get_child_count() > 0) { - child = child->get_child(0); - if (!Object::cast_to(child)) { - continue; - } - - } else { - continue; - } - } - - MeshInstance3D *mi = Object::cast_to(child); - Ref mesh = mi->get_mesh(); - if (mesh.is_null()) { - continue; - } - - mesh = mesh->duplicate(); - for (int j = 0; j < mesh->get_surface_count(); ++j) { - Ref mat = mi->get_surface_override_material(j); - - if (mat.is_valid()) { - mesh->surface_set_material(j, mat); - } - } - - int id = p_library->find_item_by_name(mi->get_name()); - if (id < 0) { - id = p_library->get_last_unused_item_id(); - p_library->create_item(id); - p_library->set_item_name(id, mi->get_name()); - } - - p_library->set_item_mesh(id, mesh); - - if (p_apply_xforms) { - p_library->set_item_mesh_transform(id, mi->get_transform()); - } else { - p_library->set_item_mesh_transform(id, Transform3D()); - } - - mesh_instances[id] = mi; - - Vector collisions; - - for (int j = 0; j < mi->get_child_count(); j++) { - Node *child2 = mi->get_child(j); - if (!Object::cast_to(child2)) { - continue; - } - - StaticBody3D *sb = Object::cast_to(child2); - List shapes; - sb->get_shape_owners(&shapes); - - for (uint32_t &E : shapes) { - if (sb->is_shape_owner_disabled(E)) { - continue; - } - - Transform3D shape_transform; - if (p_apply_xforms) { - shape_transform = mi->get_transform(); - } - shape_transform *= sb->get_transform() * sb->shape_owner_get_transform(E); - - for (int k = 0; k < sb->shape_owner_get_shape_count(E); k++) { - Ref collision = sb->shape_owner_get_shape(E, k); - if (!collision.is_valid()) { - continue; - } - MeshLibrary::ShapeData shape_data; - shape_data.shape = collision; - shape_data.local_transform = shape_transform; - collisions.push_back(shape_data); - } - } - } - - p_library->set_item_shapes(id, collisions); - - Ref navigation_mesh; - Transform3D navigation_mesh_transform; - for (int j = 0; j < mi->get_child_count(); j++) { - Node *child2 = mi->get_child(j); - if (!Object::cast_to(child2)) { - continue; - } - NavigationRegion3D *sb = Object::cast_to(child2); - navigation_mesh = sb->get_navigation_mesh(); - navigation_mesh_transform = sb->get_transform(); - if (!navigation_mesh.is_null()) { - break; - } - } - if (!navigation_mesh.is_null()) { - p_library->set_item_navigation_mesh(id, navigation_mesh); - p_library->set_item_navigation_mesh_transform(id, navigation_mesh_transform); - } + _import_scene_parse_node(p_library, mesh_instances, p_scene->get_child(i), p_merge, p_apply_xforms); } //generate previews! @@ -221,6 +120,93 @@ void MeshLibraryEditor::_import_scene_cbk(const String &p_str) { menu->get_popup()->set_item_disabled(menu->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE), false); } +void MeshLibraryEditor::_import_scene_parse_node(Ref p_library, HashMap &p_mesh_instances, Node *p_node, bool p_merge, bool p_apply_xforms) { + MeshInstance3D *mesh_instance_node = Object::cast_to(p_node); + + if (!mesh_instance_node) { + // No MeshInstance so search deeper ... + for (int i = 0; i < p_node->get_child_count(); i++) { + _import_scene_parse_node(p_library, p_mesh_instances, p_node->get_child(i), p_merge, p_apply_xforms); + } + return; + } + + Ref source_mesh = mesh_instance_node->get_mesh(); + if (source_mesh.is_null()) { + return; + } + + int item_id = p_library->find_item_by_name(mesh_instance_node->get_name()); + if (item_id < 0) { + item_id = p_library->get_last_unused_item_id(); + p_library->create_item(item_id); + p_library->set_item_name(item_id, mesh_instance_node->get_name()); + } else if (!p_merge) { + WARN_PRINT(vformat("MeshLibrary export found a MeshInstance3D with a duplicated name '%s' in the exported scene that overrides a previously parsed MeshInstance3D item with the same name.", mesh_instance_node->get_name())); + } + p_mesh_instances[item_id] = mesh_instance_node; + + Ref item_mesh = source_mesh->duplicate(); + for (int i = 0; i < item_mesh->get_surface_count(); i++) { + Ref surface_override_material = mesh_instance_node->get_surface_override_material(i); + if (surface_override_material.is_valid()) { + item_mesh->surface_set_material(i, surface_override_material); + } + } + p_library->set_item_mesh(item_id, item_mesh); + + Transform3D item_mesh_transform; + if (p_apply_xforms) { + item_mesh_transform = mesh_instance_node->get_transform(); + } + p_library->set_item_mesh_transform(item_id, item_mesh_transform); + + Vector collisions; + for (int i = 0; i < mesh_instance_node->get_child_count(); i++) { + StaticBody3D *static_body_node = Object::cast_to(mesh_instance_node->get_child(i)); + if (!static_body_node) { + continue; + } + List shapes; + static_body_node->get_shape_owners(&shapes); + for (uint32_t &E : shapes) { + if (static_body_node->is_shape_owner_disabled(E)) { + continue; + } + Transform3D shape_transform; + if (p_apply_xforms) { + shape_transform = mesh_instance_node->get_transform(); + } + shape_transform *= static_body_node->get_transform() * static_body_node->shape_owner_get_transform(E); + for (int k = 0; k < static_body_node->shape_owner_get_shape_count(E); k++) { + Ref collision_shape = static_body_node->shape_owner_get_shape(E, k); + if (!collision_shape.is_valid()) { + continue; + } + MeshLibrary::ShapeData shape_data; + shape_data.shape = collision_shape; + shape_data.local_transform = shape_transform; + collisions.push_back(shape_data); + } + } + } + p_library->set_item_shapes(item_id, collisions); + + for (int i = 0; i < mesh_instance_node->get_child_count(); i++) { + NavigationRegion3D *navigation_region_node = Object::cast_to(mesh_instance_node->get_child(i)); + if (!navigation_region_node) { + continue; + } + Ref navigation_mesh = navigation_region_node->get_navigation_mesh(); + if (!navigation_mesh.is_null()) { + Transform3D navigation_mesh_transform = navigation_region_node->get_transform(); + p_library->set_item_navigation_mesh(item_id, navigation_mesh); + p_library->set_item_navigation_mesh_transform(item_id, navigation_mesh_transform); + break; + } + } +} + Error MeshLibraryEditor::update_library_file(Node *p_base_scene, Ref ml, bool p_merge, bool p_apply_xforms) { _import_scene(p_base_scene, ml, p_merge, p_apply_xforms); return OK; diff --git a/editor/plugins/mesh_library_editor_plugin.h b/editor/plugins/mesh_library_editor_plugin.h index c0900c8f357..7bdc70a00bc 100644 --- a/editor/plugins/mesh_library_editor_plugin.h +++ b/editor/plugins/mesh_library_editor_plugin.h @@ -37,6 +37,7 @@ class EditorFileDialog; class ConfirmationDialog; class MenuButton; +class MeshInstance3D; class MeshLibraryEditor : public Control { GDCLASS(MeshLibraryEditor, Control); @@ -65,6 +66,7 @@ class MeshLibraryEditor : public Control { void _menu_update_confirm(bool p_apply_xforms); static void _import_scene(Node *p_scene, Ref p_library, bool p_merge, bool p_apply_xforms); + static void _import_scene_parse_node(Ref p_library, HashMap &p_mesh_instances, Node *p_node, bool p_merge, bool p_apply_xforms); protected: static void _bind_methods();