diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui index a9c048932b4..1fc4d1c8166 100644 --- a/resources/ui_layout/print.ui +++ b/resources/ui_layout/print.ui @@ -247,6 +247,7 @@ group:Wipe tower setting:label_width$3:width$5:sidetext$mm:wipe_tower_x setting:label_width$3:width$5:sidetext$mm:wipe_tower_y end_line + setting:wipe_tower_brim setting:wipe_tower_width setting:wipe_tower_rotation_angle setting:wipe_tower_bridging diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp index 59cfabab53f..9c24cc61c89 100644 --- a/src/libslic3r/GCode/WipeTower.cpp +++ b/src/libslic3r/GCode/WipeTower.cpp @@ -23,6 +23,7 @@ TODO LIST #include "Analyzer.hpp" #include "BoundingBox.hpp" +#include "Flow.hpp" #if defined(__linux) || defined(__GNUC__ ) #include @@ -523,6 +524,7 @@ class WipeTowerWriter WipeTower::WipeTower(const PrintConfig& config, const std::vector>& wiping_matrix, size_t initial_tool) : + m_config(&config), m_semm(config.single_extruder_multi_material.value), m_wipe_tower_pos(config.wipe_tower_x, config.wipe_tower_y), m_wipe_tower_width(float(config.wipe_tower_width)), @@ -556,53 +558,54 @@ WipeTower::WipeTower(const PrintConfig& config, const std::vectorfilament_type.get_at(idx); + m_filpar[idx].temperature = m_config->temperature.get_at(idx); + m_filpar[idx].first_layer_temperature = m_config->first_layer_temperature.get_at(idx); // If this is a single extruder MM printer, we will use all the SE-specific config values. // Otherwise, the defaults will be used to turn off the SE stuff. if (m_semm) { - m_filpar[idx].loading_speed = float(config.filament_loading_speed.get_at(idx)); - m_filpar[idx].loading_speed_start = float(config.filament_loading_speed_start.get_at(idx)); - m_filpar[idx].unloading_speed = float(config.filament_unloading_speed.get_at(idx)); - m_filpar[idx].unloading_speed_start = float(config.filament_unloading_speed_start.get_at(idx)); - m_filpar[idx].delay = float(config.filament_toolchange_delay.get_at(idx)); - m_filpar[idx].cooling_moves = config.filament_cooling_moves.get_at(idx); - m_filpar[idx].cooling_initial_speed = float(config.filament_cooling_initial_speed.get_at(idx)); - m_filpar[idx].cooling_final_speed = float(config.filament_cooling_final_speed.get_at(idx)); + m_filpar[idx].loading_speed = float(m_config->filament_loading_speed.get_at(idx)); + m_filpar[idx].loading_speed_start = float(m_config->filament_loading_speed_start.get_at(idx)); + m_filpar[idx].unloading_speed = float(m_config->filament_unloading_speed.get_at(idx)); + m_filpar[idx].unloading_speed_start = float(m_config->filament_unloading_speed_start.get_at(idx)); + m_filpar[idx].delay = float(m_config->filament_toolchange_delay.get_at(idx)); + m_filpar[idx].cooling_moves = m_config->filament_cooling_moves.get_at(idx); + m_filpar[idx].cooling_initial_speed = float(m_config->filament_cooling_initial_speed.get_at(idx)); + m_filpar[idx].cooling_final_speed = float(m_config->filament_cooling_final_speed.get_at(idx)); //start skinnydip - m_filpar[idx].filament_enable_toolchange_temp = config.filament_enable_toolchange_temp.get_at(idx); // skinnydip - m_filpar[idx].filament_toolchange_temp = config.filament_toolchange_temp.get_at(idx); // skinnydip - m_filpar[idx].filament_enable_toolchange_part_fan = config.filament_enable_toolchange_part_fan.get_at(idx); // skinnydip - m_filpar[idx].filament_toolchange_part_fan_speed = config.filament_toolchange_part_fan_speed.get_at(idx); // skinnydip - m_filpar[idx].filament_use_skinnydip = config.filament_use_skinnydip.get_at(idx); // skinnydip - m_filpar[idx].filament_use_fast_skinnydip = config.filament_use_fast_skinnydip.get_at(idx); // skinnydip - m_filpar[idx].filament_skinnydip_distance = float(config.filament_skinnydip_distance.get_at(idx)); // skinnydip - m_filpar[idx].filament_melt_zone_pause = config.filament_melt_zone_pause.get_at(idx); // skinnydip - m_filpar[idx].filament_cooling_zone_pause = config.filament_cooling_zone_pause.get_at(idx); // skinnydip - m_filpar[idx].filament_dip_insertion_speed = float(config.filament_dip_insertion_speed.get_at(idx)); // skinnydip - m_filpar[idx].filament_dip_extraction_speed = float(config.filament_dip_extraction_speed.get_at(idx));// skinnydip + m_filpar[idx].filament_enable_toolchange_temp = m_config->filament_enable_toolchange_temp.get_at(idx); // skinnydip + m_filpar[idx].filament_toolchange_temp = m_config->filament_toolchange_temp.get_at(idx); // skinnydip + m_filpar[idx].filament_enable_toolchange_part_fan = m_config->filament_enable_toolchange_part_fan.get_at(idx); // skinnydip + m_filpar[idx].filament_toolchange_part_fan_speed = m_config->filament_toolchange_part_fan_speed.get_at(idx); // skinnydip + m_filpar[idx].filament_use_skinnydip = m_config->filament_use_skinnydip.get_at(idx); // skinnydip + m_filpar[idx].filament_use_fast_skinnydip = m_config->filament_use_fast_skinnydip.get_at(idx); // skinnydip + m_filpar[idx].filament_skinnydip_distance = float(m_config->filament_skinnydip_distance.get_at(idx)); // skinnydip + m_filpar[idx].filament_melt_zone_pause = m_config->filament_melt_zone_pause.get_at(idx); // skinnydip + m_filpar[idx].filament_cooling_zone_pause = m_config->filament_cooling_zone_pause.get_at(idx); // skinnydip + m_filpar[idx].filament_dip_insertion_speed = float(m_config->filament_dip_insertion_speed.get_at(idx)); // skinnydip + m_filpar[idx].filament_dip_extraction_speed = float(m_config->filament_dip_extraction_speed.get_at(idx));// skinnydip //end_skinnydip } - m_filpar[idx].filament_area = float((M_PI/4.f) * pow(config.filament_diameter.get_at(idx), 2)); // all extruders are assumed to have the same filament diameter at this point - float nozzle_diameter = float(config.nozzle_diameter.get_at(idx)); + m_filpar[idx].filament_area = float((M_PI/4.f) * pow(m_config->filament_diameter.get_at(idx), 2)); // all extruders are assumed to have the same filament diameter at this point + float nozzle_diameter = float(m_config->nozzle_diameter.get_at(idx)); m_filpar[idx].nozzle_diameter = nozzle_diameter; // to be used in future with (non-single) multiextruder MM - float max_vol_speed = float(config.filament_max_volumetric_speed.get_at(idx)); + float max_vol_speed = float(m_config->filament_max_volumetric_speed.get_at(idx)); if (max_vol_speed!= 0.f) m_filpar[idx].max_e_speed = (max_vol_speed / filament_area()); + m_nozzle_diameter = nozzle_diameter; // all extruders are now assumed to have the same diameter m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter if (m_semm) { - std::istringstream stream{config.filament_ramming_parameters.get_at(idx)}; + std::istringstream stream{m_config->filament_ramming_parameters.get_at(idx)}; float speed = 0.f; stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator; m_filpar[idx].ramming_line_width_multiplicator /= 100; @@ -849,27 +852,24 @@ WipeTower::ToolChangeResult WipeTower::toolchange_Brim(bool sideOnly, float y_of Vec2f::Zero(), m_wipe_tower_width, m_wipe_tower_depth); + double unscaled_brim_width = m_config->wipe_tower_brim.get_abs_value(m_nozzle_diameter); + Slic3r::Flow brim_flow(m_config->first_layer_extrusion_width.get_abs_value(m_nozzle_diameter), m_layer_height, m_nozzle_diameter); - WipeTowerWriter writer(m_layer_height, m_brim_width, m_gcode_flavor, m_filpar); - writer.set_extrusion_flow(m_extrusion_flow * 1.1f) - .set_z(m_z_pos) // Let the writer know the current Z position as a base for Z-hop. - .set_initial_tool(m_current_tool) - .append(";-------------------------------------\n" - "; CP WIPE TOWER FIRST LAYER BRIM START\n"); - - Vec2f initial_position = wipeTower_box.lu - Vec2f(m_brim_width * 6.f, 0); - writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation); - - writer.extrude_explicit(wipeTower_box.ld - Vec2f(m_brim_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); + WipeTowerWriter writer(m_layer_height, brim_flow.width, m_gcode_flavor, m_filpar); + std::cout << "flow from " << (m_extrusion_flow * 1.1f) << " to " << brim_flow.mm3_per_mm() << "\n"; + writer.set_extrusion_flow(brim_flow.mm3_per_mm()) + .set_z(m_z_pos) // Let the writer know the current Z position as a base for Z-hop. + .set_initial_tool(m_current_tool) + .append(";-------------------------------------\n" + "; CP WIPE TOWER FIRST LAYER BRIM START\n"); // 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. + // Extrude X rounds of a brim around the future wipe tower. box_coordinates box(wipeTower_box); + box.expand(brim_flow.spacing()- brim_flow.width); // ensure that the brim is attached to the wipe tower // the brim shall have 'normal' spacing with no extra void space - float spacing = m_brim_width - m_layer_height*float(1.-M_PI_4); - for (size_t i = 0; i < 4; ++ i) { - box.expand(spacing); + for (float i = 0; i < unscaled_brim_width; i += brim_flow.spacing()) { + box.expand(brim_flow.spacing()); writer.travel (box.ld, 7000) .extrude(box.lu, 2100).extrude(box.ru) .extrude(box.rd ).extrude(box.ld); @@ -883,7 +883,7 @@ WipeTower::ToolChangeResult WipeTower::toolchange_Brim(bool sideOnly, float y_of // Save actual brim width to be later passed to the Print object, which will use it // for skirt calculation and pass it to GLCanvas for precise preview box - m_wipe_tower_brim_width = wipeTower_box.ld.x() - box.ld.x() + spacing/2.f; + m_wipe_tower_brim_width = wipeTower_box.ld.x() - box.ld.x() + brim_flow.spacing() /2.f; m_print_brim = false; // Mark the brim as extruded diff --git a/src/libslic3r/GCode/WipeTower.hpp b/src/libslic3r/GCode/WipeTower.hpp index e6651a6da77..18689eee04e 100644 --- a/src/libslic3r/GCode/WipeTower.hpp +++ b/src/libslic3r/GCode/WipeTower.hpp @@ -84,7 +84,7 @@ class WipeTower WipeTower(const PrintConfig& config, const std::vector>& wiping_matrix, size_t initial_tool); // Set the extruder properties. - void set_extruder(size_t idx, const PrintConfig& config); + void set_extruder(size_t idx); // Appends into internal structure m_plan containing info about the future wipe tower // to be used before building begins. The entries must be added ordered in z. @@ -216,7 +216,7 @@ class WipeTower return m_filpar[0].filament_area; // all extruders are assumed to have the same filament diameter at this point } - + const PrintConfig *m_config; bool m_semm = true; // Are we using a single extruder multimaterial printer? Vec2f m_wipe_tower_pos; // Left front corner of the wipe tower in mm. float m_wipe_tower_width; // Width of the wipe tower. @@ -250,8 +250,8 @@ class WipeTower float m_bed_width; // width of the bed bounding box Vec2f m_bed_bottom_left; // bottom-left corner coordinates (for rectangular beds) + float m_nozzle_diameter = 0.4f; float m_perimeter_width = 0.4f * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. - float m_brim_width = 0.4f * Width_To_Nozzle_Ratio * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. float m_extrusion_flow = 0.038f; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. // Extruder specific parameters. diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 1bc130cc4bb..58bbbfa0040 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -234,7 +234,8 @@ bool Print::invalidate_state_by_config_options(const std::vector(this)->m_wipe_tower_data.depth = (900.f/width) * float(extruders_cnt - 1); - const_cast(this)->m_wipe_tower_data.brim_width = 4.5f * brim_spacing; + const_cast(this)->m_wipe_tower_data.brim_width = unscaled_brim_width; } return m_wipe_tower_data; @@ -2457,8 +2458,7 @@ void Print::_make_wipe_tower() // Set the extruder & material properties at the wipe tower object. for (size_t i = 0; i < number_of_extruders; ++i) - - wipe_tower.set_extruder(i, m_config); + wipe_tower.set_extruder(i); m_wipe_tower_data.priming = Slic3r::make_unique>( wipe_tower.prime((float)this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false)); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index e27849ad3da..a5c27d97639 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3206,6 +3206,12 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionEnum(waLinear)); + def = this->add("wipe_tower_brim", coFloatOrPercent); + def->label = L("Wipe tower brim width"); + def->tooltip = L("Width of the brim for the wipe tower. Can be in mm of in % of the (assumed) only one nozzle diameter."); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(150,true)); + def = this->add("wipe_tower_x", coFloat); def->label = L("X"); def->full_label = L("Wipe tower X"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 5ba6b096d35..bde272d3b1a 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1029,6 +1029,7 @@ class PrintConfig : public MachineEnvelopeConfig, public GCodeConfig ConfigOptionInts top_fan_speed; ConfigOptionBools wipe; ConfigOptionBool wipe_tower; + ConfigOptionFloatOrPercent wipe_tower_brim; ConfigOptionFloat wipe_tower_x; ConfigOptionFloat wipe_tower_y; ConfigOptionFloat wipe_tower_width; @@ -1108,6 +1109,7 @@ class PrintConfig : public MachineEnvelopeConfig, public GCodeConfig OPT_PTR(top_fan_speed); OPT_PTR(wipe); OPT_PTR(wipe_tower); + OPT_PTR(wipe_tower_brim); OPT_PTR(wipe_tower_x); OPT_PTR(wipe_tower_y); OPT_PTR(wipe_tower_width); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 108330795e7..58fc8322ac2 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -403,7 +403,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field("standby_temperature_delta", have_ooze_prevention); bool have_wipe_tower = config->opt_bool("wipe_tower"); - for (auto el : { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging" }) + for (auto el : { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "wipe_tower_brim" }) toggle_field(el, have_wipe_tower); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 97f5a43b50b..eff186f9850 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2040,7 +2040,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) "duplicate_distance", "extruder_clearance_radius", "skirts", "skirt_distance", "brim_width", "variable_layer_height", "serial_port", "serial_speed", "host_type", "print_host", "printhost_apikey", "printhost_cafile", "nozzle_diameter", "single_extruder_multi_material", - "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", + "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim", "extruder_colour", "filament_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", diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index f011770e2a6..4bc0e26a09a 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -496,6 +496,7 @@ const std::vector& Preset::print_options() "hole_to_polyhole", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", + "wipe_tower_brim", "single_extruder_multi_material_priming", "wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits",