Merge branch 'lm_wipe_tower_border'

This commit is contained in:
Lukas Matena 2023-05-26 12:45:01 +02:00
commit f3fae24313
15 changed files with 105 additions and 24 deletions

View File

@ -168,6 +168,11 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height); this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height);
if (this->insert_wipe_tower_extruder()) {
this->reorder_extruders(first_extruder);
this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height);
}
this->collect_extruder_statistics(prime_multi_material); this->collect_extruder_statistics(prime_multi_material);
this->mark_skirt_layers(print.config(), max_layer_height); this->mark_skirt_layers(print.config(), max_layer_height);
@ -462,6 +467,27 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
} }
} }
bool ToolOrdering::insert_wipe_tower_extruder()
{
// In case that wipe_tower_extruder is set to non-zero, we must make sure that the extruder will be in the list.
bool changed = false;
if (m_print_config_ptr->wipe_tower_extruder != 0) {
for (LayerTools& lt : m_layer_tools) {
if (lt.wipe_tower_partitions > 0) {
lt.extruders.emplace_back(m_print_config_ptr->wipe_tower_extruder - 1);
sort_remove_duplicates(lt.extruders);
changed = true;
}
}
// Now convert the 0-based list to 1-based again.
for (LayerTools& lt : m_layer_tools) {
for (auto& extruder : lt.extruders)
++extruder;
}
}
return changed;
}
void ToolOrdering::collect_extruder_statistics(bool prime_multi_material) void ToolOrdering::collect_extruder_statistics(bool prime_multi_material)
{ {
m_first_printing_extruder = (unsigned int)-1; m_first_printing_extruder = (unsigned int)-1;

View File

@ -167,6 +167,7 @@ private:
void collect_extruders(const PrintObject &object, const std::vector<std::pair<double, unsigned int>> &per_layer_extruder_switches); void collect_extruders(const PrintObject &object, const std::vector<std::pair<double, unsigned int>> &per_layer_extruder_switches);
void reorder_extruders(unsigned int last_extruder_id); void reorder_extruders(unsigned int last_extruder_id);
void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_layer_height); void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_layer_height);
bool insert_wipe_tower_extruder();
void mark_skirt_layers(const PrintConfig &config, coordf_t max_layer_height); void mark_skirt_layers(const PrintConfig &config, coordf_t max_layer_height);
void collect_extruder_statistics(bool prime_multi_material); void collect_extruder_statistics(bool prime_multi_material);

View File

@ -581,7 +581,7 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config)
m_filpar.push_back(FilamentParameters()); m_filpar.push_back(FilamentParameters());
m_filpar[idx].material = config.filament_type.get_at(idx); m_filpar[idx].material = config.filament_type.get_at(idx);
m_filpar[idx].is_soluble = config.filament_soluble.get_at(idx); m_filpar[idx].is_soluble = config.wipe_tower_extruder == 0 ? config.filament_soluble.get_at(idx) : (idx != config.wipe_tower_extruder - 1);
m_filpar[idx].temperature = config.temperature.get_at(idx); m_filpar[idx].temperature = config.temperature.get_at(idx);
m_filpar[idx].first_layer_temperature = config.first_layer_temperature.get_at(idx); m_filpar[idx].first_layer_temperature = config.first_layer_temperature.get_at(idx);

View File

@ -456,7 +456,7 @@ static std::vector<std::string> s_Preset_print_options {
"top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "infill_anchor", "infill_anchor_max", "bridge_flow_ratio", "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "infill_anchor", "infill_anchor_max", "bridge_flow_ratio",
"elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "gcode_resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "gcode_resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y",
"wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width", "wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width",
"wipe_tower_no_sparse_layers", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits", "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits",
"perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", "perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
"wall_distribution_count", "min_feature_size", "min_bead_width" "wall_distribution_count", "min_feature_size", "min_bead_width"
}; };

View File

