The multi-color printing wipe tower now includes the Bambu RIB wall feature (#9881)

* Add new Bambu RIB wall feature, including only the rib wall generation algorithm.

* Fix Linux compilation errors.

* Attempt to fix flatpak build

---------

Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
This commit is contained in:
anjis 2025-06-15 14:53:35 +08:00 committed by GitHub
parent b72e28c116
commit ecfe53e488
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 1034 additions and 135 deletions

View file

@ -845,9 +845,10 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
// All G1 commands should be translated and rotated. X and Y coords are
// only pushed to the output when they differ from last time.
// WT generator can override this by appending the never_skip_tag
if (line.find("G1 ") == 0) {
bool never_skip = false;
auto it = line.find(WipeTower::never_skip_tag());
if (line.find("G1 ") == 0 || line.find("G2 ") == 0 || line.find("G3 ") == 0) {
std::string cur_gcode_start = line.find("G1 ") == 0 ? "G1 " : (line.find("G2 ") == 0 ? "G2 " : "G3 ");
bool never_skip = false;
auto it = line.find(WipeTower::never_skip_tag());
if (it != std::string::npos) {
// remove the tag and remember we saw it
never_skip = true;
@ -855,7 +856,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
}
std::ostringstream line_out;
std::istringstream line_str(line);
line_str >> std::noskipws; // don't skip whitespace
line_str >> std::noskipws; // don't skip whitespace
char ch = 0;
while (line_str >> ch) {
if (ch == 'X' || ch == 'Y')
@ -869,13 +870,13 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
if (transformed_pos != old_pos || never_skip) {
line = line_out.str();
std::ostringstream oss;
oss << std::fixed << std::setprecision(3) << "G1 ";
oss << std::fixed << std::setprecision(3) << cur_gcode_start;
if (transformed_pos.x() != old_pos.x() || never_skip)
oss << " X" << transformed_pos.x() - extruder_offset.x();
if (transformed_pos.y() != old_pos.y() || never_skip)
oss << " Y" << transformed_pos.y() - extruder_offset.y();
oss << " ";
line.replace(line.find("G1 "), 3, oss.str());
line.replace(line.find(cur_gcode_start), 3, oss.str());
old_pos = transformed_pos;
}
}

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,7 @@
#include <algorithm>
#include "libslic3r/Point.hpp"
#include "libslic3r/Polygon.hpp"
#include "WipeTower.hpp"
namespace Slic3r
{
@ -85,7 +86,8 @@ public:
while (!m_plan.empty() && m_layer_info->z < print_z - WT_EPSILON && m_layer_info+1 != m_plan.end())
++m_layer_info;
m_current_shape = (! this->is_first_layer() && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL;
//m_current_shape = (! this->is_first_layer() && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL;
m_current_shape = SHAPE_NORMAL;
if (this->is_first_layer()) {
m_num_layer_changes = 0;
m_num_tool_changes = 0;
@ -156,6 +158,8 @@ public:
bool multitool_ramming;
float multitool_ramming_time = 0.f;
float filament_minimal_purge_on_wipe_tower = 0.f;
float retract_length;
float retract_speed;
};
private:
@ -196,6 +200,14 @@ private:
float m_first_layer_speed = 0.f;
size_t m_first_layer_idx = size_t(-1);
int m_wall_type;
bool m_used_fillet = true;
float m_rib_width = 10;
float m_extra_rib_length = 0;
float m_rib_length = 0;
bool m_enable_arc_fitting = false;
// G-code generator parameters.
float m_cooling_tube_retraction = 0.f;
float m_cooling_tube_length = 0.f;
@ -315,6 +327,24 @@ private:
WipeTowerWriter2 &writer,
const WipeTower::box_coordinates &cleaning_box,
float wipe_volume);
Polygon generate_support_rib_wall(WipeTowerWriter2& writer,
const WipeTower::box_coordinates& wt_box,
double feedrate,
bool first_layer,
bool rib_wall,
bool extrude_perimeter,
bool skip_points);
Polygon generate_support_cone_wall(
WipeTowerWriter2& writer,
const WipeTower::box_coordinates& wt_box,
double feedrate,
bool infill_cone,
float spacing);
Polygon generate_rib_polygon(const WipeTower::box_coordinates& wt_box);
};

View file

@ -830,7 +830,9 @@ static std::vector<std::string> s_Preset_print_options {
"tree_support_brim_width", "gcode_comments", "gcode_label_objects",
"initial_layer_travel_speed", "exclude_object", "slow_down_layers", "infill_anchor", "infill_anchor_max","initial_layer_min_bead_width",
"make_overhang_printable", "make_overhang_printable_angle", "make_overhang_printable_hole_size" ,"notes",
"wipe_tower_cone_angle", "wipe_tower_extra_spacing","wipe_tower_max_purge_speed", "wipe_tower_filament", "wiping_volumes_extruders","wipe_tower_bridging", "wipe_tower_extra_flow","single_extruder_multi_material_priming",
"wipe_tower_cone_angle", "wipe_tower_extra_spacing","wipe_tower_max_purge_speed",
"wipe_tower_wall_type", "wipe_tower_extra_rib_length", "wipe_tower_rib_width", "wipe_tower_fillet_wall",
"wipe_tower_filament", "wiping_volumes_extruders","wipe_tower_bridging", "wipe_tower_extra_flow","single_extruder_multi_material_priming",
"wipe_tower_rotation_angle", "tree_support_branch_distance_organic", "tree_support_branch_diameter_organic", "tree_support_branch_angle_organic",
"hole_to_polyhole", "hole_to_polyhole_threshold", "hole_to_polyhole_twisted", "mmu_segmented_region_max_width", "mmu_segmented_region_interlocking_depth",
"small_area_infill_flow_compensation", "small_area_infill_flow_compensation_model",

View file

@ -304,6 +304,10 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "wipe_tower_cone_angle"
|| opt_key == "wipe_tower_extra_spacing"
|| opt_key == "wipe_tower_max_purge_speed"
|| opt_key == "wipe_tower_wall_type"
|| opt_key == "wipe_tower_extra_rib_length"
|| opt_key == "wipe_tower_rib_width"
|| opt_key == "wipe_tower_fillet_wall"
|| opt_key == "wipe_tower_filament"
|| opt_key == "wiping_volumes_extruders"
|| opt_key == "enable_filament_ramming"

View file

@ -445,6 +445,13 @@ static const t_config_enum_values s_keys_map_CounterboreHoleBridgingOption{
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(CounterboreHoleBridgingOption)
static const t_config_enum_values s_keys_map_WipeTowerWallType{
{"rectangle", wtwRectangle},
{"cone", wtwCone},
{"rib", wtwRib},
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(WipeTowerWallType)
static void assign_printer_technology_to_unknown(t_optiondef_map &options, PrinterTechnology printer_technology)
{
for (std::pair<const t_config_option_key, ConfigOptionDef> &kvp : options)
@ -5394,7 +5401,7 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->min = 0.;
def->max = 90.;
def->set_default_value(new ConfigOptionFloat(0.));
def->set_default_value(new ConfigOptionFloat(30.0));
def = this->add("wipe_tower_max_purge_speed", coFloat);
def->label = L("Maximum wipe tower print speed");
@ -5409,6 +5416,46 @@ void PrintConfigDef::init_fff_params()
def->min = 10;
def->set_default_value(new ConfigOptionFloat(90.));
def = this->add("wipe_tower_wall_type", coEnum);
def->label = L("Wall type");
def->tooltip = L("Wipe tower outer wall type.\n"
"1. Rectangle: The default wall type, a rectangle with fixed width and height.\n"
"2. Cone: A cone with a fillet at the bottom to help stabilize the wipe tower.\n"
"3. Rib: Adds four ribs to the tower wall for enhanced stability.");
def->enum_keys_map = &ConfigOptionEnum<WipeTowerWallType>::get_enum_values();
def->enum_values.emplace_back("rectangle");
def->enum_values.emplace_back("cone");
def->enum_values.emplace_back("rib");
def->enum_labels.emplace_back("Rectangle");
def->enum_labels.emplace_back("Cone");
def->enum_labels.emplace_back("Rib");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<WipeTowerWallType>(wtwRectangle));
def = this->add("wipe_tower_extra_rib_length", coFloat);
def->label = L("Extra rib length");
def->tooltip = L("Positive values can increase the size of the rib wall, while negative values can reduce the size."
"However, the size of the rib wall can not be smaller than that determined by the cleaning volume.");
def->sidetext = L("mm");
def->max = 300;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0));
def = this->add("wipe_tower_rib_width", coFloat);
def->label = L("Rib width");
def->tooltip = L("Rib width");
def->sidetext = L("mm");
def->mode = comAdvanced;
def->min = 0;
def->set_default_value(new ConfigOptionFloat(8));
def = this->add("wipe_tower_fillet_wall", coBool);
def->label = L("Fillet wall");
def->tooltip = L("The wall of prime tower will fillet.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(true));
def = this->add("wipe_tower_filament", coInt);
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
def->label = L("Wipe tower");

View file

@ -332,6 +332,12 @@ enum CounterboreHoleBridgingOption {
chbNone, chbBridges, chbFilled
};
enum WipeTowerWallType {
wtwRectangle = 0,
wtwCone,
wtwRib
};
static std::string bed_type_to_gcode_string(const BedType type)
{
std::string type_str;
@ -439,7 +445,9 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(GCodeThumbnailsFormat)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(CounterboreHoleBridgingOption)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrintHostType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(WipeTowerWallType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PerimeterGeneratorType)
#undef CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS
class DynamicPrintConfig;
@ -1327,6 +1335,10 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionFloat, wipe_tower_cone_angle))
((ConfigOptionPercent, wipe_tower_extra_spacing))
((ConfigOptionFloat, wipe_tower_max_purge_speed))
((ConfigOptionEnum<WipeTowerWallType>, wipe_tower_wall_type))
((ConfigOptionFloat, wipe_tower_extra_rib_length))
((ConfigOptionFloat, wipe_tower_rib_width))
((ConfigOptionBool, wipe_tower_fillet_wall))
((ConfigOptionInt, wipe_tower_filament))
((ConfigOptionFloats, wiping_volumes_extruders))
((ConfigOptionInts, idle_temperature))

View file

@ -686,10 +686,19 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
for (auto el : {"wipe_tower_rotation_angle", "wipe_tower_cone_angle",
"wipe_tower_extra_spacing", "wipe_tower_max_purge_speed",
"wipe_tower_wall_type",
"wipe_tower_extra_rib_length","wipe_tower_rib_width","wipe_tower_fillet_wall",
"wipe_tower_bridging", "wipe_tower_extra_flow",
"wipe_tower_no_sparse_layers"})
toggle_line(el, have_prime_tower && !is_BBL_Printer);
WipeTowerWallType wipe_tower_wall_type = config->opt_enum<WipeTowerWallType>("wipe_tower_wall_type");
toggle_line("wipe_tower_cone_angle", have_prime_tower && !is_BBL_Printer && wipe_tower_wall_type == WipeTowerWallType::wtwCone);
toggle_line("wipe_tower_extra_rib_length", have_prime_tower && !is_BBL_Printer && wipe_tower_wall_type == WipeTowerWallType::wtwRib);
toggle_line("wipe_tower_rib_width", have_prime_tower && !is_BBL_Printer && wipe_tower_wall_type == WipeTowerWallType::wtwRib);
toggle_line("wipe_tower_fillet_wall", have_prime_tower && !is_BBL_Printer && wipe_tower_wall_type == WipeTowerWallType::wtwRib);
toggle_line("single_extruder_multi_material_priming", !bSEMM && have_prime_tower && !is_BBL_Printer);
toggle_line("prime_volume",have_prime_tower && (!purge_in_primetower || !bSEMM));

View file

@ -2828,7 +2828,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
"brim_width", "wall_loops", "wall_filament", "sparse_infill_density", "sparse_infill_filament", "top_shell_layers",
"enable_support", "support_filament", "support_interface_filament",
"support_top_z_distance", "support_bottom_z_distance", "raft_layers",
"wipe_tower_rotation_angle", "wipe_tower_cone_angle", "wipe_tower_extra_spacing", "wipe_tower_extra_flow", "wipe_tower_max_purge_speed", "wipe_tower_filament",
"wipe_tower_rotation_angle", "wipe_tower_cone_angle", "wipe_tower_extra_spacing", "wipe_tower_extra_flow", "wipe_tower_max_purge_speed",
"wipe_tower_wall_type", "wipe_tower_extra_rib_length","wipe_tower_rib_width","wipe_tower_fillet_wall",
"wipe_tower_filament",
"best_object_pos"
}))
, sidebar(new Sidebar(q))

View file

@ -2323,10 +2323,14 @@ void TabPrint::build()
optgroup->append_single_option_line("prime_tower_brim_width");
optgroup->append_single_option_line("wipe_tower_rotation_angle");
optgroup->append_single_option_line("wipe_tower_bridging");
optgroup->append_single_option_line("wipe_tower_cone_angle");
optgroup->append_single_option_line("wipe_tower_extra_spacing");
optgroup->append_single_option_line("wipe_tower_extra_flow");
optgroup->append_single_option_line("wipe_tower_max_purge_speed");
optgroup->append_single_option_line("wipe_tower_wall_type");
optgroup->append_single_option_line("wipe_tower_cone_angle");
optgroup->append_single_option_line("wipe_tower_extra_rib_length");
optgroup->append_single_option_line("wipe_tower_rib_width");
optgroup->append_single_option_line("wipe_tower_fillet_wall");
optgroup->append_single_option_line("wipe_tower_no_sparse_layers");
optgroup->append_single_option_line("single_extruder_multi_material_priming");