From ea13ff860de2227ad343b8a2d9a2e37150473d09 Mon Sep 17 00:00:00 2001 From: Vincent Date: Wed, 1 Sep 2021 01:17:33 +0200 Subject: [PATCH] implement individual mesh transform for meshlibrary items (cherry picked from commit 70108fd8509a09230933872c3042a7c7ef2545b8) --- doc/classes/MeshLibrary.xml | 15 +++++ editor/editor_node.cpp | 6 +- editor/editor_node.h | 1 + editor/plugins/mesh_library_editor_plugin.cpp | 62 +++++++++++++------ editor/plugins/mesh_library_editor_plugin.h | 14 +++-- modules/gridmap/grid_map.cpp | 2 +- modules/gridmap/grid_map_editor_plugin.cpp | 6 ++ scene/resources/mesh_library.cpp | 19 ++++++ scene/resources/mesh_library.h | 3 + 9 files changed, 101 insertions(+), 27 deletions(-) diff --git a/doc/classes/MeshLibrary.xml b/doc/classes/MeshLibrary.xml index 342432d7498..06f6551eda7 100644 --- a/doc/classes/MeshLibrary.xml +++ b/doc/classes/MeshLibrary.xml @@ -45,6 +45,13 @@ Returns the item's mesh. + + + + + Returns the transform applied to the item's mesh. + + @@ -102,6 +109,14 @@ Sets the item's mesh. + + + + + + Sets the transform to apply to the item's mesh. + + diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4b59d047fb9..7788e6f448f 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1727,7 +1727,7 @@ void EditorNode::_dialog_action(String p_file) { ml = Ref(memnew(MeshLibrary)); } - MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(), ml, true); + MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(), ml, true, file_export_lib_apply_xforms->is_pressed()); Error err = ResourceSaver::save(p_file, ml); if (err) { @@ -6751,6 +6751,10 @@ EditorNode::EditorNode() { file_export_lib_merge->set_text(TTR("Merge With Existing")); file_export_lib_merge->set_pressed(true); file_export_lib->get_vbox()->add_child(file_export_lib_merge); + file_export_lib_apply_xforms = memnew(CheckBox); + file_export_lib_apply_xforms->set_text(TTR("Apply MeshInstance Transforms")); + file_export_lib_apply_xforms->set_pressed(false); + file_export_lib->get_vbox()->add_child(file_export_lib_apply_xforms); gui_base->add_child(file_export_lib); file_script = memnew(EditorFileDialog); diff --git a/editor/editor_node.h b/editor/editor_node.h index 70809015ee2..7ac9a16b07a 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -335,6 +335,7 @@ private: EditorFileDialog *file_script; EditorFileDialog *file_android_build_source; CheckBox *file_export_lib_merge; + CheckBox *file_export_lib_apply_xforms; String current_path; MenuButton *update_spinner; diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index 9caa72d80a1..661f13d3c90 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -47,23 +47,25 @@ void MeshLibraryEditor::edit(const Ref &p_mesh_library) { } } -void MeshLibraryEditor::_menu_confirm() { +void MeshLibraryEditor::_menu_remove_confirm() { switch (option) { case MENU_OPTION_REMOVE_ITEM: { mesh_library->remove_item(to_erase); } break; - case MENU_OPTION_UPDATE_FROM_SCENE: { - String existing = mesh_library->get_meta("_editor_source_scene"); - ERR_FAIL_COND(existing == ""); - _import_scene_cbk(existing); - - } break; default: { }; } } -void MeshLibraryEditor::_import_scene(Node *p_scene, Ref p_library, bool p_merge) { +void MeshLibraryEditor::_menu_update_confirm(bool p_apply_xforms) { + cd_update->hide(); + apply_xforms = p_apply_xforms; + String existing = mesh_library->get_meta("_editor_source_scene"); + ERR_FAIL_COND(existing == ""); + _import_scene_cbk(existing); +} + +void MeshLibraryEditor::_import_scene(Node *p_scene, Ref p_library, bool p_merge, bool p_apply_xforms) { if (!p_merge) { p_library->clear(); } @@ -108,6 +110,13 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref p_library, } 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, Transform()); + } + mesh_instances[id] = mi; Vector collisions; @@ -197,15 +206,16 @@ void MeshLibraryEditor::_import_scene_cbk(const String &p_str) { ERR_FAIL_COND_MSG(!scene, "Cannot create an instance from PackedScene '" + p_str + "'."); - _import_scene(scene, mesh_library, option == MENU_OPTION_UPDATE_FROM_SCENE); + _import_scene(scene, mesh_library, option == MENU_OPTION_UPDATE_FROM_SCENE, apply_xforms); memdelete(scene); mesh_library->set_meta("_editor_source_scene", p_str); + menu->get_popup()->set_item_disabled(menu->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE), false); } -Error MeshLibraryEditor::update_library_file(Node *p_base_scene, Ref ml, bool p_merge) { - _import_scene(p_base_scene, ml, p_merge); +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; } @@ -219,23 +229,29 @@ void MeshLibraryEditor::_menu_cbk(int p_option) { String p = editor->get_inspector()->get_selected_path(); if (p.begins_with("/MeshLibrary/item") && p.get_slice_count("/") >= 3) { to_erase = p.get_slice("/", 3).to_int(); - cd->set_text(vformat(TTR("Remove item %d?"), to_erase)); - cd->popup_centered(Size2(300, 60)); + cd_remove->set_text(vformat(TTR("Remove item %d?"), to_erase)); + cd_remove->popup_centered(Size2(300, 60)); } } break; case MENU_OPTION_IMPORT_FROM_SCENE: { + apply_xforms = false; + file->popup_centered_ratio(); + } break; + case MENU_OPTION_IMPORT_FROM_SCENE_APPLY_XFORMS: { + apply_xforms = true; file->popup_centered_ratio(); } break; case MENU_OPTION_UPDATE_FROM_SCENE: { - cd->set_text(vformat(TTR("Update from existing scene?:\n%s"), String(mesh_library->get_meta("_editor_source_scene")))); - cd->popup_centered(Size2(500, 60)); + cd_update->set_text(vformat(TTR("Update from existing scene?:\n%s"), String(mesh_library->get_meta("_editor_source_scene")))); + cd_update->popup_centered(Size2(500, 60)); } break; } } void MeshLibraryEditor::_bind_methods() { ClassDB::bind_method("_menu_cbk", &MeshLibraryEditor::_menu_cbk); - ClassDB::bind_method("_menu_confirm", &MeshLibraryEditor::_menu_confirm); + ClassDB::bind_method("_menu_remove_confirm", &MeshLibraryEditor::_menu_remove_confirm); + ClassDB::bind_method("_menu_update_confirm", &MeshLibraryEditor::_menu_update_confirm); ClassDB::bind_method("_import_scene_cbk", &MeshLibraryEditor::_import_scene_cbk); } @@ -261,16 +277,22 @@ MeshLibraryEditor::MeshLibraryEditor(EditorNode *p_editor) { menu->get_popup()->add_item(TTR("Add Item"), MENU_OPTION_ADD_ITEM); menu->get_popup()->add_item(TTR("Remove Selected Item"), MENU_OPTION_REMOVE_ITEM); menu->get_popup()->add_separator(); - menu->get_popup()->add_item(TTR("Import from Scene"), MENU_OPTION_IMPORT_FROM_SCENE); + menu->get_popup()->add_item(TTR("Import from Scene (Ignore Transforms)"), MENU_OPTION_IMPORT_FROM_SCENE); + menu->get_popup()->add_item(TTR("Import from Scene (Apply Transforms)"), MENU_OPTION_IMPORT_FROM_SCENE_APPLY_XFORMS); menu->get_popup()->add_item(TTR("Update from Scene"), MENU_OPTION_UPDATE_FROM_SCENE); menu->get_popup()->set_item_disabled(menu->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE), true); menu->get_popup()->connect("id_pressed", this, "_menu_cbk"); menu->hide(); editor = p_editor; - cd = memnew(ConfirmationDialog); - add_child(cd); - cd->get_ok()->connect("pressed", this, "_menu_confirm"); + cd_remove = memnew(ConfirmationDialog); + add_child(cd_remove); + cd_remove->get_ok()->connect("pressed", this, "_menu_remove_confirm"); + cd_update = memnew(ConfirmationDialog); + add_child(cd_update); + cd_update->get_ok()->set_text("Apply without Transforms"); + cd_update->get_ok()->connect("pressed", this, "_menu_update_confirm", varray(false)); + cd_update->add_button("Apply with Transforms")->connect("pressed", this, "_menu_update_confirm", varray(true)); } void MeshLibraryEditorPlugin::edit(Object *p_node) { diff --git a/editor/plugins/mesh_library_editor_plugin.h b/editor/plugins/mesh_library_editor_plugin.h index fbcd13575ca..17b8ecd82ca 100644 --- a/editor/plugins/mesh_library_editor_plugin.h +++ b/editor/plugins/mesh_library_editor_plugin.h @@ -41,8 +41,10 @@ class MeshLibraryEditor : public Control { EditorNode *editor; MenuButton *menu; - ConfirmationDialog *cd; + ConfirmationDialog *cd_remove; + ConfirmationDialog *cd_update; EditorFileDialog *file; + bool apply_xforms; int to_erase; enum { @@ -50,15 +52,17 @@ class MeshLibraryEditor : public Control { MENU_OPTION_ADD_ITEM, MENU_OPTION_REMOVE_ITEM, MENU_OPTION_UPDATE_FROM_SCENE, - MENU_OPTION_IMPORT_FROM_SCENE + MENU_OPTION_IMPORT_FROM_SCENE, + MENU_OPTION_IMPORT_FROM_SCENE_APPLY_XFORMS }; int option; void _import_scene_cbk(const String &p_str); void _menu_cbk(int p_option); - void _menu_confirm(); + void _menu_remove_confirm(); + void _menu_update_confirm(bool p_apply_xforms); - static void _import_scene(Node *p_scene, Ref p_library, bool p_merge); + static void _import_scene(Node *p_scene, Ref p_library, bool p_merge, bool p_apply_xforms); protected: static void _bind_methods(); @@ -67,7 +71,7 @@ public: MenuButton *get_menu_button() const { return menu; } void edit(const Ref &p_mesh_library); - static Error update_library_file(Node *p_base_scene, Ref ml, bool p_merge = true); + static Error update_library_file(Node *p_base_scene, Ref ml, bool p_merge = true, bool p_apply_xforms = false); MeshLibraryEditor(EditorNode *p_editor); }; diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index b173e743eef..027906a5b87 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -460,7 +460,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) { } Pair p; - p.first = xform; + p.first = xform * mesh_library->get_item_mesh_transform(c.item); p.second = E->get(); multimesh_items[c.item].push_back(p); } diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 8a97d8156a6..8a4f0788655 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -261,6 +261,12 @@ void GridMapEditor::_update_cursor_transform() { cursor_transform.basis *= node->get_cell_scale(); cursor_transform = node->get_global_transform() * cursor_transform; + if (selected_palette >= 0) { + if (node && !node->get_mesh_library().is_null()) { + cursor_transform *= node->get_mesh_library()->get_item_mesh_transform(selected_palette); + } + } + if (cursor_instance.is_valid()) { VisualServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); VisualServer::get_singleton()->instance_set_visible(cursor_instance, cursor_visible); diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp index 6ab15a095c6..41144892f30 100644 --- a/scene/resources/mesh_library.cpp +++ b/scene/resources/mesh_library.cpp @@ -43,6 +43,8 @@ bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) { set_item_name(idx, p_value); } else if (what == "mesh") { set_item_mesh(idx, p_value); + } else if (what == "mesh_transform") { + set_item_mesh_transform(idx, p_value); } else if (what == "shape") { Vector shapes; ShapeData sd; @@ -77,6 +79,8 @@ bool MeshLibrary::_get(const StringName &p_name, Variant &r_ret) const { r_ret = get_item_name(idx); } else if (what == "mesh") { r_ret = get_item_mesh(idx); + } else if (what == "mesh_transform") { + r_ret = get_item_mesh_transform(idx); } else if (what == "shapes") { r_ret = _get_item_shapes(idx); } else if (what == "navmesh") { @@ -127,6 +131,14 @@ void MeshLibrary::set_item_mesh(int p_item, const Ref &p_mesh) { _change_notify(); } +void MeshLibrary::set_item_mesh_transform(int p_item, const Transform &p_transform) { + ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); + item_map[p_item].mesh_transform = p_transform; + notify_change_to_owners(); + emit_changed(); + _change_notify(); +} + void MeshLibrary::set_item_shapes(int p_item, const Vector &p_shapes) { ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); item_map[p_item].shapes = p_shapes; @@ -170,6 +182,11 @@ Ref MeshLibrary::get_item_mesh(int p_item) const { return item_map[p_item].mesh; } +Transform MeshLibrary::get_item_mesh_transform(int p_item) const { + ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Transform(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); + return item_map[p_item].mesh_transform; +} + Vector MeshLibrary::get_item_shapes(int p_item) const { ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Vector(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); return item_map[p_item].shapes; @@ -267,12 +284,14 @@ void MeshLibrary::_bind_methods() { ClassDB::bind_method(D_METHOD("create_item", "id"), &MeshLibrary::create_item); ClassDB::bind_method(D_METHOD("set_item_name", "id", "name"), &MeshLibrary::set_item_name); ClassDB::bind_method(D_METHOD("set_item_mesh", "id", "mesh"), &MeshLibrary::set_item_mesh); + ClassDB::bind_method(D_METHOD("set_item_mesh_transform", "id", "mesh_transform"), &MeshLibrary::set_item_mesh_transform); ClassDB::bind_method(D_METHOD("set_item_navmesh", "id", "navmesh"), &MeshLibrary::set_item_navmesh); ClassDB::bind_method(D_METHOD("set_item_navmesh_transform", "id", "navmesh"), &MeshLibrary::set_item_navmesh_transform); ClassDB::bind_method(D_METHOD("set_item_shapes", "id", "shapes"), &MeshLibrary::_set_item_shapes); ClassDB::bind_method(D_METHOD("set_item_preview", "id", "texture"), &MeshLibrary::set_item_preview); ClassDB::bind_method(D_METHOD("get_item_name", "id"), &MeshLibrary::get_item_name); ClassDB::bind_method(D_METHOD("get_item_mesh", "id"), &MeshLibrary::get_item_mesh); + ClassDB::bind_method(D_METHOD("get_item_mesh_transform", "id"), &MeshLibrary::get_item_mesh_transform); ClassDB::bind_method(D_METHOD("get_item_navmesh", "id"), &MeshLibrary::get_item_navmesh); ClassDB::bind_method(D_METHOD("get_item_navmesh_transform", "id"), &MeshLibrary::get_item_navmesh_transform); ClassDB::bind_method(D_METHOD("get_item_shapes", "id"), &MeshLibrary::_get_item_shapes); diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h index ddfbb3bbd14..7f8f6346e5d 100644 --- a/scene/resources/mesh_library.h +++ b/scene/resources/mesh_library.h @@ -52,6 +52,7 @@ public: Vector shapes; Ref preview; Transform navmesh_transform; + Transform mesh_transform; Ref navmesh; }; @@ -71,12 +72,14 @@ public: void create_item(int p_item); void set_item_name(int p_item, const String &p_name); void set_item_mesh(int p_item, const Ref &p_mesh); + void set_item_mesh_transform(int p_item, const Transform &p_transform); void set_item_navmesh(int p_item, const Ref &p_navmesh); void set_item_navmesh_transform(int p_item, const Transform &p_transform); void set_item_shapes(int p_item, const Vector &p_shapes); void set_item_preview(int p_item, const Ref &p_preview); String get_item_name(int p_item) const; Ref get_item_mesh(int p_item) const; + Transform get_item_mesh_transform(int p_item) const; Ref get_item_navmesh(int p_item) const; Transform get_item_navmesh_transform(int p_item) const; Vector get_item_shapes(int p_item) const;