ENH: Increase TPU printing speed.

1.add parameters precooling_temperature, ramming ravel time,prime_tower
max speed , ramming_vol_speed;
2.support modify the wipe tower wipe and lift speed

jira: none
Change-Id: Ic9661e514ef0d4e4c0dcebb5e56f0c962e6c7b9a
This commit is contained in:
jiangkai.zhao 2025-03-14 10:56:33 +08:00 committed by lane.wei
parent ee76a2191f
commit d6fc36daba
13 changed files with 229 additions and 85 deletions

View File

@ -363,6 +363,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
double wipe_speed = gcodegen.config().role_base_wipe_speed && cur_speed > EPSILON ? cur_speed / 60 :
gcodegen.writer().config.travel_speed.get_at(get_extruder_index(gcodegen.writer().config, gcodegen.writer().filament()->id())) * gcodegen.config().wipe_speed.value / 100;
if (toolchange) { wipe_speed = gcodegen.m_print->config().prime_tower_max_speed.value; }
// get the retraction length
double length = toolchange
@ -899,7 +900,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
gcodegen.m_wipe.reset_path();
for (const Vec2f& wipe_pt : tcr.wipe_path)
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, transform_wt_pt(wipe_pt) + plate_origin_2d));
gcode += gcodegen.retract(false, false, auto_lift_type, true);
gcode += gcodegen.retract(true, false, auto_lift_type, true);
}
// Let the planner know we are traveling between objects.
@ -5961,9 +5962,9 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType li
if (m_writer.filament()->retraction_length() > 0 || m_config.use_firmware_retraction) {
// BBS: force to use normal lift for spiral vase mode
if (apply_instantly)
gcode += m_writer.eager_lift(lift_type);
gcode += m_writer.eager_lift(lift_type,toolchange);
else
gcode += m_writer.lazy_lift(lift_type, m_spiral_vase != nullptr);
gcode += m_writer.lazy_lift(lift_type, m_spiral_vase != nullptr, toolchange);
}

View File

@ -20,9 +20,11 @@ float flat_iron_area = 4.f;
constexpr float flat_iron_speed = 10.f * 60.f;
static const double wipe_tower_wall_infill_overlap = 0.0;
static constexpr double WIPE_TOWER_RESOLUTION = 0.1;
static constexpr double WT_SIMPLIFY_TOLERANCE_SCALED = 0.001 / SCALING_FACTOR;
static constexpr double WT_SIMPLIFY_TOLERANCE_SCALED = 0.001 / SCALING_FACTOR;
static constexpr int arc_fit_size = 20;
#define SCALED_WIPE_TOWER_RESOLUTION (WIPE_TOWER_RESOLUTION / SCALING_FACTOR)
enum class LimitFlow { None, LimitPrintFlow, LimitRammingFlow };
inline float align_round(float value, float base)
{
return std::round(value / base) * base;
@ -638,7 +640,7 @@ public:
float get_and_reset_used_filament_length() { float temp = m_used_filament_length; m_used_filament_length = 0.f; return temp; }
// Extrude with an explicitely provided amount of extrusion.
WipeTowerWriter& extrude_explicit(float x, float y, float e, float f = 0.f, bool record_length = false, bool limit_volumetric_flow = true)
WipeTowerWriter &extrude_explicit(float x, float y, float e, float f = 0.f, bool record_length = false ,LimitFlow limit_flow = LimitFlow::LimitPrintFlow)
{
if ((std::abs(x - m_current_pos.x()) <= (float)EPSILON) && (std::abs(y - m_current_pos.y()) < (float)EPSILON) && e == 0.f && (f == 0.f || f == m_current_feedrate))
// Neither extrusion nor a travel move.
@ -680,9 +682,11 @@ public:
m_gcode += set_format_E(e);
if (f != 0.f && f != m_current_feedrate) {
if (limit_volumetric_flow) {
if (limit_flow!= LimitFlow::None) {
float e_speed = e / (((len == 0.f) ? std::abs(e) : len) / f * 60.f);
f /= std::max(1.f, e_speed / m_filpar[m_current_tool].max_e_speed);
float tmp = m_filpar[m_current_tool].max_e_speed;
if (limit_flow == LimitFlow::LimitRammingFlow) tmp = m_filpar[m_current_tool].max_e_ramming_speed;
f /= std::max(1.f, e_speed / tmp);
}
m_gcode += set_format_F(f);
}
@ -697,7 +701,7 @@ public:
}
// Extrude with an explicitely provided amount of extrusion.
WipeTowerWriter &extrude_arc_explicit(ArcSegment &arc, float f = 0.f, bool record_length = false, bool limit_volumetric_flow = true)
WipeTowerWriter &extrude_arc_explicit(ArcSegment &arc, float f = 0.f, bool record_length = false, LimitFlow limit_flow = LimitFlow::LimitPrintFlow)
{
float x = (float)unscale(arc.end_point).x();
float y = (float)unscale(arc.end_point).y();
@ -747,9 +751,11 @@ public:
if (e != 0.f) m_gcode += set_format_E(e);
if (f != 0.f && f != m_current_feedrate) {
if (limit_volumetric_flow) {
if (limit_flow != LimitFlow::None) {
float e_speed = e / (((len == 0.f) ? std::abs(e) : len) / f * 60.f);
f /= std::max(1.f, e_speed / m_filpar[m_current_tool].max_e_speed);
float tmp = m_filpar[m_current_tool].max_e_speed;
if (limit_flow == LimitFlow::LimitRammingFlow) tmp = m_filpar[m_current_tool].max_e_ramming_speed;
f /= std::max(1.f, e_speed / tmp);
}
m_gcode += set_format_F(f);
}
@ -763,8 +769,10 @@ public:
return *this;
}
WipeTowerWriter& extrude_explicit(const Vec2f &dest, float e, float f = 0.f, bool record_length = false, bool limit_volumetric_flow = true)
{ return extrude_explicit(dest.x(), dest.y(), e, f, record_length); }
WipeTowerWriter &extrude_explicit(const Vec2f &dest, float e, float f = 0.f, bool record_length = false, LimitFlow limit_flow = LimitFlow::LimitPrintFlow)
{
return extrude_explicit(dest.x(), dest.y(), e, f, record_length, limit_flow);
}
// Travel to a new XY position. f=0 means use the current value.
WipeTowerWriter& travel(float x, float y, float f = 0.f)
@ -774,15 +782,15 @@ public:
{ return extrude_explicit(dest.x(), dest.y(), 0.f, f); }
// Extrude a line from current position to x, y with the extrusion amount given by m_extrusion_flow.
WipeTowerWriter& extrude(float x, float y, float f = 0.f)
WipeTowerWriter &extrude(float x, float y, float f = 0.f, LimitFlow limit_flow = LimitFlow::LimitPrintFlow)
{
float dx = x - m_current_pos.x();
float dy = y - m_current_pos.y();
return extrude_explicit(x, y, std::sqrt(dx*dx+dy*dy) * m_extrusion_flow, f, true);
return extrude_explicit(x, y, std::sqrt(dx * dx + dy * dy) * m_extrusion_flow, f, false, limit_flow);
}
WipeTowerWriter &extrude_arc(ArcSegment &arc, float f = 0.f)
WipeTowerWriter &extrude_arc(ArcSegment &arc, float f = 0.f, LimitFlow limit_flow = LimitFlow::LimitPrintFlow)
{
return extrude_arc_explicit(arc, f, true);
return extrude_arc_explicit(arc, f, false , limit_flow);
}
WipeTowerWriter& extrude(const Vec2f &dest, const float f = 0.f)
@ -968,7 +976,7 @@ public:
}
float end_point = x() + (farthest_x > x() ? 1.f : -1.f) * x_distance;
return extrude_explicit(end_point, y(), loading_dist, x_speed * 60.f, false, false);
return extrude_explicit(end_point, y(), loading_dist, x_speed * 60.f, false, LimitFlow::None);
}
// Elevate the extruder head above the current print_z position.
@ -989,8 +997,8 @@ public:
// extrude quickly amount e to x2 with feed f.
WipeTowerWriter& ram(float x1, float x2, float dy, float e0, float e, float f)
{
extrude_explicit(x1, m_current_pos.y() + dy, e0, f, true, false);
extrude_explicit(x2, m_current_pos.y(), e, 0.f, true, false);
extrude_explicit(x1, m_current_pos.y() + dy, e0, f, true, LimitFlow::None);
extrude_explicit(x2, m_current_pos.y(), e, 0.f, true, LimitFlow::None);
return *this;
}
@ -999,8 +1007,8 @@ public:
// at the current Y position to spread the leaking material.
WipeTowerWriter& cool(float x1, float x2, float e1, float e2, float f)
{
extrude_explicit(x1, m_current_pos.y(), e1, f, false, false);
extrude_explicit(x2, m_current_pos.y(), e2, false, false);
extrude_explicit(x1, m_current_pos.y(), e1, f, false, LimitFlow::None);
extrude_explicit(x2, m_current_pos.y(), e2, 0.f, false, LimitFlow::None);
return *this;
}
@ -1507,7 +1515,8 @@ WipeTower::WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origi
m_rib_width((float)config.prime_tower_rib_width.value),
m_used_fillet(config.prime_tower_fillet_wall.value),
m_extra_spacing((float)config.prime_tower_infill_gap.value/100.f),
m_tower_framework(config.prime_tower_enable_framework.value)
m_tower_framework(config.prime_tower_enable_framework.value),
m_max_speed((float)config.prime_tower_max_speed.value*60.f)
{
// Read absolute value of first layer speed, if given as percentage,
// it is taken over following default. Speeds from config are not
@ -1592,6 +1601,24 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config)
if (max_vol_speed!= 0.f)
m_filpar[idx].max_e_speed = (max_vol_speed / filament_area());
float ramming_vol_speed = float(config.filament_ramming_volumetric_speed.get_at(idx));
if (config.filament_ramming_volumetric_speed.is_nil(idx) || is_approx(config.filament_ramming_volumetric_speed.get_at(idx),-1.)) ramming_vol_speed = max_vol_speed;
m_filpar[idx].max_e_ramming_speed = (ramming_vol_speed / filament_area());
std::unordered_set<int> uniqueElements(m_filament_map.begin(), m_filament_map.end());
m_filpar[idx].precool_t.resize(uniqueElements.size(), 0.f);
m_filpar[idx].precool_t_first_layer.resize(uniqueElements.size(), 0.f);
if (config.enable_pre_heating.value && !config.filament_pre_cooling_temperature.is_nil(idx) && config.filament_pre_cooling_temperature.get_at(idx) != 0) {
for (int i = 0; i < m_filpar[idx].precool_t.size(); i++) {
m_filpar[idx].precool_t[i] = std::max(0.f, float(config.nozzle_temperature.get_at(idx)) - float(config.filament_pre_cooling_temperature.get_at(idx))) /
float(config.hotend_cooling_rate.values.at(i));
m_filpar[idx].precool_t_first_layer[i] = std::max(0.f, float(config.nozzle_temperature_initial_layer.get_at(idx)) -
float(config.filament_pre_cooling_temperature.get_at(idx))) /
float(config.hotend_cooling_rate.values.at(i));
}
}
if (!config.filament_ramming_travel_time.is_nil(idx))
m_filpar[idx].ramming_travel_time = float(config.filament_ramming_travel_time.get_at(idx));
m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter
m_nozzle_change_perimeter_width = 2*m_perimeter_width;
// BBS: remove useless config
@ -2507,7 +2534,7 @@ void WipeTower::plan_toolchange(float z_par, float layer_height_par, unsigned in
double e_flow = nozzle_change_extrusion_flow(layer_height_par);
double length = m_filaments_change_length[old_tool] / e_flow;
int nozzle_change_line_count = length / (m_wipe_tower_width - 2*m_nozzle_change_perimeter_width) + 1;
if (has_tpu_filament())
if (m_need_reverse_travel)
nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_nozzle_change_perimeter_width;
else
nozzle_change_depth = nozzle_change_line_count * m_nozzle_change_perimeter_width;
@ -2643,6 +2670,11 @@ bool WipeTower::is_tpu_filament(int filament_id) const
return m_filpar[filament_id].material == "TPU";
}
bool WipeTower::is_need_reverse_travel(int filament_id) const
{
return m_filpar[filament_id].ramming_travel_time > EPSILON;
}
// BBS: consider both soluable and support properties
// Return index of first toolchange that switches to non-soluble and non-support extruder
// ot -1 if there is no such toolchange.
@ -2655,14 +2687,13 @@ int WipeTower::first_toolchange_to_nonsoluble_nonsupport(
return -1;
}
static WipeTower::ToolChangeResult merge_tcr(WipeTower::ToolChangeResult& first,
WipeTower::ToolChangeResult& second)
WipeTower::ToolChangeResult WipeTower::merge_tcr(ToolChangeResult &first, ToolChangeResult &second)
{
assert(first.new_tool == second.initial_tool);
WipeTower::ToolChangeResult out = first;
if ((first.end_pos - second.start_pos).norm() > (float)EPSILON) {
std::string travel_gcode = "G1 X" + Slic3r::float_to_string_decimal_point(second.start_pos.x(), 3)
+ " Y" + Slic3r::float_to_string_decimal_point(second.start_pos.y(), 3) +"F5400" + "\n";
std::string travel_gcode = "G1 X" + Slic3r::float_to_string_decimal_point(second.start_pos.x(), 3) + " Y" +
Slic3r::float_to_string_decimal_point(second.start_pos.y(), 3) + "F" + std::to_string(m_max_speed) + "\n";
bool need_insert_travel = true;
if (second.is_tool_change
&& is_approx(second.start_pos.x(), second.tool_change_start_pos.x())
@ -2712,7 +2743,7 @@ void WipeTower::get_wall_skip_points(const WipeTowerInfo &layer)
size_t old_filament = tool_change.old_tool;
size_t new_filament = tool_change.new_tool;
float spacing = m_layer_info->extra_spacing;
if (has_tpu_filament() && m_layer_info->extra_spacing < m_tpu_fixed_spacing) spacing = 1;
if (m_need_reverse_travel && m_layer_info->extra_spacing < m_tpu_fixed_spacing) spacing = 1;
float nozzle_change_depth = tool_change.nozzle_change_depth * spacing;
//float nozzle_change_depth = tool_change.nozzle_change_depth * (has_tpu_filament() ? m_tpu_fixed_spacing : layer.extra_spacing);
auto* block = get_block_by_category(m_filpar[new_filament].category, false);
@ -2775,7 +2806,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool, bool sol
wipe_depth = b.required_depth;
purge_volume = b.purge_volume;
nozzle_change_depth = b.nozzle_change_depth;
if (has_tpu_filament())
if (m_need_reverse_travel)
nozzle_change_line_count = ((b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width) / 2;
else
nozzle_change_line_count = (b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width;
@ -2817,8 +2848,8 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool, bool sol
is_first_layer() ? m_filpar[new_tool].nozzle_temperature_initial_layer : m_filpar[new_tool].nozzle_temperature);
toolchange_Change(writer, new_tool, m_filpar[new_tool].material); // Change the tool, set a speed override for soluble and flex materials.
toolchange_Load(writer, cleaning_box);
if (m_is_multi_extruder && is_tpu_filament(new_tool)) {
# if 0
if (m_is_multi_extruder && is_need_reverse_travel(new_tool)) {
float dy = m_layer_info->extra_spacing * m_nozzle_change_perimeter_width;
if (m_layer_info->extra_spacing < m_tpu_fixed_spacing) {
dy = m_tpu_fixed_spacing * m_nozzle_change_perimeter_width;
@ -2849,7 +2880,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool, bool sol
}
writer.travel(initial_position);
}
#endif
toolchange_wipe_new(writer, cleaning_box, wipe_length, solid_toolchange);
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Tower_End) + "\n");
@ -2882,14 +2913,13 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
if (new_filament_id != (unsigned int) (-1)) {
for (const auto &b : m_layer_info->tool_changes)
if (b.new_tool == new_filament_id) {
if (has_tpu_filament())
if (m_need_reverse_travel)
nozzle_change_line_count = ((b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width) / 2;
else
nozzle_change_line_count = (b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width;
break;
}
}
auto format_nozzle_change_line = [](bool start, int old_filament_id, int new_filament_id) -> std::string {
char buff[64];
std::string tag = start ? GCodeProcessor::reserved_tag(GCodeProcessor::ETags::NozzleChangeStart) : GCodeProcessor::reserved_tag(GCodeProcessor::ETags::NozzleChangeEnd);
@ -2898,13 +2928,11 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
};
float nz_extrusion_flow = nozzle_change_extrusion_flow(m_layer_height);
float nozzle_change_speed = 60.0f * m_filpar[m_current_tool].max_e_speed / nz_extrusion_flow;
nozzle_change_speed = solid_infill ? 40.f * 60.f : nozzle_change_speed;//If the contact layers belong to different categories, then reduce the speed.
float nozzle_change_speed = 60.0f * m_filpar[m_current_tool].max_e_ramming_speed / nz_extrusion_flow;
if (solid_infill)
nozzle_change_speed = std::min( 40.f * 60.f , nozzle_change_speed);//If the contact layers belong to different categories, then reduce the speed.
if (is_tpu_filament(m_current_tool)) {
nozzle_change_speed *= 0.25;
}
float bridge_speed = std::min(60.0f * m_filpar[m_current_tool].max_e_speed / nozzle_change_extrusion_flow(0.2), nozzle_change_speed); // limit the bridge speed by add flow
float bridge_speed = std::min(60.0f * m_filpar[m_current_tool].max_e_ramming_speed / nozzle_change_extrusion_flow(0.2), nozzle_change_speed); // limit the bridge speed by add flow
WipeTowerWriter writer(m_layer_height, m_nozzle_change_perimeter_width, m_gcode_flavor, m_filpar);
writer.set_extrusion_flow(nz_extrusion_flow)
@ -2920,13 +2948,13 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
}
m_cur_block = block;
float dy = m_layer_info->extra_spacing * m_nozzle_change_perimeter_width;
if (has_tpu_filament() && m_extra_spacing < m_tpu_fixed_spacing)
if (m_need_reverse_travel && m_extra_spacing < m_tpu_fixed_spacing)
dy = m_tpu_fixed_spacing * m_nozzle_change_perimeter_width;
float x_offset = m_perimeter_width + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2;
box_coordinates cleaning_box(Vec2f(x_offset,block->cur_depth + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2),
m_wipe_tower_width - 2 * x_offset,
nozzle_change_line_count * dy - (m_nozzle_change_perimeter_width - m_perimeter_width) / 2);
nozzle_change_line_count * dy - (m_nozzle_change_perimeter_width - m_perimeter_width) / 2);//top can not print
Vec2f initial_position = cleaning_box.ld;
writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation);
@ -2934,10 +2962,20 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
const float &xl = cleaning_box.ld.x();
const float &xr = cleaning_box.rd.x();
dy = solid_infill ? m_nozzle_change_perimeter_width : dy;
nozzle_change_line_count = solid_infill ? std::numeric_limits<int>::max() : nozzle_change_line_count;
if (solid_infill)
nozzle_change_line_count = std::floor(EPSILON + (cleaning_box.ru[1] - cleaning_box.rd[1] + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2.f) /
m_nozzle_change_perimeter_width);
m_left_to_right = true;
int real_nozzle_change_line_count = 0;
bool need_change_flow = false;
float ramming_length = nozzle_change_line_count * (xr - xl);
int extruder_id = m_filament_map[m_current_tool]-1;
float per_cooling_max_speed = m_filpar[m_current_tool].precool_t[extruder_id] > EPSILON ? ramming_length / m_filpar[m_current_tool].precool_t[extruder_id] * 60.f :
nozzle_change_speed;
if (is_first_layer())
per_cooling_max_speed = m_filpar[m_current_tool].precool_t_first_layer[extruder_id] > EPSILON ? ramming_length / m_filpar[m_current_tool].precool_t_first_layer[extruder_id] * 60.f :
nozzle_change_speed;
if (nozzle_change_speed > per_cooling_max_speed) nozzle_change_speed = per_cooling_max_speed;
if (bridge_speed > per_cooling_max_speed) bridge_speed = per_cooling_max_speed;
for (int i = 0; true; ++i) {
if (need_thick_bridge_flow(writer.pos().y())) {
writer.set_extrusion_flow(nozzle_change_extrusion_flow(0.2));
@ -2945,10 +2983,9 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
need_change_flow = true;
}
if (m_left_to_right)
writer.extrude(xr + wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), need_change_flow ? bridge_speed : nozzle_change_speed);
writer.extrude(xr + wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), need_change_flow ? bridge_speed : nozzle_change_speed,LimitFlow::LimitRammingFlow);
else
writer.extrude(xl - wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), need_change_flow ? bridge_speed : nozzle_change_speed);
real_nozzle_change_line_count++;
writer.extrude(xl - wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), need_change_flow ? bridge_speed : nozzle_change_speed,LimitFlow::LimitRammingFlow);
if (i == nozzle_change_line_count - 1)
break;
if ((writer.y() + dy - cleaning_box.ru.y()+(m_nozzle_change_perimeter_width+m_perimeter_width)/2) > (float)EPSILON) break;
@ -2957,29 +2994,40 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) + std::to_string(m_layer_height) + "\n");
need_change_flow = false;
}
writer.extrude(writer.x(), writer.y() + dy, nozzle_change_speed);
writer.extrude(writer.x(), writer.y() + dy, nozzle_change_speed, LimitFlow::LimitRammingFlow);
m_left_to_right = !m_left_to_right;
}
if (need_change_flow) {
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) + std::to_string(m_layer_height) + "\n");
}
writer.set_extrusion_flow(nz_extrusion_flow); // Reset the extrusion flow.
block->cur_depth += real_nozzle_change_line_count * dy;
block->cur_depth += nozzle_change_line_count * dy;
block->last_nozzle_change_id = old_filament_id;
NozzleChangeResult result;
if (is_tpu_filament(m_current_tool)) {
if (is_need_reverse_travel(m_current_tool)) {
bool left_to_right = !m_left_to_right;
int tpu_line_count = (real_nozzle_change_line_count + 2 - 1) / 2; // nozzle_change_line_count / 2 round up
nozzle_change_speed *= 2;
int tpu_line_count = nozzle_change_line_count - 1 ; // nozzle_change_line_count / 2 round up
if (tpu_line_count <= 0) tpu_line_count = 1;
nozzle_change_speed *= 2; // due to nozzle change 2 perimeter
float need_reverse_travel_dis = m_filpar[m_current_tool].ramming_travel_time * nozzle_change_speed/60.f;
float real_travel_dis = tpu_line_count * (xr - xl - 2 * m_perimeter_width);
if (real_travel_dis < need_reverse_travel_dis)
nozzle_change_speed *= real_travel_dis / need_reverse_travel_dis;
writer.travel(writer.x(), writer.y() - m_nozzle_change_perimeter_width);
for (int i = 0; true; ++i) {
need_reverse_travel_dis -= (xr - xl - 2 * m_perimeter_width);
float offset_dis = 0.f;
if (need_reverse_travel_dis < 0) {
offset_dis = -need_reverse_travel_dis;
}
if (left_to_right)
writer.travel(xr - m_perimeter_width, writer.y(), nozzle_change_speed);
writer.travel(xr - m_perimeter_width - offset_dis, writer.y(), nozzle_change_speed);
else
writer.travel(xl + m_perimeter_width, writer.y(), nozzle_change_speed);
writer.travel(xl + m_perimeter_width + offset_dis , writer.y(), nozzle_change_speed);
if (need_reverse_travel_dis < EPSILON) break;
if (i == tpu_line_count - 1)
break;
@ -3020,7 +3068,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer_new(bool extrude_perimeter,
// Slow down on the 1st layer.
bool first_layer = is_first_layer();
// BBS: speed up perimeter speed to 90mm/s for non-first layer
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, 5400.f) : std::min(60.0f * m_filpar[m_current_tool].max_e_speed / m_extrusion_flow, 5400.f);
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, m_max_speed) : std::min(60.0f * m_filpar[m_current_tool].max_e_speed / m_extrusion_flow, m_max_speed);
float fill_box_depth = m_wipe_tower_depth - 2 * m_perimeter_width;
if (m_wipe_tower_blocks.size() == 1) {
@ -3191,7 +3239,7 @@ WipeTower::ToolChangeResult WipeTower::finish_block(const WipeTowerBlock &block,
// Slow down on the 1st layer.
bool first_layer = is_first_layer();
// BBS: speed up perimeter speed to 90mm/s for non-first layer
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, 5400.f) : std::min(60.0f * m_filpar[filament_id].max_e_speed / m_extrusion_flow, 5400.f);
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, m_max_speed) : std::min(60.0f * m_filpar[filament_id].max_e_speed / m_extrusion_flow, m_max_speed);
box_coordinates fill_box(Vec2f(0, 0), 0, 0);
fill_box = box_coordinates(Vec2f(m_perimeter_width, block.cur_depth), m_wipe_tower_width - 2 * m_perimeter_width, block.start_depth + block.layer_depths[m_cur_layer_id] - block.cur_depth - m_perimeter_width);
@ -3305,7 +3353,7 @@ WipeTower::ToolChangeResult WipeTower::finish_block_solid(const WipeTowerBlock &
// Slow down on the 1st layer.
bool first_layer = is_first_layer();
// BBS: speed up perimeter speed to 90mm/s for non-first layer
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, 5400.f) : std::min(60.0f * m_filpar[filament_id].max_e_speed / m_extrusion_flow, 5400.f);
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, m_max_speed) : std::min(60.0f * m_filpar[filament_id].max_e_speed / m_extrusion_flow, m_max_speed);
feedrate = interface_solid ? 20.f * 60.f : feedrate;
box_coordinates fill_box(Vec2f(0, 0), 0, 0);
fill_box = box_coordinates(Vec2f(m_perimeter_width, block.cur_depth), m_wipe_tower_width - 2 * m_perimeter_width,
@ -3688,7 +3736,7 @@ void WipeTower::plan_tower_new()
double e_flow = nozzle_change_extrusion_flow(m_plan[idx].height);
double length = m_filaments_change_length[toolchange.old_tool] / e_flow;
int nozzle_change_line_count = length / (m_wipe_tower_width - 2*m_nozzle_change_perimeter_width) + 1;
if (has_tpu_filament())
if (m_need_reverse_travel)
nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_nozzle_change_perimeter_width;
else
nozzle_change_depth = nozzle_change_line_count * m_nozzle_change_perimeter_width;
@ -4163,7 +4211,7 @@ WipeTower::ToolChangeResult WipeTower::only_generate_out_wall(bool is_new_mode)
// Slow down on the 1st layer.
bool first_layer = is_first_layer();
// BBS: speed up perimeter speed to 90mm/s for non-first layer
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, 5400.f) : std::min(60.0f * m_filpar[m_current_tool].max_e_speed / m_extrusion_flow, 5400.f);
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, m_max_speed) : std::min(60.0f * m_filpar[m_current_tool].max_e_speed / m_extrusion_flow, m_max_speed);
float fill_box_y = m_layer_info->toolchanges_depth() + m_perimeter_width;
box_coordinates fill_box(Vec2f(m_perimeter_width, fill_box_y), m_wipe_tower_width - 2 * m_perimeter_width, m_layer_info->depth - fill_box_y);

