diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index f7d2f75c0..95ab112a2 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -700,7 +700,7 @@ sub load_files { . "Instead of considering them as multiple objects, should I consider\n" . "this file as a single object having multiple parts?\n"), L('Multi-part object detected'), wxICON_WARNING | wxYES | wxNO); - $model->convert_multipart_object if $dialog->ShowModal() == wxID_YES; + $model->convert_multipart_object if $dialog->ShowModal(scalar(@$nozzle_dmrs)) == wxID_YES; } if ($one_by_one) { @@ -717,7 +717,7 @@ sub load_files { . "Instead of considering them as multiple objects, should I consider\n" . "these files to represent a single object having multiple parts?\n"), L('Multi-part object detected'), wxICON_WARNING | wxYES | wxNO); - $new_model->convert_multipart_object if $dialog->ShowModal() == wxID_YES; + $new_model->convert_multipart_object if $dialog->ShowModal(scalar(@$nozzle_dmrs)) == wxID_YES; push @obj_idx, $self->load_model_objects(@{$new_model->objects}); } diff --git a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm index 28e3bf92b..a632edeea 100644 --- a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm +++ b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm @@ -475,7 +475,8 @@ sub on_btn_split { my $itemData = $self->get_selection; if ($itemData && $itemData->{type} eq 'volume') { my $volume = $self->{model_object}->volumes->[$itemData->{volume_id}]; - $self->{parts_changed} = 1 if $volume->split > 1; + my $nozzle_dmrs = $self->GetParent->GetParent->GetParent->{config}->get('nozzle_diameter'); + $self->{parts_changed} = 1 if $volume->split(scalar(@$nozzle_dmrs)) > 1; } $self->_parts_changed; diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 8ad479532..dc8e5d691 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -1287,6 +1287,10 @@ void GCode::process_layer( m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back()) : this->set_extruder(extruder_id); + // let analyzer tag generator aware of a role type change + if (m_enable_analyzer && layer_tools.has_wipe_tower && m_wipe_tower) + m_last_analyzer_extrusion_role = erWipeTower; + if (extrude_skirt) { auto loops_it = skirt_loops_per_extruder.find(extruder_id); if (loops_it != skirt_loops_per_extruder.end()) { @@ -2170,7 +2174,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, double F = speed * 60; // convert mm/sec to mm/min // extrude arc or line - if (m_enable_extrusion_role_markers || m_enable_analyzer) + if (m_enable_extrusion_role_markers) { if (path.role() != m_last_extrusion_role) { @@ -2181,18 +2185,20 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, sprintf(buf, ";_EXTRUSION_ROLE:%d\n", int(m_last_extrusion_role)); gcode += buf; } - if (m_enable_analyzer) - { - char buf[32]; - sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), int(m_last_extrusion_role)); - gcode += buf; - } } } // adds analyzer tags and updates analyzer's tracking data if (m_enable_analyzer) { + if (path.role() != m_last_analyzer_extrusion_role) + { + m_last_analyzer_extrusion_role = path.role(); + char buf[32]; + sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), int(m_last_analyzer_extrusion_role)); + gcode += buf; + } + if (m_last_mm3_per_mm != path.mm3_per_mm) { m_last_mm3_per_mm = path.mm3_per_mm; @@ -2230,6 +2236,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, if (path.role() == erExternalPerimeter) comment += ";_EXTERNAL_PERIMETER"; } + // F is mm per minute. gcode += m_writer.set_speed(F, "", comment); double path_length = 0.; diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp index 968cd14de..d028e90aa 100644 --- a/xs/src/libslic3r/GCode.hpp +++ b/xs/src/libslic3r/GCode.hpp @@ -121,6 +121,7 @@ public: m_enable_cooling_markers(false), m_enable_extrusion_role_markers(false), m_enable_analyzer(false), + m_last_analyzer_extrusion_role(erNone), m_layer_count(0), m_layer_index(-1), m_layer(nullptr), @@ -253,6 +254,7 @@ protected: // Extended markers will be added during G-code generation. // The G-code Analyzer will remove these comments from the final G-code. bool m_enable_analyzer; + ExtrusionRole m_last_analyzer_extrusion_role; // How many times will change_layer() be called? // change_layer() will update the progress bar. unsigned int m_layer_count; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index ad7d91c50..b414186be 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -126,6 +126,11 @@ public: m_extrusions.emplace_back(WipeTower::Extrusion(WipeTower::xy(rot.x, rot.y), width, m_current_tool)); } + // adds tag for analyzer + char buf[64]; + sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower); + m_gcode += buf; + m_gcode += "G1"; if (rot.x != rotated_current_pos.x) { m_gcode += set_format_X(rot.x); // Transform current position back to wipe tower coordinates (was updated by set_format_X) @@ -488,11 +493,6 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( .travel(cleaning_box.ld, 7200) .set_extruder_trimpot(750); // Increase the extruder driver current to allow fast ramming. - // adds tag for analyzer - char buf[32]; - sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower); - writer.append(buf); - for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) { unsigned int tool = tools[idx_tool]; m_left_to_right = true; @@ -585,12 +585,6 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo xy initial_position = cleaning_box.ld + WipeTower::xy(0.f,m_depth_traversed); writer.set_initial_position(initial_position); - - // adds tag for analyzer - char buf[32]; - sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower); - writer.append(buf); - // Increase the extruder driver current to allow fast ramming. writer.set_extruder_trimpot(750); @@ -658,12 +652,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, flo xy initial_position = wipeTower_box.lu - xy(m_perimeter_width * 6.f, 0); writer.set_initial_position(initial_position); - // adds tag for analyzer - char buf[32]; - sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower); - writer.append(buf) - .extrude_explicit(wipeTower_box.ld - xy(m_perimeter_width * 6.f, 0), // Prime the extruder left of the wipe tower. - 1.5f * m_extrusion_flow * (wipeTower_box.lu.y - wipeTower_box.ld.y), 2400); + writer.extrude_explicit(wipeTower_box.ld - xy(m_perimeter_width * 6.f, 0), // Prime the extruder left of the wipe tower. + 1.5f * m_extrusion_flow * (wipeTower_box.lu.y - wipeTower_box.ld.y), 2400); // The tool is supposed to be active and primed at the time when the wipe tower brim is extruded. // Extrude 4 rounds of a brim around the future wipe tower. diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index 0f14af369..755941144 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -404,7 +404,7 @@ bool Model::looks_like_multipart_object() const return false; } -void Model::convert_multipart_object() +void Model::convert_multipart_object(unsigned int max_extruders) { if (this->objects.empty()) return; @@ -421,7 +421,7 @@ void Model::convert_multipart_object() if (new_v != nullptr) { new_v->name = o->name; - new_v->config.set_deserialize("extruder", get_auto_extruder_id_as_string()); + new_v->config.set_deserialize("extruder", get_auto_extruder_id_as_string(max_extruders)); } } @@ -451,20 +451,50 @@ void Model::adjust_min_z() } } -unsigned int Model::get_auto_extruder_id() +bool Model::fits_print_volume(const DynamicPrintConfig* config) const +{ + if (config == nullptr) + return false; + + if (objects.empty()) + return true; + + const ConfigOptionPoints* opt = dynamic_cast(config->option("bed_shape")); + if (opt == nullptr) + return false; + + BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values)); + BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config->opt_float("max_print_height"))); + // Allow the objects to protrude below the print bed + print_volume.min.z = -1e10; + return print_volume.contains(transformed_bounding_box()); +} + +bool Model::fits_print_volume(const FullPrintConfig &config) const +{ + if (objects.empty()) + return true; + BoundingBox bed_box_2D = get_extents(Polygon::new_scale(config.bed_shape.values)); + BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config.max_print_height)); + // Allow the objects to protrude below the print bed + print_volume.min.z = -1e10; + return print_volume.contains(transformed_bounding_box()); +} + +unsigned int Model::get_auto_extruder_id(unsigned int max_extruders) { unsigned int id = s_auto_extruder_id; - if (++s_auto_extruder_id > 4) + if (++s_auto_extruder_id > max_extruders) reset_auto_extruder_id(); return id; } -std::string Model::get_auto_extruder_id_as_string() +std::string Model::get_auto_extruder_id_as_string(unsigned int max_extruders) { char str_extruder[64]; - sprintf(str_extruder, "%ud", get_auto_extruder_id()); + sprintf(str_extruder, "%ud", get_auto_extruder_id(max_extruders)); return str_extruder; } @@ -966,7 +996,7 @@ ModelMaterial* ModelVolume::assign_unique_material() // Split this volume, append the result to the object owning this volume. // Return the number of volumes created from this one. // This is useful to assign different materials to different volumes of an object. -size_t ModelVolume::split() +size_t ModelVolume::split(unsigned int max_extruders) { TriangleMeshPtrs meshptrs = this->mesh.split(); if (meshptrs.size() <= 1) { @@ -989,7 +1019,7 @@ size_t ModelVolume::split() char str_idx[64]; sprintf(str_idx, "_%d", idx + 1); this->object->volumes[ivolume]->name = name + str_idx; - this->object->volumes[ivolume]->config.set_deserialize("extruder", Model::get_auto_extruder_id_as_string()); + this->object->volumes[ivolume]->config.set_deserialize("extruder", Model::get_auto_extruder_id_as_string(max_extruders)); delete mesh; ++ idx; } diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index 0baea979c..8b63c3641 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -173,8 +173,8 @@ public: // Split this volume, append the result to the object owning this volume. // Return the number of volumes created from this one. // This is useful to assign different materials to different volumes of an object. - size_t split(); - + size_t split(unsigned int max_extruders); + ModelMaterial* assign_unique_material(); private: @@ -280,15 +280,15 @@ public: void duplicate_objects_grid(size_t x, size_t y, coordf_t dist); bool looks_like_multipart_object() const; - void convert_multipart_object(); + void convert_multipart_object(unsigned int max_extruders); // Ensures that the min z of the model is not negative void adjust_min_z(); void print_info() const { for (const ModelObject *o : this->objects) o->print_info(); } - static unsigned int get_auto_extruder_id(); - static std::string get_auto_extruder_id_as_string(); + static unsigned int get_auto_extruder_id(unsigned int max_extruders); + static std::string get_auto_extruder_id_as_string(unsigned int max_extruders); static void reset_auto_extruder_id(); }; diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index 02017839a..25c26c380 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -95,7 +95,7 @@ void duplicate_objects_grid(unsigned int x, unsigned int y, double dist); bool looks_like_multipart_object() const; - void convert_multipart_object(); + void convert_multipart_object(unsigned int max_extruders); void print_info() const; @@ -343,7 +343,7 @@ ModelMaterial::attributes() void set_modifier(bool modifier) %code%{ THIS->modifier = modifier; %}; - size_t split(); + size_t split(unsigned int max_extruders); ModelMaterial* assign_unique_material(); };