diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index bc84963da0..9cad57e693 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -2530,6 +2530,7 @@ void GCodeProcessorResult::reset() { long_retraction_when_cut = false; timelapse_warning_code = 0; printable_height = 0.0f; + machine_frame_transform_active = false; settings_ids.reset(); filaments_count = 0; backtrace_enabled = false; @@ -3061,6 +3062,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config) // multi-extruder validator can undo it and compare against build-volume // bounds rather than machine-frame positions. m_machine_frame_transform.init_from_config(config); + m_result.machine_frame_transform_active = m_machine_frame_transform.is_active(); auto filament_maps = config.option("filament_map"); if (filament_maps != nullptr) { diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 63f38bf5ef..7b90840ad2 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -285,6 +285,11 @@ class Print; // as gcode_Z + this offset, so the designed-view back-transform must subtract it // to recover the model's belt coordinate. float belt_z_origin{ 0.f }; + // Belt printer: post-gcode shear/scale/post_remap is configured and + // non-identity. When set, the layer Z values in `moves` are in the + // machine frame and should not be compared against `printable_height` + // (which lives in the build-volume frame). + bool machine_frame_transform_active{ false }; RemapAxis preslice_remap_x{ RemapAxis::PosX }; RemapAxis preslice_remap_y{ RemapAxis::PosY }; RemapAxis preslice_remap_z{ RemapAxis::PosZ }; @@ -377,6 +382,7 @@ class Print; initial_layer_time = other.initial_layer_time; belt_tilt_angle = other.belt_tilt_angle; belt_z_origin = other.belt_z_origin; + machine_frame_transform_active = other.machine_frame_transform_active; preslice_remap_x = other.preslice_remap_x; preslice_remap_y = other.preslice_remap_y; preslice_remap_z = other.preslice_remap_z; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index c9fd0118d0..ba28f96804 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -14,6 +14,7 @@ #include "GCode.hpp" #include "BeltGCode.hpp" #include "BeltTransform.hpp" +#include "GCode/MachineFrameTransform.hpp" #include "GCode/WipeTower.hpp" #include "GCode/WipeTower2.hpp" #include "Utils.hpp" @@ -1436,9 +1437,17 @@ StringObjectException Print::validate(std::vector *warnin // is not comparable to printable_height (which is gantry clearance in the // build-volume frame). Compare against the model's pre-shear Z instead, // mirroring the bbox computed in PrintObject::update_slicing_parameters. + // When the post-gcode MachineFrameTransform is active the printer's + // physical Z mapping is non-trivial — skip the check entirely. const bool belt_printer = this->config().belt_printer.value; + bool skip_max_height_check = false; + if (belt_printer) { + MachineFrameTransform machine_frame; + machine_frame.init_from_config(this->config()); + skip_max_height_check = machine_frame.is_active(); + } const double shrinkage_compensation_z = this->shrinkage_compensation().z(); - for (size_t print_object_idx = 0; print_object_idx < m_objects.size(); ++ print_object_idx) { + for (size_t print_object_idx = 0; !skip_max_height_check && print_object_idx < m_objects.size(); ++ print_object_idx) { const PrintObject &print_object = *m_objects[print_object_idx]; double effective_max_z = 0; diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index a034f3dce8..42a4f6b9fb 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1521,6 +1521,7 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const m_custom_gcode_per_print_z = gcode_result.custom_gcode_per_print_z; m_max_print_height = gcode_result.printable_height; + m_machine_frame_transform_active = gcode_result.machine_frame_transform_active; m_z_offset = gcode_result.z_offset; @@ -1736,6 +1737,7 @@ void GCodeViewer::reset() m_paths_bounding_box = BoundingBoxf3(); m_max_bounding_box = BoundingBoxf3(); m_max_print_height = 0.0f; + m_machine_frame_transform_active = false; m_z_offset = 0.0f; m_extruders_count = 0; m_filament_diameters = std::vector(); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 66d9cbb444..9ee680d889 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -203,6 +203,7 @@ private: //BBS: add shell bounding box BoundingBoxf3 m_shell_bounding_box; float m_max_print_height{ 0.0f }; + bool m_machine_frame_transform_active{ false }; float m_z_offset{ 0.0f }; ConfigOptionMode m_user_mode; @@ -289,6 +290,7 @@ public: std::vector get_plater_extruder(); const float get_max_print_height() const { return m_max_print_height; } + bool is_machine_frame_transform_active() const { return m_machine_frame_transform_active; } const BoundingBoxf3& get_paths_bounding_box() const { return m_paths_bounding_box; } const BoundingBoxf3& get_max_bounding_box() const { return m_max_bounding_box; } const BoundingBoxf3& get_shell_bounding_box() const { return m_shell_bounding_box; } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 3345a88386..e3e84bc1c7 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -10315,7 +10315,11 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning) if (current_printer_technology() != ptSLA) { unsigned int max_z_layer = m_gcode_viewer.get_layers_z_range().back(); if (warning == EWarning::ToolHeightOutside) // check if max z_layer height exceed max print height - show = m_gcode_viewer.has_data() && (m_gcode_viewer.get_layers_zs()[max_z_layer] - m_gcode_viewer.get_max_print_height() >= 1e-6); + // Belt printer with active post-gcode machine-frame transform: layer Z values + // live in the machine frame, not the build-volume frame, so the comparison + // against printable_height is meaningless. Suppress the warning entirely. + show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_machine_frame_transform_active() + && (m_gcode_viewer.get_layers_zs()[max_z_layer] - m_gcode_viewer.get_max_print_height() >= 1e-6); else if (warning == EWarning::ToolpathOutside) { // check if max x,y coords exceed bed area show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed() && (m_gcode_viewer.get_max_print_height() -m_gcode_viewer.get_layers_zs()[max_z_layer] >= 1e-6);