diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 9fd24c377..16cc75225 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1353,37 +1353,6 @@ void ModelObject::delete_connectors() } } -void ModelObject::synchronize_model_after_cut() -{ - for (ModelObject* obj : m_model->objects) { - if (obj == this || obj->cut_id.is_equal(this->cut_id)) - continue; - if (obj->is_cut() && obj->cut_id.has_same_id(this->cut_id)) - obj->cut_id.copy(this->cut_id); - } - this->invalidate_cut(); -} - -void ModelObject::apply_cut_attributes(ModelObjectCutAttributes attributes) -{ - // we don't save cut information, if result will not contains all parts of initial object - if (!attributes.has(ModelObjectCutAttribute::KeepUpper) || - !attributes.has(ModelObjectCutAttribute::KeepLower) || - attributes.has(ModelObjectCutAttribute::InvalidateCutInfo)) - return; - - if (cut_id.id().invalid()) - cut_id.init(); - { - int cut_obj_cnt = -1; - if (attributes.has(ModelObjectCutAttribute::KeepUpper)) cut_obj_cnt++; - if (attributes.has(ModelObjectCutAttribute::KeepLower)) cut_obj_cnt++; - if (attributes.has(ModelObjectCutAttribute::CreateDowels)) cut_obj_cnt++; - if (cut_obj_cnt > 0) - cut_id.increase_check_sum(size_t(cut_obj_cnt)); - } -} - void ModelObject::clone_for_cut(ModelObject** obj) { (*obj) = ModelObject::new_clone(*this); @@ -1636,9 +1605,6 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Transform3d& cut_matrix, BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - start"; - // apply cut attributes for object - apply_cut_attributes(attributes); - // Clone the object to duplicate instances, materials etc. ModelObject* upper{ nullptr }; if (attributes.has(ModelObjectCutAttribute::KeepUpper)) @@ -1709,8 +1675,6 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Transform3d& cut_matrix, BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - end"; - synchronize_model_after_cut(); - return res; } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 7dcc427bf..21e7d4c68 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -469,13 +469,7 @@ public: void delete_connectors(); void clone_for_cut(ModelObject **obj); - void apply_cut_attributes(ModelObjectCutAttributes attributes); private: - // FIXME: These functions would best not be here at all. It might make sense to separate the - // cut-related methods elsewhere. Same holds for cut_connectors data member, which is currently - // just a temporary variable used by cut gizmo only. - void synchronize_model_after_cut(); - void process_connector_cut(ModelVolume* volume, const Transform3d& instance_matrix, const Transform3d& cut_matrix, ModelObjectCutAttributes attributes, ModelObject* upper, ModelObject* lower, std::vector& dowels); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 7edd43ccb..25da892ba 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -2424,7 +2424,7 @@ bool GLGizmoCut3D::has_valid_contour() const return clipper && clipper->has_valid_contour(); } -void GLGizmoCut3D::apply_connectors_in_model(ModelObject* mo, bool &create_dowels_as_separate_object) +void GLGizmoCut3D::apply_connectors_in_model(ModelObject* mo, int &dowels_count) { if (m_connector_mode == CutConnectorMode::Manual) { clear_selection(); @@ -2435,7 +2435,7 @@ void GLGizmoCut3D::apply_connectors_in_model(ModelObject* mo, bool &create_dowel if (connector.attribs.type == CutConnectorType::Dowel) { if (connector.attribs.style == CutConnectorStyle::Prism) connector.height *= 2; - create_dowels_as_separate_object = true; + dowels_count ++; } else { // calculate shift of the connector center regarding to the position on the cut plane @@ -2464,6 +2464,34 @@ Transform3d GLGizmoCut3D::get_cut_matrix(const Selection& selection) return translation_transform(cut_center_offset) * m_rotation_m; } +void update_object_cut_id(CutObjectBase& cut_id, ModelObjectCutAttributes attributes, const int dowels_count) +{ + // we don't save cut information, if result will not contains all parts of initial object + if (!attributes.has(ModelObjectCutAttribute::KeepUpper) || + !attributes.has(ModelObjectCutAttribute::KeepLower) || + attributes.has(ModelObjectCutAttribute::InvalidateCutInfo)) + return; + + if (cut_id.id().invalid()) + cut_id.init(); + // increase check sum, if it's needed + { + int cut_obj_cnt = -1; + if (attributes.has(ModelObjectCutAttribute::KeepUpper)) cut_obj_cnt++; + if (attributes.has(ModelObjectCutAttribute::KeepLower)) cut_obj_cnt++; + if (attributes.has(ModelObjectCutAttribute::CreateDowels)) cut_obj_cnt+= dowels_count; + if (cut_obj_cnt > 0) + cut_id.increase_check_sum(size_t(cut_obj_cnt)); + } +} + +void synchronize_model_after_cut(Model& model, const CutObjectBase& cut_id) +{ + for (ModelObject* obj : model.objects) + if (obj->is_cut() && obj->cut_id.has_same_id(cut_id) && !obj->cut_id.is_equal(cut_id)) + obj->cut_id.copy(cut_id); +} + void GLGizmoCut3D::perform_cut(const Selection& selection) { if (!can_perform_cut()) @@ -2492,11 +2520,13 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) ModelObject* cut_mo = cut_by_contour ? m_part_selection.model_object() : nullptr; if (cut_mo) cut_mo->cut_connectors = mo->cut_connectors; + else + cut_mo = mo; - bool create_dowels_as_separate_object = false; + int dowels_count = 0; const bool has_connectors = !mo->cut_connectors.empty(); // update connectors pos as offset of its center before cut performing - apply_connectors_in_model(cut_mo ? cut_mo : mo , create_dowels_as_separate_object); + apply_connectors_in_model(cut_mo , dowels_count); wxBusyCursor wait; @@ -2509,33 +2539,27 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) only_if(m_place_on_cut_lower, ModelObjectCutAttribute::PlaceOnCutLower) | only_if(m_rotate_upper, ModelObjectCutAttribute::FlipUpper) | only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower) | - only_if(create_dowels_as_separate_object, ModelObjectCutAttribute::CreateDowels) | - only_if(!has_connectors, ModelObjectCutAttribute::InvalidateCutInfo); + only_if(dowels_count > 0, ModelObjectCutAttribute::CreateDowels) | + only_if(!has_connectors && cut_mo->cut_id.id().invalid(), ModelObjectCutAttribute::InvalidateCutInfo); + + // update cut_id for the cut object in respect to the attributes + update_object_cut_id(cut_mo->cut_id, attributes, dowels_count); ModelObjectPtrs cut_object_ptrs; if (cut_by_contour) { - // apply cut attributes for object - if (m_keep_upper && m_keep_lower) - cut_mo->apply_cut_attributes(ModelObjectCutAttribute::KeepLower | ModelObjectCutAttribute::KeepUpper | - only_if(create_dowels_as_separate_object, ModelObjectCutAttribute::CreateDowels)); - // Clone the object to duplicate instances, materials etc. ModelObject* upper{ nullptr }; if (m_keep_upper) cut_mo->clone_for_cut(&upper); ModelObject* lower{ nullptr }; if (m_keep_lower) cut_mo->clone_for_cut(&lower); - auto add_cut_objects = [this, &instance_idx, &cut_matrix](ModelObjectPtrs& cut_objects, ModelObject* upper, ModelObject* lower, bool invalidate_cut = true) { + auto add_cut_objects = [this, &instance_idx, &cut_matrix](ModelObjectPtrs& cut_objects, ModelObject* upper, ModelObject* lower) { if (upper && !upper->volumes.empty()) { ModelObject::reset_instance_transformation(upper, instance_idx, cut_matrix, m_place_on_cut_upper, m_rotate_upper); - if (invalidate_cut) - upper->invalidate_cut(); cut_objects.push_back(upper); } if (lower && !lower->volumes.empty()) { ModelObject::reset_instance_transformation(lower, instance_idx, cut_matrix, m_place_on_cut_lower, m_place_on_cut_lower || m_rotate_lower); - if (invalidate_cut) - lower->invalidate_cut(); cut_objects.push_back(lower); } }; @@ -2573,7 +2597,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) if (volumes.size() == cut_parts_cnt) { // Means that object is cut without connectors - // Just add Upper and Lower objects to cut_object_ptrs and invalidate any cut information + // Just add Upper and Lower objects to cut_object_ptrs add_cut_objects(cut_object_ptrs, upper, lower); } else if (volumes.size() > cut_parts_cnt) { @@ -2597,8 +2621,8 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) for (const ModelVolume* volume : cut_connectors_obj[1]->volumes) lower->add_volume(*volume, volume->type()); - // Add Upper and Lower objects to cut_object_ptrs with saved cut information - add_cut_objects(cut_object_ptrs, upper, lower, false); + // Add Upper and Lower objects to cut_object_ptrs + add_cut_objects(cut_object_ptrs, upper, lower); // Add Dowel-connectors as separate objects to cut_object_ptrs if (cut_connectors_obj.size() >= 3) @@ -2632,14 +2656,18 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) } } else - cut_object_ptrs = mo->cut(instance_idx, cut_matrix, attributes); + cut_object_ptrs = cut_mo->cut(instance_idx, cut_matrix, attributes); + // save cut_id to post update synchronization + const CutObjectBase cut_id = cut_mo->cut_id; + + // update cut results on plater and in the model plater->cut(object_idx, cut_object_ptrs); + + synchronize_model_after_cut(plater->model(), cut_id); } } - - // Unprojects the mouse position on the mesh and saves hit point and normal of the facet into pos_and_normal // Return false if no intersection was found, true otherwise. bool GLGizmoCut3D::unproject_on_cut_plane(const Vec2d& mouse_position, Vec3d& pos, Vec3d& pos_world, bool respect_disabled_contour/* = true*/) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index 6d1a8e4e5..51174a51a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -315,7 +315,7 @@ private: bool can_perform_cut() const; bool has_valid_contour() const; - void apply_connectors_in_model(ModelObject* mo, bool &create_dowels_as_separate_object); + void apply_connectors_in_model(ModelObject* mo, int &dowels_count); bool cut_line_processing() const; void discard_cut_line_processing();