From 3fd9b7ef8ac3606469821ac74ef1dc165ba55261 Mon Sep 17 00:00:00 2001 From: "zhimin.zeng" Date: Fri, 23 May 2025 11:18:24 +0800 Subject: [PATCH] FIX: modify the behavior of wipe tower The prime tower is not allowed to extend beyond the plate boundary when moving it. jira: STUDIO-11817 & STUDIO-12313 Change-Id: Icbb85dad26531b0ac01f088fc086b4ff499ac423 (cherry picked from commit 8f4d5f44d721fa9cae70cd9b47735c93151f2b81) --- src/slic3r/GUI/GLCanvas3D.cpp | 67 ++++++++++------------------------- src/slic3r/GUI/GLCanvas3D.hpp | 2 ++ src/slic3r/GUI/Selection.cpp | 5 ++- 3 files changed, 25 insertions(+), 49 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f831bf42d9..790cf68ab8 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2953,31 +2953,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if (!current_print->is_step_done(psWipeTower) || !current_print->wipe_tower_data().wipe_tower_mesh_data) { // update for wipe tower position { - bool need_update = false; - if (x + margin + wipe_tower_size(0) > plate_bbox_x_max_local_coord) { - x = plate_bbox_x_max_local_coord - wipe_tower_size(0) - margin; - need_update = true; - } else if (x < margin + plate_bbox_x_min_local_coord) { - x = margin + plate_bbox_x_min_local_coord; - need_update = true; - } - if (need_update) { - ConfigOptionFloat wt_x_opt(x); - dynamic_cast(proj_cfg.option("wipe_tower_x"))->set_at(&wt_x_opt, plate_id, 0); - need_update = false; - } - - if (y + margin + wipe_tower_size(1) > plate_bbox_y_max_local_coord) { - y = plate_bbox_y_max_local_coord - wipe_tower_size(1) - margin; - need_update = true; - } else if (y < margin) { - y = margin; - need_update = true; - } - if (need_update) { - ConfigOptionFloat wt_y_opt(y); - dynamic_cast(proj_cfg.option("wipe_tower_y"))->set_at(&wt_y_opt, plate_id, 0); - } int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(1000 + plate_id, x + plate_origin(0), y + plate_origin(1), (float) wipe_tower_size(0), (float) wipe_tower_size(1), (float) wipe_tower_size(2), a, @@ -2994,15 +2969,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re BoundingBoxf3 plate_bbox = wxGetApp().plater()->get_partplate_list().get_plate(plate_id)->get_build_volume(true); BoundingBox plate_bbox2d = BoundingBox(scaled(Vec2f(plate_bbox.min[0], plate_bbox.min[1])), scaled(Vec2f(plate_bbox.max[0], plate_bbox.max[1]))); Vec2f offset = WipeTower::move_box_inside_box(tower_bottom_bbox, plate_bbox2d, scaled(margin)); - if (!is_approx(offset[0], 0.f)) { - ConfigOptionFloat wt_x_opt(x + offset[0]); - dynamic_cast(proj_cfg.option("wipe_tower_x"))->set_at(&wt_x_opt, plate_id, 0); - } - if (!is_approx(offset[1], 0.f)) { - ConfigOptionFloat wt_y_opt(y + offset[1]); - dynamic_cast(proj_cfg.option("wipe_tower_y"))->set_at(&wt_y_opt, plate_id, 0); - } - int volume_idx_wipe_tower_new = m_volumes.load_real_wipe_tower_preview(1000 + plate_id, x + plate_origin(0) + offset[0], y + plate_origin(1) + offset[1], + int volume_idx_wipe_tower_new = m_volumes.load_real_wipe_tower_preview(1000 + plate_id, x + plate_origin(0), y + plate_origin(1), current_print->wipe_tower_data().wipe_tower_mesh_data->real_wipe_tower_mesh, current_print->wipe_tower_data().wipe_tower_mesh_data->real_brim_mesh, true,a,/*!print->is_step_done(psWipeTower)*/ true, m_initialized); @@ -3035,10 +3002,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re //BBS:exclude the assmble view if (m_canvas_type != ECanvasType::CanvasAssembleView) { - _set_warning_notification_if_needed(EWarning::GCodeConflict); - _set_warning_notification(EWarning::FilamentUnPrintableOnFirstLayer, false); - _set_warning_notification_if_needed(EWarning::MultiExtruderPrintableError); - _set_warning_notification_if_needed(EWarning::MultiExtruderHeightOutside); + _update_slice_error_status(); // checks for geometry outside the print volume to render it accordingly if (!m_volumes.empty()) { ModelInstanceEPrintVolumeState state; @@ -3048,8 +3012,10 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re const bool fullyOut = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Fully_Outside); // const bool objectLimited = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Limited); + bool show_read_wipe_tower = wxGetApp().plater()->get_partplate_list().get_selected_plate()->fff_print()->is_step_done(psWipeTower); bool wipe_tower_outside = m_volumes.check_wipe_tower_outside_state(m_bed.build_volume()); - _set_warning_notification(EWarning::PrimeTowerOutside, !wipe_tower_outside); + bool show_wipe_tower_outside_error = show_read_wipe_tower ? !wipe_tower_outside : false; + _set_warning_notification(EWarning::PrimeTowerOutside, show_wipe_tower_outside_error); auto clash_flag = construct_error_string(object_results, get_object_clashed_text()); auto unprintable_flag= construct_extruder_unprintable_error(object_results, get_left_extruder_unprintable_text(), get_right_extruder_unprintable_text()); @@ -3073,7 +3039,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re bool mix_pla_and_petg = cur_plate->check_mixture_of_pla_and_petg(wxGetApp().preset_bundle->full_config()); _set_warning_notification(EWarning::MixUsePLAAndPETG, !mix_pla_and_petg); - bool model_fits = contained_min_one && !m_model->objects.empty() && !partlyOut && object_results.filaments.empty() && tpu_valid && filament_printable; + bool model_fits = contained_min_one && !m_model->objects.empty() && !partlyOut && object_results.filaments.empty() && tpu_valid && filament_printable && !show_wipe_tower_outside_error; post_event(Event(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, model_fits)); ppl.get_curr_plate()->update_slice_ready_status(model_fits); } @@ -3165,13 +3131,7 @@ void GLCanvas3D::load_gcode_preview(const GCodeProcessorResult& gcode_result, co if (wxGetApp().is_editor()) { //BBS: always load shell at preview, do this in load_shells - //m_gcode_viewer.update_shells_color_by_extruder(m_config); - _set_warning_notification_if_needed(EWarning::ToolHeightOutside); - _set_warning_notification_if_needed(EWarning::ToolpathOutside); - _set_warning_notification_if_needed(EWarning::GCodeConflict); - _set_warning_notification_if_needed(EWarning::MultiExtruderPrintableError); - _set_warning_notification_if_needed(EWarning::MultiExtruderHeightOutside); - _set_warning_notification_if_needed(EWarning::FilamentUnPrintableOnFirstLayer); + _update_slice_error_status(); } m_gcode_viewer.refresh(gcode_result, str_tool_colors); @@ -6631,6 +6591,16 @@ void GLCanvas3D::render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned //BBS: GUI refractor +void GLCanvas3D::_update_slice_error_status() +{ + _set_warning_notification_if_needed(EWarning::ToolHeightOutside); + _set_warning_notification_if_needed(EWarning::ToolpathOutside); + _set_warning_notification_if_needed(EWarning::GCodeConflict); + _set_warning_notification_if_needed(EWarning::MultiExtruderPrintableError); + _set_warning_notification_if_needed(EWarning::MultiExtruderHeightOutside); + _set_warning_notification_if_needed(EWarning::FilamentUnPrintableOnFirstLayer); +} + void GLCanvas3D::_switch_toolbars_icon_filename() { BackgroundTexture::Metadata background_data; @@ -10133,7 +10103,8 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) text = _u8L("PLA and PETG filaments detected in the mixture. Adjust parameters according to the Wiki to ensure print quality."); break; case EWarning::PrimeTowerOutside: - text = _u8L("The prime tower extends beyond the plate boundary, which may cause part of the prime tower to lie outside the printable area after slicing."); + text = _u8L("The prime tower extends beyond the plate boundary."); + error = ErrorType::SLICING_ERROR; break; } //BBS: this may happened when exit the app, plater is null diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index f369e0802d..499090d531 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -1189,6 +1189,8 @@ public: private: bool _is_shown_on_screen() const; + void _update_slice_error_status(); + void _switch_toolbars_icon_filename(); bool _init_toolbars(); bool _init_main_toolbar(); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index a2aa77fdca..34063c1ca9 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1194,7 +1194,10 @@ void Selection::translate(const Vec3d &displacement, TransformationType transfor Vec3d tower_size = v.bounding_box().size(); Vec3d tower_origin = m_cache.volumes_data[i].get_volume_position(); Vec3d actual_displacement = displacement; - const double margin = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx)->fff_print()->is_step_done(psWipeTower)?2.:WIPE_TOWER_MARGIN; + bool show_read_wipe_tower = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx)->fff_print()->is_step_done(psWipeTower); + float brim_width = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_float("prime_tower_brim_width"); + + const double margin = show_read_wipe_tower ? WIPE_TOWER_MARGIN : brim_width + 0.5; // 0.5 is the line width of wipe tower actual_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix())