diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index cf13068efa7a..d913d0b3b1f9 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -28,6 +28,12 @@ Clears all baked meshes. See [method make_baked_meshes]. + + + + Clears cells that do not exist in the grid map. + + diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp index 2956cb12abc8..0089a1dbd335 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.cpp +++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp @@ -185,6 +185,12 @@ void GridMapEditor::_menu_option(int p_option) { _fill_selection(); } break; + case MENU_OPTION_CLEAR_ALL_CELLS: { + _clear_all_cells(); + } break; + case MENU_OPTION_FIX_INVALID_CELLS: { + _fix_invalid_cells(); + } break; case MENU_OPTION_GRIDMAP_SETTINGS: { settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size() + Size2(50, 50) * EDSCALE); } break; @@ -502,6 +508,24 @@ void GridMapEditor::_fill_selection() { undo_redo->commit_action(); } +void GridMapEditor::_clear_all_cells() { + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Clear All Cells")); + undo_redo->add_undo_method(node, "set", "data", node->get("data")); + node->clear(); + undo_redo->add_do_method(node, "set", "data", node->get("data")); + undo_redo->commit_action(); +} + +void GridMapEditor::_fix_invalid_cells() { + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Fix Invalid Cells")); + undo_redo->add_undo_method(node, "set", "data", node->get("data")); + node->fix_invalid_cells(); + undo_redo->add_do_method(node, "set", "data", node->get("data")); + undo_redo->commit_action(); +} + void GridMapEditor::_clear_clipboard_data() { for (const ClipboardItem &E : clipboard_items) { if (E.instance.is_null()) { @@ -1323,6 +1347,9 @@ GridMapEditor::GridMapEditor() { options->get_popup()->add_check_shortcut(ED_GET_SHORTCUT("grid_map/keep_selected"), MENU_OPTION_PASTE_SELECTS); options->get_popup()->set_item_checked(options->get_popup()->get_item_index(MENU_OPTION_PASTE_SELECTS), true); options->get_popup()->add_separator(); + options->get_popup()->add_item(TTR("Clear All Cells"), MENU_OPTION_CLEAR_ALL_CELLS); + options->get_popup()->add_item(TTR("Fix Invalid Cells"), MENU_OPTION_FIX_INVALID_CELLS); + options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Settings..."), MENU_OPTION_GRIDMAP_SETTINGS); settings_dialog = memnew(ConfirmationDialog); diff --git a/modules/gridmap/editor/grid_map_editor_plugin.h b/modules/gridmap/editor/grid_map_editor_plugin.h index 71407132e2bd..1f55e196e750 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.h +++ b/modules/gridmap/editor/grid_map_editor_plugin.h @@ -197,6 +197,8 @@ class GridMapEditor : public VBoxContainer { MENU_OPTION_SELECTION_CUT, MENU_OPTION_SELECTION_CLEAR, MENU_OPTION_SELECTION_FILL, + MENU_OPTION_CLEAR_ALL_CELLS, + MENU_OPTION_FIX_INVALID_CELLS, MENU_OPTION_GRIDMAP_SETTINGS }; @@ -247,6 +249,8 @@ class GridMapEditor : public VBoxContainer { void _delete_selection(); void _fill_selection(); + void _clear_all_cells(); + void _fix_invalid_cells(); bool do_input_action(Camera3D *p_camera, const Point2 &p_point, bool p_click); diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 9329849964f8..a188e2bad860 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -280,16 +280,19 @@ RID GridMap::get_navigation_map() const { #endif // NAVIGATION_3D_DISABLED void GridMap::set_mesh_library(const Ref &p_mesh_library) { - if (mesh_library.is_valid()) { - mesh_library->disconnect_changed(callable_mp(this, &GridMap::_recreate_octant_data)); - } - mesh_library = p_mesh_library; - if (mesh_library.is_valid()) { - mesh_library->connect_changed(callable_mp(this, &GridMap::_recreate_octant_data)); - } + if (mesh_library != p_mesh_library) { + if (mesh_library.is_valid()) { + mesh_library->disconnect_changed(callable_mp(this, &GridMap::_recreate_octant_data)); + } - _recreate_octant_data(); - emit_signal(CoreStringName(changed)); + mesh_library = p_mesh_library; + if (mesh_library.is_valid()) { + mesh_library->connect_changed(callable_mp(this, &GridMap::_recreate_octant_data)); + } + + _recreate_octant_data(); + emit_signal(CoreStringName(changed)); + } } Ref GridMap::get_mesh_library() const { @@ -1130,6 +1133,16 @@ void GridMap::clear() { clear_baked_meshes(); } +void GridMap::fix_invalid_cells() { + ERR_FAIL_COND_MSG(mesh_library.is_null(), "Cannot fix invalid cells if MeshLibrary is not open."); + + for (HashMap::Iterator I = cell_map.begin(); I; ++I) { + if (!mesh_library.is_valid() || !mesh_library->has_item(I->value.item)) { + set_cell_item(I->key, INVALID_CELL_ITEM); + } + } +} + #ifndef DISABLE_DEPRECATED void GridMap::resource_changed(const Ref &p_res) { } @@ -1222,6 +1235,7 @@ void GridMap::_bind_methods() { ClassDB::bind_method(D_METHOD("get_center_z"), &GridMap::get_center_z); ClassDB::bind_method(D_METHOD("clear"), &GridMap::clear); + ClassDB::bind_method(D_METHOD("fix_invalid_cells"), &GridMap::fix_invalid_cells); ClassDB::bind_method(D_METHOD("get_used_cells"), &GridMap::get_used_cells); ClassDB::bind_method(D_METHOD("get_used_cells_by_item", "item"), &GridMap::get_used_cells_by_item); diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index c5730a5e1cde..fcd485f9a5a8 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -307,6 +307,7 @@ class GridMap : public Node3D { void make_baked_meshes(bool p_gen_lightmap_uv = false, float p_lightmap_uv_texel_size = 0.1); void clear(); + void fix_invalid_cells(); Array get_bake_meshes(); RID get_bake_mesh_instance(int p_idx);