Update object list after undo/redo

This commit is contained in:
YuSanka 2019-07-04 17:33:19 +02:00
parent 1798e2a84c
commit a29cc9e242
8 changed files with 89 additions and 19 deletions

View File

@ -508,8 +508,8 @@ private:
ModelVolume(ModelObject *object, const ModelVolume &other, const TriangleMesh &&mesh) :
name(other.name), m_mesh(new TriangleMesh(std::move(mesh))), config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation)
{
assert(this->id().valid()); assert(this->config.id().valid()); assert(this->id() != this->config.id());
assert(this->id() == other.id() && this->config.id() == other.config.id());
// assert(this->id().valid()); assert(this->config.id().valid()); assert(this->id() != this->config.id());
// assert(this->id() == other.id() && this->config.id() == other.config.id());
this->set_material_id(other.material_id());
this->config.set_new_unique_id();
if (mesh.stl.stats.number_of_facets > 1)

View File

@ -65,6 +65,11 @@ static int extruders_count()
return wxGetApp().extruders_cnt();
}
static void take_snapshot(const wxString& snapshot_name)
{
wxGetApp().plater()->take_snapshot(snapshot_name);
}
ObjectList::ObjectList(wxWindow* parent) :
wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE),
m_parent(parent)
@ -580,7 +585,6 @@ void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& vol
if (volumes.empty())
return;
ModelObject& model_object = *(*m_objects)[obj_idx];
const auto object_item = m_objects_model->GetItemById(obj_idx);
wxDataViewItemArray items;
@ -816,6 +820,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
if (m_dragged_data.type() == itInstance)
{
take_snapshot(_(L("Instances to Separated Objects")));
instances_to_separated_object(m_dragged_data.obj_idx(), m_dragged_data.inst_idxs());
m_dragged_data.clear();
return;
@ -833,6 +838,8 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
// if (to_volume_id > from_volume_id) to_volume_id--;
// #endif // __WXGTK__
take_snapshot(_(L("Remov Volume(s)")));
auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes;
auto delta = to_volume_id < from_volume_id ? -1 : 1;
int cnt = 0;
@ -1427,6 +1434,8 @@ void ObjectList::load_subobject(ModelVolumeType type)
if (m_objects_model->GetItemType(item)&itInstance)
item = m_objects_model->GetItemById(obj_idx);
take_snapshot(_(L("Load Part")));
std::vector<std::pair<wxString, bool>> volumes_info;
load_part((*m_objects)[obj_idx], volumes_info, type);
@ -1502,6 +1511,8 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
if (instance_idx == -1)
return;
take_snapshot(_(L("Add Generic Subobject")));
// Selected object
ModelObject &model_object = *(*m_objects)[obj_idx];
// Bounding box of the selected instance in world coordinate system including the translation, without modifiers.
@ -1616,6 +1627,8 @@ void ObjectList::del_instances_from_object(const int obj_idx)
if (instances.size() <= 1)
return;
take_snapshot(_(L("Delete All Instances from Object")));
while ( instances.size()> 1)
instances.pop_back();
@ -1645,6 +1658,8 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con
return false;
}
take_snapshot(_(L("Delete Subobject")));
object->delete_volume(idx);
if (object->volumes.size() == 1)
@ -1661,6 +1676,8 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con
Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last intance from object.")));
return false;
}
take_snapshot(_(L("Delete Instance")));
object->delete_instance(idx);
}
else
@ -1688,6 +1705,8 @@ void ObjectList::split()
return;
}
take_snapshot(_(L("Split to Parts")));
wxBusyCursor wait;
auto model_object = (*m_objects)[obj_idx];
@ -1945,6 +1964,8 @@ void ObjectList::delete_from_model_and_list(const ItemType type, const int obj_i
if ( !(type&(itObject|itVolume|itInstance)) )
return;
take_snapshot(_(L("Delete Selected Item")));
if (type&itObject) {
del_object(obj_idx);
delete_object_from_list(obj_idx);
@ -2502,6 +2523,8 @@ void ObjectList::change_part_type()
if (new_type == type || new_type == ModelVolumeType::INVALID)
return;
take_snapshot(_(L("Paste from Clipboard")));
const auto item = GetSelection();
volume->set_type(new_type);
m_objects_model->SetVolumeType(item, new_type);
@ -2862,5 +2885,22 @@ void ObjectList::set_extruder_for_selected_items(const int extruder) const
wxGetApp().plater()->update();
}
void ObjectList::recreate_object_list()
{
m_prevent_list_events = true;
m_prevent_canvas_selection_update = true;
m_objects_model->DeleteAll();
size_t obj_idx = 0;
while (obj_idx < m_objects->size()) {
add_object_to_list(obj_idx);
++obj_idx;
}
m_prevent_canvas_selection_update = false;
m_prevent_list_events = false;
}
} //namespace GUI
} //namespace Slic3r

