From 8f4d5f44d721fa9cae70cd9b47735c93151f2b81 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 --- src/libslic3r/libslic3r.h | 1 - src/slic3r/GUI/GLCanvas3D.cpp | 68 ++++++++++------------------------- src/slic3r/GUI/GLCanvas3D.hpp | 2 ++ src/slic3r/GUI/Selection.cpp | 6 ++-- 4 files changed, 25 insertions(+), 52 deletions(-) diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index c3f220098..5c7829abb 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -75,7 +75,6 @@ static constexpr double INSET_OVERLAP_TOLERANCE = 0.4; static constexpr double EXTERNAL_INFILL_MARGIN = 3; static constexpr double BRIDGE_INFILL_MARGIN = 1; static constexpr double WIPE_TOWER_MARGIN = 0.2; -static constexpr double MIN_WIPE_TOWER_SIZE = 5; //FIXME Better to use an inline function with an explicit return type. //inline coord_t scale_(coordf_t v) { return coord_t(floor(v / SCALING_FACTOR + 0.5f)); } #define scale_(val) ((val) / SCALING_FACTOR) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 9a6daa1d4..da4d683b2 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3198,34 +3198,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re coordf_t plate_bbox_y_max_local_coord = plate_bbox_2d.max(1) - plate_origin(1); if (!current_print->is_step_done(psWipeTower) || !current_print->wipe_tower_data().wipe_tower_mesh_data) { - Vec2d min_wipe_tower_size(MIN_WIPE_TOWER_SIZE, MIN_WIPE_TOWER_SIZE); // update for wipe tower position { - bool need_update = false; - if (x + margin + min_wipe_tower_size(0) > plate_bbox_x_max_local_coord) { - x = plate_bbox_x_max_local_coord - min_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 + min_wipe_tower_size(1) > plate_bbox_y_max_local_coord) { - y = plate_bbox_y_max_local_coord - min_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, @@ -3241,15 +3215,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); @@ -3284,10 +3250,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; @@ -3297,8 +3260,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()); @@ -3322,7 +3287,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); } @@ -3450,13 +3415,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); @@ -6529,6 +6488,16 @@ void GLCanvas3D::render_thumbnail_framebuffer(const std::shared_ptrget_partplate_list().get_plate(plate_idx)->fff_print()->is_step_done(psWipeTower); - const double margin = WIPE_TOWER_MARGIN; + 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()) .inverse() * displacement; - BoundingBoxf3 tower_bbox = show_read_wipe_tower ? v.bounding_box() : BoundingBoxf3(Vec3d(0, 0, 0), Vec3d(MIN_WIPE_TOWER_SIZE, MIN_WIPE_TOWER_SIZE, MIN_WIPE_TOWER_SIZE)); + BoundingBoxf3 tower_bbox = v.bounding_box(); tower_bbox.translate(actual_displacement + tower_origin); BoundingBox tower_bbox2d = BoundingBox(scaled(Vec2f(tower_bbox.min[0], tower_bbox.min[1])), scaled(Vec2f(tower_bbox.max[0], tower_bbox.max[1]))); Vec2f offset = WipeTower::move_box_inside_box(tower_bbox2d, plate_bbox2d,scaled(margin));