diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 5e8c07dd9f..820124a7ea 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -651,7 +651,7 @@ void GLGizmoCut3D::on_load(cereal::BinaryInputArchive& ar) m_connector_depth_ratio, m_connector_size, m_connector_mode, m_connector_type, m_connector_style, m_connector_shape_id, m_ar_plane_center, m_ar_rotations); - set_center_pos(m_ar_plane_center); + set_center_pos(m_ar_plane_center, true); m_rotation_gizmo.set_center(m_ar_plane_center); m_rotation_gizmo.set_rotation(m_ar_rotations); force_update_clipper_on_render = true; @@ -771,21 +771,12 @@ void GLGizmoCut3D::on_stop_dragging() } } -void GLGizmoCut3D::set_center_pos(const Vec3d& center_pos) +void GLGizmoCut3D::set_center_pos(const Vec3d& center_pos, bool force/* = false*/) { - const BoundingBoxf3 tbb = transformed_bounding_box(true); - if (!tbb.contains(center_pos)) - return; - - m_plane_center = center_pos; - - // !!! ysFIXME add smart clamp calculation - // Clamp the center position of the cut plane to the object's bounding box - //m_plane_center = Vec3d(std::clamp(center_pos.x(), m_min_pos.x(), m_max_pos.x()), - // std::clamp(center_pos.y(), m_min_pos.y(), m_max_pos.y()), - // std::clamp(center_pos.z(), m_min_pos.z(), m_max_pos.z())); - - m_center_offset = m_plane_center - m_bb_center; + if (force || transformed_bounding_box(true).contains(center_pos)) { + m_plane_center = center_pos; + m_center_offset = m_plane_center - m_bb_center; + } } BoundingBoxf3 GLGizmoCut3D::bounding_box() const @@ -806,18 +797,18 @@ BoundingBoxf3 GLGizmoCut3D::transformed_bounding_box(bool revert_move /*= false* { // #ysFIXME !!! BoundingBoxf3 ret; - const Selection& selection = m_parent.get_selection(); - const Selection::IndicesList& idxs = selection.get_volume_idxs(); - const int instance_idx = selection.get_instance_idx(); - const int object_idx = selection.get_object_idx(); - if (instance_idx < 0 || object_idx < 0) + const ModelObject* mo = m_c->selection_info()->model_object(); + if (!mo) return ret; + const int instance_idx = m_c->selection_info()->get_active_instance(); + if (instance_idx < 0) + return ret; + const ModelInstance* mi = mo->instances[instance_idx]; - const Vec3d& instance_offset = wxGetApp().plater()->model().objects[object_idx]->instances[instance_idx]->get_offset(); - + const Vec3d& instance_offset = mi->get_offset(); Vec3d cut_center_offset = m_plane_center - instance_offset; - cut_center_offset[Z] -= selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z(); + cut_center_offset[Z] -= m_c->selection_info()->get_sla_shift(); const Vec3d& rotation = m_rotation_gizmo.get_rotation(); const auto move = Geometry::assemble_transform(-cut_center_offset); @@ -828,6 +819,8 @@ BoundingBoxf3 GLGizmoCut3D::transformed_bounding_box(bool revert_move /*= false* const auto cut_matrix = (revert_move ? move2 : Transform3d::Identity()) * rot_x * rot_y * rot_z * move; + const Selection& selection = m_parent.get_selection(); + const Selection::IndicesList& idxs = selection.get_volume_idxs(); 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 @@ -853,7 +846,7 @@ bool GLGizmoCut3D::update_bb() m_max_pos = box.max; m_min_pos = box.min; m_bb_center = box.center(); - set_center_pos(m_bb_center + m_center_offset); + set_center_pos(m_bb_center + m_center_offset, true); m_plane.reset(); m_cone.reset(); @@ -1270,9 +1263,9 @@ void GLGizmoCut3D::perform_cut(const Selection& selection) const bool has_connectors = !mo->cut_connectors.empty(); { - Plater::TakeSnapshot snapshot(plater, _L("Cut by Plane")); // update connectors pos as offset of its center before cut performing if (has_connectors && m_connector_mode == CutConnectorMode::Manual) { + Plater::TakeSnapshot snapshot(plater, _L("Cut by Plane")); for (CutConnector& connector : mo->cut_connectors) { connector.rotation = m_rotation_gizmo.get_rotation(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index 6edcded0f4..439abea8da 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -167,7 +167,7 @@ private: void render_cut_center_graber(); void render_cut_line(); void perform_cut(const Selection& selection); - void set_center_pos(const Vec3d& center_pos); + void set_center_pos(const Vec3d& center_pos, bool force = false); bool update_bb(); void reset_connectors(); void update_connector_shape(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index 7f60892b1b..e7ba37010e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -414,8 +414,11 @@ void ObjectClipper::render_cut() const if (m_clp_ratio == 0.) return; const SelectionInfo* sel_info = get_pool()->selection_info(); + int sel_instance_idx = sel_info->get_active_instance(); + if (sel_instance_idx < 0) + return; const ModelObject* mo = sel_info->model_object(); - const Geometry::Transformation inst_trafo = mo->instances[sel_info->get_active_instance()]->get_transformation(); + const Geometry::Transformation inst_trafo = mo->instances[sel_instance_idx]->get_transformation(); size_t clipper_id = 0; for (const ModelVolume* mv : mo->volumes) { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index a1694dc176..26c7da784b 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1780,7 +1780,7 @@ struct Plater::priv std::string get_config(const std::string &key) const; std::vector load_files(const std::vector& input_files, bool load_model, bool load_config, bool used_inches = false); - std::vector load_model_objects(const ModelObjectPtrs& model_objects, bool allow_negative_z = false); + std::vector load_model_objects(const ModelObjectPtrs& model_objects, bool allow_negative_z = false, bool call_selection_changed = true); fs::path get_export_file_path(GUI::FileType file_type); wxString get_export_file(GUI::FileType file_type); @@ -2691,7 +2691,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ // #define AUTOPLACEMENT_ON_LOAD -std::vector Plater::priv::load_model_objects(const ModelObjectPtrs& model_objects, bool allow_negative_z) +std::vector Plater::priv::load_model_objects(const ModelObjectPtrs& model_objects, bool allow_negative_z, bool call_selection_changed /*= true*/) { const Vec3d bed_size = Slic3r::to_3d(this->bed.build_volume().bounding_volume2d().size(), 1.0) - 2.0 * Vec3d::Ones(); @@ -2774,17 +2774,18 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs& mode notification_manager->close_notification_of_type(NotificationType::UpdatedItemsInfo); for (const size_t idx : obj_idxs) { - wxGetApp().obj_list()->add_object_to_list(idx); + wxGetApp().obj_list()->add_object_to_list(idx, call_selection_changed); } - update(); - // Update InfoItems in ObjectList after update() to use of a correct value of the GLCanvas3D::is_sinking(), - // which is updated after a view3D->reload_scene(false, flags & (unsigned int)UpdateParams::FORCE_FULL_SCREEN_REFRESH) call - for (const size_t idx : obj_idxs) - wxGetApp().obj_list()->update_info_items(idx); - - object_list_changed(); + if (call_selection_changed) { + update(); + // Update InfoItems in ObjectList after update() to use of a correct value of the GLCanvas3D::is_sinking(), + // which is updated after a view3D->reload_scene(false, flags & (unsigned int)UpdateParams::FORCE_FULL_SCREEN_REFRESH) call + for (const size_t idx : obj_idxs) + wxGetApp().obj_list()->update_info_items(idx); + object_list_changed(); + } this->schedule_background_process(); return obj_idxs; @@ -5919,18 +5920,29 @@ void Slic3r::GUI::Plater::cut(size_t obj_idx, size_t instance_idx, const Vec3d& wxCHECK_RET(instance_idx < object->instances.size(), "instance_idx out of bounds"); - //Plater::TakeSnapshot snapshot(this, _L("Cut by Plane")); + this->suppress_snapshots(); wxBusyCursor wait; const auto new_objects = object->cut(instance_idx, cut_center, cut_rotation, attributes); - remove(obj_idx); - p->load_model_objects(new_objects); + model().delete_object(obj_idx); + sidebar().obj_list()->delete_object_from_list(obj_idx); + + // suppress to call selection update for Object List to avoid call of early Gizmos on/off update + p->load_model_objects(new_objects, false, false); Selection& selection = p->get_selection(); size_t last_id = p->model.objects.size() - 1; for (size_t i = 0; i < new_objects.size(); ++i) selection.add_object((unsigned int)(last_id - i), i == 0); + this->allow_snapshots(); + + // now process all updates of the 3d scene + update(); + // Update InfoItems in ObjectList after update() to use of a correct value of the GLCanvas3D::is_sinking(), + // which is updated after a view3D->reload_scene(false, flags & (unsigned int)UpdateParams::FORCE_FULL_SCREEN_REFRESH) call + for (size_t idx = 0; idx < p->model.objects.size(); idx++) + wxGetApp().obj_list()->update_info_items(idx); } void Plater::export_gcode(bool prefer_removable)