diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 398756fc9..0c4c2ed2b 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -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) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index d7d1a1af7..acb6d3a86 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -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> 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 \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 166606e2e..3d312d9c9 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -300,6 +300,8 @@ public: void msw_rescale(); + void recreate_object_list(); + private: #ifdef __WXOSX__ // void OnChar(wxKeyEvent& event); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4a743aab1..184b23c9b 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -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 &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("wipe_tower_x", true)->value = evt.data(0); cfg.opt("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("wipe_tower_x", true)->value = evt.data(0); cfg.opt("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 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() diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 2986d97dd..ffb423758 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -311,7 +311,7 @@ void Selection::add_all() this->set_bounding_boxes_dirty(); } -void Selection::set_deserialized(EMode mode, const std::vector> &volumes_and_instances) +void Selection::set_deserialized(EMode mode, const std::vector> &volumes_and_instances) { if (! m_valid) return; @@ -320,11 +320,9 @@ void Selection::set_deserialized(EMode mode, const std::vectorselected = 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(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(); } diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 8168e5e88..35336c2b3 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -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> &volumes_and_instances); + void set_deserialized(EMode mode, const std::vector> &volumes_and_instances); // Update the selection based on the new instance IDs. void instances_changed(const std::vector &instance_ids_selected); diff --git a/src/slic3r/Utils/UndoRedo.cpp b/src/slic3r/Utils/UndoRedo.cpp index 528c1c135..11fceee0a 100644 --- a/src/slic3r/Utils/UndoRedo.cpp +++ b/src/slic3r/Utils/UndoRedo.cpp @@ -652,10 +652,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(m_selection); // Save the snapshot info. m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id); diff --git a/src/slic3r/Utils/UndoRedo.hpp b/src/slic3r/Utils/UndoRedo.hpp index e50f6ad63..92946d761 100644 --- a/src/slic3r/Utils/UndoRedo.hpp +++ b/src/slic3r/Utils/UndoRedo.hpp @@ -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> volumes_and_instances; + unsigned char mode; + std::vector> volumes_and_instances; template void serialize(Archive &ar) { ar(mode, volumes_and_instances); } };