View File

@ -300,6 +300,8 @@ public:
void msw_rescale();
void recreate_object_list();
private:
#ifdef __WXOSX__
// void OnChar(wxKeyEvent& event);

View File

@ -1738,7 +1738,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
view3D_canvas->Bind(EVT_GLCANVAS_QUESTION_MARK, [this](SimpleEvent&) { wxGetApp().keyboard_shortcuts(); });
view3D_canvas->Bind(EVT_GLCANVAS_INCREASE_INSTANCES, [this](Event<int> &evt)
{ if (evt.data == 1) this->q->increase_instances(); else if (this->can_decrease_instances()) this->q->decrease_instances(); });
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); });
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) {
this->take_snapshot(_(L("Instance Moved")));
update(); });
view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this);
view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_ROTATED, &priv::on_wipetower_rotated, this);
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_ROTATED, [this](SimpleEvent&) { update(); });
@ -2337,17 +2339,21 @@ void Plater::priv::object_list_changed()
void Plater::priv::select_all()
{
// this->take_snapshot(_(L("Select All")));
view3D->select_all();
this->sidebar->obj_list()->update_selections();
}
void Plater::priv::deselect_all()
{
// this->take_snapshot(_(L("Deselect All")));
view3D->deselect_all();
}
void Plater::priv::remove(size_t obj_idx)
{
this->take_snapshot(_(L("Remove Object")));
// Prevent toolpaths preview from rendering while we modify the Print object
preview->set_enabled(false);
@ -2364,6 +2370,7 @@ void Plater::priv::remove(size_t obj_idx)
void Plater::priv::delete_object_from_model(size_t obj_idx)
{
// this->take_snapshot(_(L("Delete Object"))); // ys_FIXME What is the difference with "Remove Object"?
model.delete_object(obj_idx);
update();
object_list_changed();
@ -2398,17 +2405,20 @@ void Plater::priv::reset()
void Plater::priv::mirror(Axis axis)
{
this->take_snapshot(_(L("Mirror")));
view3D->mirror_selection(axis);
}
void Plater::priv::arrange()
{
this->take_snapshot(_(L("Arrange")));
m_ui_jobs.start(Jobs::Arrange);
}
// This method will find an optimal orientation for the currently selected item
// Very similar in nature to the arrange method above...
void Plater::priv::sla_optimize_rotation() {
this->take_snapshot(_(L("Optimize Rotation")));
m_ui_jobs.start(Jobs::Rotoptimize);
}
@ -2564,6 +2574,8 @@ void Plater::priv::split_object()
Slic3r::GUI::warning_catcher(q, _(L("The selected object couldn't be split because it contains only one part.")));
else
{
this->take_snapshot(_(L("Split to Objects")));
unsigned int counter = 1;
for (ModelObject* m : new_objects)
m->name = current_model_object->name + "_" + std::to_string(counter++);
@ -2835,6 +2847,9 @@ void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* =
{
if (obj_idx < 0)
return;
this->take_snapshot(_(L("Fix Throught NetFabb")));
fix_model_by_win10_sdk_gui(*model.objects[obj_idx], vol_idx);
this->update();
this->object_list_changed();
@ -3074,6 +3089,8 @@ void Plater::priv::on_action_layersediting(SimpleEvent&)
void Plater::priv::on_object_select(SimpleEvent& evt)
{
// this->take_snapshot(_(L("Object Selection")));
wxGetApp().obj_list()->update_selections();
selection_changed();
}
@ -3135,6 +3152,8 @@ void Plater::priv::on_right_click(Vec2dEvent& evt)
void Plater::priv::on_wipetower_moved(Vec3dEvent &evt)
{
this->take_snapshot(_(L("Wipe Tower Moved")));
DynamicPrintConfig cfg;
cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = evt.data(0);
cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = evt.data(1);
@ -3143,6 +3162,8 @@ void Plater::priv::on_wipetower_moved(Vec3dEvent &evt)
void Plater::priv::on_wipetower_rotated(Vec3dEvent& evt)
{
this->take_snapshot(_(L("Wipe Tower Rotated")));
DynamicPrintConfig cfg;
cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = evt.data(0);
cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = evt.data(1);
@ -3514,7 +3535,9 @@ void Plater::priv::update_after_undo_redo()
this->update(false); // update volumes from the deserializd model
//YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time)
this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack.selection_deserialized().mode), this->undo_redo_stack.selection_deserialized().volumes_and_instances);
// wxGetApp().obj_list()->update_selections();
wxGetApp().obj_list()->recreate_object_list();
wxGetApp().obj_list()->update_selections();
// selection_changed();
//FIXME what about the state of the manipulators?
//FIXME what about the focus? Cursor in the side panel?
@ -3580,6 +3603,8 @@ void Plater::add_model()
if (input_files.empty())
return;
this->take_snapshot(_(L("Add object(s)")));
std::vector<fs::path> input_paths;
for (const auto &file : input_files) {
input_paths.push_back(into_path(file));
@ -3717,6 +3742,8 @@ void Plater::set_number_of_copies(/*size_t num*/)
if (num < 0)
return;
this->take_snapshot(wxString::Format(_(L("Set numbers of copies to %d")), num));
int diff = (int)num - (int)model_object->instances.size();
if (diff > 0)
increase_instances(diff);
@ -3745,6 +3772,8 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_uppe
return;
}
this->take_snapshot(_(L("Cut")));
wxBusyCursor wait;
const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower);
@ -4245,8 +4274,11 @@ void Plater::copy_selection_to_clipboard()
void Plater::paste_from_clipboard()
{
if (can_paste_from_clipboard())
p->view3D->get_canvas3d()->get_selection().paste_from_clipboard();
if (!can_paste_from_clipboard())
return;
this->take_snapshot(_(L("Paste From Clipboard")));
p->view3D->get_canvas3d()->get_selection().paste_from_clipboard();
}
void Plater::msw_rescale()

View File

@ -311,7 +311,7 @@ void Selection::add_all()
this->set_bounding_boxes_dirty();
}
void Selection::set_deserialized(EMode mode, const std::vector<std::pair<ObjectID, ObjectID>> &volumes_and_instances)
void Selection::set_deserialized(EMode mode, const std::vector<std::pair<size_t, size_t>> &volumes_and_instances)
{
if (! m_valid)
return;
@ -320,11 +320,9 @@ void Selection::set_deserialized(EMode mode, const std::vector<std::pair<ObjectI
for (unsigned int i : m_list)
(*m_volumes)[i]->selected = false;
m_list.clear();
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++ i) {
const GLVolume::CompositeID &id = (*m_volumes)[i]->composite_id;
if (std::binary_search(volumes_and_instances.begin(), volumes_and_instances.end(), std::make_pair<ObjectID, ObjectID>(id.volume_id, id.instance_id)))
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++ i)
if (std::binary_search(volumes_and_instances.begin(), volumes_and_instances.end(), (*m_volumes)[i]->geometry_id))
this->do_add_volume(i);
}
update_type();
this->set_bounding_boxes_dirty();
}

View File

@ -238,7 +238,7 @@ public:
void add_all();
// To be called after Undo or Redo once the volumes are updated.
void set_deserialized(EMode mode, const std::vector<std::pair<ObjectID, ObjectID>> &volumes_and_instances);
void set_deserialized(EMode mode, const std::vector<std::pair<size_t, size_t>> &volumes_and_instances);
// Update the selection based on the new instance IDs.
void instances_changed(const std::vector<size_t> &instance_ids_selected);

View File

@ -566,10 +566,8 @@ void StackImpl::take_snapshot(const std::string &snapshot_name, const Slic3r::Mo
m_selection.volumes_and_instances.clear();
m_selection.volumes_and_instances.reserve(selection.get_volume_idxs().size());
m_selection.mode = selection.get_mode();
for (unsigned int volume_idx : selection.get_volume_idxs()) {
const Slic3r::GLVolume::CompositeID &id = selection.get_volume(volume_idx)->composite_id;
m_selection.volumes_and_instances.emplace_back(id.volume_id, id.instance_id);
}
for (unsigned int volume_idx : selection.get_volume_idxs())
m_selection.volumes_and_instances.emplace_back(selection.get_volume(volume_idx)->geometry_id);
this->save_mutable_object<Selection, Selection>(m_selection);
// Save the snapshot info.
m_active_snapshot_time = m_current_time ++;

View File

@ -31,8 +31,8 @@ struct Snapshot
// Excerpt of Slic3r::GUI::Selection for serialization onto the Undo / Redo stack.
struct Selection : public Slic3r::ObjectBase {
unsigned char mode;
std::vector<std::pair<ObjectID, ObjectID>> volumes_and_instances;
unsigned char mode;
std::vector<std::pair<size_t, size_t>> volumes_and_instances;
template<class Archive> void serialize(Archive &ar) { ar(mode, volumes_and_instances); }
};