mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-15 23:15:56 +08:00
skirt brim
supermerill/SuperSlicer#795 also little fix: now preview shows object skirt & brim.
This commit is contained in:
parent
43a7d347be
commit
1c3ad9de01
@ -177,6 +177,7 @@ group:Skirt
|
||||
setting:skirt_distance
|
||||
setting:skirt_height
|
||||
setting:draft_shield
|
||||
setting:skirt_brim
|
||||
setting:min_skirt_length
|
||||
group:Brim
|
||||
setting:brim_width
|
||||
|
@ -833,6 +833,8 @@ namespace DoExport {
|
||||
}
|
||||
if (compute_min_mm3_per_mm.is_compatible({ erSkirt })) {
|
||||
mm3_per_mm.push_back(compute_min_mm3_per_mm.reset_use_get(print.skirt()));
|
||||
if(print.skirt_first_layer())
|
||||
mm3_per_mm.push_back(compute_min_mm3_per_mm.reset_use_get(*print.skirt_first_layer()));
|
||||
mm3_per_mm.push_back(compute_min_mm3_per_mm.reset_use_get(print.brim()));
|
||||
}
|
||||
// filter out 0-width segments
|
||||
@ -2082,7 +2084,14 @@ namespace Skirt {
|
||||
// not at the print_z of the interlaced support material layers.
|
||||
std::map<uint16_t, std::pair<size_t, size_t>> skirt_loops_per_extruder_out;
|
||||
if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities.empty()) {
|
||||
skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out);
|
||||
if (print.skirt_first_layer()) {
|
||||
size_t n_loops = print.skirt_first_layer()->entities.size();
|
||||
size_t n_tools = layer_tools.extruders.size();
|
||||
size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools;
|
||||
for (size_t i = 0; i < n_loops; i += lines_per_extruder)
|
||||
skirt_loops_per_extruder_out[layer_tools.extruders[i / lines_per_extruder]] = std::pair<size_t, size_t>(i, std::min(i + lines_per_extruder, n_loops));
|
||||
} else
|
||||
skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out);
|
||||
skirt_done.emplace_back(layer_tools.print_z);
|
||||
}
|
||||
return skirt_loops_per_extruder_out;
|
||||
@ -2443,9 +2452,10 @@ void GCode::process_layer(
|
||||
Flow layer_skirt_flow(print.skirt_flow(extruder_id));
|
||||
layer_skirt_flow.height = float(m_skirt_done.back() - (m_skirt_done.size() == 1 ? 0. : m_skirt_done[m_skirt_done.size() - 2]));
|
||||
double mm3_per_mm = layer_skirt_flow.mm3_per_mm();
|
||||
const ExtrusionEntityCollection& coll = first_layer && print.skirt_first_layer() ? *print.skirt_first_layer() : print.skirt();
|
||||
for (size_t i = loops.first; i < loops.second; ++i) {
|
||||
// Adjust flow according to this layer's layer height.
|
||||
ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(print.skirt().entities[i]);
|
||||
ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(coll.entities[i]);
|
||||
for (ExtrusionPath &path : loop.paths) {
|
||||
assert(layer_skirt_flow.height == layer_skirt_flow.height);
|
||||
assert(mm3_per_mm == mm3_per_mm);
|
||||
@ -2475,6 +2485,7 @@ void GCode::process_layer(
|
||||
m_avoid_crossing_perimeters.disable_once();
|
||||
}
|
||||
//extrude object-only skirt
|
||||
//TODO: use it also for wiping like the other one (as they are exlusiev)
|
||||
if (single_object_instance_idx != size_t(-1) && !layers.front().object()->skirt().empty()
|
||||
&& extruder_id == layer_tools.extruders.front()) {
|
||||
//if first layer, ask for a bigger lift for travel to object, to be on the safe side
|
||||
@ -2483,8 +2494,12 @@ void GCode::process_layer(
|
||||
const PrintObject *print_object = layers.front().object();
|
||||
this->set_origin(unscale(print_object->instances()[single_object_instance_idx].shift));
|
||||
if (this->m_layer != nullptr && (this->m_layer->id() < m_config.skirt_height || print.has_infinite_skirt() )) {
|
||||
for (const ExtrusionEntity *ee : print_object->skirt().entities)
|
||||
gcode += this->extrude_entity(*ee, "", m_config.support_material_speed.value);
|
||||
if(first_layer && print.skirt_first_layer())
|
||||
for (const ExtrusionEntity* ee : print_object->skirt_first_layer()->entities)
|
||||
gcode += this->extrude_entity(*ee, "", m_config.support_material_speed.value);
|
||||
else
|
||||
for (const ExtrusionEntity *ee : print_object->skirt().entities)
|
||||
gcode += this->extrude_entity(*ee, "", m_config.support_material_speed.value);
|
||||
}
|
||||
}
|
||||
//extrude object-only brim
|
||||
|
@ -528,6 +528,7 @@ const std::vector<std::string>& Preset::print_options()
|
||||
"travel_acceleration",
|
||||
// skirt
|
||||
"skirts", "skirt_distance", "skirt_height",
|
||||
"skirt_brim",
|
||||
"skirt_extrusion_width",
|
||||
"min_skirt_length",
|
||||
"draft_shield",
|
||||
|
@ -200,6 +200,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
||||
opt_key == "skirts"
|
||||
|| opt_key == "skirt_height"
|
||||
|| opt_key == "draft_shield"
|
||||
|| opt_key == "skirt_brim"
|
||||
|| opt_key == "skirt_distance"
|
||||
|| opt_key == "min_skirt_length"
|
||||
|| opt_key == "complete_objects_one_skirt"
|
||||
@ -1641,7 +1642,7 @@ BoundingBox Print::total_bounding_box() const
|
||||
extra = std::max(extra, m_config.brim_width.value + brim_flow.width/2);
|
||||
}
|
||||
if (this->has_skirt()) {
|
||||
int skirts = m_config.skirts.value;
|
||||
int skirts = m_config.skirts.value + m_config.skirt_brim.value;
|
||||
if (skirts == 0 && this->has_infinite_skirt()) skirts = 1;
|
||||
Flow skirt_flow = this->skirt_flow();
|
||||
extra = std::max(
|
||||
@ -1748,11 +1749,13 @@ void Print::process()
|
||||
}
|
||||
if (this->set_started(psSkirt)) {
|
||||
m_skirt.clear();
|
||||
m_skirt_first_layer.reset();
|
||||
|
||||
m_skirt_convex_hull.clear();
|
||||
m_first_layer_convex_hull.points.clear();
|
||||
for (PrintObject *obj : m_objects) {
|
||||
obj->m_skirt.clear();
|
||||
obj->m_skirt_first_layer.reset();
|
||||
}
|
||||
if (this->has_skirt()) {
|
||||
this->set_status(88, L("Generating skirt"));
|
||||
@ -1762,11 +1765,11 @@ void Print::process()
|
||||
const std::vector<PrintInstance> copies{ obj->instances() };
|
||||
obj->m_instances.clear();
|
||||
obj->m_instances.emplace_back();
|
||||
this->_make_skirt({ obj }, obj->m_skirt);
|
||||
this->_make_skirt({ obj }, obj->m_skirt, obj->m_skirt_first_layer);
|
||||
obj->m_instances = copies;
|
||||
}
|
||||
} else {
|
||||
this->_make_skirt(m_objects, m_skirt);
|
||||
this->_make_skirt(m_objects, m_skirt, m_skirt_first_layer);
|
||||
}
|
||||
}
|
||||
this->set_done(psSkirt);
|
||||
@ -1888,7 +1891,7 @@ std::string Print::export_gcode(const std::string& path_template, GCodeProcessor
|
||||
return path.c_str();
|
||||
}
|
||||
|
||||
void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out)
|
||||
void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out, std::optional<ExtrusionEntityCollection>& out_first_layer)
|
||||
{
|
||||
// First off we need to decide how tall the skirt must be.
|
||||
// The skirt_height option from config is expressed in layers, but our
|
||||
@ -1973,9 +1976,11 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
|
||||
|
||||
// Number of skirt loops per skirt layer.
|
||||
size_t n_skirts = m_config.skirts.value;
|
||||
size_t n_skirts_first_layer = n_skirts + m_config.skirt_brim.value;
|
||||
if (this->has_infinite_skirt() && n_skirts == 0)
|
||||
n_skirts = 1;
|
||||
|
||||
if (m_config.skirt_brim.value > 0)
|
||||
out_first_layer.emplace();
|
||||
// Initial offset of the brim inner edge from the object (possible with a support & raft).
|
||||
// The skirt will touch the brim if the brim is extruded.
|
||||
auto distance = float(scale_(m_config.skirt_distance.value) - this->skirt_flow(extruders[extruders.size()-1]).spacing()/2.);
|
||||
@ -1986,7 +1991,8 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
|
||||
// Draw outlines from outside to inside.
|
||||
// Loop while we have less skirts than required or any extruder hasn't reached the min length if any.
|
||||
std::vector<coordf_t> extruded_length(extruders.size(), 0.);
|
||||
for (size_t i = n_skirts, extruder_idx = 0, nb_skirts = 1; i > 0; -- i) {
|
||||
for (size_t i = std::max(n_skirts, n_skirts_first_layer), extruder_idx = 0, nb_skirts = 1; i > 0; -- i) {
|
||||
bool first_layer_only = i <= (n_skirts_first_layer - n_skirts);
|
||||
Flow flow = this->skirt_flow(extruders[extruders.size() - (1+ extruder_idx)]);
|
||||
float spacing = flow.spacing();
|
||||
double mm3_per_mm = flow.mm3_per_mm();
|
||||
@ -2016,8 +2022,11 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
|
||||
eloop.paths.back().polyline = loop.split_at_first_point();
|
||||
//we make it clowkwise, but as it will be reversed, it will be ccw
|
||||
eloop.make_clockwise();
|
||||
out.append(eloop);
|
||||
if (m_config.min_skirt_length.value > 0) {
|
||||
if(!first_layer_only)
|
||||
out.append(eloop);
|
||||
if(out_first_layer)
|
||||
out_first_layer->append(eloop);
|
||||
if (m_config.min_skirt_length.value > 0 && !first_layer_only) {
|
||||
// The skirt length is limited. Sum the total amount of filament length extruded, in mm.
|
||||
extruded_length[extruder_idx] += unscale<double>(loop.length()) * extruders_e_per_mm[extruder_idx];
|
||||
if (extruded_length[extruder_idx] < m_config.min_skirt_length.value) {
|
||||
@ -2043,6 +2052,8 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
|
||||
}
|
||||
// Brims were generated inside out, reverse to print the outmost contour first.
|
||||
out.reverse();
|
||||
if (out_first_layer)
|
||||
out_first_layer->reverse();
|
||||
|
||||
// Remember the outer edge of the last skirt line extruded as m_skirt_convex_hull.
|
||||
for (Polygon &poly : offset(convex_hull, distance + 0.5f * float(this->skirt_flow(extruders[extruders.size() - 1]).scaled_spacing()), ClipperLib::jtRound, float(scale_(0.1))))
|
||||
|
@ -202,6 +202,7 @@ public:
|
||||
void project_and_append_custom_facets(bool seam, EnforcerBlockerType type, std::vector<ExPolygons>& expolys) const;
|
||||
|
||||
/// skirts if done per copy and not per platter
|
||||
const std::optional<ExtrusionEntityCollection>& skirt_first_layer() const { return m_skirt_first_layer; }
|
||||
const ExtrusionEntityCollection& skirt() const { return m_skirt; }
|
||||
const ExtrusionEntityCollection& brim() const { return m_brim; }
|
||||
|
||||
@ -271,6 +272,7 @@ private:
|
||||
|
||||
// Ordered collections of extrusion paths to build skirt loops and brim.
|
||||
// have to be duplicated per copy
|
||||
std::optional<ExtrusionEntityCollection> m_skirt_first_layer;
|
||||
ExtrusionEntityCollection m_skirt;
|
||||
ExtrusionEntityCollection m_brim;
|
||||
|
||||
@ -460,6 +462,7 @@ public:
|
||||
// If zero, then the print is empty and the print shall not be executed.
|
||||
uint16_t num_object_instances() const;
|
||||
|
||||
const std::optional<ExtrusionEntityCollection>& skirt_first_layer() const { return m_skirt_first_layer; }
|
||||
const ExtrusionEntityCollection& skirt() const { return m_skirt; }
|
||||
const ExtrusionEntityCollection& brim() const { return m_brim; }
|
||||
// Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line.
|
||||
@ -501,7 +504,7 @@ private:
|
||||
t_config_option_keys &full_config_diff,
|
||||
DynamicPrintConfig &filament_overrides) const;
|
||||
|
||||
void _make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out);
|
||||
void _make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out, std::optional<ExtrusionEntityCollection> &out_first_layer);
|
||||
void _make_brim(const Flow &flow, const PrintObjectPtrs &objects, ExPolygons &unbrimmable, ExtrusionEntityCollection &out);
|
||||
void _make_brim_ears(const Flow &flow, const PrintObjectPtrs &objects, ExPolygons &unbrimmable, ExtrusionEntityCollection &out);
|
||||
void _make_brim_interior(const Flow &flow, const PrintObjectPtrs &objects, ExPolygons &unbrimmable, ExtrusionEntityCollection &out);
|
||||
@ -525,6 +528,7 @@ private:
|
||||
PrintRegionPtrs m_regions;
|
||||
|
||||
// Ordered collections of extrusion paths to build skirt loops and brim.
|
||||
std::optional<ExtrusionEntityCollection> m_skirt_first_layer;
|
||||
ExtrusionEntityCollection m_skirt;
|
||||
ExtrusionEntityCollection m_brim;
|
||||
// Convex hull of the 1st layer extrusions.
|
||||
|
@ -674,6 +674,13 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("draft_shield", coBool);
|
||||
def->label = L("Draft shield");
|
||||
def->tooltip = L("If enabled, the skirt will be as tall as a highest printed object. "
|
||||
"This is useful to protect an ABS or ASA print from warping and detaching from print bed due to wind draft.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("duplicate_distance", coFloat);
|
||||
def->label = L("Distance between objects");
|
||||
def->category = OptionCategory::output;
|
||||
@ -3272,6 +3279,14 @@ void PrintConfigDef::init_fff_params()
|
||||
def->set_default_value(new ConfigOptionFloat(30);
|
||||
def->set_default_value(new ConfigOptionFloat(30));
|
||||
#endif
|
||||
def = this->add("skirt_brim", coInt);
|
||||
def->label = L("Brim");
|
||||
def->full_label = L("Skirt brim");
|
||||
def->category = OptionCategory::skirtBrim;
|
||||
def->tooltip = L("Extra skirt lines on the first layer.");
|
||||
def->sidetext = L("lines");
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
||||
def = this->add("skirt_distance", coFloat);
|
||||
def->label = L("Distance from object");
|
||||
@ -3287,7 +3302,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->label = L("Skirt height");
|
||||
def->category = OptionCategory::skirtBrim;
|
||||
def->tooltip = L("Height of skirt expressed in layers. Set this to a tall value to use skirt "
|
||||
"as a shield against drafts.");
|
||||
"as a shield against drafts.");
|
||||
def->sidetext = L("layers");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
@ -3306,13 +3321,6 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
|
||||
|
||||
def = this->add("draft_shield", coBool);
|
||||
def->label = L("Draft shield");
|
||||
def->tooltip = L("If enabled, the skirt will be as tall as a highest printed object. "
|
||||
"This is useful to protect an ABS or ASA print from warping and detaching from print bed due to wind draft.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("skirts", coInt);
|
||||
def->label = L("Loops (minimum)");
|
||||
def->full_label = L("Skirt Loops");
|
||||
@ -5530,6 +5538,7 @@ void PrintConfigDef::to_prusa(t_config_option_key& opt_key, std::string& value,
|
||||
"retract_lift_top",
|
||||
"seam_angle_cost",
|
||||
"seam_travel_cost",
|
||||
"skirt_brim",
|
||||
"skirt_extrusion_width",
|
||||
"small_perimeter_min_length",
|
||||
"small_perimeter_max_length",
|
||||
@ -5754,7 +5763,10 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei
|
||||
|
||||
const double first_layer_height = config->get_abs_value("first_layer_height");
|
||||
//add the skirt
|
||||
if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() >= 1 && !config->option("complete_objects_one_skirt")->getBool()) {
|
||||
int skirts = config->option("skirts")->getInt();
|
||||
if (skirts > 0 && ref_height == 0)
|
||||
skirts += config->option("skirt_brim")->getInt();
|
||||
if (skirts > 0 && config->option("skirt_height")->getInt() >= 1 && !config->option("complete_objects_one_skirt")->getBool()) {
|
||||
if (ref_height == 0) {
|
||||
skirt_dist = config->option("skirt_distance")->getFloat();
|
||||
Flow skirt_flow = Flow::new_from_config_width(
|
||||
@ -5763,7 +5775,7 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei
|
||||
(float)max_nozzle_diam,
|
||||
(float)first_layer_height
|
||||
);
|
||||
skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)config->option("skirts")->getInt() - 1));
|
||||
skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)skirts - 1));
|
||||
base_dist = std::max(base_dist, skirt_dist + 1);
|
||||
//set to 0 becasue it's incorporated into the base_dist, so we don't want to be added in to it again.
|
||||
skirt_dist = 0;
|
||||
@ -5777,7 +5789,7 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei
|
||||
(float)max_nozzle_diam,
|
||||
(float)first_layer_height
|
||||
);
|
||||
skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)config->option("skirts")->getInt() - 1));
|
||||
skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)skirts - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1329,6 +1329,7 @@ public:
|
||||
ConfigOptionFloat resolution;
|
||||
ConfigOptionFloats retract_before_travel;
|
||||
ConfigOptionBools retract_layer_change;
|
||||
ConfigOptionInt skirt_brim;
|
||||
ConfigOptionFloat skirt_distance;
|
||||
ConfigOptionInt skirt_height;
|
||||
ConfigOptionFloatOrPercent skirt_extrusion_width;
|
||||
@ -1426,6 +1427,7 @@ protected:
|
||||
OPT_PTR(resolution);
|
||||
OPT_PTR(retract_before_travel);
|
||||
OPT_PTR(retract_layer_change);
|
||||
OPT_PTR(skirt_brim);
|
||||
OPT_PTR(skirt_distance);
|
||||
OPT_PTR(skirt_extrusion_width);
|
||||
OPT_PTR(skirt_height);
|
||||
|
@ -440,7 +440,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
||||
bool have_skirt = config->opt_int("skirts") > 0;
|
||||
toggle_field("skirt_height", have_skirt && !config->opt_bool("draft_shield"));
|
||||
toggle_field("skirt_width", have_skirt);
|
||||
for (auto el : { "skirt_distance", "draft_shield", "min_skirt_length" })
|
||||
for (auto el : { "skirt_distance", "skirt_brim", "draft_shield", "min_skirt_length" })
|
||||
toggle_field(el, have_skirt);
|
||||
|
||||
bool have_brim = config->opt_float("brim_width") > 0 || config->opt_float("brim_width_interior") > 0;
|
||||
|
@ -5793,9 +5793,27 @@ void GLCanvas3D::_load_print_toolpaths()
|
||||
volume->print_zs.emplace_back(print_zs[i]);
|
||||
volume->offsets.emplace_back(volume->indexed_vertex_array.quad_indices.size());
|
||||
volume->offsets.emplace_back(volume->indexed_vertex_array.triangle_indices.size());
|
||||
if (i == 0)
|
||||
if (i == 0) {
|
||||
//skirt & brim from print
|
||||
_3DScene::extrusionentity_to_verts(print->brim(), print_zs[i], Point(0, 0), *volume);
|
||||
_3DScene::extrusionentity_to_verts(print->skirt(), print_zs[i], Point(0, 0), *volume);
|
||||
if(print->skirt_first_layer())
|
||||
_3DScene::extrusionentity_to_verts(*print->skirt_first_layer(), print_zs[i], Point(0, 0), *volume);
|
||||
//skirt & brim from objects
|
||||
for (const PrintObject* print_object : print->objects()) {
|
||||
if (!print_object->brim().empty())
|
||||
_3DScene::extrusionentity_to_verts(print_object->brim(), print_zs[i], Point(0, 0), *volume);
|
||||
if (print_object->skirt_first_layer())
|
||||
_3DScene::extrusionentity_to_verts(*print_object->skirt_first_layer(), print_zs[i], Point(0, 0), *volume);
|
||||
}
|
||||
}
|
||||
//skirts from print
|
||||
if (i != 0 || !print->skirt_first_layer())
|
||||
_3DScene::extrusionentity_to_verts(print->skirt(), print_zs[i], Point(0, 0), *volume);
|
||||
//skirts from objects
|
||||
for (const PrintObject* print_object : print->objects()) {
|
||||
if ( !print_object->skirt().empty() && (i != 0 || !print_object->skirt_first_layer()))
|
||||
_3DScene::extrusionentity_to_verts(print_object->skirt(), print_zs[i], Point(0, 0), *volume);
|
||||
}
|
||||
// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
|
||||
if (volume->indexed_vertex_array.vertices_and_normals_interleaved.size() > MAX_VERTEX_BUFFER_SIZE) {
|
||||
GLVolume &vol = *volume;
|
||||
|
@ -1984,7 +1984,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
"first_layer_extrusion_width",
|
||||
"perimeter_extrusion_width",
|
||||
"extrusion_width",
|
||||
"skirts", "skirt_distance", "skirt_height", "draft_shield",
|
||||
"skirts", "skirt_brim", "skirt_distance", "skirt_height", "draft_shield",
|
||||
"brim_width", "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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user