Add nozzle flow variant & make some options multi-variant (#13712)

# Description

Port BBS per-extruder config variants toggle, thanks Bambu!

Also fix invalid num error when resetting multi-variant filament
overrides.

TODOs:

- [x] Make more configs multi-variant (such as speeds)
- [x] Add flow variant (normal/high flow) combo box
- [x] Add botton to sync config to other variant


# Screenshots/Recordings/Graphs

<img width="846" height="1494" alt="image"
src="https://github.com/user-attachments/assets/47abf053-f5b8-4c86-ac0b-c0323ed8b242"
/>

<img width="1478" height="1189" alt="707420e5be01c30af3e6ede1f3dc9b67"
src="https://github.com/user-attachments/assets/11268712-da65-42ab-9cb8-3cede7790a5c"
/>

<img width="1478" height="1189" alt="81d5d3877f4d5bf9dccd44d7f0b30aa7"
src="https://github.com/user-attachments/assets/cda5ea51-07c3-48fc-bfbb-1428dca14e26"
/>


## Tests

<!--
> Please describe the tests that you have conducted to verify the
changes made in this PR.
-->

<!--
> A guide for users on how to download the artifacts from this PR.
-->

[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
Fix #10336
This commit is contained in:
SoftFever
2026-06-28 22:30:40 +08:00
committed by GitHub
53 changed files with 2727 additions and 1353 deletions
+59
View File
@@ -685,6 +685,32 @@ bool ConfigBase::set_deserialize_raw(const t_config_option_key &opt_key_src, con
return success;
}
double ConfigBase::get_abs_value_at(const t_config_option_key &opt_key, size_t index) const
{
const ConfigOption *raw_opt = this->option(opt_key);
assert(raw_opt != nullptr);
if (raw_opt->type() == coFloats) {
return static_cast<const ConfigOptionFloats*>(raw_opt)->get_at(index);
}
if (raw_opt->type() == coFloatsOrPercents) {
const ConfigDef *def = this->def();
if (def == nullptr) throw NoDefinitionException(opt_key);
const ConfigOptionDef *opt_def = def->get(opt_key);
assert(opt_def != nullptr);
if (opt_def->ratio_over.empty()) {
return 0;
} else {
const ConfigOption *ratio_opt = this->option(opt_def->ratio_over);
assert(ratio_opt->type() == coFloats);
const ConfigOptionFloats *ratio_values = static_cast<const ConfigOptionFloats *>(ratio_opt);
return static_cast<const ConfigOptionFloatsOrPercents *>(raw_opt)->get_at(index).get_abs_value(ratio_values->get_at(index));
}
}
throw ConfigurationError("ConfigBase::get_abs_value_at(): Not a valid option type for get_abs_value_at()");
}
// Return an absolute value of a possibly relative config variable.
// For example, return absolute infill extrusion width, either from an absolute value, or relative to the layer height.
double ConfigBase::get_abs_value(const t_config_option_key &opt_key) const
@@ -1886,6 +1912,39 @@ t_config_option_keys DynamicConfig::equal(const DynamicConfig &other) const
return equal;
}
double& DynamicConfig::opt_float(const t_config_option_key &opt_key, unsigned int idx)
{
if (ConfigOptionFloats *opt_floats = dynamic_cast<ConfigOptionFloats *>(this->option(opt_key))) {
return opt_floats->get_at(idx);
} else {
ConfigOptionFloatsNullable *opt_floats_nullable = dynamic_cast<ConfigOptionFloatsNullable *>(this->option(opt_key));
assert(opt_floats_nullable != nullptr);
return opt_floats_nullable->get_at(idx);
}
}
const double& DynamicConfig::opt_float(const t_config_option_key &opt_key, unsigned int idx) const
{
if (const ConfigOptionFloats *opt_floats = dynamic_cast<const ConfigOptionFloats *>(this->option(opt_key))) {
return opt_floats->get_at(idx);
} else if (const ConfigOptionFloatsNullable *opt_floats_nullable = dynamic_cast<const ConfigOptionFloatsNullable *>(this->option(opt_key))) {
return opt_floats_nullable->get_at(idx);
} else {
assert(false);
return 0;
}
}
bool DynamicConfig::opt_bool(const t_config_option_key &opt_key, unsigned int idx) const {
if (const ConfigOptionBools *opts = dynamic_cast<const ConfigOptionBools *>(this->option(opt_key))) {
return opts->get_at(idx) != 0;
}
else {
const ConfigOptionBoolsNullable *opt_s = dynamic_cast<const ConfigOptionBoolsNullable *>(this->option(opt_key));
assert(opt_s != nullptr);
return opt_s->get_at(idx) != 0;
}
}
}
#include <cereal/types/polymorphic.hpp>
+20 -5
View File
@@ -30,8 +30,14 @@
namespace Slic3r {
struct FloatOrPercent
{
double value;
bool percent;
double value = 0;
bool percent = false;
FloatOrPercent() {}
FloatOrPercent(double value_, bool percent_) : value(value_), percent(percent_) { }
double get_abs_value(double ratio_over) const { return this->percent ? (ratio_over * this->value / 100) : this->value; }
private:
friend class cereal::access;
template<class Archive> void serialize(Archive& ar) { ar(this->value); ar(this->percent); }
@@ -2726,6 +2732,7 @@ public:
void set_deserialize_strict(std::initializer_list<SetDeserializeItem> items)
{ ConfigSubstitutionContext ctxt{ ForwardCompatibilitySubstitutionRule::Disable }; this->set_deserialize(items, ctxt); }
double get_abs_value_at(const t_config_option_key &opt_key, size_t index) const;
double get_abs_value(const t_config_option_key &opt_key) const;
double get_abs_value(const t_config_option_key &opt_key, double ratio_over) const;
void setenv_() const;
@@ -2900,13 +2907,17 @@ public:
double& opt_float(const t_config_option_key &opt_key) { return this->option<ConfigOptionFloat>(opt_key)->value; }
const double& opt_float(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionFloat*>(this->option(opt_key))->value; }
double& opt_float(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionFloats>(opt_key)->get_at(idx); }
const double& opt_float(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionFloats*>(this->option(opt_key))->get_at(idx); }
double & opt_float(const t_config_option_key &opt_key, unsigned int idx);
const double & opt_float(const t_config_option_key &opt_key, unsigned int idx) const;
double & opt_float_nullable(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionFloatsNullable>(opt_key)->get_at(idx); }
const double & opt_float_nullable(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionFloatsNullable *>(this->option(opt_key))->get_at(idx); }
int& opt_int(const t_config_option_key &opt_key) { return this->option<ConfigOptionInt>(opt_key)->value; }
int opt_int(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionInt*>(this->option(opt_key))->value; }
int& opt_int(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionInts>(opt_key)->get_at(idx); }
int opt_int(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); }
int& opt_int_nullable(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionIntsNullable>(opt_key)->get_at(idx);}
const int & opt_int_nullable(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionIntsNullable*>(this->option(opt_key))->get_at(idx);}
// In ConfigManipulation::toggle_print_fff_options, it is called on option with type ConfigOptionEnumGeneric* and also ConfigOptionEnum*.
// Thus the virtual method getInt() is used to retrieve the enum value.
@@ -2914,9 +2925,13 @@ public:
ENUM opt_enum(const t_config_option_key &opt_key) const { return static_cast<ENUM>(this->option(opt_key)->getInt()); }
// BBS
int opt_enum(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionEnumsGeneric*>(this->option(opt_key))->get_at(idx); }
int opt_enum_nullable(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionEnumsGenericNullable*>(this->option(opt_key))->get_at(idx); }
bool opt_bool(const t_config_option_key &opt_key) const { return this->option<ConfigOptionBool>(opt_key)->value != 0; }
bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option<ConfigOptionBools>(opt_key)->get_at(idx) != 0; }
bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const;
bool opt_bool_nullable(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionBoolsNullable*>(this->option(opt_key))->get_at(idx);}
// Command line processing
bool read_cli(int argc, const char* const argv[], t_config_option_keys* extra, t_config_option_keys* keys = nullptr);
+5 -5
View File
@@ -960,15 +960,15 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
params.role_speed = 0;
if (params.extrusion_role == erBridgeInfill)
params.role_speed = region_config.bridge_speed;
params.role_speed = region_config.bridge_speed.get_at(layer.get_extruder_id(params.extruder));
else if (params.extrusion_role == erInternalBridgeInfill)
params.role_speed = region_config.get_abs_value("internal_bridge_speed");
params.role_speed = region_config.get_abs_value_at("internal_bridge_speed", layer.get_extruder_id(params.extruder));
else if (params.extrusion_role == erInternalInfill)
params.role_speed = region_config.sparse_infill_speed;
params.role_speed = region_config.sparse_infill_speed.get_at(layer.get_extruder_id(params.extruder));
else if (params.extrusion_role == erTopSolidInfill)
params.role_speed = region_config.top_surface_speed;
params.role_speed = region_config.top_surface_speed.get_at(layer.get_extruder_id(params.extruder));
else if (params.extrusion_role == erSolidInfill)
params.role_speed = region_config.internal_solid_infill_speed;
params.role_speed = region_config.internal_solid_infill_speed.get_at(layer.get_extruder_id(params.extruder));
// Calculate flow spacing for infill pattern generation.
if (surface.is_solid() || is_bridge) {
params.spacing = params.flow.spacing();
+175 -142
View File
@@ -337,7 +337,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
if(retraction_length_remaining <=EPSILON) return {retractionBeforeWipe,0.f};
// Calculate wipe speed
double wipe_speed = config.role_based_wipe_speed ? writer.get_current_speed() / 60.0 : config.get_abs_value("wipe_speed");
double wipe_speed = config.role_based_wipe_speed ? writer.get_current_speed() / 60.0 : config.get_abs_value("wipe_speed", gcodegen.config().travel_speed.get_at(gcodegen.cur_extruder_index()));
wipe_speed = std::max(wipe_speed, 10.0);
// Process wipe path & calculate wipe path length
@@ -429,7 +429,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
/* Reduce feedrate a bit; travel speed is often too high to move on existing material.
Too fast = ripping of existing material; too slow = short wipe path, thus more blob. */
double _wipe_speed = gcodegen.config().get_abs_value("wipe_speed");// gcodegen.writer().config.travel_speed.value * 0.8;
double _wipe_speed = gcodegen.config().get_abs_value("wipe_speed", gcodegen.config().travel_speed.get_at(gcodegen.cur_extruder_index()));// gcodegen.writer().config.travel_speed.value * 0.8;
if(gcodegen.config().role_based_wipe_speed)
_wipe_speed = gcodegen.writer().get_current_speed() / 60.0;
if(_wipe_speed < 10)
@@ -515,7 +515,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
outer_wall_line_width = default_line_width == 0.0 ? filament_diameter : default_line_width;
}
Flow outer_wall_flow = Flow(outer_wall_line_width, config.layer_height, config.nozzle_diameter.get_at(extruder_id));
float outer_wall_speed = print.default_region_config().outer_wall_speed.value;
float outer_wall_speed = print.default_region_config().outer_wall_speed.get_at(extruder_id);
outer_wall_volumetric_speed = outer_wall_speed * outer_wall_flow.mm3_per_mm();
if (outer_wall_volumetric_speed > filament_max_volumetric_speed)
outer_wall_volumetric_speed = filament_max_volumetric_speed;
@@ -1602,6 +1602,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_writer.filament()->extruder_id())
#define FILAMENT_CONFIG(OPT) m_config.OPT.get_at(m_writer.filament()->id())
#define NOZZLE_CONFIG(OPT) m_config.OPT.get_at(cur_extruder_index())
void GCode::PlaceholderParserIntegration::reset()
{
@@ -2806,11 +2807,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
print.throw_if_canceled();
m_cooling_buffer = make_unique<CoolingBuffer>(*this);
m_cooling_buffer->set_current_extruder(initial_extruder_id);
int extruder_id = get_extruder_id(initial_extruder_id);
m_cooling_buffer = make_unique<CoolingBuffer>(*this);
m_cooling_buffer->set_current_extruder(initial_extruder_id, extruder_id);
// Orca: Initialise AdaptivePA processor filter
m_pa_processor = std::make_unique<AdaptivePAProcessor>(*this, tool_ordering.all_extruders());
@@ -3245,12 +3246,12 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
if (print.calib_params().mode == CalibMode::Calib_PA_Line) {
std::string gcode;
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Layer_Change) + "\n";
if ((print.default_object_config().outer_wall_acceleration.value > 0 && print.default_object_config().outer_wall_acceleration.value > 0)) {
gcode += m_writer.set_print_acceleration((unsigned int)floor(print.default_object_config().outer_wall_acceleration.value + 0.5));
if ((NOZZLE_CONFIG(outer_wall_acceleration) > 0 && NOZZLE_CONFIG(outer_wall_acceleration) > 0)) {
gcode += m_writer.set_print_acceleration((unsigned int)floor(NOZZLE_CONFIG(outer_wall_acceleration) + 0.5));
}
if (print.default_object_config().outer_wall_jerk.value > 0) {
double jerk = print.default_object_config().outer_wall_jerk.value;
if (NOZZLE_CONFIG(outer_wall_jerk) > 0) {
double jerk = NOZZLE_CONFIG(outer_wall_jerk);
gcode += m_writer.set_jerk_xy(jerk);
}
@@ -3333,8 +3334,8 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
file.writeln(printing_by_object_gcode);
}
// Reset the cooling buffer internal state (the current position, feed rate, accelerations).
m_cooling_buffer->set_current_extruder(initial_extruder_id, get_extruder_id(initial_extruder_id));
m_cooling_buffer->reset(this->writer().get_position());
m_cooling_buffer->set_current_extruder(initial_extruder_id);
// Process all layers of a single object instance (sequential mode) with a parallel pipeline:
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
// and export G-code into file.
@@ -3645,6 +3646,13 @@ void GCode::check_placeholder_parser_failed()
}
}
size_t GCode::cur_extruder_index() const
{
//TODO: check if the function is duplicated
//just return m_writer.filament()->extruder_id()
return get_extruder_id(m_writer.filament()->id());
}
size_t GCode::get_extruder_id(unsigned int filament_id) const
{
if (m_print) {
@@ -3940,51 +3948,75 @@ void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print)
const auto flavor = print.config().gcode_flavor.value;
if ((flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware || flavor == gcfRepRapFirmware) &&
print.config().emit_machine_limits_to_gcode.value == true) {
// Get all physical tool ids current print will use
std::unordered_set<unsigned int> used_extruders;
for (const auto& extruder : m_writer.extruders()) {
used_extruders.insert(extruder.extruder_id());
}
// Get the max limit value among used extruders
auto get_max_value = [&used_extruders](const std::string key, const ConfigOptionFloats& v) {
unsigned int stride = 1;
if (printer_options_with_variant_2.count(key) > 0) {
stride = 2;
}
double value = std::numeric_limits<double>::lowest();
for (unsigned int extruder : used_extruders) {
value = std::max(value, v.values[extruder * stride]);
}
assert(value > std::numeric_limits<double>::lowest());
return value;
};
#define MAX_LIMIT(OPT) get_max_value(#OPT, print.config().OPT)
int factor = flavor == gcfRepRapFirmware ? 60 : 1; // RRF M203 and M566 are in mm/min
file.write_format("M201 X%d Y%d Z%d E%d\n",
int(print.config().machine_max_acceleration_x.values.front() + 0.5),
int(print.config().machine_max_acceleration_y.values.front() + 0.5),
int(print.config().machine_max_acceleration_z.values.front() + 0.5),
int(print.config().machine_max_acceleration_e.values.front() + 0.5));
int(MAX_LIMIT(machine_max_acceleration_x) + 0.5),
int(MAX_LIMIT(machine_max_acceleration_y) + 0.5),
int(MAX_LIMIT(machine_max_acceleration_z) + 0.5),
int(MAX_LIMIT(machine_max_acceleration_e) + 0.5));
file.write_format("M203 X%d Y%d Z%d E%d\n",
int(print.config().machine_max_speed_x.values.front() * factor + 0.5),
int(print.config().machine_max_speed_y.values.front() * factor + 0.5),
int(print.config().machine_max_speed_z.values.front() * factor + 0.5),
int(print.config().machine_max_speed_e.values.front() * factor + 0.5));
int(MAX_LIMIT(machine_max_speed_x) * factor + 0.5),
int(MAX_LIMIT(machine_max_speed_y) * factor + 0.5),
int(MAX_LIMIT(machine_max_speed_z) * factor + 0.5),
int(MAX_LIMIT(machine_max_speed_e) * factor + 0.5));
// Now M204 - acceleration. This one is quite hairy thanks to how Marlin guys care about
// Legacy Marlin should export travel acceleration the same as printing acceleration.
// MarlinFirmware has the two separated.
int travel_acc = flavor == gcfMarlinLegacy
? int(print.config().machine_max_acceleration_extruding.values.front() + 0.5)
: int(print.config().machine_max_acceleration_travel.values.front() + 0.5);
? int(MAX_LIMIT(machine_max_acceleration_extruding) + 0.5)
: int(MAX_LIMIT(machine_max_acceleration_travel) + 0.5);
if (flavor == gcfRepRapFirmware)
file.write_format("M204 P%d T%d ; sets acceleration (P, T), mm/sec^2\n",
int(print.config().machine_max_acceleration_extruding.values.front() + 0.5),
int(MAX_LIMIT(machine_max_acceleration_extruding) + 0.5),
travel_acc);
else if (flavor == gcfMarlinFirmware)
// New Marlin uses M204 P[print] R[retract] T[travel]
file.write_format("M204 P%d R%d T%d ; sets acceleration (P, T) and retract acceleration (R), mm/sec^2\n",
int(print.config().machine_max_acceleration_extruding.values.front() + 0.5),
int(print.config().machine_max_acceleration_retracting.values.front() + 0.5),
int(print.config().machine_max_acceleration_travel.values.front() + 0.5));
int(MAX_LIMIT(machine_max_acceleration_extruding) + 0.5),
int(MAX_LIMIT(machine_max_acceleration_retracting) + 0.5),
int(MAX_LIMIT(machine_max_acceleration_travel) + 0.5));
else
file.write_format("M204 P%d R%d T%d\n",
int(print.config().machine_max_acceleration_extruding.values.front() + 0.5),
int(print.config().machine_max_acceleration_retracting.values.front() + 0.5),
int(MAX_LIMIT(machine_max_acceleration_extruding) + 0.5),
int(MAX_LIMIT(machine_max_acceleration_retracting) + 0.5),
travel_acc);
assert(is_decimal_separator_point());
file.write_format(flavor == gcfRepRapFirmware
? "M566 X%.2lf Y%.2lf Z%.2lf E%.2lf ; sets the jerk limits, mm/min\n"
: "M205 X%.2lf Y%.2lf Z%.2lf E%.2lf ; sets the jerk limits, mm/sec\n",
print.config().machine_max_jerk_x.values.front() * factor,
print.config().machine_max_jerk_y.values.front() * factor,
print.config().machine_max_jerk_z.values.front() * factor,
print.config().machine_max_jerk_e.values.front() * factor);
MAX_LIMIT(machine_max_jerk_x) * factor,
MAX_LIMIT(machine_max_jerk_y) * factor,
MAX_LIMIT(machine_max_jerk_z) * factor,
MAX_LIMIT(machine_max_jerk_e) * factor);
// New Marlin uses M205 J[mm] for junction deviation (only apply if it is > 0)
file.write_format(writer().set_junction_deviation(config().machine_max_junction_deviation.values.front()).c_str());
file.write_format(writer().set_junction_deviation(MAX_LIMIT(machine_max_junction_deviation)).c_str());
// Orca: Override input shaping values
if (print.config().input_shaping_emit.value && flavor != gcfMarlinLegacy) {
@@ -3997,6 +4029,7 @@ void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print)
}
}
}
#undef MAX_LIMIT
}
// BBS
@@ -4434,10 +4467,10 @@ std::string GCode::generate_skirt(const Print &print,
if (first_layer && i==loops.first) {
//set skirt start point location
const Point desired_start_point = Skirt::find_start_point(loop, skirt_start_angle);
gcode += this->extrude_loop(loop, "skirt", m_config.support_speed.value, {}, &desired_start_point);
gcode += this->extrude_loop(loop, "skirt", NOZZLE_CONFIG(support_speed), {}, &desired_start_point);
}
else
gcode += this->extrude_loop(loop, "skirt", m_config.support_speed.value);
gcode += this->extrude_loop(loop, "skirt", NOZZLE_CONFIG(support_speed));
// If we only want a single wall on non-first layers, break now
if (!first_layer && print.m_config.single_loop_draft_shield) {
@@ -4499,7 +4532,7 @@ std::string GCode::generate_object_brim(const Print &print, const PrintObject &o
m_avoid_crossing_perimeters.use_external_mp();
for (const ExtrusionEntity* ee : brim.entities)
if (ee != nullptr)
gcode += this->extrude_entity(*ee, "brim", m_config.support_speed.value);
gcode += this->extrude_entity(*ee, "brim", NOZZLE_CONFIG(support_speed));
m_avoid_crossing_perimeters.use_external_mp(false);
m_avoid_crossing_perimeters.disable_once();
for (ObjectID object_id : object_ids)
@@ -4698,12 +4731,12 @@ LayerResult GCode::process_layer(
}
case CalibMode::Calib_VFA_Tower: {
auto _speed = print.calib_params().start + std::floor(print_z / 5.0) * print.calib_params().step;
m_calib_config.set_key_value("outer_wall_speed", new ConfigOptionFloat(std::round(_speed)));
m_calib_config.set_key_value("outer_wall_speed", new ConfigOptionFloatsNullable({std::round(_speed)}));
break;
}
case CalibMode::Calib_Vol_speed_Tower: {
auto _speed = print.calib_params().start + print_z * print.calib_params().step;
m_calib_config.set_key_value("outer_wall_speed", new ConfigOptionFloat(std::round(_speed)));
m_calib_config.set_key_value("outer_wall_speed", new ConfigOptionFloatsNullable({std::round(_speed)}));
break;
}
case CalibMode::Calib_Retraction_tower: {
@@ -4760,16 +4793,16 @@ LayerResult GCode::process_layer(
//BBS
if (first_layer) {
// Orca: we don't need to optimize the Klipper as only set once
if (m_config.default_acceleration.value > 0 && m_config.initial_layer_acceleration.value > 0) {
gcode += m_writer.set_print_acceleration((unsigned int)floor(m_config.initial_layer_acceleration.value + 0.5));
if (NOZZLE_CONFIG(default_acceleration) > 0 && NOZZLE_CONFIG(initial_layer_acceleration) > 0) {
gcode += m_writer.set_print_acceleration((unsigned int)floor(NOZZLE_CONFIG(initial_layer_acceleration) + 0.5));
}
if (m_config.default_jerk.value > 0 && m_config.initial_layer_jerk.value > 0) {
gcode += m_writer.set_jerk_xy(m_config.initial_layer_jerk.value);
if (NOZZLE_CONFIG(default_jerk) > 0 && NOZZLE_CONFIG(initial_layer_jerk) > 0) {
gcode += m_writer.set_jerk_xy(NOZZLE_CONFIG(initial_layer_jerk));
}
if (m_writer.get_gcode_flavor() == gcfMarlinFirmware && m_config.default_junction_deviation.value > 0) {
gcode += m_writer.set_junction_deviation(m_config.default_junction_deviation.value);
if (m_writer.get_gcode_flavor() == gcfMarlinFirmware && NOZZLE_CONFIG(default_junction_deviation) > 0) {
gcode += m_writer.set_junction_deviation(NOZZLE_CONFIG(default_junction_deviation));
}
}
@@ -4790,12 +4823,12 @@ LayerResult GCode::process_layer(
}
// Reset acceleration at sencond layer
// Orca: only set once, don't need to call set_accel_and_jerk
if (m_config.default_acceleration.value > 0 && m_config.initial_layer_acceleration.value > 0) {
gcode += m_writer.set_print_acceleration((unsigned int) floor(m_config.default_acceleration.value + 0.5));
if (NOZZLE_CONFIG(default_acceleration) > 0 && NOZZLE_CONFIG(initial_layer_acceleration) > 0) {
gcode += m_writer.set_print_acceleration((unsigned int) floor(NOZZLE_CONFIG(default_acceleration) + 0.5));
}
if (m_config.default_jerk.value > 0 && m_config.initial_layer_jerk.value > 0) {
gcode += m_writer.set_jerk_xy(m_config.default_jerk.value);
if (NOZZLE_CONFIG(default_jerk) > 0 && NOZZLE_CONFIG(initial_layer_jerk) > 0) {
gcode += m_writer.set_jerk_xy(NOZZLE_CONFIG(default_jerk));
}
// Transition from 1st to 2nd layer. Adjust nozzle temperatures as prescribed by the nozzle dependent
@@ -4850,8 +4883,8 @@ LayerResult GCode::process_layer(
for (const auto &layer_to_print : layers) {
if (layer_to_print.object_layer) {
const auto& regions = layer_to_print.object_layer->regions();
const bool enable_overhang_speed = std::any_of(regions.begin(), regions.end(), [](const LayerRegion* r) {
return r->has_extrusions() && r->region().config().enable_overhang_speed;
const bool enable_overhang_speed = std::any_of(regions.begin(), regions.end(), [this](const LayerRegion* r) {
return r->has_extrusions() && r->region().config().enable_overhang_speed.get_at(cur_extruder_index());
});
if (enable_overhang_speed) {
m_extrusion_quality_estimator.prepare_for_new_layer(layer_to_print.original_object,
@@ -5391,7 +5424,7 @@ LayerResult GCode::process_layer(
this->set_origin(0., 0.);
m_avoid_crossing_perimeters.use_external_mp();
for (const ExtrusionEntity* ee : print.m_supportBrimMap.at(instance_to_print.print_object.id()).entities) {
gcode += this->extrude_entity(*ee, "brim", m_config.support_speed.value);
gcode += this->extrude_entity(*ee, "brim", NOZZLE_CONFIG(support_speed));
}
m_avoid_crossing_perimeters.use_external_mp(false);
// Allow a straight travel move to the first object point.
@@ -5805,11 +5838,11 @@ std::string GCode::extrude_loop(const ExtrusionLoop& loop_ref,
// SoftFever: check loop lenght for small perimeter.
double small_peri_speed = -1;
if (speed == -1 && loop.length() <= SMALL_PERIMETER_LENGTH(m_config.small_perimeter_threshold.value)) {
if(m_config.small_perimeter_speed == 0)
small_peri_speed = m_config.outer_wall_speed * 0.5;
if (speed == -1 && loop.length() <= SMALL_PERIMETER_LENGTH(NOZZLE_CONFIG(small_perimeter_threshold))) {
if(NOZZLE_CONFIG(small_perimeter_speed).value == 0)
small_peri_speed = NOZZLE_CONFIG(outer_wall_speed) * 0.5;
else
small_peri_speed = m_config.small_perimeter_speed.get_abs_value(m_config.outer_wall_speed);
small_peri_speed = NOZZLE_CONFIG(small_perimeter_speed).get_abs_value(NOZZLE_CONFIG(outer_wall_speed));
}
// extrude along the path
@@ -6199,8 +6232,8 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
if (!support_fills.no_sort)
chain_and_reorder_extrusion_entities(extrusions, m_last_pos.to_point());
const double support_speed = m_config.support_speed.value;
const double support_interface_speed = m_config.get_abs_value("support_interface_speed");
//const double support_speed = m_config.support_speed.value;
//const double support_interface_speed = m_config.get_abs_value("support_interface_speed");
for (const ExtrusionEntity *ee : extrusions) {
ExtrusionRole role = ee->role();
assert(role == erSupportMaterial || role == erSupportMaterialInterface || role == erSupportTransition || role == erIroning);
@@ -6411,47 +6444,47 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
unsigned int acceleration_i = 0;
double jerk = 0;
// adjust acceleration
if (m_config.default_acceleration.value > 0) {
if (NOZZLE_CONFIG(default_acceleration) > 0) {
double acceleration;
if (this->on_first_layer() && m_config.initial_layer_acceleration.value > 0) {
acceleration = m_config.initial_layer_acceleration.value;
if (this->on_first_layer() && NOZZLE_CONFIG(initial_layer_acceleration) > 0) {
acceleration = NOZZLE_CONFIG(initial_layer_acceleration);
#if 0
} else if (this->object_layer_over_raft() && m_config.first_layer_acceleration_over_raft.value > 0) {
acceleration = m_config.first_layer_acceleration_over_raft.value;
#endif
} else if (m_config.get_abs_value("bridge_acceleration") > 0 && is_bridge(path.role())) {
acceleration = m_config.get_abs_value("bridge_acceleration");
} else if (m_config.get_abs_value("sparse_infill_acceleration") > 0 && (path.role() == erInternalInfill)) {
acceleration = m_config.get_abs_value("sparse_infill_acceleration");
} else if (m_config.get_abs_value("internal_solid_infill_acceleration") > 0 && (path.role() == erSolidInfill)) {
acceleration = m_config.get_abs_value("internal_solid_infill_acceleration");
} else if (m_config.outer_wall_acceleration.value > 0 && is_external_perimeter(path.role())) {
acceleration = m_config.outer_wall_acceleration.value;
} else if (m_config.inner_wall_acceleration.value > 0 && is_internal_perimeter(path.role())) {
acceleration = m_config.inner_wall_acceleration.value;
} else if (m_config.top_surface_acceleration.value > 0 && is_top_surface(path.role())) {
acceleration = m_config.top_surface_acceleration.value;
} else if (m_config.get_abs_value_at("bridge_acceleration", cur_extruder_index()) > 0 && is_bridge(path.role())) {
acceleration = m_config.get_abs_value_at("bridge_acceleration", cur_extruder_index());
} else if (m_config.get_abs_value_at("sparse_infill_acceleration", cur_extruder_index()) > 0 && (path.role() == erInternalInfill)) {
acceleration = m_config.get_abs_value_at("sparse_infill_acceleration", cur_extruder_index());
} else if (m_config.get_abs_value_at("internal_solid_infill_acceleration", cur_extruder_index()) > 0 && (path.role() == erSolidInfill)) {
acceleration = m_config.get_abs_value_at("internal_solid_infill_acceleration", cur_extruder_index());
} else if (NOZZLE_CONFIG(outer_wall_acceleration) > 0 && is_external_perimeter(path.role())) {
acceleration = NOZZLE_CONFIG(outer_wall_acceleration);
} else if (NOZZLE_CONFIG(inner_wall_acceleration) > 0 && is_internal_perimeter(path.role())) {
acceleration = NOZZLE_CONFIG(inner_wall_acceleration);
} else if (NOZZLE_CONFIG(top_surface_acceleration) > 0 && is_top_surface(path.role())) {
acceleration = NOZZLE_CONFIG(top_surface_acceleration);
} else {
acceleration = m_config.default_acceleration.value;
acceleration = NOZZLE_CONFIG(default_acceleration);
}
acceleration_i = (unsigned int)floor(acceleration + 0.5);
}
// adjust X Y jerk
if (m_config.default_jerk.value > 0) {
if (this->on_first_layer() && m_config.initial_layer_jerk.value > 0) {
jerk = m_config.initial_layer_jerk.value;
} else if (m_config.outer_wall_jerk.value > 0 && is_external_perimeter(path.role())) {
jerk = m_config.outer_wall_jerk.value;
} else if (m_config.inner_wall_jerk.value > 0 && is_internal_perimeter(path.role())) {
jerk = m_config.inner_wall_jerk.value;
} else if (m_config.top_surface_jerk.value > 0 && is_top_surface(path.role())) {
jerk = m_config.top_surface_jerk.value;
} else if (m_config.infill_jerk.value > 0 && is_infill(path.role())) {
jerk = m_config.infill_jerk.value;
if (NOZZLE_CONFIG(default_jerk) > 0) {
if (this->on_first_layer() && NOZZLE_CONFIG(initial_layer_jerk) > 0) {
jerk = NOZZLE_CONFIG(initial_layer_jerk);
} else if (NOZZLE_CONFIG(outer_wall_jerk) > 0 && is_external_perimeter(path.role())) {
jerk = NOZZLE_CONFIG(outer_wall_jerk);
} else if (NOZZLE_CONFIG(inner_wall_jerk) > 0 && is_internal_perimeter(path.role())) {
jerk = NOZZLE_CONFIG(inner_wall_jerk);
} else if (NOZZLE_CONFIG(top_surface_jerk) > 0 && is_top_surface(path.role())) {
jerk = NOZZLE_CONFIG(top_surface_jerk);
} else if (NOZZLE_CONFIG(infill_jerk) > 0 && is_infill(path.role())) {
jerk = NOZZLE_CONFIG(infill_jerk);
}
else {
jerk = m_config.default_jerk.value;
jerk = NOZZLE_CONFIG(default_jerk);
}
}
@@ -6514,37 +6547,37 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
// set speed
if (speed == -1) {
if (path.role() == erPerimeter) {
speed = m_config.get_abs_value("inner_wall_speed");
speed = NOZZLE_CONFIG(inner_wall_speed);
if (sloped) {
speed = std::min(speed, m_config.scarf_joint_speed.get_abs_value(m_config.get_abs_value("inner_wall_speed")));
speed = std::min(speed, m_config.scarf_joint_speed.get_abs_value(speed));
}
} else if (path.role() == erExternalPerimeter) {
speed = m_config.get_abs_value("outer_wall_speed");
speed = NOZZLE_CONFIG(outer_wall_speed);
if (sloped) {
speed = std::min(speed, m_config.scarf_joint_speed.get_abs_value(m_config.get_abs_value("outer_wall_speed")));
speed = std::min(speed, m_config.scarf_joint_speed.get_abs_value(speed));
}
}
else if(path.role() == erInternalBridgeInfill) {
speed = m_config.get_abs_value("internal_bridge_speed");
speed = m_config.get_abs_value_at("internal_bridge_speed", cur_extruder_index());
} else if (path.role() == erOverhangPerimeter || path.role() == erSupportTransition || path.role() == erBridgeInfill) {
speed = m_config.get_abs_value("bridge_speed");
speed = NOZZLE_CONFIG(bridge_speed);
} else if (path.role() == erInternalInfill) {
speed = m_config.get_abs_value("sparse_infill_speed");
speed = NOZZLE_CONFIG(sparse_infill_speed);
} else if (path.role() == erSolidInfill) {
speed = m_config.get_abs_value("internal_solid_infill_speed");
speed = NOZZLE_CONFIG(internal_solid_infill_speed);
} else if (path.role() == erTopSolidInfill) {
speed = m_config.get_abs_value("top_surface_speed");
speed = NOZZLE_CONFIG(top_surface_speed);
} else if (path.role() == erIroning) {
speed = m_config.get_abs_value("ironing_speed");
} else if (path.role() == erBottomSurface) {
speed = m_config.get_abs_value("initial_layer_infill_speed");
speed = NOZZLE_CONFIG(initial_layer_infill_speed);
} else if (path.role() == erGapFill) {
speed = m_config.get_abs_value("gap_infill_speed");
speed = NOZZLE_CONFIG(gap_infill_speed);
}
else if (path.role() == erSupportMaterial ||
path.role() == erSupportMaterialInterface) {
const double support_speed = m_config.support_speed.value;
const double support_interface_speed = m_config.get_abs_value("support_interface_speed");
const double support_speed = NOZZLE_CONFIG(support_speed);
const double support_interface_speed = NOZZLE_CONFIG(support_interface_speed);
speed = (path.role() == erSupportMaterial) ? support_speed : support_interface_speed;
} else {
throw Slic3r::InvalidArgument("Invalid speed");
@@ -6565,16 +6598,16 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
//BBS: for solid infill of first layer, speed can be higher as long as
//wall lines have be attached
if (path.role() != erBottomSurface) {
speed = is_perimeter(path.role()) ? m_config.get_abs_value("initial_layer_speed") :
m_config.get_abs_value("initial_layer_infill_speed");
speed = is_perimeter(path.role()) ? NOZZLE_CONFIG(initial_layer_speed) :
NOZZLE_CONFIG(initial_layer_infill_speed);
}
} else if (m_config.slow_down_layers > 1 && m_config.raft_layers == 0) {
if (_layer > 0 && _layer < m_config.slow_down_layers) {
const auto first_layer_speed =
is_perimeter(path.role())
? m_config.get_abs_value("initial_layer_speed")
: m_config.get_abs_value("initial_layer_infill_speed");
? NOZZLE_CONFIG(initial_layer_speed)
: NOZZLE_CONFIG(initial_layer_infill_speed);
if (first_layer_speed < speed) {
speed = std::min(
speed,
@@ -6586,8 +6619,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
if (_layer > m_config.raft_layers && (_layer - m_config.raft_layers) < m_config.slow_down_layers) {
const auto first_layer_speed
= is_perimeter(path.role()) ? m_config.get_abs_value("initial_layer_speed") :
m_config.get_abs_value("initial_layer_infill_speed");
= is_perimeter(path.role()) ? NOZZLE_CONFIG(initial_layer_speed) :
NOZZLE_CONFIG(initial_layer_infill_speed);
if (first_layer_speed < speed) {
speed = std::min(speed, Slic3r::lerp(first_layer_speed, speed,
(double) (_layer - m_config.raft_layers) / m_config.slow_down_layers));
@@ -6653,10 +6686,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
bool variable_speed = false;
std::vector<ProcessedPoint> new_points {};
if (m_config.enable_overhang_speed && !this->on_first_layer() && !object_layer_over_raft() &&
if (NOZZLE_CONFIG(enable_overhang_speed) && !this->on_first_layer() && !object_layer_over_raft() &&
(is_bridge(path.role()) || is_perimeter(path.role()))) {
bool is_external = is_external_perimeter(path.role());
double ref_speed = is_external ? m_config.get_abs_value("outer_wall_speed") : m_config.get_abs_value("inner_wall_speed");
double ref_speed = is_external ? NOZZLE_CONFIG(outer_wall_speed) : NOZZLE_CONFIG(inner_wall_speed);
if (ref_speed == 0)
ref_speed = FILAMENT_CONFIG(filament_max_volumetric_speed) / _mm3_per_mm;
@@ -6669,46 +6702,46 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
ConfigOptionPercents overhang_overlap_levels({90, 75, 50, 25, 13, 0});
if (m_config.slowdown_for_curled_perimeters){
if (NOZZLE_CONFIG(slowdown_for_curled_perimeters)){
ConfigOptionFloatsOrPercents dynamic_overhang_speeds(
{FloatOrPercent{100, true},
(m_config.get_abs_value("overhang_1_4_speed", ref_speed) < 0.5) ?
(NOZZLE_CONFIG(overhang_1_4_speed).get_abs_value(ref_speed) < 0.5) ?
FloatOrPercent{100, true} :
FloatOrPercent{m_config.get_abs_value("overhang_1_4_speed", ref_speed) * 100 / ref_speed, true},
(m_config.get_abs_value("overhang_2_4_speed", ref_speed) < 0.5) ?
FloatOrPercent{NOZZLE_CONFIG(overhang_1_4_speed).get_abs_value(ref_speed) * 100 / ref_speed, true},
(NOZZLE_CONFIG(overhang_2_4_speed).get_abs_value(ref_speed) < 0.5) ?
FloatOrPercent{100, true} :
FloatOrPercent{m_config.get_abs_value("overhang_2_4_speed", ref_speed) * 100 / ref_speed, true},
(m_config.get_abs_value("overhang_3_4_speed", ref_speed) < 0.5) ?
FloatOrPercent{NOZZLE_CONFIG(overhang_2_4_speed).get_abs_value(ref_speed) * 100 / ref_speed, true},
(NOZZLE_CONFIG(overhang_3_4_speed).get_abs_value(ref_speed) < 0.5) ?
FloatOrPercent{100, true} :
FloatOrPercent{m_config.get_abs_value("overhang_3_4_speed", ref_speed) * 100 / ref_speed, true},
(m_config.get_abs_value("overhang_4_4_speed", ref_speed) < 0.5) ?
FloatOrPercent{NOZZLE_CONFIG(overhang_3_4_speed).get_abs_value(ref_speed) * 100 / ref_speed, true},
(NOZZLE_CONFIG(overhang_4_4_speed).get_abs_value(ref_speed) < 0.5) ?
FloatOrPercent{100, true} :
FloatOrPercent{m_config.get_abs_value("overhang_4_4_speed", ref_speed) * 100 / ref_speed, true},
(m_config.get_abs_value("overhang_4_4_speed", ref_speed) < 0.5) ?
FloatOrPercent{NOZZLE_CONFIG(overhang_4_4_speed).get_abs_value(ref_speed) * 100 / ref_speed, true},
(NOZZLE_CONFIG(overhang_4_4_speed).get_abs_value(ref_speed) < 0.5) ?
FloatOrPercent{100, true} :
FloatOrPercent{m_config.get_abs_value("overhang_4_4_speed", ref_speed) * 100 / ref_speed, true}});
FloatOrPercent{NOZZLE_CONFIG(overhang_4_4_speed).get_abs_value(ref_speed) * 100 / ref_speed, true}});
new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, overhang_overlap_levels, dynamic_overhang_speeds,
ref_speed, speed, m_config.slowdown_for_curled_perimeters);
ref_speed, speed, NOZZLE_CONFIG(slowdown_for_curled_perimeters));
}else{
ConfigOptionFloatsOrPercents dynamic_overhang_speeds(
{FloatOrPercent{100, true},
(m_config.get_abs_value("overhang_1_4_speed", ref_speed) < 0.5) ?
(NOZZLE_CONFIG(overhang_1_4_speed).get_abs_value(ref_speed) < 0.5) ?
FloatOrPercent{100, true} :
FloatOrPercent{m_config.get_abs_value("overhang_1_4_speed", ref_speed) * 100 / ref_speed, true},
(m_config.get_abs_value("overhang_2_4_speed", ref_speed) < 0.5) ?
FloatOrPercent{NOZZLE_CONFIG(overhang_1_4_speed).get_abs_value(ref_speed) * 100 / ref_speed, true},
(NOZZLE_CONFIG(overhang_2_4_speed).get_abs_value(ref_speed) < 0.5) ?
FloatOrPercent{100, true} :
FloatOrPercent{m_config.get_abs_value("overhang_2_4_speed", ref_speed) * 100 / ref_speed, true},
(m_config.get_abs_value("overhang_3_4_speed", ref_speed) < 0.5) ?
FloatOrPercent{NOZZLE_CONFIG(overhang_2_4_speed).get_abs_value(ref_speed) * 100 / ref_speed, true},
(NOZZLE_CONFIG(overhang_3_4_speed).get_abs_value(ref_speed) < 0.5) ?
FloatOrPercent{100, true} :
FloatOrPercent{m_config.get_abs_value("overhang_3_4_speed", ref_speed) * 100 / ref_speed, true},
(m_config.get_abs_value("overhang_4_4_speed", ref_speed) < 0.5) ?
FloatOrPercent{NOZZLE_CONFIG(overhang_3_4_speed).get_abs_value(ref_speed) * 100 / ref_speed, true},
(NOZZLE_CONFIG(overhang_4_4_speed).get_abs_value(ref_speed) < 0.5) ?
FloatOrPercent{100, true} :
FloatOrPercent{m_config.get_abs_value("overhang_4_4_speed", ref_speed) * 100 / ref_speed, true},
FloatOrPercent{m_config.get_abs_value("bridge_speed") * 100 / ref_speed, true}});
FloatOrPercent{NOZZLE_CONFIG(overhang_4_4_speed).get_abs_value(ref_speed) * 100 / ref_speed, true},
FloatOrPercent{NOZZLE_CONFIG(bridge_speed) * 100 / ref_speed, true}});
new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, overhang_overlap_levels, dynamic_overhang_speeds,
ref_speed, speed, m_config.slowdown_for_curled_perimeters);
ref_speed, speed, NOZZLE_CONFIG(slowdown_for_curled_perimeters));
}
variable_speed = std::any_of(new_points.begin(), new_points.end(),
[speed](const ProcessedPoint &p) { return fabs(double(p.speed) - speed) > 1; }); // Ignore small speed variations (under 1mm/sec)
@@ -7367,40 +7400,40 @@ std::string GCode::travel_to(const Point& point, ExtrusionRole role, std::string
unsigned int acceleration_to_set = 0;
if (this->on_first_layer()) {
unsigned int initial_layer_travel_acceleration = m_config.get_abs_value("initial_layer_travel_acceleration");
double initial_layer_travel_jerk = m_config.get_abs_value("initial_layer_travel_jerk");
unsigned int initial_layer_travel_acceleration = m_config.get_abs_value_at("initial_layer_travel_acceleration", cur_extruder_index());
double initial_layer_travel_jerk = m_config.get_abs_value_at("initial_layer_travel_jerk", cur_extruder_index());
if (m_config.default_acceleration.value > 0 && initial_layer_travel_acceleration > 0) {
if (NOZZLE_CONFIG(default_acceleration) > 0 && initial_layer_travel_acceleration > 0) {
acceleration_to_set = (unsigned int) floor(initial_layer_travel_acceleration + 0.5);
}
if (m_config.default_jerk.value > 0 && initial_layer_travel_jerk > 0) {
if (NOZZLE_CONFIG(default_jerk)> 0 && initial_layer_travel_jerk > 0) {
jerk_to_set = initial_layer_travel_jerk;
}
} else { // ORCA: Handle short-travel acceleration and jerk for outer perimeters (if applicable)
const bool is_short_travel = travel.length() < scale_(EXTRUDER_CONFIG(retraction_minimum_travel));
if (m_config.default_acceleration.value > 0) {
if (NOZZLE_CONFIG(default_acceleration) > 0) {
if (role == erOverhangPerimeter && is_short_travel) {
const double bridge_acceleration = m_config.get_abs_value("bridge_acceleration");
const double bridge_acceleration = m_config.get_abs_value_at("bridge_acceleration", cur_extruder_index());
if (bridge_acceleration > 0)
acceleration_to_set = (unsigned int) floor(bridge_acceleration + 0.5);
} else if (role == erExternalPerimeter && is_short_travel) {
if (m_config.outer_wall_acceleration.value > 0)
acceleration_to_set = (unsigned int) floor(m_config.outer_wall_acceleration.value + 0.5);
if (NOZZLE_CONFIG(outer_wall_acceleration) > 0)
acceleration_to_set = (unsigned int) floor(NOZZLE_CONFIG(outer_wall_acceleration) + 0.5);
} else {
if (m_config.travel_acceleration.value > 0)
acceleration_to_set = (unsigned int) floor(m_config.travel_acceleration.value + 0.5);
if (NOZZLE_CONFIG(travel_acceleration) > 0)
acceleration_to_set = (unsigned int) floor(NOZZLE_CONFIG(travel_acceleration) + 0.5);
}
}
if (m_config.default_jerk.value > 0) {
if (NOZZLE_CONFIG(default_jerk) > 0) {
if ((role == erExternalPerimeter || role == erOverhangPerimeter) && is_short_travel) {
if (m_config.outer_wall_jerk.value > 0)
jerk_to_set = m_config.outer_wall_jerk.value;
if (NOZZLE_CONFIG(outer_wall_jerk) > 0)
jerk_to_set = NOZZLE_CONFIG(outer_wall_jerk);
} else {
if (m_config.travel_jerk.value > 0)
jerk_to_set = m_config.travel_jerk.value;
if (NOZZLE_CONFIG(travel_jerk) > 0)
jerk_to_set = NOZZLE_CONFIG(travel_jerk);
}
}
}
+1
View File
@@ -392,6 +392,7 @@ private:
//BBS
void check_placeholder_parser_failed();
size_t cur_extruder_index() const;
size_t get_extruder_id(unsigned int filament_id) const;
void set_last_pos(const Point &pos) { m_last_pos = Point3(pos, 0); m_last_pos_defined = true; }
+2 -2
View File
@@ -18,7 +18,7 @@
namespace Slic3r {
CoolingBuffer::CoolingBuffer(GCode &gcodegen) : m_config(gcodegen.config()), m_toolchange_prefix(gcodegen.writer().toolchange_prefix()), m_current_extruder(0)
CoolingBuffer::CoolingBuffer(GCode &gcodegen) : m_config(gcodegen.config()), m_toolchange_prefix(gcodegen.writer().toolchange_prefix()), m_current_extruder(0), m_current_nozzle(0)
{
this->reset(gcodegen.writer().get_position());
@@ -37,7 +37,7 @@ void CoolingBuffer::reset(const Vec3d &position)
m_current_pos[0] = float(position.x());
m_current_pos[1] = float(position.y());
m_current_pos[2] = float(position.z());
m_current_pos[4] = float(m_config.travel_speed.value);
m_current_pos[4] = float(m_config.travel_speed.get_at(m_current_nozzle));
m_fan_speed = -1;
m_additional_fan_speed = -1;
m_current_fan_speed = -1;
+2 -1
View File
@@ -25,7 +25,7 @@ class CoolingBuffer {
public:
CoolingBuffer(GCode &gcodegen);
void reset(const Vec3d &position);
void set_current_extruder(unsigned int extruder_id) { m_current_extruder = extruder_id; }
void set_current_extruder(unsigned int extruder_id, unsigned int nozzle_id) { m_current_extruder = extruder_id; m_current_nozzle = nozzle_id; }
std::string process_layer(std::string &&gcode, size_t layer_id, bool flush);
private:
@@ -55,6 +55,7 @@ private:
// the PrintConfig slice of FullPrintConfig is constant, thus no thread synchronization is required.
const PrintConfig &m_config;
unsigned int m_current_extruder;
unsigned int m_current_nozzle;
//BBS: current fan speed
int m_current_fan_speed;
};
+2 -2
View File
@@ -1472,7 +1472,7 @@ WipeTower::WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origi
m_bridging(10.f),
m_no_sparse_layers(config.wipe_tower_no_sparse_layers),
m_gcode_flavor(config.gcode_flavor),
m_travel_speed(config.travel_speed),
m_travel_speed(config.travel_speed.get_at(get_extruder_index(config, (unsigned int)initial_tool))),
m_current_tool(initial_tool),
//wipe_volumes(flush_matrix)
m_enable_timelapse_print(config.timelapse_type.value == TimelapseType::tlSmooth),
@@ -1497,7 +1497,7 @@ WipeTower::WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origi
// it is taken over following default. Speeds from config are not
// easily accessible here.
const float default_speed = 60.f;
m_first_layer_speed = config.get_abs_value("initial_layer_speed");
m_first_layer_speed = config.initial_layer_speed.get_at(get_extruder_index(config, (unsigned int)initial_tool));
if (m_first_layer_speed == 0.f) // just to make sure autospeed doesn't break it.
m_first_layer_speed = default_speed / 2.f;
+4 -4
View File
@@ -1262,9 +1262,9 @@ WipeTower2::WipeTower2(const PrintConfig& config, const PrintRegionConfig& defau
m_bridging(float(config.wipe_tower_bridging)),
m_no_sparse_layers(config.wipe_tower_no_sparse_layers),
m_gcode_flavor(config.gcode_flavor),
m_travel_speed(config.travel_speed),
m_infill_speed(default_region_config.sparse_infill_speed),
m_perimeter_speed(default_region_config.inner_wall_speed),
m_travel_speed(config.travel_speed.get_at(get_extruder_index(config, (unsigned int)initial_tool))),
m_infill_speed(default_region_config.sparse_infill_speed.get_at(get_extruder_index(config, (unsigned int)initial_tool))),
m_perimeter_speed(default_region_config.inner_wall_speed.get_at(get_extruder_index(config, (unsigned int)initial_tool))),
m_current_tool(initial_tool),
wipe_volumes(wiping_matrix), m_wipe_tower_max_purge_speed(float(config.wipe_tower_max_purge_speed)),
m_enable_arc_fitting(config.enable_arc_fitting),
@@ -1280,7 +1280,7 @@ WipeTower2::WipeTower2(const PrintConfig& config, const PrintRegionConfig& defau
// it is taken over following default. Speeds from config are not
// easily accessible here.
const float default_speed = 60.f;
m_first_layer_speed = config.initial_layer_speed;
m_first_layer_speed = config.initial_layer_speed.get_at(get_extruder_index(config, (unsigned int)initial_tool));
if (m_first_layer_speed == 0.f) // just to make sure autospeed doesn't break it.
m_first_layer_speed = default_speed / 2.f;
+101 -53
View File
@@ -28,6 +28,39 @@ bool GCodeWriter::supports_separate_travel_acceleration(GCodeFlavor flavor)
void GCodeWriter::apply_print_config(const PrintConfig &print_config)
{
this->config.apply(print_config, true);
// Some machine limits are stride-2 (normal, silent) pairs, here we extract the value that will be used,
// which is always normal mode at the moment
// TODO: support silent? Any printer actually have that?
auto get_machine_limits = [](const std::string key, const ConfigOptionFloats& opt) -> std::vector<double> {
unsigned int stride = 1;
unsigned int offset = 0;
if (printer_options_with_variant_2.count(key) > 0) {
stride = 2;
// offset = <TODO: current print mode>;
}
std::vector<double> results;
results.reserve(opt.values.size() / stride);
for (unsigned int i = offset; i < opt.values.size(); i += stride) {
results.emplace_back(opt.values[i]);
}
return results;
};
auto rounded = [](std::vector<double>&& vec) -> std::vector<double>&&{
std::transform(vec.cbegin(), vec.cend(), vec.begin(), [](const double v) { return std::round(v); });
return std::move(vec);
};
auto to_uint = [](const std::vector<double>& vec) {
std::vector<unsigned int> r;
std::transform(vec.begin(), vec.end(), std::back_inserter(r), [](const double v) { return static_cast<unsigned int>(v); });
return r;
};
#define LIMITS(OPT) get_machine_limits(#OPT, print_config.OPT)
#define LIMITS_UINT(OPT) to_uint(rounded(LIMITS(OPT)))
m_single_extruder_multi_material = print_config.single_extruder_multi_material.value;
bool use_mach_limits = print_config.gcode_flavor.value == gcfMarlinLegacy || print_config.gcode_flavor.value == gcfMarlinFirmware ||
print_config.gcode_flavor.value == gcfKlipper || print_config.gcode_flavor.value == gcfRepRapFirmware;
@@ -35,29 +68,40 @@ void GCodeWriter::apply_print_config(const PrintConfig &print_config)
// For Klipper, SET_VELOCITY_LIMIT ACCEL= applies to all moves, so the effective cap
// is the minimum of the extruding limit and the per-axis X/Y limits.
// This ensures user-configured Motion Ability limits are honoured (#12244).
unsigned int extruding_limit = std::lrint(print_config.machine_max_acceleration_extruding.values.front());
auto extruding_limit = LIMITS_UINT(machine_max_acceleration_extruding);
if (print_config.gcode_flavor.value == gcfKlipper) {
unsigned int x_limit = std::lrint(print_config.machine_max_acceleration_x.values.front());
unsigned int y_limit = std::lrint(print_config.machine_max_acceleration_y.values.front());
if (x_limit > 0) extruding_limit = std::min(extruding_limit, x_limit);
if (y_limit > 0) extruding_limit = std::min(extruding_limit, y_limit);
auto x_limit = LIMITS_UINT(machine_max_acceleration_x);
auto y_limit = LIMITS_UINT(machine_max_acceleration_y);
for (size_t i = 0; i < extruding_limit.size(); i++) {
if (x_limit[i] > 0) extruding_limit[i] = std::min(extruding_limit[i], x_limit[i]);
if (y_limit[i] > 0) extruding_limit[i] = std::min(extruding_limit[i], y_limit[i]);
}
}
m_max_acceleration = extruding_limit;
m_max_acceleration = std::move(extruding_limit);
} else {
m_max_acceleration = 0;
m_max_acceleration.clear();
}
if (use_mach_limits && supports_separate_travel_acceleration(print_config.gcode_flavor.value)) {
m_max_travel_acceleration = LIMITS_UINT(machine_max_acceleration_travel);
} else {
m_max_travel_acceleration.clear();
}
m_max_travel_acceleration = static_cast<unsigned int>(
std::round((use_mach_limits && supports_separate_travel_acceleration(print_config.gcode_flavor.value)) ?
print_config.machine_max_acceleration_travel.values.front() :
0));
if (use_mach_limits) {
m_max_jerk_x = std::lrint(print_config.machine_max_jerk_x.values.front());
m_max_jerk_y = std::lrint(print_config.machine_max_jerk_y.values.front());
m_max_junction_deviation = (print_config.machine_max_junction_deviation.values.front());
};
m_max_jerk_z = print_config.machine_max_jerk_z.values.front();
m_max_jerk_e = print_config.machine_max_jerk_e.values.front();
m_max_jerk_x = rounded(LIMITS(machine_max_jerk_x));
m_max_jerk_y = rounded(LIMITS(machine_max_jerk_y));
m_max_junction_deviation = LIMITS(machine_max_junction_deviation);
} else {
m_max_jerk_x.clear();
m_max_jerk_y.clear();
m_max_junction_deviation.clear();
}
m_max_jerk_z = LIMITS(machine_max_jerk_z);
m_max_jerk_e = LIMITS(machine_max_jerk_e);
m_resolution = print_config.resolution.value;
#undef LIMITS
#undef LIMITS_UINT
}
void GCodeWriter::set_extruders(std::vector<unsigned int> extruder_ids)
@@ -212,14 +256,18 @@ std::string GCodeWriter::set_chamber_temperature(int temperature, bool wait)
return gcode.str();
}
#define EXTRUDER_LIMIT(OPT) \
(filament() ? ((OPT).size() <= filament()->extruder_id() ? 0 : (OPT)[filament()->extruder_id()]) : \
((OPT).empty() ? 0 : *std::max_element((OPT).cbegin(), (OPT).cend())))
// copied from PrusaSlicer
std::string GCodeWriter::set_acceleration_internal(Acceleration type, unsigned int acceleration)
{
// Clamp the acceleration to the allowed maximum.
if (type == Acceleration::Print && m_max_acceleration > 0 && acceleration > m_max_acceleration)
acceleration = m_max_acceleration;
if (type == Acceleration::Travel && m_max_travel_acceleration > 0 && acceleration > m_max_travel_acceleration)
acceleration = m_max_travel_acceleration;
if (type == Acceleration::Print && EXTRUDER_LIMIT(m_max_acceleration) > 0 && acceleration > EXTRUDER_LIMIT(m_max_acceleration))
acceleration = EXTRUDER_LIMIT(m_max_acceleration);
if (type == Acceleration::Travel && EXTRUDER_LIMIT(m_max_travel_acceleration) > 0 && acceleration > EXTRUDER_LIMIT(m_max_travel_acceleration))
acceleration = EXTRUDER_LIMIT(m_max_travel_acceleration);
// Are we setting travel acceleration for a flavour that supports separate travel and print acc?
bool separate_travel = (type == Acceleration::Travel && supports_separate_travel_acceleration(this->config.gcode_flavor));
@@ -262,10 +310,10 @@ std::string GCodeWriter::set_jerk_xy(double jerk)
std::ostringstream gcode;
if (FLAVOR_IS(gcfKlipper)) {
// Clamp the jerk to the allowed maximum.
if (m_max_jerk_x > 0 && jerk > m_max_jerk_x)
jerk = m_max_jerk_x;
if (m_max_jerk_y > 0 && jerk > m_max_jerk_y)
jerk = m_max_jerk_y;
if (EXTRUDER_LIMIT(m_max_jerk_x) > 0 && jerk > EXTRUDER_LIMIT(m_max_jerk_x))
jerk = EXTRUDER_LIMIT(m_max_jerk_x);
if (EXTRUDER_LIMIT(m_max_jerk_y) > 0 && jerk > EXTRUDER_LIMIT(m_max_jerk_y))
jerk = EXTRUDER_LIMIT(m_max_jerk_y);
gcode << "SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY=" << jerk;
@@ -274,12 +322,12 @@ std::string GCodeWriter::set_jerk_xy(double jerk)
double jerk_xy = jerk;
// Clamp against the X machine limit
if (m_max_jerk_x > 0 && jerk_xy > m_max_jerk_x)
jerk_xy = m_max_jerk_x;
if (EXTRUDER_LIMIT(m_max_jerk_x) > 0 && jerk_xy > EXTRUDER_LIMIT(m_max_jerk_x))
jerk_xy = EXTRUDER_LIMIT(m_max_jerk_x);
// Clamp against the Y machine limit as well to be safe
if (m_max_jerk_y > 0 && jerk_xy > m_max_jerk_y)
jerk_xy = m_max_jerk_y;
if (EXTRUDER_LIMIT(m_max_jerk_y) > 0 && jerk_xy > EXTRUDER_LIMIT(m_max_jerk_y))
jerk_xy = EXTRUDER_LIMIT(m_max_jerk_y);
// Output the lowest safe limit using ONLY the X parameter
gcode << "M207 X" << jerk_xy;
@@ -287,16 +335,16 @@ std::string GCodeWriter::set_jerk_xy(double jerk)
double jerk_x = jerk;
double jerk_y = jerk;
// Clamp the axis jerk to the allowed maximum.
if (m_max_jerk_x > 0 && jerk > m_max_jerk_x)
jerk_x = m_max_jerk_x;
if (m_max_jerk_y > 0 && jerk > m_max_jerk_y)
jerk_y = m_max_jerk_y;
if (EXTRUDER_LIMIT(m_max_jerk_x) > 0 && jerk > EXTRUDER_LIMIT(m_max_jerk_x))
jerk_x = EXTRUDER_LIMIT(m_max_jerk_x);
if (EXTRUDER_LIMIT(m_max_jerk_y) > 0 && jerk > EXTRUDER_LIMIT(m_max_jerk_y))
jerk_y = EXTRUDER_LIMIT(m_max_jerk_y);
gcode << "M205 X" << jerk_x << " Y" << jerk_y;
}
//the is_bbl check should be in the else statement above so that it doesn't inadverently added Z & E to klipper
if (m_is_bbl_printers)
gcode << std::setprecision(2) << " Z" << m_max_jerk_z << " E" << m_max_jerk_e;
gcode << std::setprecision(2) << " Z" << EXTRUDER_LIMIT(m_max_jerk_z) << " E" << EXTRUDER_LIMIT(m_max_jerk_e);
if (GCodeWriter::full_gcode_comment) gcode << " ; adjust jerk";
gcode << "\n";
@@ -312,8 +360,8 @@ std::string GCodeWriter::set_accel_and_jerk(unsigned int acceleration, double je
throw std::runtime_error(_u8L("set_accel_and_jerk() is only supported by Klipper"));
// Clamp the acceleration to the allowed maximum.
if (m_max_acceleration > 0 && acceleration > m_max_acceleration)
acceleration = m_max_acceleration;
if (EXTRUDER_LIMIT(m_max_acceleration) > 0 && acceleration > EXTRUDER_LIMIT(m_max_acceleration))
acceleration = EXTRUDER_LIMIT(m_max_acceleration);
bool is_empty = true;
std::ostringstream gcode;
@@ -327,10 +375,10 @@ std::string GCodeWriter::set_accel_and_jerk(unsigned int acceleration, double je
is_empty = false;
}
// Clamp the jerk to the allowed maximum.
if (m_max_jerk_x > 0 && jerk > m_max_jerk_x)
jerk = m_max_jerk_x;
if (m_max_jerk_y > 0 && jerk > m_max_jerk_y)
jerk = m_max_jerk_y;
if (EXTRUDER_LIMIT(m_max_jerk_x) > 0 && jerk > EXTRUDER_LIMIT(m_max_jerk_x))
jerk = EXTRUDER_LIMIT(m_max_jerk_x);
if (EXTRUDER_LIMIT(m_max_jerk_y) > 0 && jerk > EXTRUDER_LIMIT(m_max_jerk_y))
jerk = EXTRUDER_LIMIT(m_max_jerk_y);
if (jerk > 0.01 && !is_approx(jerk, m_last_jerk)) {
gcode << " SQUARE_CORNER_VELOCITY=" << jerk;
@@ -351,13 +399,13 @@ std::string GCodeWriter::set_accel_and_jerk(unsigned int acceleration, double je
std::string GCodeWriter::set_junction_deviation(double junction_deviation){
std::ostringstream gcode;
if (FLAVOR_IS(gcfMarlinFirmware) && m_max_junction_deviation > 0 && junction_deviation > 0) {
if (FLAVOR_IS(gcfMarlinFirmware) && EXTRUDER_LIMIT(m_max_junction_deviation) > 0 && junction_deviation > 0) {
// Clamp the junction deviation to the allowed maximum.
gcode << "M205 J";
if (junction_deviation <= m_max_junction_deviation) {
if (junction_deviation <= EXTRUDER_LIMIT(m_max_junction_deviation)) {
gcode << std::fixed << std::setprecision(3) << junction_deviation;
} else {
gcode << std::fixed << std::setprecision(3) << m_max_junction_deviation;
gcode << std::fixed << std::setprecision(3) << EXTRUDER_LIMIT(m_max_junction_deviation);
}
if (GCodeWriter::full_gcode_comment) {
gcode << " ; Junction Deviation";
@@ -610,7 +658,7 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com
GCodeG1Formatter w;
w.emit_xy(point_on_plate);
auto speed = m_is_first_layer
? this->config.get_abs_value("initial_layer_travel_speed") : this->config.travel_speed.value;
? this->config.get_abs_value_at("initial_layer_travel_speed", get_extruder_index(this->config, filament()->id())) : this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id()));
w.emit_f(speed * 60.0);
//BBS
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
@@ -696,7 +744,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
// BBS
Vec3d dest_point = point;
auto travel_speed =
m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed") : this->config.travel_speed.value;
m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", get_extruder_index(this->config, filament()->id())) : this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id()));
//BBS: a z_hop need to be handle when travel
if (std::abs(m_to_lift) > EPSILON) {
assert(std::abs(m_lifted) < EPSILON);
@@ -793,13 +841,13 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
{
//force to move xy first then z after filament change
w.emit_xy(Vec2d(point_on_plate.x(), point_on_plate.y()));
w.emit_f(this->config.travel_speed.value * 60.0);
w.emit_f(this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())) * 60.0);
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
out_string = w.string() + _travel_to_z(point_on_plate.z(), comment);
} else {
GCodeG1Formatter w;
w.emit_xyz(point_on_plate);
w.emit_f(this->config.travel_speed.value * 60.0);
w.emit_f(this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())) * 60.0);
w.emit_comment(GCodeWriter::full_gcode_comment, comment);
out_string = w.string();
}
@@ -832,10 +880,10 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment)
{
m_pos(2) = z;
double speed = this->config.travel_speed_z.value;
double speed = this->config.travel_speed_z.get_at(get_extruder_index(this->config, filament()->id()));
if (speed == 0.) {
speed = m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed")
: this->config.travel_speed.value;
speed = m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", get_extruder_index(this->config, filament()->id()))
: this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id()));
}
GCodeG1Formatter w;
@@ -849,11 +897,11 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment)
std::string GCodeWriter::_spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment)
{
std::string output;
double speed = this->config.travel_speed_z.value;
double speed = this->config.travel_speed_z.get_at(get_extruder_index(this->config, filament()->id()));
if (speed == 0.) {
speed = m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed")
: this->config.travel_speed.value;
speed = m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", get_extruder_index(this->config, filament()->id()))
: this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id()));
}
if (!this->config.enable_arc_fitting) { // Orca: if arc fitting is disabled, approximate the arc with small linear segments
+13 -13
View File
@@ -135,22 +135,22 @@ public:
bool m_single_extruder_multi_material;
std::vector<Extruder*> m_curr_filament_extruder;
int m_curr_extruder_id;
unsigned int m_last_acceleration;
unsigned int m_last_travel_acceleration;
unsigned int m_max_travel_acceleration;
unsigned int m_last_acceleration;
unsigned int m_last_travel_acceleration;
std::vector<unsigned int> m_max_travel_acceleration;
// Limit for setting the acceleration, to respect the machine limits set for the Marlin firmware.
// If set to zero, the limit is not in action.
unsigned int m_max_acceleration;
double m_max_jerk_x;
double m_max_jerk_y;
double m_last_jerk;
double m_max_jerk_z;
double m_max_jerk_e;
double m_max_junction_deviation;
// If set to zero, the limit is not in action. Indexed by 0-based physical nozzle id.
std::vector<unsigned int> m_max_acceleration;
std::vector<double> m_max_jerk_x;
std::vector<double> m_max_jerk_y;
double m_last_jerk;
std::vector<double> m_max_jerk_z;
std::vector<double> m_max_jerk_e;
std::vector<double> m_max_junction_deviation;
unsigned int m_travel_acceleration;
unsigned int m_travel_jerk;
// unsigned int m_travel_acceleration;
// unsigned int m_travel_jerk;
//BBS
+6 -6
View File
@@ -136,7 +136,7 @@ ExPolygons Layer::merged(float offset_scaled) const
return out;
}
bool Layer::is_perimeter_compatible(const PrintRegion& a, const PrintRegion& b)
bool Layer::is_perimeter_compatible(const Print& print, const PrintRegion& a, const PrintRegion& b)
{
const PrintRegionConfig& config = a.config();
const PrintRegionConfig& other_config = b.config();
@@ -146,10 +146,10 @@ bool Layer::is_perimeter_compatible(const PrintRegion& a, const PrintRegion& b)
&& config.wall_loops == other_config.wall_loops
&& config.wall_sequence == other_config.wall_sequence
&& config.is_infill_first == other_config.is_infill_first
&& config.inner_wall_speed == other_config.inner_wall_speed
&& config.outer_wall_speed == other_config.outer_wall_speed
&& config.small_perimeter_speed == other_config.small_perimeter_speed
&& config.gap_infill_speed.value == other_config.gap_infill_speed.value
&& config.inner_wall_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) == other_config.inner_wall_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id))
&& config.outer_wall_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) == other_config.outer_wall_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id))
&& config.small_perimeter_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) == other_config.small_perimeter_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id))
&& config.gap_infill_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) == other_config.gap_infill_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id))
&& config.filter_out_gap_fill.value == other_config.filter_out_gap_fill.value
&& config.detect_overhang_wall == other_config.detect_overhang_wall
&& config.overhang_reverse == other_config.overhang_reverse
@@ -209,7 +209,7 @@ void Layer::make_perimeters()
if (! (*it)->slices.empty()) {
LayerRegion* other_layerm = *it;
const PrintRegion &other_region = other_layerm->region();
if (is_perimeter_compatible(this_region, other_region))
if (is_perimeter_compatible(*m_object->print(), this_region, other_region))
{
other_layerm->perimeters.clear();
other_layerm->fills.clear();
+2 -1
View File
@@ -17,6 +17,7 @@ class LayerRegion;
using LayerRegionPtrs = std::vector<LayerRegion*>;
class PrintRegion;
class PrintObject;
class Print;
namespace FillAdaptive {
struct Octree;
@@ -186,7 +187,7 @@ public:
}
// Whether two regions can be printed in a continues perimeter
static bool is_perimeter_compatible(const PrintRegion& a, const PrintRegion& b);
static bool is_perimeter_compatible(const Print& print, const PrintRegion& a, const PrintRegion& b);
void make_perimeters();
// Phony version of make_fills() without parameters for Perl integration only.
void make_fills() { this->make_fills(nullptr, nullptr); }
+13 -13
View File
@@ -2972,31 +2972,31 @@ void Model::setPrintSpeedTable(const DynamicPrintConfig& config, const PrintConf
//Slic3r::DynamicPrintConfig config = wxGetApp().preset_bundle->full_config();
printSpeedMap.maxSpeed = 0;
if (config.has("inner_wall_speed")) {
printSpeedMap.perimeterSpeed = config.opt_float("inner_wall_speed");
printSpeedMap.perimeterSpeed = config.opt_float_nullable("inner_wall_speed", 0);
if (printSpeedMap.perimeterSpeed > printSpeedMap.maxSpeed)
printSpeedMap.maxSpeed = printSpeedMap.perimeterSpeed;
}
if (config.has("outer_wall_speed")) {
printSpeedMap.externalPerimeterSpeed = config.opt_float("outer_wall_speed");
printSpeedMap.externalPerimeterSpeed = config.opt_float_nullable("outer_wall_speed", 0);
printSpeedMap.maxSpeed = std::max(printSpeedMap.maxSpeed, printSpeedMap.externalPerimeterSpeed);
}
if (config.has("sparse_infill_speed")) {
printSpeedMap.infillSpeed = config.opt_float("sparse_infill_speed");
printSpeedMap.infillSpeed = config.opt_float_nullable("sparse_infill_speed", 0);
if (printSpeedMap.infillSpeed > printSpeedMap.maxSpeed)
printSpeedMap.maxSpeed = printSpeedMap.infillSpeed;
}
if (config.has("internal_solid_infill_speed")) {
printSpeedMap.solidInfillSpeed = config.opt_float("internal_solid_infill_speed");
printSpeedMap.solidInfillSpeed = config.opt_float_nullable("internal_solid_infill_speed", 0);
if (printSpeedMap.solidInfillSpeed > printSpeedMap.maxSpeed)
printSpeedMap.maxSpeed = printSpeedMap.solidInfillSpeed;
}
if (config.has("top_surface_speed")) {
printSpeedMap.topSolidInfillSpeed = config.opt_float("top_surface_speed");
printSpeedMap.topSolidInfillSpeed = config.opt_float_nullable("top_surface_speed", 0);
if (printSpeedMap.topSolidInfillSpeed > printSpeedMap.maxSpeed)
printSpeedMap.maxSpeed = printSpeedMap.topSolidInfillSpeed;
}
if (config.has("support_speed")) {
printSpeedMap.supportSpeed = config.opt_float("support_speed");
printSpeedMap.supportSpeed = config.opt_float_nullable("support_speed", 0);
if (printSpeedMap.supportSpeed > printSpeedMap.maxSpeed)
printSpeedMap.maxSpeed = printSpeedMap.supportSpeed;
@@ -3228,21 +3228,21 @@ double Model::findMaxSpeed(const ModelObject* object) {
double smallPerimeterSpeedObj = Model::printSpeedMap.smallPerimeterSpeed;
for (std::string objectKey : objectKeys) {
if (objectKey == "inner_wall_speed"){
perimeterSpeedObj = object->config.opt_float(objectKey);
perimeterSpeedObj = object->config.get().opt_float_nullable(objectKey, 0);
externalPerimeterSpeedObj = Model::printSpeedMap.externalPerimeterSpeed / Model::printSpeedMap.perimeterSpeed * perimeterSpeedObj;
}
if (objectKey == "sparse_infill_speed")
infillSpeedObj = object->config.opt_float(objectKey);
infillSpeedObj = object->config.get().opt_float_nullable(objectKey, 0);
if (objectKey == "internal_solid_infill_speed")
solidInfillSpeedObj = object->config.opt_float(objectKey);
solidInfillSpeedObj = object->config.get().opt_float_nullable(objectKey, 0);
if (objectKey == "top_surface_speed")
topSolidInfillSpeedObj = object->config.opt_float(objectKey);
topSolidInfillSpeedObj = object->config.get().opt_float_nullable(objectKey, 0);
if (objectKey == "support_speed")
supportSpeedObj = object->config.opt_float(objectKey);
supportSpeedObj = object->config.get().opt_float_nullable(objectKey, 0);
if (objectKey == "outer_wall_speed")
externalPerimeterSpeedObj = object->config.opt_float(objectKey);
externalPerimeterSpeedObj = object->config.get().opt_float_nullable(objectKey, 0);
if (objectKey == "small_perimeter_speed")
smallPerimeterSpeedObj = object->config.opt_float(objectKey);
smallPerimeterSpeedObj = object->config.get().opt_float_nullable(objectKey, 0);
}
objMaxSpeed = std::max(perimeterSpeedObj, std::max(externalPerimeterSpeedObj, std::max(infillSpeedObj, std::max(solidInfillSpeedObj, std::max(topSolidInfillSpeedObj, std::max(supportSpeedObj, std::max(smallPerimeterSpeedObj, objMaxSpeed)))))));
if (objMaxSpeed <= 0) objMaxSpeed = 250.;
+1 -1
View File
@@ -1352,7 +1352,7 @@ static inline std::vector<std::vector<ExPolygons>> segmentation_top_and_bottom_l
out.extrusion_width = std::max<float>(out.extrusion_width, outer_wall_line_width);
out.top_shell_layers = std::max<int>(out.top_shell_layers, config.top_shell_layers);
out.bottom_shell_layers = std::max<int>(out.bottom_shell_layers, config.bottom_shell_layers);
out.small_region_threshold = config.gap_infill_speed.value > 0 ?
out.small_region_threshold = config.gap_infill_speed.get_at(print_object.print()->get_extruder_id(config.outer_wall_filament_id - 1)) > 0 ?
// Gap fill enabled. Enable a single line of 1/2 extrusion width.
0.5f * outer_wall_line_width :
// Gap fill disabled. Enable two lines slightly overlapping.
+2 -2
View File
@@ -581,7 +581,7 @@ void PerimeterGenerator::split_top_surfaces(const ExPolygons &orig_polygons, ExP
coord_t ext_perimeter_width = this->ext_perimeter_flow.scaled_width();
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
bool has_gap_fill = this->config->gap_infill_speed.value > 0;
bool has_gap_fill = this->config->gap_infill_speed.get_at(get_extruder_index(*print_config, this->config->outer_wall_filament_id - 1)) > 0;
// split the polygons with top/not_top
// get the offset from solid surface anchor
@@ -1189,7 +1189,7 @@ void PerimeterGenerator::process_classic()
// internal flow which is unrelated.
coord_t min_spacing = coord_t(perimeter_spacing * (1 - INSET_OVERLAP_TOLERANCE));
coord_t ext_min_spacing = coord_t(ext_perimeter_spacing * (1 - INSET_OVERLAP_TOLERANCE));
bool has_gap_fill = this->config->gap_infill_speed.value > 0;
bool has_gap_fill = this->config->gap_infill_speed.get_at(get_extruder_index(*print_config, this->config->outer_wall_filament_id - 1)) > 0;
// BBS: this flow is for smaller external perimeter for small area
coord_t ext_min_spacing_smaller = coord_t(ext_perimeter_spacing * (1 - SMALLER_EXT_INSET_OVERLAP_TOLERANCE));
+2 -2
View File
@@ -3832,9 +3832,9 @@ void PresetBundle::update_filament_count()
: filament_presets.back());
}
bool PresetBundle::support_different_extruders()
bool PresetBundle::support_different_extruders() const
{
Preset& printer_preset = this->printers.get_edited_preset();
const Preset& printer_preset = this->printers.get_edited_preset();
int extruder_count;
bool supported = printer_preset.config.support_different_extruders(extruder_count);
+1 -1
View File
@@ -370,7 +370,7 @@ public:
//BBS: add some functions for multiple extruders
int get_printer_extruder_count() const;
bool support_different_extruders();
bool support_different_extruders() const;
// Orca: Ensure filament_presets has at least one slot per nozzle on FFF printers.
// Called from (load|update)_selections before the parallel project_config arrays
+145 -139
View File
@@ -1349,8 +1349,8 @@ StringObjectException Print::validate(std::vector<StringObjectException> *warnin
const auto all_regions = m_objects.front()->all_regions();
if (all_regions.size() > 1) {
// Orca: make sure regions are not compatible
if (std::any_of(all_regions.begin() + 1, all_regions.end(), [ra = all_regions.front()](const auto rb) {
return !Layer::is_perimeter_compatible(ra, rb);
if (std::any_of(all_regions.begin() + 1, all_regions.end(), [this, ra = all_regions.front()](const auto rb) {
return !Layer::is_perimeter_compatible(*this, ra, rb);
})) {
return {L("Spiral (vase) mode does not work when an object contains more than one material."), nullptr, "spiral_mode"};
}
@@ -1782,146 +1782,152 @@ StringObjectException Print::validate(std::vector<StringObjectException> *warnin
// shrinkage warnings below.
StringObjectException motion_warning;
try {
auto check_motion_ability_object_setting = [&](const std::vector<std::string>& keys_to_check, double limit) -> std::string {
std::string warning_key;
for (const auto& key : keys_to_check) {
if (m_default_object_config.get_abs_value(key) > limit) {
warning_key = key;
break;
}
}
return warning_key;
};
auto check_motion_ability_region_setting = [&](const std::vector<std::string>& keys_to_check, double limit) -> std::string {
std::string warning_key;
for (const auto& key : keys_to_check) {
if (m_default_region_config.get_abs_value(key) > limit) {
warning_key = key;
break;
}
}
return warning_key;
};
std::string warning_key;
const auto max_junction_deviation = m_config.machine_max_junction_deviation.values[0];
const bool ignore_jerk_validation = m_config.gcode_flavor == gcfMarlinFirmware && max_junction_deviation > 0;
// check jerk
if (!ignore_jerk_validation) {
if (m_default_object_config.default_jerk == 1 || m_default_object_config.outer_wall_jerk == 1 ||
m_default_object_config.inner_wall_jerk == 1) {
motion_warning.string = L("Setting the jerk speed too low could lead to artifacts on curved surfaces");
if (m_default_object_config.outer_wall_jerk == 1)
warning_key = "outer_wall_jerk";
else if (m_default_object_config.inner_wall_jerk == 1)
warning_key = "inner_wall_jerk";
else
warning_key = "default_jerk";
motion_warning.opt_key = warning_key;
}
if (warning_key.empty() && m_default_object_config.default_jerk > 0) {
std::vector<std::string> jerk_to_check = {"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk",
"top_surface_jerk", "initial_layer_jerk", "travel_jerk"};
const auto max_jerk = std::min(m_config.machine_max_jerk_x.values[0], m_config.machine_max_jerk_y.values[0]);
warning_key.clear();
warning_key = check_motion_ability_object_setting(jerk_to_check, max_jerk);
if (!warning_key.empty()) {
motion_warning.string = L(
"The jerk setting exceeds the printer's maximum jerk (machine_max_jerk_x/machine_max_jerk_y).\n"
"Orca will automatically cap the jerk speed to ensure it doesn't surpass the printer's capabilities.\n"
"You can adjust the maximum jerk setting in your printer's configuration to get higher speeds.");
motion_warning.opt_key = warning_key;
}
}
}
// check junction deviation
else if (m_default_object_config.default_junction_deviation.value > max_junction_deviation) {
motion_warning.string = L( "Junction deviation setting exceeds the printer's maximum value (machine_max_junction_deviation).\n"
"Orca will automatically cap the junction deviation to ensure it doesn't surpass the printer's capabilities.\n"
"You can adjust the machine_max_junction_deviation value in your printer's configuration to get higher limits.");
motion_warning.opt_key = "default_junction_deviation";
}
// check acceleration
const auto max_accel = m_config.machine_max_acceleration_extruding.values[0];
if (warning_key.empty() && m_default_object_config.default_acceleration > 0 && max_accel > 0) {
const bool support_travel_acc = (m_config.gcode_flavor == gcfRepetier || m_config.gcode_flavor == gcfMarlinFirmware ||
m_config.gcode_flavor == gcfRepRapFirmware);
std::vector<std::string> accel_to_check;
if (!support_travel_acc)
accel_to_check = {
"default_acceleration",
"inner_wall_acceleration",
"outer_wall_acceleration",
"bridge_acceleration",
"initial_layer_acceleration",
"sparse_infill_acceleration",
"internal_solid_infill_acceleration",
"top_surface_acceleration",
"travel_acceleration",
};
else
accel_to_check = {
"default_acceleration",
"inner_wall_acceleration",
"outer_wall_acceleration",
"bridge_acceleration",
"initial_layer_acceleration",
"sparse_infill_acceleration",
"internal_solid_infill_acceleration",
"top_surface_acceleration",
};
warning_key = check_motion_ability_object_setting(accel_to_check, max_accel);
if (!warning_key.empty()) {
motion_warning.string = L("The acceleration setting exceeds the printer's maximum acceleration "
"(machine_max_acceleration_extruding).\nOrca will "
"automatically cap the acceleration speed to ensure it doesn't surpass the printer's "
"capabilities.\nYou can adjust the "
"machine_max_acceleration_extruding value in your printer's configuration to get higher speeds.");
motion_warning.opt_key = warning_key;
}
if (support_travel_acc) {
const auto max_travel = m_config.machine_max_acceleration_travel.values[0];
if (max_travel > 0) {
accel_to_check = {
"travel_acceleration",
};
warning_key = check_motion_ability_object_setting(accel_to_check, max_travel);
if (!warning_key.empty()) {
motion_warning.string = L(
"The travel acceleration setting exceeds the printer's maximum travel acceleration "
"(machine_max_acceleration_travel).\nOrca will "
"automatically cap the travel acceleration speed to ensure it doesn't surpass the printer's "
"capabilities.\nYou can adjust the "
"machine_max_acceleration_travel value in your printer's configuration to get higher speeds.");
motion_warning.opt_key = warning_key;
auto check_extruder = [&](const int extruder_id) {
auto check_motion_ability_object_setting = [&](const std::vector<std::string>& keys_to_check, double limit) -> std::string {
std::string warning_key;
for (const auto& key : keys_to_check) {
if (m_default_object_config.get_abs_value_at(key, extruder_id) > limit) {
warning_key = key;
break;
}
}
}
}
return warning_key;
};
auto check_motion_ability_region_setting = [&](const std::vector<std::string>& keys_to_check, double limit) -> std::string {
std::string warning_key;
for (const auto& key : keys_to_check) {
if (m_default_region_config.get_abs_value_at(key, extruder_id) > limit) {
warning_key = key;
break;
}
}
return warning_key;
};
std::string warning_key;
// check speed
// Orca: disable the speed check for now as we don't cap the speed
// if (warning_key.empty()) {
// auto speed_to_check = {"inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed",
// "top_surface_speed", "bridge_speed", "internal_bridge_speed", "gap_infill_speed"};
// const auto max_speed = std::min(m_config.machine_max_speed_x.values[0], m_config.machine_max_speed_y.values[0]);
// warning_key.clear();
// warning_key = check_motion_ability_region_setting(speed_to_check, max_speed);
// if (warning_key.empty() && m_config.travel_speed > max_speed)
// warning_key = "travel_speed";
// if (!warning_key.empty()) {
// warning->string = L(
// "The speed setting exceeds the printer's maximum speed (machine_max_speed_x/machine_max_speed_y).\nOrca will "
// "automatically cap the print speed to ensure it doesn't surpass the printer's capabilities.\nYou can adjust the "
// "maximum speed setting in your printer's configuration to get higher speeds.");
// warning->opt_key = warning_key;
// }
// }
const auto max_junction_deviation = m_config.machine_max_junction_deviation.values[0]; // TODO: fix this
const bool ignore_jerk_validation = m_config.gcode_flavor == gcfMarlinFirmware && max_junction_deviation > 0;
// check jerk
if (!ignore_jerk_validation) {
if (m_default_object_config.default_jerk.get_at(extruder_id) == 1 || m_default_object_config.outer_wall_jerk.get_at(extruder_id) == 1 ||
m_default_object_config.inner_wall_jerk.get_at(extruder_id) == 1) {
motion_warning.string = L("Setting the jerk speed too low could lead to artifacts on curved surfaces");
if (m_default_object_config.outer_wall_jerk.get_at(extruder_id) == 1)
warning_key = "outer_wall_jerk";
else if (m_default_object_config.inner_wall_jerk.get_at(extruder_id) == 1)
warning_key = "inner_wall_jerk";
else
warning_key = "default_jerk";
motion_warning.opt_key = warning_key;
}
if (warning_key.empty() && m_default_object_config.default_jerk.get_at(extruder_id) > 0) {
std::vector<std::string> jerk_to_check = {"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk",
"top_surface_jerk", "initial_layer_jerk", "travel_jerk"};
const auto max_jerk = std::min(m_config.machine_max_jerk_x.values[0], m_config.machine_max_jerk_y.values[0]);
warning_key.clear();
warning_key = check_motion_ability_object_setting(jerk_to_check, max_jerk);
if (!warning_key.empty()) {
motion_warning.string = L(
"The jerk setting exceeds the printer's maximum jerk (machine_max_jerk_x/machine_max_jerk_y).\n"
"Orca will automatically cap the jerk speed to ensure it doesn't surpass the printer's capabilities.\n"
"You can adjust the maximum jerk setting in your printer's configuration to get higher speeds.");
motion_warning.opt_key = warning_key;
}
}
}
// Check junction deviation
// Orca: Only marlin FW supports max junction deviation. Dont display warning if firmware is not supporting it.
const bool support_max_junction_deviation = ( m_config.gcode_flavor == gcfMarlinFirmware);
if (warning_key.empty() && m_default_object_config.default_junction_deviation.get_at(extruder_id) > max_junction_deviation && support_max_junction_deviation) {
motion_warning.string = L( "Junction deviation setting exceeds the printer's maximum value (machine_max_junction_deviation).\n"
"Orca will automatically cap the junction deviation to ensure it doesn't surpass the printer's capabilities.\n"
"You can adjust the machine_max_junction_deviation value in your printer's configuration to get higher limits.");
motion_warning.opt_key = "default_junction_deviation";
}
// check acceleration
const auto max_accel = m_config.machine_max_acceleration_extruding.values[0];
if (warning_key.empty() && m_default_object_config.default_acceleration.get_at(extruder_id) > 0 && max_accel > 0) {
const bool support_travel_acc = (m_config.gcode_flavor == gcfRepetier || m_config.gcode_flavor == gcfMarlinFirmware ||
m_config.gcode_flavor == gcfRepRapFirmware);
std::vector<std::string> accel_to_check;
if (!support_travel_acc)
accel_to_check = {
"default_acceleration",
"inner_wall_acceleration",
"outer_wall_acceleration",
"bridge_acceleration",
"initial_layer_acceleration",
"sparse_infill_acceleration",
"internal_solid_infill_acceleration",
"top_surface_acceleration",
"travel_acceleration",
};
else
accel_to_check = {
"default_acceleration",
"inner_wall_acceleration",
"outer_wall_acceleration",
"bridge_acceleration",
"initial_layer_acceleration",
"sparse_infill_acceleration",
"internal_solid_infill_acceleration",
"top_surface_acceleration",
};
warning_key = check_motion_ability_object_setting(accel_to_check, max_accel);
if (!warning_key.empty()) {
motion_warning.string = L("The acceleration setting exceeds the printer's maximum acceleration "
"(machine_max_acceleration_extruding).\nOrca will "
"automatically cap the acceleration speed to ensure it doesn't surpass the printer's "
"capabilities.\nYou can adjust the "
"machine_max_acceleration_extruding value in your printer's configuration to get higher speeds.");
motion_warning.opt_key = warning_key;
}
if (support_travel_acc) {
const auto max_travel = m_config.machine_max_acceleration_travel.values[0];
if (max_travel > 0) {
accel_to_check = {
"travel_acceleration",
};
warning_key = check_motion_ability_object_setting(accel_to_check, max_travel);
if (!warning_key.empty()) {
motion_warning.string = L(
"The travel acceleration setting exceeds the printer's maximum travel acceleration "
"(machine_max_acceleration_travel).\nOrca will "
"automatically cap the travel acceleration speed to ensure it doesn't surpass the printer's "
"capabilities.\nYou can adjust the "
"machine_max_acceleration_travel value in your printer's configuration to get higher speeds.");
motion_warning.opt_key = warning_key;
}
}
}
}
// check speed
// Orca: disable the speed check for now as we don't cap the speed
// if (warning_key.empty()) {
// auto speed_to_check = {"inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed",
// "top_surface_speed", "bridge_speed", "internal_bridge_speed", "gap_infill_speed"};
// const auto max_speed = std::min(m_config.machine_max_speed_x.values[0], m_config.machine_max_speed_y.values[0]);
// warning_key.clear();
// warning_key = check_motion_ability_region_setting(speed_to_check, max_speed);
// if (warning_key.empty() && m_config.travel_speed > max_speed)
// warning_key = "travel_speed";
// if (!warning_key.empty()) {
// motion_warning.string = L(
// "The speed setting exceeds the printer's maximum speed (machine_max_speed_x/machine_max_speed_y).\nOrca will "
// "automatically cap the print speed to ensure it doesn't surpass the printer's capabilities.\nYou can adjust the "
// "maximum speed setting in your printer's configuration to get higher speeds.");
// motion_warning.opt_key = warning_key;
// }
// }
};
check_extruder(0); // TODO: check used extruder variants
// check wall sequence and precise outer wall
if (m_default_region_config.precise_outer_wall && m_default_region_config.wall_sequence != WallSequence::InnerOuter)
+1 -1
View File
@@ -1189,7 +1189,7 @@ private:
std::vector<unsigned int> m_slice_used_filaments_first_layer;
//BBS: plate's origin
Vec3d m_origin;
Vec3d m_origin {0, 0, 0};
//BBS: modified_count
int m_modified_count {0};
//BBS
+2 -1
View File
@@ -1163,8 +1163,9 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
//apply extruder related values
if (!extruder_applied) {
new_full_config.update_values_to_printer_extruders(new_full_config, printer_options_with_variant_1, "printer_extruder_id", "printer_extruder_variant");
// variant_2 must be processed first, because variant_1 will make `printer_extruder_id` and `printer_extruder_variant` half of the size that makes `get_index_for_extruder` no longer work properly
new_full_config.update_values_to_printer_extruders(new_full_config, printer_options_with_variant_2, "printer_extruder_id", "printer_extruder_variant", 2);
new_full_config.update_values_to_printer_extruders(new_full_config, printer_options_with_variant_1, "printer_extruder_id", "printer_extruder_variant");
//update print config related with variants
new_full_config.update_values_to_printer_extruders(new_full_config, print_options_with_variant, "print_extruder_id", "print_extruder_variant");
File diff suppressed because it is too large Load Diff
+55 -44
View File
@@ -430,6 +430,17 @@ enum FilamentMapMode {
extern std::string get_extruder_variant_string(ExtruderType extruder_type, NozzleVolumeType nozzle_volume_type);
static std::set<NozzleVolumeType> get_valid_nozzle_volume_type() {
std::set<NozzleVolumeType> type;
for (int i = 0; i <= nvtMaxNozzleVolumeType; ++i) {
auto t = static_cast<NozzleVolumeType>(i);
// TODO: Orca: Support hybrid
//if (t == nvtHybrid) continue;
type.insert(t);
}
return type;
}
std::string get_nozzle_volume_type_string(NozzleVolumeType nozzle_volume_type);
static std::string bed_type_to_gcode_string(const BedType type)
@@ -658,7 +669,7 @@ public:
//BBS
bool is_using_different_extruders();
bool support_different_extruders(int& extruder_count);
bool support_different_extruders(int& extruder_count) const;
int get_index_for_extruder(int extruder_or_filament_id, std::string id_name, ExtruderType extruder_type, NozzleVolumeType nozzle_volume_type, std::string variant_name, unsigned int stride = 1) const;
void update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name, unsigned int stride = 1, unsigned int extruder_id = 0);
void update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name);
@@ -965,13 +976,13 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionInt, support_interface_bottom_layers))
// Spacing between interface lines (the hatching distance). Set zero to get a solid interface.
((ConfigOptionFloat, support_interface_spacing))
((ConfigOptionFloat, support_interface_speed))
((ConfigOptionFloatsNullable, support_interface_speed))
((ConfigOptionEnum<SupportMaterialPattern>, support_base_pattern))
((ConfigOptionEnum<SupportMaterialInterfacePattern>, support_interface_pattern))
// Spacing between support material lines (the hatching distance).
((ConfigOptionFloat, support_base_pattern_spacing))
((ConfigOptionFloat, support_expansion))
((ConfigOptionFloat, support_speed))
((ConfigOptionFloatsNullable, support_speed))
((ConfigOptionEnum<SupportMaterialStyle>, support_style))
// Orca: a flag enabling the ability to override flow ratios
@@ -1039,25 +1050,25 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, min_length_factor))
// Move all acceleration and jerk settings to object
((ConfigOptionFloat, default_acceleration))
((ConfigOptionFloat, outer_wall_acceleration))
((ConfigOptionFloat, inner_wall_acceleration))
((ConfigOptionFloat, top_surface_acceleration))
((ConfigOptionFloat, initial_layer_acceleration))
((ConfigOptionFloatOrPercent, bridge_acceleration))
((ConfigOptionFloat, travel_acceleration))
((ConfigOptionFloatOrPercent, sparse_infill_acceleration))
((ConfigOptionFloatOrPercent, internal_solid_infill_acceleration))
((ConfigOptionFloatsNullable, default_acceleration))
((ConfigOptionFloatsNullable, outer_wall_acceleration))
((ConfigOptionFloatsNullable, inner_wall_acceleration))
((ConfigOptionFloatsNullable, top_surface_acceleration))
((ConfigOptionFloatsNullable, initial_layer_acceleration))
((ConfigOptionFloatsOrPercentsNullable, bridge_acceleration))
((ConfigOptionFloatsNullable, travel_acceleration))
((ConfigOptionFloatsOrPercentsNullable, sparse_infill_acceleration))
((ConfigOptionFloatsOrPercentsNullable, internal_solid_infill_acceleration))
((ConfigOptionFloat, default_jerk))
((ConfigOptionFloat, outer_wall_jerk))
((ConfigOptionFloat, inner_wall_jerk))
((ConfigOptionFloat, infill_jerk))
((ConfigOptionFloat, top_surface_jerk))
((ConfigOptionFloat, initial_layer_jerk))
((ConfigOptionFloat, travel_jerk))
((ConfigOptionFloatsNullable, default_jerk))
((ConfigOptionFloatsNullable, outer_wall_jerk))
((ConfigOptionFloatsNullable, inner_wall_jerk))
((ConfigOptionFloatsNullable, infill_jerk))
((ConfigOptionFloatsNullable, top_surface_jerk))
((ConfigOptionFloatsNullable, initial_layer_jerk))
((ConfigOptionFloatsNullable, travel_jerk))
((ConfigOptionBool, precise_z_height))
((ConfigOptionFloat, default_junction_deviation))
((ConfigOptionFloatsNullable, default_junction_deviation))
((ConfigOptionBool, interlocking_beam))
((ConfigOptionFloat,interlocking_beam_width))
@@ -1084,8 +1095,8 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, bridge_flow))
((ConfigOptionFloatOrPercent, bridge_line_width))
((ConfigOptionFloat, internal_bridge_flow))
((ConfigOptionFloat, bridge_speed))
((ConfigOptionFloatOrPercent, internal_bridge_speed))
((ConfigOptionFloatsNullable, bridge_speed))
((ConfigOptionFloatsOrPercentsNullable, internal_bridge_speed))
((ConfigOptionEnum<EnsureVerticalShellThickness>, ensure_vertical_shell_thickness))
((ConfigOptionPercent, top_surface_density))
((ConfigOptionPercent, bottom_surface_density))
@@ -1093,7 +1104,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionEnum<InfillPattern>, bottom_surface_pattern))
((ConfigOptionEnum<InfillPattern>, internal_solid_infill_pattern))
((ConfigOptionFloatOrPercent, outer_wall_line_width))
((ConfigOptionFloat, outer_wall_speed))
((ConfigOptionFloatsNullable, outer_wall_speed))
((ConfigOptionFloat, infill_direction))
((ConfigOptionFloat, solid_infill_direction))
((ConfigOptionString, solid_infill_rotate_template))
@@ -1122,12 +1133,12 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionInt, fuzzy_skin_ripples_per_layer))
((ConfigOptionPercent, fuzzy_skin_ripple_offset))
((ConfigOptionInt, fuzzy_skin_layers_between_ripple_offset))
((ConfigOptionFloat, gap_infill_speed))
((ConfigOptionFloatsNullable, gap_infill_speed))
((ConfigOptionInt, sparse_infill_filament_id))
((ConfigOptionFloatOrPercent, sparse_infill_line_width))
((ConfigOptionPercent, infill_wall_overlap))
((ConfigOptionPercent, top_bottom_infill_wall_overlap))
((ConfigOptionFloat, sparse_infill_speed))
((ConfigOptionFloatsNullable, sparse_infill_speed))
((ConfigOptionPercent, skeleton_infill_density))
((ConfigOptionPercent, skin_infill_density))
((ConfigOptionFloat, infill_lock_depth))
@@ -1159,7 +1170,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionInt, outer_wall_filament_id))
((ConfigOptionInt, inner_wall_filament_id))
((ConfigOptionFloatOrPercent, inner_wall_line_width))
((ConfigOptionFloat, inner_wall_speed))
((ConfigOptionFloatsNullable, inner_wall_speed))
// Total number of perimeters.
((ConfigOptionInt, wall_loops))
((ConfigOptionBool, alternate_extra_wall))
@@ -1168,19 +1179,19 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionInt, top_surface_filament_id))
((ConfigOptionInt, bottom_surface_filament_id))
((ConfigOptionFloatOrPercent, internal_solid_infill_line_width))
((ConfigOptionFloat, internal_solid_infill_speed))
((ConfigOptionFloatsNullable, internal_solid_infill_speed))
// Detect thin walls.
((ConfigOptionBool, detect_thin_wall))
((ConfigOptionFloatOrPercent, top_surface_line_width))
((ConfigOptionInt, top_shell_layers))
((ConfigOptionFloat, top_shell_thickness))
((ConfigOptionFloat, top_surface_speed))
((ConfigOptionFloatsNullable, top_surface_speed))
//BBS
((ConfigOptionBool, enable_overhang_speed))
((ConfigOptionFloatOrPercent, overhang_1_4_speed))
((ConfigOptionFloatOrPercent, overhang_2_4_speed))
((ConfigOptionFloatOrPercent, overhang_3_4_speed))
((ConfigOptionFloatOrPercent, overhang_4_4_speed))
((ConfigOptionBoolsNullable, enable_overhang_speed))
((ConfigOptionFloatsOrPercentsNullable, overhang_1_4_speed))
((ConfigOptionFloatsOrPercentsNullable, overhang_2_4_speed))
((ConfigOptionFloatsOrPercentsNullable, overhang_3_4_speed))
((ConfigOptionFloatsOrPercentsNullable, overhang_4_4_speed))
((ConfigOptionBool, only_one_wall_top))
//SoftFever
@@ -1196,8 +1207,8 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, precise_outer_wall))
((ConfigOptionPercent, bridge_density))
((ConfigOptionFloat, filter_out_gap_fill))
((ConfigOptionFloatOrPercent, small_perimeter_speed))
((ConfigOptionFloat, small_perimeter_threshold))
((ConfigOptionFloatsOrPercentsNullable, small_perimeter_speed))
((ConfigOptionFloatsNullable, small_perimeter_threshold))
((ConfigOptionFloat, top_solid_infill_flow_ratio))
((ConfigOptionFloat, bottom_solid_infill_flow_ratio))
((ConfigOptionFloatOrPercent, infill_anchor))
@@ -1206,7 +1217,7 @@ PRINT_CONFIG_CLASS_DEFINE(
// Orca
((ConfigOptionBool, make_overhang_printable))
((ConfigOptionBool, extra_perimeters_on_overhangs))
((ConfigOptionBool, slowdown_for_curled_perimeters))
((ConfigOptionBoolsNullable, slowdown_for_curled_perimeters))
((ConfigOptionBool, hole_to_polyhole))
((ConfigOptionFloatOrPercent, hole_to_polyhole_threshold))
((ConfigOptionBool, hole_to_polyhole_twisted))
@@ -1369,7 +1380,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, max_volumetric_extrusion_rate_slope))
((ConfigOptionFloat, max_volumetric_extrusion_rate_slope_segment_length))
((ConfigOptionBool, extrusion_rate_smoothing_external_perimeter_only))
((ConfigOptionBool, extrusion_rate_smoothing_external_perimeter_only))
((ConfigOptionPercents, retract_before_wipe))
@@ -1401,8 +1412,8 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionString, change_extrusion_role_gcode))
((ConfigOptionString, process_change_extrusion_role_gcode))
((ConfigOptionStrings, filament_change_extrusion_role_gcode))
((ConfigOptionFloat, travel_speed))
((ConfigOptionFloat, travel_speed_z))
((ConfigOptionFloatsNullable, travel_speed))
((ConfigOptionFloatsNullable, travel_speed_z))
((ConfigOptionBool, silent_mode))
((ConfigOptionString, machine_pause_gcode))
((ConfigOptionString, template_custom_gcode))
@@ -1426,9 +1437,9 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, use_relative_e_distances))
((ConfigOptionBool, accel_to_decel_enable))
((ConfigOptionPercent, accel_to_decel_factor))
((ConfigOptionFloatOrPercent, initial_layer_travel_speed))
((ConfigOptionFloatOrPercent, initial_layer_travel_acceleration))
((ConfigOptionFloatOrPercent, initial_layer_travel_jerk))
((ConfigOptionFloatsOrPercentsNullable, initial_layer_travel_speed))
((ConfigOptionFloatsOrPercentsNullable, initial_layer_travel_acceleration))
((ConfigOptionFloatsOrPercentsNullable, initial_layer_travel_jerk))
((ConfigOptionBool, bbl_calib_mark_logo))
((ConfigOptionBool, disable_m73))
@@ -1538,10 +1549,10 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionInts, complete_print_exhaust_fan_speed))
((ConfigOptionFloatOrPercent, initial_layer_line_width))
((ConfigOptionFloat, initial_layer_print_height))
((ConfigOptionFloat, initial_layer_speed))
((ConfigOptionFloatsNullable, initial_layer_speed))
//BBS
((ConfigOptionFloat, initial_layer_infill_speed))
((ConfigOptionFloatsNullable, initial_layer_infill_speed))
((ConfigOptionInts, nozzle_temperature_initial_layer))
((ConfigOptionInts, full_fan_speed_layer))
((ConfigOptionFloats, fan_max_speed))
+9 -7
View File
@@ -897,13 +897,15 @@ void PrintObject::generate_support_material()
void PrintObject::estimate_curled_extrusions()
{
if (this->set_started(posEstimateCurledExtrusions)) {
if ( std::any_of(this->print()->m_print_regions.begin(), this->print()->m_print_regions.end(),
[](const PrintRegion *region) { return region->config().enable_overhang_speed.getBool(); })) {
if ( std::any_of(this->print()->m_print_regions.begin(), this->print()->m_print_regions.end(), [](const PrintRegion* region) {
const auto& cfg = region->config().enable_overhang_speed.values;
return std::any_of(cfg.begin(), cfg.end(), [](const unsigned char v) { return (bool) v; });
})) {
// Estimate curling of support material and add it to the malformaition lines of each layer
float support_flow_width = support_material_flow(this, this->config().layer_height).width();
SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values,
float(this->print()->default_object_config().inner_wall_acceleration.getFloat()),
/*float(this->print()->default_object_config().inner_wall_acceleration.getFloat()),*/
this->config().raft_layers.getInt(), this->config().brim_type.value,
float(this->config().brim_width.getFloat())};
SupportSpotsGenerator::estimate_malformations(this->layers(), params);
@@ -1150,11 +1152,11 @@ bool PrintObject::invalidate_state_by_config_options(
// todo multi_extruders: Parameter migration between single and double extruder printers
auto is_gap_fill_changed_state_due_to_speed = [&opt_key, &old_config, &new_config]() -> bool {
if (opt_key == "gap_infill_speed") {
const auto *old_gap_fill_speed = old_config.option<ConfigOptionFloat>(opt_key);
const auto *new_gap_fill_speed = new_config.option<ConfigOptionFloat>(opt_key);
const auto *old_gap_fill_speed = old_config.option<ConfigOptionFloatsNullable>(opt_key);
const auto *new_gap_fill_speed = new_config.option<ConfigOptionFloatsNullable>(opt_key);
assert(old_gap_fill_speed && new_gap_fill_speed);
return (old_gap_fill_speed->value > 0.f && new_gap_fill_speed->value == 0.f) ||
(old_gap_fill_speed->value == 0.f && new_gap_fill_speed->value > 0.f);
return (old_gap_fill_speed->values.size() != new_gap_fill_speed->values.size())
|| (old_gap_fill_speed->values != new_gap_fill_speed->values);
}
return false;
};
@@ -18,8 +18,8 @@ namespace SupportSpotsGenerator {
struct Params
{
Params(
const std::vector<std::string> &filament_types, float max_acceleration, int raft_layers_count, BrimType brim_type, float brim_width)
: max_acceleration(max_acceleration), raft_layers_count(raft_layers_count), brim_type(brim_type), brim_width(brim_width)
const std::vector<std::string> &filament_types/*, float max_acceleration*/, int raft_layers_count, BrimType brim_type, float brim_width)
: /*max_acceleration(max_acceleration), */raft_layers_count(raft_layers_count), brim_type(brim_type), brim_width(brim_width)
{
if (filament_types.size() > 1) {
BOOST_LOG_TRIVIAL(warning)
@@ -36,8 +36,8 @@ struct Params
// the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2]
const float bridge_distance = 16.0f; // mm
const float max_acceleration; // mm/s^2 ; max acceleration of object in XY -- should be applicable only to printers with bed slinger,
// however we do not have such info yet. The force is usually small anyway, so not such a big deal to include it everytime
// const float max_acceleration; // mm/s^2 ; max acceleration of object in XY -- should be applicable only to printers with bed slinger,
// // however we do not have such info yet. The force is usually small anyway, so not such a big deal to include it everytime
const int raft_layers_count;
std::string filament_type;
+1 -1
View File
@@ -16,7 +16,7 @@ float CalibPressureAdvance::find_optimal_PA_speed(const DynamicPrintConfig &conf
const float nozzle_diameter = config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(extruder_id);
if (line_width <= 0.) line_width = Flow::auto_extrusion_width(frPerimeter, nozzle_diameter);
Flow pattern_line = Flow(line_width, layer_height, nozzle_diameter);
auto pa_speed = std::min(std::max(general_suggested_min_speed, config.option<ConfigOptionFloat>("outer_wall_speed")->value),
auto pa_speed = std::min(std::max(general_suggested_min_speed, config.option<ConfigOptionFloatsNullable>("outer_wall_speed")->get_at(extruder_id)),
filament_max_volumetric_speed / pattern_line.mm3_per_mm());
return std::floor(pa_speed);
+5 -5
View File
@@ -280,7 +280,7 @@ private:
struct SuggestedConfigCalibPAPattern
{
const std::vector<std::pair<std::string, double>> float_pairs{{"initial_layer_speed", 30}};
const std::vector<std::pair<std::string, std::vector<double>>> floats_pairs{{"initial_layer_speed", {30}}};
const std::vector<std::pair<std::string, double>> nozzle_ratio_pairs{{"line_width", 112.5}, {"initial_layer_line_width", 140}};
@@ -312,13 +312,13 @@ public:
protected:
// todo multi_extruders:
double speed_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_speed")->value; };
double speed_perimeter() const { return m_config.option<ConfigOptionFloat>("outer_wall_speed")->value; };
double accel_perimeter() const { return m_config.option<ConfigOptionFloat>("outer_wall_acceleration")->value; }
double speed_first_layer() const { return m_config.get_abs_value_at("initial_layer_speed", m_params.extruder_id); };
double speed_perimeter() const { return m_config.get_abs_value_at("outer_wall_speed", m_params.extruder_id); };
double accel_perimeter() const { return m_config.get_abs_value_at("outer_wall_acceleration", m_params.extruder_id); }
double line_width_first_layer() const
{
// TODO: FIXME: find out current filament/extruder?
const double nozzle_diameter = m_config.opt_float("nozzle_diameter", 0);
const double nozzle_diameter = m_config.opt_float("nozzle_diameter", m_params.extruder_id);
return m_config.get_abs_value("initial_layer_line_width", nozzle_diameter);
};
double line_width() const;