View File

@ -302,6 +302,15 @@ public:
void set_filament_map(const std::vector<int> &filament_map) { m_filament_map = filament_map; }
void set_has_tpu_filament(bool has_tpu) { m_has_tpu_filament = has_tpu; }
void set_need_reverse_travel() {
for (int i = 0; i < m_filpar.size(); i++) {
if(m_filpar[i].ramming_travel_time>EPSILON)
{
m_need_reverse_travel = true;
return;
}
}
}
bool has_tpu_filament() const { return m_has_tpu_filament; }
struct FilamentParameters {
@ -330,6 +339,10 @@ public:
float retract_length;
float retract_speed;
float wipe_dist;
float max_e_ramming_speed = 0.f;
float ramming_travel_time=0.f; //Travel time after ramming
std::vector<float> precool_t;//Pre-cooling time, set to 0 to ensure the ramming speed is controlled solely by ramming volumetric speed.
std::vector<float> precool_t_first_layer;
};
@ -433,6 +446,7 @@ private:
bool m_used_fillet{false};
Vec2f m_rib_offset{Vec2f(0.f, 0.f)};
bool m_tower_framework{false};
bool m_need_reverse_travel{false};
// G-code generator parameters.
// BBS: remove useless config
@ -480,6 +494,7 @@ private:
bool m_left_to_right = true;
float m_extra_spacing = 1.f;
float m_tpu_fixed_spacing = 2;
float m_max_speed = 5400.f; // the maximum printing speed on the prime tower.
std::vector<Vec2f> m_wall_skip_points;
std::map<float,Polylines> m_outer_wall;
bool is_first_layer() const { return size_t(m_layer_info - m_plan.begin()) == m_first_layer_idx; }
@ -501,7 +516,7 @@ private:
void save_on_last_wipe();
bool is_tpu_filament(int filament_id) const;
bool is_need_reverse_travel(int filament) const;
// BBS
box_coordinates align_perimeter(const box_coordinates& perimeter_box);
@ -567,6 +582,7 @@ private:
const box_coordinates &cleaning_box,
float wipe_volume);
void get_wall_skip_points(const WipeTowerInfo &layer);
ToolChangeResult merge_tcr(ToolChangeResult &first, ToolChangeResult &second);
};

View File

@ -353,7 +353,7 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com
/* If this method is called more than once before calling unlift(),
it will not perform subsequent lifts, even if Z was raised manually
(i.e. with travel_to_z()) and thus _lifted was reduced. */
std::string GCodeWriter::lazy_lift(LiftType lift_type, bool spiral_vase)
std::string GCodeWriter::lazy_lift(LiftType lift_type, bool spiral_vase, bool tool_change)
{
// check whether the above/below conditions are met
double target_lift = 0;
@ -363,14 +363,16 @@ std::string GCodeWriter::lazy_lift(LiftType lift_type, bool spiral_vase)
int filament_id = filament()->id();
double above = this->config.retract_lift_above.get_at(extruder_id);
double below = this->config.retract_lift_below.get_at(extruder_id);
if (m_pos.z() >= above && m_pos.z() <= below)
if (m_pos.z() >= above && m_pos.z() <= below){
target_lift = this->config.z_hop.get_at(filament_id);
if (tool_change && this->config.prime_tower_lift_height.value > 0) target_lift = this->config.prime_tower_lift_height.value;
}
}
// BBS
if (m_lifted == 0 && m_to_lift == 0 && target_lift > 0) {
if (spiral_vase) {
m_lifted = target_lift;
return this->_travel_to_z(m_pos(2) + target_lift, "lift Z");
return this->_travel_to_z(m_pos(2) + target_lift, "lift Z",tool_change);
}
else {
m_to_lift = target_lift;
@ -382,7 +384,8 @@ std::string GCodeWriter::lazy_lift(LiftType lift_type, bool spiral_vase)
// BBS: immediately execute an undelayed lift move with a spiral lift pattern
// designed specifically for subsequent gcode injection (e.g. timelapse)
std::string GCodeWriter::eager_lift(const LiftType type) {
std::string GCodeWriter::eager_lift(const LiftType type, bool tool_change)
{
std::string lift_move;
double target_lift = 0;
{
@ -391,8 +394,10 @@ std::string GCodeWriter::eager_lift(const LiftType type) {
int filament_id = filament()->id();
double above = this->config.retract_lift_above.get_at(extruder_id);
double below = this->config.retract_lift_below.get_at(extruder_id);
if (m_pos.z() >= above && m_pos.z() <= below)
if (m_pos.z() >= above && m_pos.z() <= below){
target_lift = this->config.z_hop.get_at(filament_id);
if (tool_change && this->config.prime_tower_lift_height.value > 0) target_lift = this->config.prime_tower_lift_height.value;
}
}
// BBS: spiral lift only safe with known position
@ -400,15 +405,15 @@ std::string GCodeWriter::eager_lift(const LiftType type) {
if (type == LiftType::SpiralLift && this->is_current_position_clear()) {
double radius = target_lift / (2 * PI * atan(GCodeWriter::slope_threshold));
// static spiral alignment when no move in x,y plane.
// spiral centra is a radius distance to the right (y=0)
// spiral centra is a radius distance to the right (y=0)
Vec2d ij_offset = { radius, 0 };
if (target_lift > 0) {
lift_move = this->_spiral_travel_to_z(m_pos(2) + target_lift, ij_offset, "spiral lift Z");
lift_move = this->_spiral_travel_to_z(m_pos(2) + target_lift, ij_offset, "spiral lift Z",tool_change);
}
}
//BBS: if position is unknown use normal lift
else if (target_lift > 0) {
lift_move = _travel_to_z(m_pos(2) + target_lift, "normal lift Z");
lift_move = _travel_to_z(m_pos(2) + target_lift, "normal lift Z",tool_change);
}
m_lifted = target_lift;
m_to_lift = 0;
@ -559,14 +564,16 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment)
return this->_travel_to_z(z, comment);
}
std::string GCodeWriter::_travel_to_z(double z, const std::string &comment)
std::string GCodeWriter::_travel_to_z(double z, const std::string &comment, bool tool_change)
{
m_pos(2) = z;
double speed = this->config.travel_speed_z.get_at(get_extruder_index(this->config, filament()->id()));
if (speed == 0.)
speed = this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id()));
if (tool_change && this->config.prime_tower_lift_speed.value>0) {
speed = this->config.prime_tower_lift_speed.value; // lift speed
}
GCodeG1Formatter w;
w.emit_z(z);
w.emit_f(speed * 60.0);
@ -575,14 +582,16 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment)
return w.string();
}
std::string GCodeWriter::_spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment)
std::string GCodeWriter::_spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment, bool tool_change)
{
m_pos(2) = z;
double speed = this->config.travel_speed_z.get_at(get_extruder_index(this->config, filament()->id()));
if (speed == 0.)
speed = this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id()));
if (tool_change && this->config.prime_tower_lift_speed.value>0) {
speed = this->config.prime_tower_lift_speed.value; // lift speed
}
std::string output = "G17\n";
GCodeG2G3Formatter w(true);
w.emit_z(z);

