From c29b7b1eef193c83914e26acb647c9d2b76bccd0 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 12 Apr 2022 14:27:34 +0200 Subject: [PATCH] Cut WIP: * Suppress to delete/add a SolidPart/NegativeVolume from/for objects which are marked as "is cut" * Suppress to delete Instances which are marked as "is cut" * Allow delete an object which is marked as "is cut", but show warning message about break of the "cut consistency". And if this deletion was performed, the all related objects will be unmarked. * m_connectors_cnt is added into CutObjectBase class to correct synchronization of a connectors count between related objects --- src/libslic3r/Model.cpp | 17 +++++++++++------ src/libslic3r/Model.hpp | 4 ++-- src/libslic3r/ObjectID.hpp | 18 ++++++++++++++++-- src/slic3r/GUI/GUI_Factories.cpp | 9 +++++++-- src/slic3r/GUI/Plater.cpp | 26 +++++++++++++++++++++----- src/slic3r/GUI/Plater.hpp | 2 +- 6 files changed, 58 insertions(+), 18 deletions(-) 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);