diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index b0e68dffff..74f1ba19ee 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -2881,9 +2881,9 @@ bool ConfigWizard::priv::check_and_install_missing_materials(Technology technolo if (only_for_model_id.empty()) ask_and_select_default_materials( _L("The following FFF printer models have no filament selected:") + - "\n\n\t" + + "\n\n" + printer_model_list(printer_models_without_material) + - "\n\n\t" + + "\n\n" + _L("Do you want to select default filaments for these FFF printer models?"), printer_models_without_material, T_FFF); @@ -2899,9 +2899,9 @@ bool ConfigWizard::priv::check_and_install_missing_materials(Technology technolo if (only_for_model_id.empty()) ask_and_select_default_materials( _L("The following SLA printer models have no materials selected:") + - "\n\n\t" + + "\n\n" + printer_model_list(printer_models_without_material) + - "\n\n\t" + + "\n\n" + _L("Do you want to select default SLA materials for these printer models?"), printer_models_without_material, T_SLA); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 1906d2c307..79ae5b8963 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2175,6 +2175,10 @@ void ObjectList::split() take_snapshot(_(L("Split to Parts"))); + // Before splitting volume we have to remove all custom supports, seams, and multimaterial painting. + wxGetApp().plater()->clear_before_change_mesh(obj_idx, _u8L("Custom supports, seams and multimaterial painting were " + "removed after splitting the object.")); + volume->split(nozzle_dmrs_cnt); (*m_objects)[obj_idx]->input_file.clear(); @@ -2186,6 +2190,10 @@ void ObjectList::split() changed_object(obj_idx); // update printable state for new volumes on canvas3D wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object(obj_idx); + + // After removing custom supports, seams, and multimaterial painting, we have to update info about the object to remove information about + // custom supports, seams, and multimaterial painting in the right panel. + wxGetApp().obj_list()->update_info_items(obj_idx); } void ObjectList::merge(bool to_multipart_object) @@ -4682,7 +4690,8 @@ void ObjectList::fix_through_netfabb() msg += "\n"; } - plater->clear_before_change_mesh(obj_idx); + plater->clear_before_change_mesh(obj_idx, _u8L("Custom supports, seams and multimaterial painting were " + "removed after repairing the mesh.")); std::string res; if (!fix_model_by_win10_sdk_gui(*(object(obj_idx)), vol_idx, progress_dlg, msg, res)) return false; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 8c33c3e037..d8064bd043 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -453,15 +453,9 @@ void GLGizmoCut3D::update_clipper() update_raycasters_for_picking_transform(); } -void GLGizmoCut3D::update_clipper_on_render() +void GLGizmoCut3D::set_center(const Vec3d& center, bool update_tbb /*=false*/) { - update_clipper(); - force_update_clipper_on_render = false; -} - -void GLGizmoCut3D::set_center(const Vec3d& center) -{ - set_center_pos(center); + set_center_pos(center, update_tbb); update_clipper(); } @@ -584,7 +578,7 @@ void GLGizmoCut3D::render_move_center_input(int axis) if (in_val != val) { move[axis] = val; - set_center(move); + set_center(move, true); } } @@ -888,21 +882,17 @@ bool GLGizmoCut3D::on_init() void GLGizmoCut3D::on_load(cereal::BinaryInputArchive& ar) { - ar( m_keep_upper, m_keep_lower, m_rotate_lower, m_rotate_upper, m_hide_cut_plane, m_mode, m_connectors_editing,//m_selected, - // m_connector_depth_ratio, m_connector_size, m_connector_mode, m_connector_type, m_connector_style, m_connector_shape_id, + ar( m_keep_upper, m_keep_lower, m_rotate_lower, m_rotate_upper, m_hide_cut_plane, m_mode, m_connectors_editing, m_ar_plane_center, m_rotation_m); set_center_pos(m_ar_plane_center, true); - force_update_clipper_on_render = true; - m_parent.request_extra_frame(); } void GLGizmoCut3D::on_save(cereal::BinaryOutputArchive& ar) const { - ar( m_keep_upper, m_keep_lower, m_rotate_lower, m_rotate_upper, m_hide_cut_plane, m_mode, m_connectors_editing,//m_selected, - // m_connector_depth_ratio, m_connector_size, m_connector_mode, m_connector_type, m_connector_style, m_connector_shape_id, + ar( m_keep_upper, m_keep_lower, m_rotate_lower, m_rotate_upper, m_hide_cut_plane, m_mode, m_connectors_editing, m_ar_plane_center, m_start_dragging_m); } @@ -923,6 +913,7 @@ void GLGizmoCut3D::on_set_state() // initiate archived values m_ar_plane_center = m_plane_center; m_start_dragging_m = m_rotation_m; + m_transformed_bounding_box = transformed_bounding_box(m_plane_center); m_parent.request_extra_frame(); } @@ -934,7 +925,6 @@ void GLGizmoCut3D::on_set_state() m_selected.clear(); m_parent.set_use_color_clip_plane(false); } - force_update_clipper_on_render = m_state == On; } void GLGizmoCut3D::on_register_raycasters_for_picking() @@ -1146,7 +1136,7 @@ void GLGizmoCut3D::dragging_grabber_z(const GLGizmoBase::UpdateData &data) const Vec3d shift = starting_vec * projection; // move cut plane center - set_center(m_plane_center + shift); + set_center(m_plane_center + shift, true); m_was_cut_plane_dragged = true; } @@ -1247,16 +1237,19 @@ void GLGizmoCut3D::on_stop_dragging() } } -void GLGizmoCut3D::set_center_pos(const Vec3d& center_pos, bool force/* = false*/) +void GLGizmoCut3D::set_center_pos(const Vec3d& center_pos, bool update_tbb /*=false*/) { - if (m_plane_center == center_pos) - return; + BoundingBoxf3 tbb = m_transformed_bounding_box; + if (update_tbb) { + Vec3d normal = m_rotation_m.inverse() * Vec3d(m_plane_center - center_pos); + tbb.translate(normal.z() * Vec3d::UnitZ()); + } + const Vec3d& instance_offset = m_parent.get_selection().get_first_volume()->get_instance_offset(); + const Vec3d trans_center_pos = (m_rotation_m.inverse() * (center_pos - instance_offset)) + tbb.center(); - bool can_set_center_pos = force; - BoundingBoxf3 tbb; + bool can_set_center_pos = tbb.contains(trans_center_pos); if (!can_set_center_pos) { - tbb = transformed_bounding_box(center_pos); - if (tbb.max.z() > -1. && tbb.min.z() < 1.) + if (tbb.max.z() > -.5 && tbb.min.z() < .5) can_set_center_pos = true; else { const double old_dist = (m_bb_center - m_plane_center).norm(); @@ -1290,55 +1283,31 @@ BoundingBoxf3 GLGizmoCut3D::bounding_box() const BoundingBoxf3 GLGizmoCut3D::transformed_bounding_box(const Vec3d& plane_center) const { - // #ysFIXME !!! - BoundingBoxf3 ret; - - const CommonGizmosDataObjects::SelectionInfo* sel_info = m_c->selection_info(); - if (!sel_info) - return ret; - const ModelObject* mo = sel_info->model_object(); - if (!mo) - return ret; - const int instance_idx = sel_info->get_active_instance(); - if (instance_idx < 0 || mo->instances.empty()) - return ret; - const ModelInstance* mi = mo->instances[instance_idx]; - - const Vec3d& instance_offset = mi->get_offset(); - Vec3d cut_center_offset = plane_center - instance_offset; - cut_center_offset[Z] -= sel_info->get_sla_shift(); - - const auto cut_matrix = Transform3d::Identity() * m_rotation_m.inverse() * translation_transform(-cut_center_offset); - const Selection& selection = m_parent.get_selection(); + + const Vec3d& instance_offset = selection.get_first_volume()->get_instance_offset(); + const auto cut_matrix = Transform3d::Identity() * m_rotation_m.inverse() * translation_transform(instance_offset - plane_center); + const Selection::IndicesList& idxs = selection.get_volume_idxs(); + BoundingBoxf3 ret; for (unsigned int i : idxs) { const GLVolume* volume = selection.get_volume(i); // respect just to the solid parts for FFF and ignore pad and supports for SLA if (!volume->is_modifier && !volume->is_sla_pad() && !volume->is_sla_support()) { -#if ENABLE_WORLD_COORDINATE const auto instance_matrix = volume->get_instance_transformation().get_matrix_no_offset(); -#else - const auto instance_matrix = assemble_transform( - Vec3d::Zero(), // don't apply offset - volume->get_instance_rotation().cwiseProduct(Vec3d(1.0, 1.0, 1.0)), - volume->get_instance_scaling_factor(), - volume->get_instance_mirror() - ); -#endif // ENABLE_WORLD_COORDINATE - auto volume_trafo = instance_matrix * volume->get_volume_transformation().get_matrix(); - ret.merge(volume->transformed_convex_hull_bounding_box(cut_matrix * volume_trafo)); } } return ret; } -bool GLGizmoCut3D::update_bb() +void GLGizmoCut3D::update_bb() { const BoundingBoxf3 box = bounding_box(); + if (!box.defined) + return; if (m_max_pos != box.max || m_min_pos != box.min) { m_bounding_box = box; @@ -1348,10 +1317,11 @@ bool GLGizmoCut3D::update_bb() m_max_pos = box.max; m_min_pos = box.min; m_bb_center = box.center(); + m_transformed_bounding_box = transformed_bounding_box(m_bb_center); if (box.contains(m_center_offset)) - set_center_pos(m_bb_center + m_center_offset, true); + set_center_pos(m_bb_center + m_center_offset); else - set_center_pos(m_bb_center, true); + set_center_pos(m_bb_center); m_radius = box.radius(); m_grabber_connection_len = 0.5 * m_radius;// std::min(0.75 * m_radius, 35.0); @@ -1376,10 +1346,7 @@ bool GLGizmoCut3D::update_bb() clear_selection(); if (CommonGizmosDataObjects::SelectionInfo* selection = m_c->selection_info()) m_selected.resize(selection->model_object()->cut_connectors.size(), false); - - return true; } - return false; } void GLGizmoCut3D::init_picking_models() @@ -1435,12 +1402,7 @@ void GLGizmoCut3D::render_clipper_cut() void GLGizmoCut3D::on_render() { - if (update_bb() || force_update_clipper_on_render) { - update_clipper_on_render(); - m_c->object_clipper()->set_behavior(m_connectors_editing, m_connectors_editing, 0.4); - } - else - update_clipper(); + update_clipper(); init_picking_models(); @@ -1653,10 +1615,10 @@ void GLGizmoCut3D::render_build_size() void GLGizmoCut3D::reset_cut_plane() { - set_center(m_bb_center); m_rotation_m = Transform3d::Identity(); m_angle_arc.reset(); - update_clipper(); + m_transformed_bounding_box = transformed_bounding_box(m_bb_center); + set_center(m_bb_center); } void GLGizmoCut3D::invalidate_cut_plane() @@ -1671,6 +1633,9 @@ void GLGizmoCut3D::invalidate_cut_plane() void GLGizmoCut3D::set_connectors_editing(bool connectors_editing) { + if (m_connectors_editing == connectors_editing) + return; + m_connectors_editing = connectors_editing; update_raycasters_for_picking(); @@ -2340,7 +2305,7 @@ bool GLGizmoCut3D::process_cut_line(SLAGizmoEventType action, const Vec2d& mouse m_rotation_m = m; m_angle_arc.reset(); - set_center(m_plane_center + cross_dir * (cross_dir.dot(pt - m_plane_center))); + set_center(m_plane_center + cross_dir * (cross_dir.dot(pt - m_plane_center)), true); discard_cut_line_processing(); } @@ -2542,6 +2507,7 @@ CommonGizmosDataID GLGizmoCut3D::on_get_requirements() const { void GLGizmoCut3D::data_changed() { + update_bb(); if (auto oc = m_c->object_clipper()) oc->set_behavior(m_connectors_editing, m_connectors_editing, double(m_contour_width)); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index 569122d4ad..5e6e4146f0 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -121,7 +121,6 @@ class GLGizmoCut3D : public GLGizmoBase float m_label_width{ 150.0 }; float m_control_width{ 200.0 }; bool m_imperial_units{ false }; - bool force_update_clipper_on_render{false}; float m_contour_width{ 0.4f }; float m_cut_plane_radius_koef{ 1.5f }; @@ -192,7 +191,6 @@ public: void rotate_vec3d_around_plane_center(Vec3d&vec); void put_connectors_on_cut_plane(const Vec3d& cp_normal, double cp_offset); void update_clipper(); - void update_clipper_on_render(); void invalidate_cut_plane(); BoundingBoxf3 bounding_box() const; @@ -258,7 +256,7 @@ protected: void data_changed() override; private: - void set_center(const Vec3d& center); + void set_center(const Vec3d& center, bool update_tbb = false); bool render_combo(const std::string& label, const std::vector& lines, size_t& selection_idx); bool render_double_input(const std::string& label, double& value_in); bool render_slider_double_input(const std::string& label, float& value_in, float& tolerance_in); @@ -284,8 +282,8 @@ private: void render_cut_plane_grabbers(); void render_cut_line(); void perform_cut(const Selection&selection); - void set_center_pos(const Vec3d¢er_pos, bool force = false); - bool update_bb(); + void set_center_pos(const Vec3d¢er_pos, bool update_tbb = false); + void update_bb(); void init_picking_models(); void init_rendering_items(); void render_clipper_cut(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index 177d9d5a7b..90552c0a5d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -540,7 +540,11 @@ void GLGizmoSimplify::apply_simplify() { const Selection& selection = m_parent.get_selection(); auto plater = wxGetApp().plater(); plater->take_snapshot(_u8L("Simplify ") + create_volumes_name(m_volume_ids, selection)); - plater->clear_before_change_mesh(selection.get_object_idx()); + plater->clear_before_change_mesh(selection.get_object_idx(), _u8L("Custom supports, seams and multimaterial painting were " + "removed after simplifying the mesh.")); + // After removing custom supports, seams, and multimaterial painting, we have to update info about the object to remove information about + // custom supports, seams, and multimaterial painting in the right panel. + wxGetApp().obj_list()->update_info_items(selection.get_object_idx()); for (const auto &item: m_state.result) { const ObjectID &id = item.first; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d4e0b8fbd0..15c5400822 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3127,6 +3127,10 @@ void Plater::priv::split_object() Model new_model = model; ModelObject* current_model_object = new_model.objects[obj_idx]; + // Before splitting object we have to remove all custom supports, seams, and multimaterial painting. + wxGetApp().plater()->clear_before_change_mesh(obj_idx, _u8L("Custom supports, seams and multimaterial painting were " + "removed after splitting the object.")); + wxBusyCursor wait; ModelObjectPtrs new_objects; current_model_object->split(&new_objects); @@ -7338,7 +7342,7 @@ bool Plater::set_printer_technology(PrinterTechnology printer_technology) return ret; } -void Plater::clear_before_change_mesh(int obj_idx) +void Plater::clear_before_change_mesh(int obj_idx, const std::string ¬ification_msg) { ModelObject* mo = model().objects[obj_idx]; @@ -7356,8 +7360,7 @@ void Plater::clear_before_change_mesh(int obj_idx) get_notification_manager()->push_notification( NotificationType::CustomSupportsAndSeamRemovedAfterRepair, NotificationManager::NotificationLevel::PrintInfoNotificationLevel, - _u8L("Custom supports, seams and multimaterial painting were " - "removed after repairing the mesh.")); + notification_msg); // _u8L("Undo the repair"), // [this, snapshot_time](wxEvtHandler*){ // // Make sure the snapshot is still available and that diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 1ecbeb1906..3dcca746da 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -273,7 +273,7 @@ public: void reslice_FFF_until_step(PrintObjectStep step, const ModelObject &object, bool postpone_error_messages = false); void reslice_SLA_until_step(SLAPrintObjectStep step, const ModelObject &object, bool postpone_error_messages = false); - void clear_before_change_mesh(int obj_idx); + void clear_before_change_mesh(int obj_idx, const std::string ¬ification_msg); void changed_mesh(int obj_idx); void changed_object(int obj_idx);