View File

@ -81,9 +81,9 @@ public:
std::string retract_for_toolchange(bool before_wipe = false);
std::string unretract();
// do lift instantly
std::string eager_lift(const LiftType type);
std::string eager_lift(const LiftType type,bool tool_change = false);
// record a lift request, do realy lift in next travel
std::string lazy_lift(LiftType lift_type = LiftType::NormalLift, bool spiral_vase = false);
std::string lazy_lift(LiftType lift_type = LiftType::NormalLift, bool spiral_vase = false, bool tool_change=false);
std::string unlift();
Vec3d get_position() const { return m_pos; }
void set_position(Vec3d& in) { m_pos = in; }
@ -152,8 +152,8 @@ private:
std::string m_gcode_label_objects_start;
std::string m_gcode_label_objects_end;
std::string _travel_to_z(double z, const std::string &comment);
std::string _spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment);
std::string _travel_to_z(double z, const std::string &comment,bool tool_change=false);
std::string _spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment, bool tool_change = false);
std::string _retract(double length, double restart_extra, const std::string &comment);
};

View File

@ -879,8 +879,8 @@ static std::vector<std::string> s_Preset_print_options {
"inner_wall_line_width", "outer_wall_line_width", "sparse_infill_line_width", "internal_solid_infill_line_width",
"top_surface_line_width", "support_line_width", "infill_wall_overlap", "bridge_flow",
"elefant_foot_compensation", "xy_contour_compensation", "xy_hole_compensation", "resolution", "enable_prime_tower", "prime_tower_enable_framework",
"prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points",
"prime_tower_rib_wall","prime_tower_extra_rib_length","prime_tower_rib_width","prime_tower_fillet_wall","prime_tower_infill_gap",
"prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points","prime_tower_max_speed",
"prime_tower_rib_wall","prime_tower_extra_rib_length","prime_tower_rib_width","prime_tower_fillet_wall","prime_tower_infill_gap","prime_tower_lift_speed","prime_tower_lift_height",
"enable_circle_compensation", "circle_compensation_manual_offset", "apply_scarf_seam_on_circles",
"wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits",
"flush_into_infill", "flush_into_objects", "flush_into_support","process_notes",
@ -908,7 +908,7 @@ static std::vector<std::string> s_Preset_print_options {
static std::vector<std::string> s_Preset_filament_options {
/*"filament_colour", */ "default_filament_colour","required_nozzle_HRC","filament_diameter", "filament_type", "filament_soluble", "filament_is_support","filament_scarf_seam_type", "filament_scarf_height", "filament_scarf_gap","filament_scarf_length",
"filament_max_volumetric_speed", "impact_strength_z",
"filament_max_volumetric_speed", "impact_strength_z", "filament_ramming_volumetric_speed",
"filament_flow_ratio", "filament_density", "filament_adhesiveness_category", "filament_cost", "filament_minimal_purge_on_wipe_tower",
"nozzle_temperature", "nozzle_temperature_initial_layer",
// BBS
@ -918,7 +918,7 @@ static std::vector<std::string> s_Preset_filament_options {
"counter_limit_min", "counter_limit_max", "hole_limit_min", "hole_limit_max", "diameter_limit",
// "bed_type",
//BBS:temperature_vitrification
"temperature_vitrification", "reduce_fan_stop_start_freq", "slow_down_for_layer_cooling", "fan_min_speed",
"temperature_vitrification", "reduce_fan_stop_start_freq", "slow_down_for_layer_cooling", "fan_min_speed","filament_ramming_travel_time","filament_pre_cooling_temperature",
"fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "pre_start_fan_time", "overhang_fan_threshold", "overhang_threshold_participating_cooling","close_fan_the_first_x_layers", "full_fan_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed",
"filament_start_gcode", "filament_end_gcode",
//exhaust fan control

View File

@ -258,9 +258,12 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "nozzle_temperature_initial_layer"
|| opt_key == "filament_minimal_purge_on_wipe_tower"
|| opt_key == "filament_max_volumetric_speed"
|| opt_key == "filament_ramming_volumetric_speed"
|| opt_key == "gcode_flavor"
|| opt_key == "single_extruder_multi_material"
|| opt_key == "nozzle_temperature"
|| opt_key == "filament_pre_cooling_temperature"
|| opt_key == "filament_ramming_travel_time"
// BBS
|| opt_key == "supertack_plate_temp"
|| opt_key == "cool_plate_temp"
@ -270,6 +273,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "enable_prime_tower"
|| opt_key == "prime_tower_enable_framework"
|| opt_key == "prime_tower_width"
|| opt_key == "prime_tower_max_speed"
|| opt_key == "prime_tower_lift_speed"
|| opt_key == "prime_tower_lift_height"
|| opt_key == "prime_tower_brim_width"
|| opt_key == "prime_tower_skip_points"
|| opt_key == "prime_tower_rib_wall"
@ -2677,7 +2683,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_need_reverse_travel();
// BBS: remove priming logic
//m_wipe_tower_data.priming = Slic3r::make_unique<std::vector<WipeTower::ToolChangeResult>>(
// wipe_tower.prime((float)this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false));

View File

@ -36,7 +36,7 @@ class SupportLayer;
// BBS
class TreeSupportData;
class TreeSupport;
class ExtrusionLayers;
struct ExtrusionLayers;
#define MARGIN_HEIGHT 1.5
#define MAX_OUTER_NOZZLE_RADIUS 4

View File

@ -1731,6 +1731,18 @@ void PrintConfigDef::init_fff_params()
def->nullable = true;
def->set_default_value(new ConfigOptionFloatsNullable { 2. });
def = this->add("filament_ramming_volumetric_speed", coFloats);
def->label = L("Ramming volumetric speed");
def->tooltip = L("This setting is used to define the ramming speed on the prime tower before nozzle change, "
"-1 means it will use the maximum volumetric speed.");
def->sidetext = L("mm³/s");
def->min = -1;
def->max = 200;
def->mode = comAdvanced;
def->nullable = true;
def->set_default_value(new ConfigOptionFloatsNullable{-1});
def = this->add("filament_minimal_purge_on_wipe_tower", coFloats);
def->label = L("Minimal purge on wipe tower");
//def->tooltip = L("After a tool change, the exact position of the newly loaded filament inside "
@ -1940,6 +1952,30 @@ void PrintConfigDef::init_fff_params()
def->mode = comSimple;
def->set_default_value(new ConfigOptionInts{ 100 });
def = this->add("filament_ramming_travel_time", coFloats);
def->label = L("Ramming travel time");
def->tooltip = L("To prevent oozing, the nozzle will perform a reverse travel movement for a certain period after "
"the ramming is complete. The setting define the travel time.");
def->mode = comAdvanced;
def->sidetext = "s";
def->min = 0;
def->nullable = true;
def->set_default_value(new ConfigOptionFloatsNullable{0});
def = this->add("filament_pre_cooling_temperature", coInts);
def->label = L("Precooling target temperature");
def->tooltip = L("This setting is used to set the target pre-cooling temperature before nozzle change to prevent oozing,"
"so if you enable this setting, your ramming time must be greater than the cooldown time."
"And this setting only takes effect when the machine has preheating. 0 means no set.");
//def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
def->mode = comAdvanced;
def->sidetext = "°C";
def->min = 0;
//def->enum_values.push_back("-1");
//def->enum_labels.push_back(L("None"));
def->nullable = true;
def->set_default_value(new ConfigOptionIntsNullable{0});
def = this->add("filament_cost", coFloats);
def->label = L("Price");
def->tooltip = L("Filament price. For statistics only");
@ -4450,6 +4486,20 @@ void PrintConfigDef::init_fff_params()
def->mode = comDevelop;
def->set_default_value(new ConfigOptionFloat(0.));
def = this->add("prime_tower_max_speed", coFloat);
def->label = L("Max speed");
def->tooltip = L("The maximum printing speed when purging in the prime tower and printing the prime tower sparse layers.");
def->sidetext = L("mm/s");
def->mode = comAdvanced;
def->min = 10;
def->set_default_value(new ConfigOptionFloat(90.));
def = this->add("prime_tower_lift_speed", coFloat);
def->set_default_value(new ConfigOptionFloat(90.));
def = this->add("prime_tower_lift_height", coFloat);
def->set_default_value(new ConfigOptionFloat(-1));
def = this->add("prime_tower_brim_width", coFloat);
def->gui_type = ConfigOptionDef::GUIType::f_enum_open;
def->label = L("Brim width");
@ -5601,6 +5651,9 @@ std::set<std::string> print_options_with_variant = {
std::set<std::string> filament_options_with_variant = {
"filament_flow_ratio",
"filament_max_volumetric_speed",
"filament_ramming_volumetric_speed",
"filament_pre_cooling_temperature",
"filament_ramming_travel_time",
//"filament_extruder_id",
"filament_extruder_variant",
"filament_retraction_length",

View File

@ -1037,7 +1037,12 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionString, filament_notes))
((ConfigOptionStrings, default_filament_colour))
((ConfigOptionInts, temperature_vitrification)) //BBS
((ConfigOptionFloatsNullable, filament_ramming_travel_time)) //BBS
((ConfigOptionIntsNullable, filament_pre_cooling_temperature))// BBS
((ConfigOptionFloatsNullable, filament_max_volumetric_speed))
((ConfigOptionFloatsNullable, filament_ramming_volumetric_speed))
((ConfigOptionFloat, prime_tower_lift_speed))
((ConfigOptionFloat, prime_tower_lift_height))
((ConfigOptionInts, required_nozzle_HRC))
((ConfigOptionEnum<FilamentMapMode>, filament_map_mode))
((ConfigOptionInts, filament_map))
@ -1220,6 +1225,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionFloat, wipe_tower_per_color_wipe))
((ConfigOptionFloat, wipe_tower_rotation_angle))
((ConfigOptionFloat, prime_tower_brim_width))
((ConfigOptionFloat, prime_tower_max_speed))
((ConfigOptionFloat, prime_tower_extra_rib_length))
((ConfigOptionFloat, prime_tower_rib_width))
((ConfigOptionPercent, prime_tower_infill_gap))

View File

@ -691,7 +691,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in
toggle_field("standby_temperature_delta", have_ooze_prevention);
bool have_prime_tower = config->opt_bool("enable_prime_tower");
for (auto el : {"prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_rib_wall", "prime_tower_infill_gap","prime_tower_enable_framework"})
for (auto el :
{"prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_rib_wall", "prime_tower_infill_gap", "prime_tower_enable_framework", "prime_tower_max_speed"})
toggle_line(el, have_prime_tower);
bool have_rib_wall = config->opt_bool("prime_tower_rib_wall")&&have_prime_tower;

View File

@ -4255,7 +4255,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
"extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
"nozzle_height", "skirt_loops", "skirt_distance",
"brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material",
"enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_enable_framework",
"enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_enable_framework","prime_tower_max_speed",
"prime_tower_rib_wall","prime_tower_extra_rib_length", "prime_tower_rib_width","prime_tower_fillet_wall", "prime_tower_infill_gap","filament_prime_volume",
"extruder_colour", "filament_colour", "filament_type", "material_colour", "printable_height", "extruder_printable_height", "printer_model", "printer_technology",
// These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor.

View File

@ -2232,6 +2232,7 @@ void TabPrint::build()
optgroup->append_single_option_line("prime_tower_skip_points", "parameter/prime-tower");
optgroup->append_single_option_line("prime_tower_enable_framework", "parameter/prime-tower");
optgroup->append_single_option_line("prime_tower_width","parameter/prime-tower");
optgroup->append_single_option_line("prime_tower_max_speed","parameter/prime-tower");
optgroup->append_single_option_line("prime_tower_brim_width","parameter/prime-tower");
optgroup->append_single_option_line("prime_tower_infill_gap","parameter/prime-tower");
optgroup->append_single_option_line("prime_tower_rib_wall", "parameter/prime-tower");
@ -3209,6 +3210,8 @@ void TabFilament::build()
//BBS
optgroup->append_single_option_line("temperature_vitrification");
optgroup->append_single_option_line("filament_ramming_travel_time", "",0);
optgroup->append_single_option_line("filament_pre_cooling_temperature", "", 0);
Line line = { L("Recommended nozzle temperature"), L("Recommended nozzle temperature range of this filament. 0 means no set") };
line.append_option(optgroup->get_option("nozzle_temperature_range_low"));
line.append_option(optgroup->get_option("nozzle_temperature_range_high"));
@ -3292,6 +3295,7 @@ void TabFilament::build()
//BBS
optgroup = page->new_optgroup(L("Volumetric speed limitation"), L"param_volumetric_speed");
optgroup->append_single_option_line("filament_max_volumetric_speed", "", 0);
optgroup->append_single_option_line("filament_ramming_volumetric_speed", "",0);
// BBS
optgroup = page->new_optgroup(L("Filament scarf seam settings"), L"param_volumetric_speed");