@ -208,6 +208,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "wipe_tower_bridging" || opt_key == "wipe_tower_bridging"
|| opt_key == "wipe_tower_extra_spacing" || opt_key == "wipe_tower_extra_spacing"
|| opt_key == "wipe_tower_no_sparse_layers" || opt_key == "wipe_tower_no_sparse_layers"
|| opt_key == "wipe_tower_extruder"
|| opt_key == "wiping_volumes_matrix" || opt_key == "wiping_volumes_matrix"
|| opt_key == "parking_pos_retraction" || opt_key == "parking_pos_retraction"
|| opt_key == "cooling_tube_retraction" || opt_key == "cooling_tube_retraction"
@ -328,6 +329,15 @@ std::vector<unsigned int> Print::extruders() const
std::vector<unsigned int> extruders = this->object_extruders(); std::vector<unsigned int> extruders = this->object_extruders();
append(extruders, this->support_material_extruders()); append(extruders, this->support_material_extruders());
sort_remove_duplicates(extruders); sort_remove_duplicates(extruders);
// The wipe tower extruder can also be set. When the wipe tower is enabled and it will be generated,
// append its extruder into the list too.
if (has_wipe_tower() && config().wipe_tower_extruder != 0 && extruders.size() > 1) {
assert(config().wipe_tower_extruder > 0 && config().wipe_tower_extruder < int(config().nozzle_diameter.size()));
extruders.emplace_back(config().wipe_tower_extruder - 1); // the config value is 1-based
sort_remove_duplicates(extruders);
}
return extruders; return extruders;
} }
@ -458,10 +468,21 @@ static inline bool sequential_print_vertical_clearance_valid(const Print &print)
boost::regex regex_g92e0 { "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$" }; boost::regex regex_g92e0 { "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$" };
// Precondition: Print::validate() requires the Print::apply() to be called its invocation. // Precondition: Print::validate() requires the Print::apply() to be called its invocation.
std::string Print::validate(std::string* warning) const std::string Print::validate(std::vector<std::string>* warnings) const
{ {
std::vector<unsigned int> extruders = this->extruders(); std::vector<unsigned int> extruders = this->extruders();
if (warnings) {
for (size_t a=0; a<extruders.size(); ++a)
for (size_t b=a+1; b<extruders.size(); ++b)
if (std::abs(m_config.bed_temperature.get_at(extruders[a]) - m_config.bed_temperature.get_at(extruders[b])) > 15
|| std::abs(m_config.first_layer_bed_temperature.get_at(extruders[a]) - m_config.first_layer_bed_temperature.get_at(extruders[b])) > 15) {
warnings->emplace_back("_BED_TEMPS_DIFFER");
goto DONE;
}
DONE:;
}
if (m_objects.empty()) if (m_objects.empty())
return _u8L("All objects are outside of the print volume."); return _u8L("All objects are outside of the print volume.");
@ -681,12 +702,12 @@ std::string Print::validate(std::string* warning) const
// Do we have custom support data that would not be used? // Do we have custom support data that would not be used?
// Notify the user in that case. // Notify the user in that case.
if (! object->has_support() && warning) { if (! object->has_support() && warnings) {
for (const ModelVolume* mv : object->model_object()->volumes) { for (const ModelVolume* mv : object->model_object()->volumes) {
bool has_enforcers = mv->is_support_enforcer() || bool has_enforcers = mv->is_support_enforcer() ||
(mv->is_model_part() && mv->supported_facets.has_facets(*mv, EnforcerBlockerType::ENFORCER)); (mv->is_model_part() && mv->supported_facets.has_facets(*mv, EnforcerBlockerType::ENFORCER));
if (has_enforcers) { if (has_enforcers) {
*warning = "_SUPPORTS_OFF"; warnings->emplace_back("_SUPPORTS_OFF");
break; break;
} }
} }

View File

@ -547,7 +547,7 @@ public:
bool has_brim() const; bool has_brim() const;
// Returns an empty string if valid, otherwise returns an error message. // Returns an empty string if valid, otherwise returns an error message.
std::string validate(std::string* warning = nullptr) const override; std::string validate(std::vector<std::string>* warnings = nullptr) const override;
double skirt_first_layer_height() const; double skirt_first_layer_height() const;
Flow brim_flow() const; Flow brim_flow() const;
Flow skirt_flow() const; Flow skirt_flow() const;

View File

@ -418,7 +418,7 @@ public:
virtual std::vector<ObjectID> print_object_ids() const = 0; virtual std::vector<ObjectID> print_object_ids() const = 0;
// Validate the print, return empty string if valid, return error if process() cannot (or should not) be started. // Validate the print, return empty string if valid, return error if process() cannot (or should not) be started.
virtual std::string validate(std::string* warning = nullptr) const { return std::string(); } virtual std::string validate(std::vector<std::string>* warnings = nullptr) const { return std::string(); }
enum ApplyStatus { enum ApplyStatus {
// No change after the Print::apply() call. // No change after the Print::apply() call.

View File

@ -3235,6 +3235,27 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(10.)); def->set_default_value(new ConfigOptionFloat(10.));
def = this->add("wipe_tower_extruder", coInt);
def->label = L("Wipe tower extruder");
def->category = L("Extruders");
def->tooltip = L("The extruder to use when printing perimeter of the wipe tower. "
"Set to 0 to use the one that is available (non-soluble would be preferred).");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(0));
def = this->add("solid_infill_every_layers", coInt);
def->label = L("Solid infill every");
def->category = L("Infill");
def->tooltip = L("This feature allows to force a solid layer every given number of layers. "
"Zero to disable. You can set this to any value (for example 9999); "
"Slic3r will automatically choose the maximum possible number of layers "
"to combine according to nozzle diameter and layer height.");
def->sidetext = L("layers");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionInt(0));
def = this->add("xy_size_compensation", coFloat); def = this->add("xy_size_compensation", coFloat);
def->label = L("XY Size Compensation"); def->label = L("XY Size Compensation");
def->category = L("Advanced"); def->category = L("Advanced");
@ -4325,6 +4346,14 @@ void DynamicPrintConfig::normalize_fdm()
} }
} }
if (this->has("wipe_tower_extruder")) {
// If invalid, replace with 0.
int extruder = this->opt<ConfigOptionInt>("wipe_tower_extruder")->value;
int num_extruders = this->opt<ConfigOptionFloats>("nozzle_diameter")->size();
if (extruder < 0 || extruder > num_extruders)
this->option("wipe_tower_extruder")->setInt(0);
}
if (!this->has("solid_infill_extruder") && this->has("infill_extruder")) if (!this->has("solid_infill_extruder") && this->has("infill_extruder"))
this->option("solid_infill_extruder", true)->setInt(this->option("infill_extruder")->getInt()); this->option("solid_infill_extruder", true)->setInt(this->option("infill_extruder")->getInt());

