From 218ab38e01f05c8a2dab994f68a2b9c2590e6894 Mon Sep 17 00:00:00 2001 From: tatjam Date: Tue, 25 Jul 2023 19:25:10 +0200 Subject: [PATCH] Dettaching works too --- imgui.ini | 2 +- src/game/scenes/editor/EditorVehicle.cpp | 56 +++++++++++++++---- src/game/scenes/editor/gui/ModifyPanel.cpp | 1 + .../editor/interfaces/ModifyInterface.cpp | 2 + src/universe/vehicle/SymmetryMode.cpp | 28 ++++++++-- src/universe/vehicle/SymmetryMode.h | 4 +- src/universe/vehicle/VehicleMeta.cpp | 14 +++++ src/universe/vehicle/VehicleMeta.h | 2 + 8 files changed, 90 insertions(+), 19 deletions(-) diff --git a/imgui.ini b/imgui.ini index 38ce2aa..3139fe5 100755 --- a/imgui.ini +++ b/imgui.ini @@ -104,7 +104,7 @@ Size=110,54 Collapsed=0 [Window][Debug menu] -Pos=547,17 +Pos=1406,134 Size=519,412 Collapsed=0 diff --git a/src/game/scenes/editor/EditorVehicle.cpp b/src/game/scenes/editor/EditorVehicle.cpp index 7e2b9b1..5899252 100755 --- a/src/game/scenes/editor/EditorVehicle.cpp +++ b/src/game/scenes/editor/EditorVehicle.cpp @@ -345,14 +345,15 @@ void EditorVehicle::detach(Piece *piece) { // TODO: This may be surprisingly expensive with many nested symmetry groups! - // Step 1: Move symmetry groups that are in piece, its children or - // its clone or cloned children into the one we are dettaching - // (This prevents removal of symmetry groups!) + // If children of our clones fully contain all roots of a symmetry group, + // move them so that the symmetry group is not lost + // (when this is not possible, sadly the groups are lost!) auto clones = veh->meta.find_symmetry_instances(piece, true); std::vector to_move; - // indices in piece_children.push_back(piece)! - std::vector new_root_indices; + // indices in piece_children.push_back(piece) for each clone! + std::vector> new_root_indices; + // Many nested loops, but they should exit fairly quickly most of the time! for(const auto& clone : clones) { if(clone.p == piece) @@ -363,15 +364,33 @@ void EditorVehicle::detach(Piece *piece) for(SymmetryMode* m : veh->meta.symmetry_groups) { - for(size_t i = 0; i < all_p.size(); i++) + bool all_found = true; + std::vector new_indices; + for(size_t j = 0; j < m->clones.size(); j++) { - if(all_p[i] == m->root) + bool found = false; + for(size_t k = 0; k < all_p.size(); k++) { - to_move.push_back(m); - new_root_indices.push_back(i); + if(all_p[k] == m->clones[j]) + { + new_indices.push_back(k); + found = true; + break; + } + } + + if(!found) + { + all_found = false; break; } } + + if(all_found) + { + to_move.push_back(m); + new_root_indices.push_back(new_indices); + } } } @@ -380,19 +399,24 @@ void EditorVehicle::detach(Piece *piece) for(size_t i = 0; i < to_move.size(); i++) { - to_move[i]->new_root(all_p[new_root_indices[i]]); + std::vector vec; + for(size_t idx : new_root_indices[i]) + { + vec.push_back(all_p[idx]); + } + to_move[i]->new_root_clones(this, vec); } // Step 2: Dettach the piece, destroy all clones and remove them from the // symmetry groups they belong to piece->attached_to = nullptr; + std::set all_modes; for(const auto& clone : clones) { for(SymmetryMode* m : clone.modes) { + all_modes.insert(m); m->remove_piece_and_children_from_symmetry(this, clone.p); - m->cleanup(); - m->update_clone_depth(); } if(clone.p != piece) @@ -414,6 +438,14 @@ void EditorVehicle::detach(Piece *piece) } } + for(SymmetryMode* m : all_modes) + { + m->cleanup(); + m->update_clone_depth(); + } + + veh->meta.cleanup_symmetry_groups(); + } diff --git a/src/game/scenes/editor/gui/ModifyPanel.cpp b/src/game/scenes/editor/gui/ModifyPanel.cpp index 34405e4..3fbffbc 100644 --- a/src/game/scenes/editor/gui/ModifyPanel.cpp +++ b/src/game/scenes/editor/gui/ModifyPanel.cpp @@ -220,6 +220,7 @@ void ModifyPanel::make_symmetry_canvas_creating() mod_int->change_state(ModifyInterface::IDLE); modifying_symmetry->leave_gui_control(); modifying_symmetry = nullptr; + edveh_int->edveh->veh->meta.cleanup_symmetry_groups(); })); layout->mark_same_line(); layout->add_widget(finish_button); diff --git a/src/game/scenes/editor/interfaces/ModifyInterface.cpp b/src/game/scenes/editor/interfaces/ModifyInterface.cpp index 130b55e..8d9aecc 100644 --- a/src/game/scenes/editor/interfaces/ModifyInterface.cpp +++ b/src/game/scenes/editor/interfaces/ModifyInterface.cpp @@ -171,6 +171,8 @@ bool ModifyInterface::do_interface_create_symmetry(Piece *hovered, GUIInput *ipt could_create = true; } + could_create &= hovered->attached_to == nullptr; + if(could_create) { highlight_symmetry(hovered); diff --git a/src/universe/vehicle/SymmetryMode.cpp b/src/universe/vehicle/SymmetryMode.cpp index fb12c9f..20bb6d2 100644 --- a/src/universe/vehicle/SymmetryMode.cpp +++ b/src/universe/vehicle/SymmetryMode.cpp @@ -85,6 +85,9 @@ bool SymmetryMode::is_piece_in_symmetry(Piece *p) void SymmetryMode::remove(EditorVehicle* edveh) { + if(root == nullptr) + return; + remove_non_root(edveh); // Return root to original position @@ -229,7 +232,6 @@ void SymmetryMode::cleanup() it = all_in_symmetry.erase(it); else it++; - } } @@ -250,8 +252,7 @@ void SymmetryMode::update_clone_depth() return; } } - // Should never be reached, unless something's very wrong - logger->check(false, "Symmetry malformed"); + logger->check(all_in_symmetry.size() == 0, "Symmetry malformed"); } void SymmetryMode::remove_piece_and_children_from_symmetry(EditorVehicle *edveh, Piece *p) @@ -276,6 +277,7 @@ void SymmetryMode::remove_piece_from_symmetry(EditorVehicle *edveh, Piece *p) return; } } + } std::vector SymmetryMode::find_clones(Piece *p, bool include_p) @@ -324,9 +326,27 @@ void SymmetryMode::show_symmetry(EditorVehicle* veh) } -void SymmetryMode::new_root(Piece *p) +void SymmetryMode::new_root_clones(EditorVehicle* edveh, std::vector p) { + logger->check(p.size() == clones.size(), "Invalid number of clones given"); + + // quick safety check + int old_size = all_in_symmetry.size(); + all_in_symmetry.clear(); + + // We now build the all_pieces_in_symmetry + for(Piece* new_root : p) + { + // TODO: This assumes good ordering of get_children_of? + // May break on some VERY WEIRD cases (manual vehicle modification?) + std::vector children = edveh->veh->get_children_of(new_root); + all_in_symmetry.push_back(new_root); + all_in_symmetry.insert(all_in_symmetry.end(), children.begin(), children.end()); + } + clones = p; + root = clones[0]; + logger->check(all_in_symmetry.size() == old_size, "Malformed new root pieces"); } diff --git a/src/universe/vehicle/SymmetryMode.h b/src/universe/vehicle/SymmetryMode.h index 161ac33..acc55f9 100644 --- a/src/universe/vehicle/SymmetryMode.h +++ b/src/universe/vehicle/SymmetryMode.h @@ -125,9 +125,9 @@ class SymmetryMode // Uses editor highlighting to show symmetry group (not debug, used for proper visualization!) void show_symmetry(EditorVehicle* veh); - // Moves the symmetry mode to have p as new root. + // Moves the symmetry mode to have p as new root clones. // TARGET MUST BE PERFECTLY SYMMETRICAL! - void new_root(Piece* p); + void new_root_clones(EditorVehicle* edveh, std::vector p); }; diff --git a/src/universe/vehicle/VehicleMeta.cpp b/src/universe/vehicle/VehicleMeta.cpp index 24df16d..fafe9ad 100644 --- a/src/universe/vehicle/VehicleMeta.cpp +++ b/src/universe/vehicle/VehicleMeta.cpp @@ -158,3 +158,17 @@ std::vector VehicleMeta::find_symmetry_groups_containing(Piece *p) return out; } +void VehicleMeta::cleanup_symmetry_groups() +{ + for(auto it = symmetry_groups.begin(); it != symmetry_groups.end(); ) + { + if((*it)->all_in_symmetry.empty()) + { + it = symmetry_groups.erase(it); + } + else + { + it++; + } + } +} \ No newline at end of file diff --git a/src/universe/vehicle/VehicleMeta.h b/src/universe/vehicle/VehicleMeta.h index 25e22b6..44c20b6 100644 --- a/src/universe/vehicle/VehicleMeta.h +++ b/src/universe/vehicle/VehicleMeta.h @@ -49,6 +49,8 @@ class VehicleMeta std::vector find_symmetry_instances(Piece* p, bool include_p); // Returns array of indices into the array std::vector find_symmetry_groups_containing(Piece* p); + // Removes empty symmetry groups. Make sure all are cleanup() before! + void cleanup_symmetry_groups();