Merge branch 'lm_wipe_tower_border'
This commit is contained in:
commit
f3fae24313
@ -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);
|
||||
|
||||
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->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)
|
||||
{
|
||||
m_first_printing_extruder = (unsigned int)-1;
|
||||
|
@ -167,6 +167,7 @@ private:
|
||||
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 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 collect_extruder_statistics(bool prime_multi_material);
|
||||
|
||||
|
@ -581,7 +581,7 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config)
|
||||
m_filpar.push_back(FilamentParameters());
|
||||
|
||||
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].first_layer_temperature = config.first_layer_temperature.get_at(idx);
|
||||
|
||||
|
@ -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",
|
||||
"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_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",
|
||||
"wall_distribution_count", "min_feature_size", "min_bead_width"
|
||||
};
|
||||
|
@ -208,6 +208,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
|| opt_key == "wipe_tower_bridging"
|
||||
|| opt_key == "wipe_tower_extra_spacing"
|
||||
|| opt_key == "wipe_tower_no_sparse_layers"
|
||||
|| opt_key == "wipe_tower_extruder"
|
||||
|| opt_key == "wiping_volumes_matrix"
|
||||
|| opt_key == "parking_pos_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();
|
||||
append(extruders, this->support_material_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;
|
||||
}
|
||||
|
||||
@ -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]*(;.*)?$" };
|
||||
|
||||
// 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();
|
||||
|
||||
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())
|
||||
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?
|
||||
// Notify the user in that case.
|
||||
if (! object->has_support() && warning) {
|
||||
if (! object->has_support() && warnings) {
|
||||
for (const ModelVolume* mv : object->model_object()->volumes) {
|
||||
bool has_enforcers = mv->is_support_enforcer() ||
|
||||
(mv->is_model_part() && mv->supported_facets.has_facets(*mv, EnforcerBlockerType::ENFORCER));
|
||||
if (has_enforcers) {
|
||||
*warning = "_SUPPORTS_OFF";
|
||||
warnings->emplace_back("_SUPPORTS_OFF");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -547,7 +547,7 @@ public:
|
||||
bool has_brim() const;
|
||||
|
||||
// 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;
|
||||
Flow brim_flow() const;
|
||||
Flow skirt_flow() const;
|
||||
|
@ -418,7 +418,7 @@ public:
|
||||
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.
|
||||
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 {
|
||||
// No change after the Print::apply() call.
|
||||
|
@ -3235,6 +3235,27 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
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->label = L("XY Size Compensation");
|
||||
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"))
|
||||
this->option("solid_infill_extruder", true)->setInt(this->option("infill_extruder")->getInt());
|
||||
|
||||
|
@ -829,6 +829,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
||||
((ConfigOptionFloat, wipe_tower_cone_angle))
|
||||
((ConfigOptionPercent, wipe_tower_extra_spacing))
|
||||
((ConfigOptionFloat, wipe_tower_bridging))
|
||||
((ConfigOptionInt, wipe_tower_extruder))
|
||||
((ConfigOptionFloats, wiping_volumes_matrix))
|
||||
((ConfigOptionFloats, wiping_volumes_extruders))
|
||||
((ConfigOptionFloat, z_offset))
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
std::string SLAPrint::validate(std::string*) const
|
||||
std::string SLAPrint::validate(std::vector<std::string>*) const
|
||||
{
|
||||
for(SLAPrintObject * po : m_objects) {
|
||||
|
||||
|
@ -494,7 +494,7 @@ public:
|
||||
|
||||
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
|
||||
// occupied layer. Slice record levels dont have to match exactly.
|
||||
|
@ -549,10 +549,10 @@ bool BackgroundSlicingProcess::empty() const
|
||||
return m_print->empty();
|
||||
}
|
||||
|
||||
std::string BackgroundSlicingProcess::validate(std::string* warning)
|
||||
std::string BackgroundSlicingProcess::validate(std::vector<std::string>* warnings)
|
||||
{
|
||||
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
|
||||
|
@ -132,7 +132,7 @@ public:
|
||||
bool empty() const;
|
||||
// Validate the print. Returns an empty string if valid, returns an error message if invalid.
|
||||
// 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.
|
||||
// Once the path is set, the G-code
|
||||
|
@ -1849,7 +1849,7 @@ struct Plater::priv
|
||||
void suppress_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"); }
|
||||
void update_print_volume_state();
|
||||
@ -2007,7 +2007,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
, 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",
|
||||
"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",
|
||||
// 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",
|
||||
@ -3198,12 +3198,12 @@ void Plater::priv::update_print_volume_state()
|
||||
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);
|
||||
else {
|
||||
std::string text = warning;
|
||||
|
||||
for (std::string text : warnings) {
|
||||
std::string hypertext = "";
|
||||
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;
|
||||
};
|
||||
}
|
||||
if (text == "_BED_TEMPS_DIFFER")
|
||||
text = _u8L("Bed temperatures for the used filaments differ significantly.");
|
||||
|
||||
notification_manager->push_notification(
|
||||
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.
|
||||
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.
|
||||
std::string warning;
|
||||
std::string err = background_process.validate(&warning);
|
||||
std::vector<std::string> warnings;
|
||||
std::string err = background_process.validate(&warnings);
|
||||
if (err.empty()) {
|
||||
notification_manager->set_all_slicing_errors_gray(true);
|
||||
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,
|
||||
// or hide the old one.
|
||||
process_validation_warning(warning);
|
||||
process_validation_warning(warnings);
|
||||
if (printer_technology == ptFFF) {
|
||||
GLCanvas3D* canvas = view3D->get_canvas3d();
|
||||
canvas->reset_sequential_print_clearance();
|
||||
@ -3328,8 +3330,8 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
||||
canvas->request_extra_frame();
|
||||
}
|
||||
}
|
||||
std::string warning;
|
||||
std::string err = background_process.validate(&warning);
|
||||
std::vector<std::string> warnings;
|
||||
std::string err = background_process.validate(&warnings);
|
||||
if (!err.empty())
|
||||
return return_state;
|
||||
}
|
||||
@ -3342,7 +3344,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
||||
//actualizate warnings
|
||||
if (invalidated != Print::APPLY_STATUS_UNCHANGED || 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_object_warnings(*this->background_process.current_print());
|
||||
show_warning_dialog = false;
|
||||
|
@ -1598,6 +1598,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("solid_infill_extruder");
|
||||
optgroup->append_single_option_line("support_material_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->append_single_option_line("ooze_prevention");
|
||||
|
Loading…
Reference in New Issue
Block a user