diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 829c76fb54..30dd64aa0a 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1,5 +1,4 @@ #include "Model.hpp" -#include "Model.hpp" #include "libslic3r.h" #include "BuildVolume.hpp" #include "Exception.hpp" @@ -611,7 +610,6 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs) this->layer_height_profile = rhs.layer_height_profile; this->printable = rhs.printable; this->origin_translation = rhs.origin_translation; - this->cut_connectors_count = rhs.cut_connectors_count; this->cut_id.copy(rhs.cut_id); m_bounding_box = rhs.m_bounding_box; m_bounding_box_valid = rhs.m_bounding_box_valid; @@ -1382,8 +1380,7 @@ void ModelObject::apply_cut_connectors(const std::string& name, CutConnectorAttr indexed_triangle_set connector_mesh = get_connector_mesh(connector_attributes); - size_t connector_id = cut_connectors_count; - + size_t connector_id = cut_id.connectors_cnt(); for (const CutConnector& connector : cut_connectors) { TriangleMesh mesh = TriangleMesh(connector_mesh); // Mesh will be centered when loading. @@ -1400,18 +1397,26 @@ void ModelObject::apply_cut_connectors(const std::string& name, CutConnectorAttr new_volume->name = name + "-" + std::to_string(++connector_id); new_volume->source.is_connector = true; } + cut_id.increase_connectors_cnt(cut_connectors.size()); - cut_connectors_count += cut_connectors.size(); // delete all connectors cut_connectors.clear(); } +void ModelObject::invalidate_cut() +{ + for (ModelObject* obj : m_model->objects) + if (obj != this && obj->cut_id.is_equal(this->cut_id)) + obj->cut_id.ivalidate(); +} + void ModelObject::synchronize_model_after_cut() { for (ModelObject* obj : m_model->objects) { if (obj == this || obj->cut_id.is_equal(this->cut_id)) continue; - obj->cut_id.set_check_sum(this->cut_id.check_sum()); + if (obj->is_cut() && obj->cut_id.has_same_id(this->cut_id)) + obj->cut_id.copy(this->cut_id); } } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 6fa724162d..3afa94c756 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -346,8 +346,6 @@ public: // Connectors to be added into the object after cut CutConnectors cut_connectors; - // count of connectors in object - size_t cut_connectors_count{ 0 }; CutObjectBase cut_id; /* This vector accumulates the total translation applied to the object by the @@ -437,6 +435,8 @@ public: ModelObjectPtrs cut(size_t instance, coordf_t z, ModelObjectCutAttributes attributes); static indexed_triangle_set get_connector_mesh(CutConnectorAttributes connector_attributes); void apply_cut_connectors(const std::string& name, CutConnectorAttributes connector_attributes); + // invalidate cut state for this and related objects from the whole model + void invalidate_cut(); void synchronize_model_after_cut(); ModelObjectPtrs cut(size_t instance, const Vec3d& cut_center, const Vec3d& cut_rotation, ModelObjectCutAttributes attributes); void split(ModelObjectPtrs* new_objects); diff --git a/src/libslic3r/ObjectID.hpp b/src/libslic3r/ObjectID.hpp index 599c243b52..42cd216991 100644 --- a/src/libslic3r/ObjectID.hpp +++ b/src/libslic3r/ObjectID.hpp @@ -130,8 +130,10 @@ private: class CutObjectBase : public ObjectBase { - // check sum of CutPartsObject + // check sum of CutParts in initial Object size_t m_check_sum{ 1 }; + // connectors count + size_t m_connectors_cnt{ 0 }; public: // Default Constructor to assign an invalid ID @@ -148,19 +150,31 @@ public: void copy(const CutObjectBase& rhs) { this->copy_id(rhs); this->m_check_sum = rhs.check_sum(); + this->m_connectors_cnt = rhs.connectors_cnt() ; } CutObjectBase operator=(const CutObjectBase& other) { this->copy(other); return *this; } + void ivalidate() { + set_invalid_id(); + m_check_sum = 1; + m_connectors_cnt = 0; + } + void init() { this->set_new_unique_id(); } bool has_same_id(const CutObjectBase& rhs) { return this->id() == rhs.id(); } - bool is_equal(const CutObjectBase& rhs) { return this->id() == rhs.id() && this->check_sum() == rhs.check_sum(); } + bool is_equal(const CutObjectBase& rhs) { return this->id() == rhs.id() && + this->check_sum() == rhs.check_sum() && + this->connectors_cnt() == rhs.connectors_cnt() ; } size_t check_sum() const { return m_check_sum; } void set_check_sum(size_t cs) { m_check_sum = cs; } void increase_check_sum(size_t cnt) { m_check_sum += cnt; } + + size_t connectors_cnt() const { return m_connectors_cnt; } + void increase_connectors_cnt(size_t connectors_cnt) { m_connectors_cnt += connectors_cnt; } }; // Unique object / instance ID for the wipe tower. diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 7b3476d711..d5e7260af4 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -494,7 +494,9 @@ void MenuFactory::append_menu_items_add_volume(wxMenu* menu) append_menu_item(menu, wxID_ANY, _(ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::MODEL_PART)].first), "", [](wxCommandEvent&) { obj_list()->load_subobject(ModelVolumeType::MODEL_PART); }, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::MODEL_PART)].second, nullptr, - []() { return obj_list()->is_instance_or_object_selected(); }, m_parent); + []() { return obj_list()->is_instance_or_object_selected() + && !obj_list()->is_selected_object_cut(); + }, m_parent); } if (mode == comSimple) { append_menu_item(menu, wxID_ANY, _(ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SUPPORT_ENFORCER)].first), "", @@ -515,7 +517,10 @@ void MenuFactory::append_menu_items_add_volume(wxMenu* menu) wxMenu* sub_menu = append_submenu_add_generic(menu, ModelVolumeType(type)); append_submenu(menu, sub_menu, wxID_ANY, _(item.first), "", item.second, - []() { return obj_list()->is_instance_or_object_selected(); }, m_parent); + [type]() { + bool can_add = type < size_t(ModelVolumeType::PARAMETER_MODIFIER) ? !obj_list()->is_selected_object_cut() : true; + return can_add && obj_list()->is_instance_or_object_selected(); + }, m_parent); } append_menu_item_layers_editing(menu); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index bff535bed0..cc577da2f7 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1794,7 +1794,7 @@ struct Plater::priv void select_all(); void deselect_all(); void remove(size_t obj_idx); - void delete_object_from_model(size_t obj_idx); + bool delete_object_from_model(size_t obj_idx); void delete_all_objects_from_model(); void reset(); void mirror(Axis axis); @@ -2959,16 +2959,32 @@ void Plater::priv::remove(size_t obj_idx) } -void Plater::priv::delete_object_from_model(size_t obj_idx) +bool Plater::priv::delete_object_from_model(size_t obj_idx) { + // check if object isn't cut + // show warning message that "cut consistancy" will not be supported any more + ModelObject* obj = model.objects[obj_idx]; + if (obj->is_cut()) { + MessageDialog dialog(q, _L("You try to delete an object which is a part of a cut object.\n" + "This action will break a cut correspondence.\n" + "After that PrusaSlicer can't garantie model consistency"), + _L("Delete object which is a part of cut object"), wxYES | wxCANCEL | wxCANCEL_DEFAULT); + dialog.SetButtonLabel(wxID_YES, _L("Delete object")); + if (dialog.ShowModal() == wxID_CANCEL) + return false; + // unmark all related CutParts of initial object + obj->invalidate_cut(); + } + wxString snapshot_label = _L("Delete Object"); - if (! model.objects[obj_idx]->name.empty()) - snapshot_label += ": " + wxString::FromUTF8(model.objects[obj_idx]->name.c_str()); + if (!obj->name.empty()) + snapshot_label += ": " + wxString::FromUTF8(obj->name.c_str()); Plater::TakeSnapshot snapshot(q, snapshot_label); m_worker.cancel_all(); model.delete_object(obj_idx); update(); object_list_changed(); + return true; } void Plater::priv::delete_all_objects_from_model() @@ -5679,7 +5695,7 @@ void Plater::reset_with_confirm() reset(); } -void Plater::delete_object_from_model(size_t obj_idx) { p->delete_object_from_model(obj_idx); } +bool Plater::delete_object_from_model(size_t obj_idx) { return p->delete_object_from_model(obj_idx); } void Plater::remove_selected() { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index a168c32d1b..39aa7cf8b9 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -242,7 +242,7 @@ public: void remove(size_t obj_idx); void reset(); void reset_with_confirm(); - void delete_object_from_model(size_t obj_idx); + bool delete_object_from_model(size_t obj_idx); void remove_selected(); void increase_instances(size_t num = 1); void decrease_instances(size_t num = 1);