Fix for #10667 - Scaling blocked (or not blocked) incorrecty after cut feature is used
* cut_id for cut object is updated from attributes before all manipulations with perform a cut * synchronization of the cut_id for whole model is execute now after all manipulations, related to the cut
This commit is contained in:
parent
32af0221f2
commit
0e452dcf74
@ -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)
|
void ModelObject::clone_for_cut(ModelObject** obj)
|
||||||
{
|
{
|
||||||
(*obj) = ModelObject::new_clone(*this);
|
(*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";
|
BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - start";
|
||||||
|
|
||||||
// apply cut attributes for object
|
|
||||||
apply_cut_attributes(attributes);
|
|
||||||
|
|
||||||
// Clone the object to duplicate instances, materials etc.
|
// Clone the object to duplicate instances, materials etc.
|
||||||
ModelObject* upper{ nullptr };
|
ModelObject* upper{ nullptr };
|
||||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper))
|
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";
|
BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - end";
|
||||||
|
|
||||||
synchronize_model_after_cut();
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,13 +469,7 @@ public:
|
|||||||
void delete_connectors();
|
void delete_connectors();
|
||||||
void clone_for_cut(ModelObject **obj);
|
void clone_for_cut(ModelObject **obj);
|
||||||
|
|
||||||
void apply_cut_attributes(ModelObjectCutAttributes attributes);
|
|
||||||
private:
|
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,
|
void process_connector_cut(ModelVolume* volume, const Transform3d& instance_matrix, const Transform3d& cut_matrix,
|
||||||
ModelObjectCutAttributes attributes, ModelObject* upper, ModelObject* lower,
|
ModelObjectCutAttributes attributes, ModelObject* upper, ModelObject* lower,
|
||||||
std::vector<ModelObject*>& dowels);
|
std::vector<ModelObject*>& dowels);
|
||||||
|
@ -2424,7 +2424,7 @@ bool GLGizmoCut3D::has_valid_contour() const
|
|||||||
return clipper && clipper->has_valid_contour();
|
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) {
|
if (m_connector_mode == CutConnectorMode::Manual) {
|
||||||
clear_selection();
|
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.type == CutConnectorType::Dowel) {
|
||||||
if (connector.attribs.style == CutConnectorStyle::Prism)
|
if (connector.attribs.style == CutConnectorStyle::Prism)
|
||||||
connector.height *= 2;
|
connector.height *= 2;
|
||||||
create_dowels_as_separate_object = true;
|
dowels_count ++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// calculate shift of the connector center regarding to the position on the cut plane
|
// 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;
|
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)
|
void GLGizmoCut3D::perform_cut(const Selection& selection)
|
||||||
{
|
{
|
||||||
if (!can_perform_cut())
|
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;
|
ModelObject* cut_mo = cut_by_contour ? m_part_selection.model_object() : nullptr;
|
||||||
if (cut_mo)
|
if (cut_mo)
|
||||||
cut_mo->cut_connectors = mo->cut_connectors;
|
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();
|
const bool has_connectors = !mo->cut_connectors.empty();
|
||||||
// update connectors pos as offset of its center before cut performing
|
// 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;
|
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_place_on_cut_lower, ModelObjectCutAttribute::PlaceOnCutLower) |
|
||||||
only_if(m_rotate_upper, ModelObjectCutAttribute::FlipUpper) |
|
only_if(m_rotate_upper, ModelObjectCutAttribute::FlipUpper) |
|
||||||
only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower) |
|
only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower) |
|
||||||
only_if(create_dowels_as_separate_object, ModelObjectCutAttribute::CreateDowels) |
|
only_if(dowels_count > 0, ModelObjectCutAttribute::CreateDowels) |
|
||||||
only_if(!has_connectors, ModelObjectCutAttribute::InvalidateCutInfo);
|
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;
|
ModelObjectPtrs cut_object_ptrs;
|
||||||
if (cut_by_contour) {
|
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.
|
// Clone the object to duplicate instances, materials etc.
|
||||||
ModelObject* upper{ nullptr };
|
ModelObject* upper{ nullptr };
|
||||||
if (m_keep_upper) cut_mo->clone_for_cut(&upper);
|
if (m_keep_upper) cut_mo->clone_for_cut(&upper);
|
||||||
ModelObject* lower{ nullptr };
|
ModelObject* lower{ nullptr };
|
||||||
if (m_keep_lower) cut_mo->clone_for_cut(&lower);
|
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()) {
|
if (upper && !upper->volumes.empty()) {
|
||||||
ModelObject::reset_instance_transformation(upper, instance_idx, cut_matrix, m_place_on_cut_upper, m_rotate_upper);
|
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);
|
cut_objects.push_back(upper);
|
||||||
}
|
}
|
||||||
if (lower && !lower->volumes.empty()) {
|
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);
|
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);
|
cut_objects.push_back(lower);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -2573,7 +2597,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
|
|||||||
if (volumes.size() == cut_parts_cnt) {
|
if (volumes.size() == cut_parts_cnt) {
|
||||||
// Means that object is cut without connectors
|
// 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);
|
add_cut_objects(cut_object_ptrs, upper, lower);
|
||||||
}
|
}
|
||||||
else if (volumes.size() > cut_parts_cnt) {
|
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)
|
for (const ModelVolume* volume : cut_connectors_obj[1]->volumes)
|
||||||
lower->add_volume(*volume, volume->type());
|
lower->add_volume(*volume, volume->type());
|
||||||
|
|
||||||
// Add Upper and Lower objects to cut_object_ptrs with saved cut information
|
// Add Upper and Lower objects to cut_object_ptrs
|
||||||
add_cut_objects(cut_object_ptrs, upper, lower, false);
|
add_cut_objects(cut_object_ptrs, upper, lower);
|
||||||
|
|
||||||
// Add Dowel-connectors as separate objects to cut_object_ptrs
|
// Add Dowel-connectors as separate objects to cut_object_ptrs
|
||||||
if (cut_connectors_obj.size() >= 3)
|
if (cut_connectors_obj.size() >= 3)
|
||||||
@ -2632,14 +2656,18 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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);
|
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
|
// 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.
|
// 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*/)
|
bool GLGizmoCut3D::unproject_on_cut_plane(const Vec2d& mouse_position, Vec3d& pos, Vec3d& pos_world, bool respect_disabled_contour/* = true*/)
|
||||||
|
@ -315,7 +315,7 @@ private:
|
|||||||
|
|
||||||
bool can_perform_cut() const;
|
bool can_perform_cut() const;
|
||||||
bool has_valid_contour() 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;
|
bool cut_line_processing() const;
|
||||||
void discard_cut_line_processing();
|
void discard_cut_line_processing();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user