Skip to content

Commit

Permalink
Dettaching works too
Browse files Browse the repository at this point in the history
  • Loading branch information
tatjam committed Jul 25, 2023
1 parent d5f9152 commit 218ab38
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 19 deletions.
2 changes: 1 addition & 1 deletion imgui.ini
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Size=110,54
Collapsed=0

[Window][Debug menu]
Pos=547,17
Pos=1406,134
Size=519,412
Collapsed=0

Expand Down
56 changes: 44 additions & 12 deletions src/game/scenes/editor/EditorVehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SymmetryMode*> to_move;
// indices in piece_children.push_back(piece)!
std::vector<size_t> new_root_indices;
// indices in piece_children.push_back(piece) for each clone!
std::vector<std::vector<size_t>> 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)
Expand All @@ -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<size_t> 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);
}
}
}

Expand All @@ -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<Piece*> 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<SymmetryMode*> 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)
Expand All @@ -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();

}


Expand Down
1 change: 1 addition & 0 deletions src/game/scenes/editor/gui/ModifyPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/game/scenes/editor/interfaces/ModifyInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
28 changes: 24 additions & 4 deletions src/universe/vehicle/SymmetryMode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -229,7 +232,6 @@ void SymmetryMode::cleanup()
it = all_in_symmetry.erase(it);
else
it++;

}
}

Expand All @@ -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)
Expand All @@ -276,6 +277,7 @@ void SymmetryMode::remove_piece_from_symmetry(EditorVehicle *edveh, Piece *p)
return;
}
}

}

std::vector<SymmetryInstance> SymmetryMode::find_clones(Piece *p, bool include_p)
Expand Down Expand Up @@ -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<Piece*> 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<Piece*> 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");
}


4 changes: 2 additions & 2 deletions src/universe/vehicle/SymmetryMode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Piece*> p);

};

Expand Down
14 changes: 14 additions & 0 deletions src/universe/vehicle/VehicleMeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,17 @@ std::vector<size_t> 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++;
}
}
}
2 changes: 2 additions & 0 deletions src/universe/vehicle/VehicleMeta.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class VehicleMeta
std::vector<SymmetryInstance> find_symmetry_instances(Piece* p, bool include_p);
// Returns array of indices into the array
std::vector<size_t> find_symmetry_groups_containing(Piece* p);
// Removes empty symmetry groups. Make sure all are cleanup() before!
void cleanup_symmetry_groups();



Expand Down

0 comments on commit 218ab38

Please sign in to comment.