View File

@ -829,6 +829,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionFloat, wipe_tower_cone_angle)) ((ConfigOptionFloat, wipe_tower_cone_angle))
((ConfigOptionPercent, wipe_tower_extra_spacing)) ((ConfigOptionPercent, wipe_tower_extra_spacing))
((ConfigOptionFloat, wipe_tower_bridging)) ((ConfigOptionFloat, wipe_tower_bridging))
((ConfigOptionInt, wipe_tower_extruder))
((ConfigOptionFloats, wiping_volumes_matrix)) ((ConfigOptionFloats, wiping_volumes_matrix))
((ConfigOptionFloats, wiping_volumes_extruders)) ((ConfigOptionFloats, wiping_volumes_extruders))
((ConfigOptionFloat, z_offset)) ((ConfigOptionFloat, z_offset))

View File

@ -534,7 +534,7 @@ std::string SLAPrint::output_filename(const std::string &filename_base) const
return this->PrintBase::output_filename(m_print_config.output_filename_format.value, ".sl1", filename_base, &config); return this->PrintBase::output_filename(m_print_config.output_filename_format.value, ".sl1", filename_base, &config);
} }
std::string SLAPrint::validate(std::string*) const std::string SLAPrint::validate(std::vector<std::string>*) const
{ {
for(SLAPrintObject * po : m_objects) { for(SLAPrintObject * po : m_objects) {

View File

@ -494,7 +494,7 @@ public:
const SLAPrintStatistics& print_statistics() const { return m_print_statistics; } const SLAPrintStatistics& print_statistics() const { return m_print_statistics; }
std::string validate(std::string* warning = nullptr) const override; std::string validate(std::vector<std::string>* warnings = nullptr) const override;
// An aggregation of SliceRecord-s from all the print objects for each // An aggregation of SliceRecord-s from all the print objects for each
// occupied layer. Slice record levels dont have to match exactly. // occupied layer. Slice record levels dont have to match exactly.

View File

@ -549,10 +549,10 @@ bool BackgroundSlicingProcess::empty() const
return m_print->empty(); return m_print->empty();
} }
std::string BackgroundSlicingProcess::validate(std::string* warning) std::string BackgroundSlicingProcess::validate(std::vector<std::string>* warnings)
{ {
assert(m_print != nullptr); assert(m_print != nullptr);
return m_print->validate(warning); return m_print->validate(warnings);
} }
// Apply config over the print. Returns false, if the new config values caused any of the already // Apply config over the print. Returns false, if the new config values caused any of the already

View File

@ -132,7 +132,7 @@ public:
bool empty() const; bool empty() const;
// Validate the print. Returns an empty string if valid, returns an error message if invalid. // Validate the print. Returns an empty string if valid, returns an error message if invalid.
// Call validate before calling start(). // Call validate before calling start().
std::string validate(std::string* warning = nullptr); std::string validate(std::vector<std::string>* warnings = nullptr);
// Set the export path of the G-code. // Set the export path of the G-code.
// Once the path is set, the G-code // Once the path is set, the G-code

View File

@ -1849,7 +1849,7 @@ struct Plater::priv
void suppress_snapshots() { m_prevent_snapshots++; } void suppress_snapshots() { m_prevent_snapshots++; }
void allow_snapshots() { m_prevent_snapshots--; } void allow_snapshots() { m_prevent_snapshots--; }
void process_validation_warning(const std::string& warning) const; void process_validation_warning(const std::vector<std::string>& warning) const;
bool background_processing_enabled() const { return this->get_config_bool("background_processing"); } bool background_processing_enabled() const { return this->get_config_bool("background_processing"); }
void update_print_volume_state(); void update_print_volume_state();
@ -2007,7 +2007,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
, config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({
"bed_shape", "bed_custom_texture", "bed_custom_model", "complete_objects", "duplicate_distance", "extruder_clearance_radius", "skirts", "skirt_distance", "bed_shape", "bed_custom_texture", "bed_custom_model", "complete_objects", "duplicate_distance", "extruder_clearance_radius", "skirts", "skirt_distance",
"brim_width", "brim_separation", "brim_type", "variable_layer_height", "nozzle_diameter", "single_extruder_multi_material", "brim_width", "brim_separation", "brim_type", "variable_layer_height", "nozzle_diameter", "single_extruder_multi_material",
"wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_cone_angle", "wipe_tower_extra_spacing", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_cone_angle", "wipe_tower_extra_spacing", "wipe_tower_extruder",
"extruder_colour", "filament_colour", "material_colour", "max_print_height", "printer_model", "printer_technology", "extruder_colour", "filament_colour", "material_colour", "max_print_height", "printer_model", "printer_technology",
// These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor. // These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor.
"layer_height", "first_layer_height", "min_layer_height", "max_layer_height", "layer_height", "first_layer_height", "min_layer_height", "max_layer_height",
@ -3198,12 +3198,12 @@ void Plater::priv::update_print_volume_state()
this->q->model().update_print_volume_state(this->bed.build_volume()); this->q->model().update_print_volume_state(this->bed.build_volume());
} }
void Plater::priv::process_validation_warning(const std::string& warning) const void Plater::priv::process_validation_warning(const std::vector<std::string>& warnings) const
{ {
if (warning.empty()) if (warnings.empty())
notification_manager->close_notification_of_type(NotificationType::ValidateWarning); notification_manager->close_notification_of_type(NotificationType::ValidateWarning);
else {
std::string text = warning; for (std::string text : warnings) {
std::string hypertext = ""; std::string hypertext = "";
std::function<bool(wxEvtHandler*)> action_fn = [](wxEvtHandler*){ return false; }; std::function<bool(wxEvtHandler*)> action_fn = [](wxEvtHandler*){ return false; };
@ -3222,6 +3222,8 @@ void Plater::priv::process_validation_warning(const std::string& warning) const
return true; return true;
}; };
} }
if (text == "_BED_TEMPS_DIFFER")
text = _u8L("Bed temperatures for the used filaments differ significantly.");
notification_manager->push_notification( notification_manager->push_notification(
NotificationType::ValidateWarning, NotificationType::ValidateWarning,
@ -3279,8 +3281,8 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
// The delayed error message is no more valid. // The delayed error message is no more valid.
delayed_error_message.clear(); delayed_error_message.clear();
// The state of the Print changed, and it is non-zero. Let's validate it and give the user feedback on errors. // The state of the Print changed, and it is non-zero. Let's validate it and give the user feedback on errors.
std::string warning; std::vector<std::string> warnings;
std::string err = background_process.validate(&warning); std::string err = background_process.validate(&warnings);
if (err.empty()) { if (err.empty()) {
notification_manager->set_all_slicing_errors_gray(true); notification_manager->set_all_slicing_errors_gray(true);
notification_manager->close_notification_of_type(NotificationType::ValidateError); notification_manager->close_notification_of_type(NotificationType::ValidateError);
@ -3289,7 +3291,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
// Pass a warning from validation and either show a notification, // Pass a warning from validation and either show a notification,
// or hide the old one. // or hide the old one.
process_validation_warning(warning); process_validation_warning(warnings);
if (printer_technology == ptFFF) { if (printer_technology == ptFFF) {
GLCanvas3D* canvas = view3D->get_canvas3d(); GLCanvas3D* canvas = view3D->get_canvas3d();
canvas->reset_sequential_print_clearance(); canvas->reset_sequential_print_clearance();
@ -3328,8 +3330,8 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
canvas->request_extra_frame(); canvas->request_extra_frame();
} }
} }
std::string warning; std::vector<std::string> warnings;
std::string err = background_process.validate(&warning); std::string err = background_process.validate(&warnings);
if (!err.empty()) if (!err.empty())
return return_state; return return_state;
} }
@ -3342,7 +3344,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
//actualizate warnings //actualizate warnings
if (invalidated != Print::APPLY_STATUS_UNCHANGED || background_process.empty()) { if (invalidated != Print::APPLY_STATUS_UNCHANGED || background_process.empty()) {
if (background_process.empty()) if (background_process.empty())
process_validation_warning(std::string()); process_validation_warning(std::vector<std::string>());
actualize_slicing_warnings(*this->background_process.current_print()); actualize_slicing_warnings(*this->background_process.current_print());
actualize_object_warnings(*this->background_process.current_print()); actualize_object_warnings(*this->background_process.current_print());
show_warning_dialog = false; show_warning_dialog = false;

View File

@ -1598,6 +1598,7 @@ void TabPrint::build()
optgroup->append_single_option_line("solid_infill_extruder"); optgroup->append_single_option_line("solid_infill_extruder");
optgroup->append_single_option_line("support_material_extruder"); optgroup->append_single_option_line("support_material_extruder");
optgroup->append_single_option_line("support_material_interface_extruder"); optgroup->append_single_option_line("support_material_interface_extruder");
optgroup->append_single_option_line("wipe_tower_extruder");
optgroup = page->new_optgroup(L("Ooze prevention")); optgroup = page->new_optgroup(L("Ooze prevention"));
optgroup->append_single_option_line("ooze_prevention"); optgroup->append_single_option_line("ooze_prevention");