fix/merge machine limits

This commit is contained in:
supermerill 2020-10-27 20:01:40 +01:00
parent b63d791685
commit 837c3e9891
11 changed files with 198 additions and 118 deletions

View File

@ -10,7 +10,7 @@ group:extruders_count_event:milling_count_event:Capabilities
setting:single_extruder_multi_material setting:single_extruder_multi_material
milling_count milling_count
group:Print Host upload group:Print Host upload
printhost print_host_upload_description
group:silent_mode_event:Firmware group:silent_mode_event:Firmware
setting:gcode_flavor setting:gcode_flavor
setting:silent_mode setting:silent_mode

View File

@ -860,7 +860,7 @@ namespace DoExport {
// shall be adjusted as well to produce a G-code block compatible with the particular firmware flavor. // shall be adjusted as well to produce a G-code block compatible with the particular firmware flavor.
// supermerill: done // supermerill: done
if (true) { if (true) {
if (config.machine_limits_usage.value != MachineLimitsUsage::Ignore) { if (config.machine_limits_usage.value < MachineLimitsUsage::Limits) {
normal_time_estimator.set_max_acceleration((float)config.machine_max_acceleration_extruding.values[0]); normal_time_estimator.set_max_acceleration((float)config.machine_max_acceleration_extruding.values[0]);
normal_time_estimator.set_retract_acceleration((float)config.machine_max_acceleration_retracting.values[0]); normal_time_estimator.set_retract_acceleration((float)config.machine_max_acceleration_retracting.values[0]);
normal_time_estimator.set_max_travel_acceleration((float)config.machine_max_acceleration_travel.values[0]); normal_time_estimator.set_max_travel_acceleration((float)config.machine_max_acceleration_travel.values[0]);
@ -886,7 +886,7 @@ namespace DoExport {
silent_time_estimator.set_dialect(config.gcode_flavor); silent_time_estimator.set_dialect(config.gcode_flavor);
silent_time_estimator.set_extrusion_axis(config.get_extrusion_axis()[0]); silent_time_estimator.set_extrusion_axis(config.get_extrusion_axis()[0]);
if (config.machine_limits_usage.value != MachineLimitsUsage::Ignore) { if (config.machine_limits_usage.value < MachineLimitsUsage::Limits) {
/* "Stealth mode" values can be just a copy of "normal mode" values /* "Stealth mode" values can be just a copy of "normal mode" values
* (when they aren't input for a printer preset). * (when they aren't input for a printer preset).
* Thus, use back value from values, instead of second one, which could be absent * Thus, use back value from values, instead of second one, which could be absent
@ -1793,13 +1793,13 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
#endif // ENABLE_GCODE_VIEWER #endif // ENABLE_GCODE_VIEWER
print.throw_if_canceled(); print.throw_if_canceled();
// calculates estimated printing time // calculates estimated printing time
#if !ENABLE_GCODE_VIEWER #if !ENABLE_GCODE_VIEWER
m_normal_time_estimator.calculate_time(false); m_normal_time_estimator.calculate_time(false);
if (m_silent_time_estimator_enabled) if (m_silent_time_estimator_enabled)
m_silent_time_estimator.calculate_time(false); m_silent_time_estimator.calculate_time(false);
if (config().time_estimation_compensation.get_abs_value(1) != 1) { if (config().time_estimation_compensation.get_abs_value(1) != 1 && config().machine_limits_usage.value <= MachineLimitsUsage::TimeEstimateOnly) {
m_normal_time_estimator.scale_time(config().time_estimation_compensation.get_abs_value(1)); m_normal_time_estimator.scale_time(config().time_estimation_compensation.get_abs_value(1));
if (m_silent_time_estimator_enabled) if (m_silent_time_estimator_enabled)
m_silent_time_estimator.scale_time(config().time_estimation_compensation.get_abs_value(1)); m_silent_time_estimator.scale_time(config().time_estimation_compensation.get_abs_value(1));
@ -1810,7 +1810,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
m_normal_time_estimator.calculate_time(true); m_normal_time_estimator.calculate_time(true);
if (m_silent_time_estimator_enabled) if (m_silent_time_estimator_enabled)
m_silent_time_estimator.calculate_time(true); m_silent_time_estimator.calculate_time(true);
if (config().time_estimation_compensation.get_abs_value(1) != 1) { if (config().time_estimation_compensation.get_abs_value(1) != 1 && config().machine_limits_usage.value <= MachineLimitsUsage::TimeEstimateOnly) {
m_normal_time_estimator.scale_time(config().time_estimation_compensation.get_abs_value(1)); m_normal_time_estimator.scale_time(config().time_estimation_compensation.get_abs_value(1));
if (m_silent_time_estimator_enabled) if (m_silent_time_estimator_enabled)
m_silent_time_estimator.scale_time(config().time_estimation_compensation.get_abs_value(1)); m_silent_time_estimator.scale_time(config().time_estimation_compensation.get_abs_value(1));
@ -1948,12 +1948,22 @@ void GCode::print_machine_envelope(FILE *file, Print &print)
fprintf(file, "M202 X%d Y%d ; sets maximum travel acceleration\n", fprintf(file, "M202 X%d Y%d ; sets maximum travel acceleration\n",
int(print.config().machine_max_acceleration_travel.values.front() + 0.5), int(print.config().machine_max_acceleration_travel.values.front() + 0.5),
int(print.config().machine_max_acceleration_travel.values.front() + 0.5)); int(print.config().machine_max_acceleration_travel.values.front() + 0.5));
if (std::set<uint8_t>{gcfMarlin, gcfLerdge, gcfRepetier, gcfRepRap, gcfSmoothie, gcfSprinter}.count(print.config().gcode_flavor.value) > 0) if (std::set<uint8_t>{gcfMarlin, gcfLerdge, gcfRepetier, gcfSmoothie, gcfSprinter}.count(print.config().gcode_flavor.value) > 0)
fprintf(file, "M203 X%d Y%d Z%d E%d ; sets maximum feedrates, mm/sec\n", fprintf(file, (print.config().gcode_flavor == gcfMarlin || print.config().gcode_flavor == gcfSmoothie)
? "M203 X%d Y%d Z%d E%d ; sets maximum feedrates, mm/sec\n"
: "M203 X%d Y%d Z%d E%d ; sets maximum feedrates, mm/min\n",
int(print.config().machine_max_feedrate_x.values.front() + 0.5), int(print.config().machine_max_feedrate_x.values.front() + 0.5),
int(print.config().machine_max_feedrate_y.values.front() + 0.5), int(print.config().machine_max_feedrate_y.values.front() + 0.5),
int(print.config().machine_max_feedrate_z.values.front() + 0.5), int(print.config().machine_max_feedrate_z.values.front() + 0.5),
int(print.config().machine_max_feedrate_e.values.front() + 0.5)); int(print.config().machine_max_feedrate_e.values.front() + 0.5));
if (print.config().gcode_flavor == gcfRepRap) {
fprintf(file, "M203 X%d Y%d Z%d E%d I%d; sets maximum feedrates, mm/min\n",
int(print.config().machine_max_feedrate_x.values.front() + 0.5),
int(print.config().machine_max_feedrate_y.values.front() + 0.5),
int(print.config().machine_max_feedrate_z.values.front() + 0.5),
int(print.config().machine_max_feedrate_e.values.front() + 0.5),
int(print.config().machine_min_extruding_rate.values.front() + 0.5));
}
if (std::set<uint8_t>{gcfMarlin, gcfLerdge}.count(print.config().gcode_flavor.value) > 0) if (std::set<uint8_t>{gcfMarlin, gcfLerdge}.count(print.config().gcode_flavor.value) > 0)
fprintf(file, "M204 P%d R%d T%d ; sets acceleration (P, T) and retract acceleration (R), mm/sec^2\n", fprintf(file, "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_extruding.values.front() + 0.5),
@ -3217,7 +3227,6 @@ void GCode::split_at_seam_pos(ExtrusionLoop& loop, std::unique_ptr<EdgeGrid::Gri
const EdgeGrid::Grid* edge_grid_ptr = (lower_layer_edge_grid && *lower_layer_edge_grid) const EdgeGrid::Grid* edge_grid_ptr = (lower_layer_edge_grid && *lower_layer_edge_grid)
? lower_layer_edge_grid->get() ? lower_layer_edge_grid->get()
: nullptr; : nullptr;
//TODO modify m_seam_placer to takers into account extra options.
Point seam = m_seam_placer.get_seam(m_layer, seam_position, loop, Point seam = m_seam_placer.get_seam(m_layer, seam_position, loop,
last_pos, EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0), last_pos, EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0),
(m_layer == NULL ? nullptr : m_layer->object()), (m_layer == NULL ? nullptr : m_layer->object()),
@ -3905,7 +3914,8 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
acceleration = m_config.infill_acceleration.value; acceleration = m_config.infill_acceleration.value;
} else { } else {
acceleration = m_config.default_acceleration.value; acceleration = m_config.default_acceleration.value;
}//TODO: add travel accel? }
//travel acceleration should be already set at startup via special gcode, and so it's automatically used by G0.
m_writer.set_acceleration((unsigned int)floor(acceleration + 0.5)); m_writer.set_acceleration((unsigned int)floor(acceleration + 0.5));
} }
@ -3944,7 +3954,7 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
if (factor < 1 && !(path.role() == erOverhangPerimeter || path.role() == erBridgeInfill)) { if (factor < 1 && !(path.role() == erOverhangPerimeter || path.role() == erBridgeInfill)) {
float small_speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed); float small_speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed);
//apply factor between feature speed and small speed //apply factor between feature speed and small speed
speed = speed * factor + (1 - factor) * small_speed; speed = speed * factor + (1.f - factor) * small_speed;
} }
} }
if (m_volumetric_speed != 0. && speed == 0) if (m_volumetric_speed != 0. && speed == 0)

View File

@ -166,6 +166,7 @@ void GCodeProcessor::TimeMachine::reset()
max_acceleration = 0.0f; max_acceleration = 0.0f;
extrude_factor_override_percentage = 1.0f; extrude_factor_override_percentage = 1.0f;
time = 0.0f; time = 0.0f;
time_acceleration = 1.0f;
curr.reset(); curr.reset();
prev.reset(); prev.reset();
gcode_time.reset(); gcode_time.reset();
@ -277,7 +278,7 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks)
size_t n_blocks_process = blocks.size() - keep_last_n_blocks; size_t n_blocks_process = blocks.size() - keep_last_n_blocks;
for (size_t i = 0; i < n_blocks_process; ++i) { for (size_t i = 0; i < n_blocks_process; ++i) {
const TimeBlock& block = blocks[i]; const TimeBlock& block = blocks[i];
float block_time = block.time(); float block_time = block.time() * time_acceleration;
time += block_time; time += block_time;
gcode_time.cache += block_time; gcode_time.cache += block_time;
moves_time[static_cast<size_t>(block.move_type)] += block_time; moves_time[static_cast<size_t>(block.move_type)] += block_time;
@ -364,7 +365,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
if (machine.enabled) { if (machine.enabled) {
ret += format_line_M73(machine.line_m73_mask.c_str(), ret += format_line_M73(machine.line_m73_mask.c_str(),
(line == First_Line_M73_Placeholder_Tag) ? 0 : 100, (line == First_Line_M73_Placeholder_Tag) ? 0 : 100,
(line == First_Line_M73_Placeholder_Tag) ? time_in_minutes(machines[i].time) : 0); (line == First_Line_M73_Placeholder_Tag) ? time_in_minutes(machine.time) : 0);
} }
} }
} }
@ -508,7 +509,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_filament_diameters[i] = static_cast<float>(config.filament_diameter.values[i]); m_filament_diameters[i] = static_cast<float>(config.filament_diameter.values[i]);
} }
if (config.machine_limits_usage.value != MachineLimitsUsage::Ignore) if (config.machine_limits_usage.value < MachineLimitsUsage::Limits)
m_time_processor.machine_limits = reinterpret_cast<const MachineEnvelopeConfig&>(config); m_time_processor.machine_limits = reinterpret_cast<const MachineEnvelopeConfig&>(config);
// Filament load / unload times are not specific to a firmware flavor. Let anybody use it if they find it useful. // Filament load / unload times are not specific to a firmware flavor. Let anybody use it if they find it useful.
@ -530,6 +531,13 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
} }
m_time_processor.export_remaining_time_enabled = config.remaining_times.value; m_time_processor.export_remaining_time_enabled = config.remaining_times.value;
if (config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value != gcfMarlin) {
double time_estimation_compensation = config.get_abs_value("time_estimation_compensation");
for (auto& machine : this->m_time_processor.machines) {
machine.time_acceleration = time_estimation_compensation;
}
}
} }
void GCodeProcessor::apply_config(const DynamicPrintConfig& config) void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
@ -664,9 +672,11 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
if (machine_max_acceleration_retracting != nullptr) if (machine_max_acceleration_retracting != nullptr)
m_time_processor.machine_limits.machine_max_acceleration_retracting.values = machine_max_acceleration_retracting->values; m_time_processor.machine_limits.machine_max_acceleration_retracting.values = machine_max_acceleration_retracting->values;
const ConfigOptionFloats* machine_min_extruding_rate = config.option<ConfigOptionFloats>("machine_min_extruding_rate"); if (std::set<uint8_t>{gcfMarlin, gcfLerdge, gcfRepetier, gcfRepRap}.count(m_flavor) > 0) {
if (machine_min_extruding_rate != nullptr) const ConfigOptionFloats* machine_min_extruding_rate = config.option<ConfigOptionFloats>("machine_min_extruding_rate");
m_time_processor.machine_limits.machine_min_extruding_rate.values = machine_min_extruding_rate->values; if (machine_min_extruding_rate != nullptr)
m_time_processor.machine_limits.machine_min_extruding_rate.values = machine_min_extruding_rate->values;
}
const ConfigOptionFloats* machine_min_travel_rate = config.option<ConfigOptionFloats>("machine_min_travel_rate"); const ConfigOptionFloats* machine_min_travel_rate = config.option<ConfigOptionFloats>("machine_min_travel_rate");
if (machine_min_travel_rate != nullptr) if (machine_min_travel_rate != nullptr)
@ -677,6 +687,23 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
m_time_processor.machines[i].max_acceleration = max_acceleration; m_time_processor.machines[i].max_acceleration = max_acceleration;
m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_ACCELERATION; m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_ACCELERATION;
} }
//adapt to firmware units
if (m_flavor != gcfMarlin && m_flavor != gcfSmoothie && m_flavor != gcfSmoothie) {
//change some fields from mm/min to mm/sec as intended
for (double& val : m_time_processor.machine_limits.machine_max_feedrate_x.values) val /= 60;
for (double& val : m_time_processor.machine_limits.machine_max_feedrate_y.values) val /= 60;
for (double& val : m_time_processor.machine_limits.machine_max_feedrate_z.values) val /= 60;
for (double& val : m_time_processor.machine_limits.machine_min_extruding_rate.values) val /= 60;
for (double& val : m_time_processor.machine_limits.machine_min_travel_rate.values) val /= 60;
}
if (m_flavor != gcfMarlin) {
double time_estimation_compensation = config.get_abs_value("time_estimation_compensation");
for (auto& machine : this->m_time_processor.machines) {
machine.time_acceleration = time_estimation_compensation;
}
}
} }
void GCodeProcessor::enable_stealth_time_estimator(bool enabled) void GCodeProcessor::enable_stealth_time_estimator(bool enabled)

View File

@ -188,6 +188,7 @@ namespace Slic3r {
float max_acceleration; // mm/s^2 float max_acceleration; // mm/s^2
float extrude_factor_override_percentage; float extrude_factor_override_percentage;
float time; // s float time; // s
float time_acceleration;
std::string line_m73_mask; std::string line_m73_mask;
State curr; State curr;
State prev; State prev;

View File

@ -22,7 +22,8 @@ void GCodeWriter::apply_print_config(const PrintConfig &print_config)
this->config.apply(print_config, true); this->config.apply(print_config, true);
m_extrusion_axis = this->config.get_extrusion_axis(); m_extrusion_axis = this->config.get_extrusion_axis();
m_single_extruder_multi_material = print_config.single_extruder_multi_material.value; m_single_extruder_multi_material = print_config.single_extruder_multi_material.value;
m_max_acceleration = std::lrint((print_config.gcode_flavor.value == gcfMarlin || print_config.gcode_flavor.value == gcfLerdge || print_config.gcode_flavor.value == gcfKlipper) && print_config.machine_limits_usage.value == MachineLimitsUsage::EmitToGCode ? m_max_acceleration = std::lrint((print_config.gcode_flavor.value == gcfMarlin || print_config.gcode_flavor.value == gcfLerdge || print_config.gcode_flavor.value == gcfKlipper)
&& print_config.machine_limits_usage.value <= MachineLimitsUsage::Limits ?
print_config.machine_max_acceleration_extruding.values.front() : 0); print_config.machine_max_acceleration_extruding.values.front() : 0);
} }

View File

@ -663,7 +663,6 @@ const std::vector<std::string>& Preset::printer_options()
"wipe_advanced_multiplier", "wipe_advanced_multiplier",
"wipe_advanced_algo", "wipe_advanced_algo",
"fan_speedup_time", "fan_speedup_time",
"print_machine_envelope",
"time_estimation_compensation", "time_estimation_compensation",
}; };
s_opts.insert(s_opts.end(), Preset::machine_limits_options().begin(), Preset::machine_limits_options().end()); s_opts.insert(s_opts.end(), Preset::machine_limits_options().begin(), Preset::machine_limits_options().end());

View File

@ -137,7 +137,6 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
"output_filename_format", "output_filename_format",
"perimeter_acceleration", "perimeter_acceleration",
"post_process", "post_process",
"print_machine_envelope",
"printer_notes", "printer_notes",
"retract_before_travel", "retract_before_travel",
"retract_before_wipe", "retract_before_wipe",

View File

@ -2082,16 +2082,23 @@ void PrintConfigDef::init_fff_params()
def->label = L("How to apply"); def->label = L("How to apply");
def->full_label = L("Purpose of Machine Limits"); def->full_label = L("Purpose of Machine Limits");
def->category = OptionCategory::limits; def->category = OptionCategory::limits;
def->tooltip = L("How to apply the Machine Limits"); def->tooltip = L("How to apply the Machine Limits."
"\n* In every case, they will be used as safeguard: Even if you use a print profile that set an acceleration of 5000,"
" if your machine limits the acceleration is 4000, the outputted gcode will use the 4000 limit."
"\n* You can also use it as safeguard and to have a better printing time estimate."
"\n* You can also use it as safeguard, to have a better printing time estimate and emit the limits as the begining of the gcode file, with M201 M202 M203 M204 and M205 commands."
" If you want only to write a sub-set, choose the 'for time estimate' option and write yourself gcodes in the custom gcode section.");
def->enum_keys_map = &ConfigOptionEnum<MachineLimitsUsage>::get_enum_values(); def->enum_keys_map = &ConfigOptionEnum<MachineLimitsUsage>::get_enum_values();
def->enum_values.push_back("emit_to_gcode"); def->enum_values.push_back("emit_to_gcode");
def->enum_values.push_back("time_estimate_only"); def->enum_values.push_back("time_estimate_only");
def->enum_values.push_back("limits");
def->enum_values.push_back("ignore"); def->enum_values.push_back("ignore");
def->enum_labels.push_back("Emit to G-code"); def->enum_labels.push_back("Also emit limits to G-code");
def->enum_labels.push_back("Use for time estimate"); def->enum_labels.push_back("Use also for time estimate");
def->enum_labels.push_back("Ignore"); def->enum_labels.push_back("Use only as safeguards");
def->enum_labels.push_back("Disable");
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<MachineLimitsUsage>(MachineLimitsUsage::EmitToGCode)); def->set_default_value(new ConfigOptionEnum<MachineLimitsUsage>(MachineLimitsUsage::TimeEstimateOnly));
{ {
struct AxisDefault { struct AxisDefault {
@ -2419,16 +2426,6 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionString("")); def->set_default_value(new ConfigOptionString(""));
def = this->add("print_machine_envelope", coBool);
def->label = L("Enable Limits");
def->category = OptionCategory::limits;
def->tooltip = L("Slic3r can add M201 M203 M202 M204 and M205 gcodes to pass the machine limits defined here to the firmware."
" Gcodes printed will depends of the firmware selected (please Report an issue if you found something wrong)."
"\nIf you want only a selection, you can write your gcode with these value, example: "
"\nM204 P[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting]");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("only_retract_when_crossing_perimeters", coBool); def = this->add("only_retract_when_crossing_perimeters", coBool);
def->label = L("Only retract when crossing perimeters"); def->label = L("Only retract when crossing perimeters");
def->category = OptionCategory::extruders; def->category = OptionCategory::extruders;
@ -4836,7 +4833,14 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
value = "50%"; value = "50%";
else else
value = "0"; value = "0";
} else if (opt_key == "print_machine_envelope") {
opt_key = "machine_limits_usage";
if (value == "1")
value = "emit_to_gcode";
else
value = "time_estimate_only";
} }
// Ignore the following obsolete configuration keys: // Ignore the following obsolete configuration keys:
static std::set<std::string> ignore = { static std::set<std::string> ignore = {
"duplicate_x", "duplicate_y", "gcode_arcs", "multiply_x", "multiply_y", "duplicate_x", "duplicate_y", "gcode_arcs", "multiply_x", "multiply_y",

View File

@ -49,23 +49,24 @@ enum WipeAlgo {
enum GCodeFlavor : uint8_t { enum GCodeFlavor : uint8_t {
gcfRepRap, gcfRepRap,
gcfSprinter,
gcfRepetier, gcfRepetier,
gcfTeacup, gcfTeacup,
gcfMakerWare, gcfMakerWare,
gcfMarlin, gcfMarlin,
gcfLerdge,
gcfKlipper, gcfKlipper,
gcfSailfish, gcfSailfish,
gcfMach3, gcfMach3,
gcfMachinekit, gcfMachinekit,
gcfSmoothie, gcfSmoothie,
gcfSprinter,
gcfNoExtrusion, gcfNoExtrusion,
gcfLerdge,
}; };
enum class MachineLimitsUsage { enum class MachineLimitsUsage : uint8_t {
EmitToGCode, EmitToGCode,
TimeEstimateOnly, TimeEstimateOnly,
Limits,
Ignore, Ignore,
Count, Count,
}; };
@ -192,6 +193,7 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<MachineLimitsUsag
if (keys_map.empty()) { if (keys_map.empty()) {
keys_map["emit_to_gcode"] = int(MachineLimitsUsage::EmitToGCode); keys_map["emit_to_gcode"] = int(MachineLimitsUsage::EmitToGCode);
keys_map["time_estimate_only"] = int(MachineLimitsUsage::TimeEstimateOnly); keys_map["time_estimate_only"] = int(MachineLimitsUsage::TimeEstimateOnly);
keys_map["limits"] = int(MachineLimitsUsage::Limits);
keys_map["ignore"] = int(MachineLimitsUsage::Ignore); keys_map["ignore"] = int(MachineLimitsUsage::Ignore);
} }
return keys_map; return keys_map;
@ -1214,7 +1216,6 @@ public:
ConfigOptionString output_filename_format; ConfigOptionString output_filename_format;
ConfigOptionFloat perimeter_acceleration; ConfigOptionFloat perimeter_acceleration;
ConfigOptionStrings post_process; ConfigOptionStrings post_process;
ConfigOptionBool print_machine_envelope;
ConfigOptionString printer_model; ConfigOptionString printer_model;
ConfigOptionString printer_notes; ConfigOptionString printer_notes;
ConfigOptionFloat resolution; ConfigOptionFloat resolution;
@ -1309,7 +1310,6 @@ protected:
OPT_PTR(output_filename_format); OPT_PTR(output_filename_format);
OPT_PTR(perimeter_acceleration); OPT_PTR(perimeter_acceleration);
OPT_PTR(post_process); OPT_PTR(post_process);
OPT_PTR(print_machine_envelope);
OPT_PTR(printer_model); OPT_PTR(printer_model);
OPT_PTR(printer_notes); OPT_PTR(printer_notes);
OPT_PTR(resolution); OPT_PTR(resolution);

View File

@ -1778,8 +1778,7 @@ bool Tab::create_pages(std::string setting_type_name, int idx_page)
} }
else if (boost::starts_with(full_line, "parent_preset_description")) { else if (boost::starts_with(full_line, "parent_preset_description")) {
build_preset_description_line(current_group.get()); build_preset_description_line(current_group.get());
} } else if (boost::starts_with(full_line, "cooling_description")) {
else if (boost::starts_with(full_line, "cooling_description")) {
TabFilament* tab = nullptr; TabFilament* tab = nullptr;
if ((tab = dynamic_cast<TabFilament*>(this)) == nullptr) continue; if ((tab = dynamic_cast<TabFilament*>(this)) == nullptr) continue;
current_line = Line{ "", "" }; current_line = Line{ "", "" };
@ -1789,8 +1788,7 @@ bool Tab::create_pages(std::string setting_type_name, int idx_page)
}; };
current_group->append_line(current_line); current_group->append_line(current_line);
current_page->descriptions.push_back("cooling"); current_page->descriptions.push_back("cooling");
} } else if (boost::starts_with(full_line, "volumetric_speed_description")) {
else if (boost::starts_with(full_line, "volumetric_speed_description")) {
TabFilament* tab = nullptr; TabFilament* tab = nullptr;
if ((tab = dynamic_cast<TabFilament*>(this)) == nullptr) continue; if ((tab = dynamic_cast<TabFilament*>(this)) == nullptr) continue;
current_line = Line{ "", "" }; current_line = Line{ "", "" };
@ -1800,8 +1798,26 @@ bool Tab::create_pages(std::string setting_type_name, int idx_page)
}; };
current_group->append_line(current_line); current_group->append_line(current_line);
current_page->descriptions.push_back("volumetric_speed"); current_page->descriptions.push_back("volumetric_speed");
} } else if (boost::starts_with(full_line, "print_host_upload_description")) {
else if (boost::starts_with(full_line, "filament_ramming_parameters")) { TabPrinter* tab = nullptr;
if ((tab = dynamic_cast<TabPrinter*>(this)) == nullptr) continue;
wxString description_line_text = _L(""
"Note: All parameters from this group are moved to the Physical Printer settings (see changelog).\n\n"
"A new Physical Printer profile is created by clicking on the \"cog\" icon right of the Printer profiles combo box, "
"by selecting the \"add or remove printers\" item in the Printer combo box. The Physical Printer profile editor opens "
"also when clicking on the \"cog\" icon in the Printer settings tab. The Physical Printer profiles are being stored "
"into SuperSlicer/physical_printer directory.");
current_line = { "", "" };
current_line.full_width = 1;
current_line.widget = [tab, description_line_text](wxWindow* parent) {
return tab->description_line_widget(parent, tab->m_presets->get_selected_preset().printer_technology() == ptFFF ?
&tab->m_fff_print_host_upload_description_line : &tab->m_sla_print_host_upload_description_line,
description_line_text);
};
current_group->append_line(current_line);
current_page->descriptions.push_back("print_host_upload");
} else if (boost::starts_with(full_line, "filament_ramming_parameters")) {
Line thisline = current_group->create_single_option_line("filament_ramming_parameters");// { _(L("Ramming")), "" }; Line thisline = current_group->create_single_option_line("filament_ramming_parameters");// { _(L("Ramming")), "" };
thisline.widget = [this](wxWindow* parent) { thisline.widget = [this](wxWindow* parent) {
auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
@ -1829,11 +1845,6 @@ bool Tab::create_pages(std::string setting_type_name, int idx_page)
if ((tab = dynamic_cast<TabPrinter*>(this)) == nullptr) continue; if ((tab = dynamic_cast<TabPrinter*>(this)) == nullptr) continue;
tab->build_unregular_pages(); tab->build_unregular_pages();
} }
//else if (full_line == "printhost") {
// TabPrinter* tab = nullptr;
// if ((tab = dynamic_cast<TabPrinter*>(this)) == nullptr) continue;
// tab->build_printhost(current_group.get());
//}
else if (full_line == "bed_shape"){ else if (full_line == "bed_shape"){
TabPrinter* tab = nullptr; TabPrinter* tab = nullptr;
if ((tab = dynamic_cast<TabPrinter*>(this)) == nullptr) continue; if ((tab = dynamic_cast<TabPrinter*>(this)) == nullptr) continue;
@ -2179,7 +2190,7 @@ void TabFilament::toggle_options()
if (!m_active_page) if (!m_active_page)
return; return;
if (m_active_page->title() == "Cooling") if ( std::find(m_active_page->descriptions.begin(), m_active_page->descriptions.end(), "cooling") != m_active_page->descriptions.end())
{ {
bool fan_always_on = m_config->opt_bool("fan_always_on", 0); bool fan_always_on = m_config->opt_bool("fan_always_on", 0);
@ -2258,27 +2269,6 @@ void TabPrinter::build()
m_presets->get_selected_preset().printer_technology() == ptSLA ? build_sla() : build_fff(); m_presets->get_selected_preset().printer_technology() == ptSLA ? build_sla() : build_fff();
} }
void TabPrinter::build_print_host_upload_group(Page* page)
{
ConfigOptionsGroupShp optgroup = page->new_optgroup(L("Print Host upload"));
wxString description_line_text = _L(""
"Note: All parameters from this group are moved to the Physical Printer settings (see changelog).\n\n"
"A new Physical Printer profile is created by clicking on the \"cog\" icon right of the Printer profiles combo box, "
"by selecting the \"add or remove printers\" item in the Printer combo box. The Physical Printer profile editor opens "
"also when clicking on the \"cog\" icon in the Printer settings tab. The Physical Printer profiles are being stored "
"into PrusaSlicer/physical_printer directory.");
Line line = { "", "" };
line.full_width = 1;
line.widget = [this, description_line_text](wxWindow* parent) {
return description_line_widget(parent, m_presets->get_selected_preset().printer_technology() == ptFFF ?
&m_fff_print_host_upload_description_line : &m_sla_print_host_upload_description_line,
description_line_text);
};
optgroup->append_line(line);
}
void TabPrinter::build_fff() void TabPrinter::build_fff()
{ {
if (!m_pages.empty()) if (!m_pages.empty())
@ -2360,15 +2350,19 @@ void TabPrinter::milling_count_changed(size_t milling_count)
void TabPrinter::append_option_line_kinematics(ConfigOptionsGroupShp optgroup, const std::string opt_key, const std::string override_sidetext) void TabPrinter::append_option_line_kinematics(ConfigOptionsGroupShp optgroup, const std::string opt_key, const std::string override_sidetext)
{ {
Option option = optgroup->get_option(opt_key, 0); Option option = optgroup->get_option(opt_key, 0);
if (!override_sidetext.empty()) if (!override_sidetext.empty()) {
option.opt.sidetext = override_sidetext; option.opt.sidetext = override_sidetext;
option.opt.sidetext_width = override_sidetext.length() + 1;
}
Line line = Line{ _(option.opt.full_label), "" }; Line line = Line{ _(option.opt.full_label), "" };
option.opt.width = 10; option.opt.width = 10;
line.append_option(option); line.append_option(option);
if (m_use_silent_mode) { if (m_use_silent_mode) {
option = optgroup->get_option(opt_key, 1); option = optgroup->get_option(opt_key, 1);
if (!override_sidetext.empty()) if (!override_sidetext.empty()) {
option.opt.sidetext = override_sidetext; option.opt.sidetext = override_sidetext;
option.opt.sidetext_width = override_sidetext.length() + 1;
}
option.opt.width = 10; option.opt.width = 10;
line.append_option(option); line.append_option(option);
} }
@ -2384,18 +2378,6 @@ PageShp TabPrinter::build_kinematics_page()
optgroup->append_single_option_line("time_estimation_compensation"); optgroup->append_single_option_line("time_estimation_compensation");
} }
optgroup = page->new_optgroup(_(L("Machine Limits"))); optgroup = page->new_optgroup(_(L("Machine Limits")));
Line current_line = Line{ "", "" };
current_line.full_width = 1;
current_line.widget = [this](wxWindow* parent) {
ogStaticText* text;
auto result = description_line_widget(parent, &text);
text->SetText(_(L("Description: The information below is used to calculate estimated printing time and as safegard when generating gcode"
" (even if the acceleration is set to 3000 in the print profile, if this is at 1500, it won't export a gcode that will tell to go over 1500)."
" You can also export these limits to the start gcode via the checkbox above (the output depends on the selected firmare).")));
return result;
};
optgroup->append_line(current_line);
optgroup->append_single_option_line("print_machine_envelope");
optgroup->append_single_option_line("machine_limits_usage"); optgroup->append_single_option_line("machine_limits_usage");
Line line { "", "" }; Line line { "", "" };
line.full_width = 1; line.full_width = 1;
@ -2403,6 +2385,7 @@ PageShp TabPrinter::build_kinematics_page()
return description_line_widget(parent, &m_machine_limits_description_line); return description_line_widget(parent, &m_machine_limits_description_line);
}; };
optgroup->append_line(line); optgroup->append_line(line);
page->descriptions.push_back("machine_limits");
if (m_use_silent_mode) { if (m_use_silent_mode) {
// Legend for OptionsGroups // Legend for OptionsGroups
@ -2431,12 +2414,13 @@ PageShp TabPrinter::build_kinematics_page()
} }
std::vector<std::string> axes{ "x", "y", "z", "e" }; std::vector<std::string> axes{ "x", "y", "z", "e" };
GCodeFlavor flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
optgroup = page->new_optgroup(L("Maximum feedrates")); optgroup = page->new_optgroup(L("Maximum feedrates"));
for (const std::string& axis : axes) { for (const std::string& axis : axes) {
if (m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfRepRap) if(std::set<uint8_t>{gcfMarlin, gcfLerdge, gcfSmoothie}.count(flavor) > 0)
append_option_line_kinematics(optgroup, "machine_max_feedrate_" + axis, "mm/min");
else
append_option_line_kinematics(optgroup, "machine_max_feedrate_" + axis); append_option_line_kinematics(optgroup, "machine_max_feedrate_" + axis);
else
append_option_line_kinematics(optgroup, "machine_max_feedrate_" + axis, "mm/min");
} }
optgroup = page->new_optgroup(L("Maximum accelerations")); optgroup = page->new_optgroup(L("Maximum accelerations"));
@ -2453,13 +2437,13 @@ PageShp TabPrinter::build_kinematics_page()
} }
optgroup = page->new_optgroup(L("Minimum feedrates")); optgroup = page->new_optgroup(L("Minimum feedrates"));
if (m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfRepRap){ if (std::set<uint8_t>{gcfMarlin, gcfLerdge, gcfSmoothie}.count(flavor) > 0) {
append_option_line_kinematics(optgroup, "machine_min_extruding_rate", "mm/min");
append_option_line_kinematics(optgroup, "machine_min_travel_rate", "mm/min");
} else {
append_option_line_kinematics(optgroup, "machine_min_extruding_rate"); append_option_line_kinematics(optgroup, "machine_min_extruding_rate");
append_option_line_kinematics(optgroup, "machine_min_travel_rate"); append_option_line_kinematics(optgroup, "machine_min_travel_rate");
} } else {
append_option_line_kinematics(optgroup, "machine_min_extruding_rate", "mm/min");
append_option_line_kinematics(optgroup, "machine_min_travel_rate", "mm/min");
}
return page; return page;
} }
@ -2504,6 +2488,7 @@ void TabPrinter::build_unregular_pages()
break; break;
} }
} }
GCodeFlavor flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
if (existed_page < n_before_extruders) { if (existed_page < n_before_extruders) {
auto page = build_kinematics_page(); auto page = build_kinematics_page();
changed = true; changed = true;
@ -2667,7 +2652,6 @@ void TabPrinter::clear_pages()
void TabPrinter::toggle_options() void TabPrinter::toggle_options()
{ {
//TODO: check if somethgin has not been wrongly erased.
if (!m_active_page || m_presets->get_edited_preset().printer_technology() == ptSLA) if (!m_active_page || m_presets->get_edited_preset().printer_technology() == ptSLA)
return; return;
@ -2687,7 +2671,7 @@ void TabPrinter::toggle_options()
bool is_marlin_flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlin; bool is_marlin_flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlin;
// Disable silent mode for non-marlin firmwares. // Disable silent mode for non-marlin firmwares.
field = get_field("silent_mode"); field = get_field("silent_mode");
if (field) field->toggle(is_marlin_flavor ); if (field) field->toggle(is_marlin_flavor);
if (m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfKlipper) if (m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfKlipper)
GCodeWriter::PausePrintCode = "PAUSE"; GCodeWriter::PausePrintCode = "PAUSE";
@ -2699,9 +2683,9 @@ void TabPrinter::toggle_options()
m_rebuild_kinematics_page = true; m_rebuild_kinematics_page = true;
} }
if (m_use_silent_mode != m_config->opt_bool("silent_mode")) { if (m_use_silent_mode != (m_last_gcode_flavor == gcfMarlin) && m_config->opt_bool("silent_mode")) {
m_rebuild_kinematics_page = true; m_rebuild_kinematics_page = true;
m_use_silent_mode = m_config->opt_bool("silent_mode"); m_use_silent_mode = (m_last_gcode_flavor == gcfMarlin) && m_config->opt_bool("silent_mode");
} }
wxString extruder_number; wxString extruder_number;
@ -2709,7 +2693,7 @@ void TabPrinter::toggle_options()
if (m_active_page->title().StartsWith("Extruder ", &extruder_number) && extruder_number.ToLong(&val) && if (m_active_page->title().StartsWith("Extruder ", &extruder_number) && extruder_number.ToLong(&val) &&
val > 0 && (size_t)val <= m_extruders_count) val > 0 && (size_t)val <= m_extruders_count)
{ {
size_t i = size_t(val - 1); size_t i = size_t(val) - 1;
bool have_retract_length = m_config->opt_float("retract_length", i) > 0; bool have_retract_length = m_config->opt_float("retract_length", i) > 0;
// when using firmware retraction, firmware decides retraction length // when using firmware retraction, firmware decides retraction length
@ -2792,11 +2776,11 @@ void TabPrinter::toggle_options()
} }
} }
if (m_active_page->title() == "Machine limits") { if (std::find(m_active_page->descriptions.begin(), m_active_page->descriptions.end(), "machine_limits") != m_active_page->descriptions.end()) {
//assert(m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlin); //assert(m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlin);
const auto *machine_limits_usage = m_config->option<ConfigOptionEnum<MachineLimitsUsage>>("machine_limits_usage"); const auto *machine_limits_usage = m_config->option<ConfigOptionEnum<MachineLimitsUsage>>("machine_limits_usage");
bool enabled = machine_limits_usage->value != MachineLimitsUsage::Ignore; bool enabled = machine_limits_usage->value != MachineLimitsUsage::Ignore;
bool silent_mode = m_config->opt_bool("silent_mode"); bool silent_mode = (m_last_gcode_flavor == gcfMarlin) && m_config->opt_bool("silent_mode");
int max_field = silent_mode ? 2 : 1; int max_field = silent_mode ? 2 : 1;
for (const std::string &opt : Preset::machine_limits_options()) for (const std::string &opt : Preset::machine_limits_options())
for (int i = 0; i < max_field; ++i) { for (int i = 0; i < max_field; ++i) {
@ -2804,6 +2788,8 @@ void TabPrinter::toggle_options()
if (field) if (field)
field->toggle(enabled); field->toggle(enabled);
} }
field = get_field("time_estimation_compensation");
if (field) field->toggle(machine_limits_usage->value <= MachineLimitsUsage::TimeEstimateOnly);
update_machine_limits_description(machine_limits_usage->value); update_machine_limits_description(machine_limits_usage->value);
} }
@ -2848,11 +2834,6 @@ void TabPrinter::update()
void TabPrinter::update_fff() void TabPrinter::update_fff()
{ {
if (m_use_silent_mode != m_config->opt_bool("silent_mode")) {
m_rebuild_kinematics_page = true;
m_use_silent_mode = m_config->opt_bool("silent_mode");
}
toggle_options(); toggle_options();
} }
@ -3732,21 +3713,80 @@ void TabPrinter::apply_extruder_cnt_from_cache()
void TabPrinter::update_machine_limits_description(const MachineLimitsUsage usage) void TabPrinter::update_machine_limits_description(const MachineLimitsUsage usage)
{ {
GCodeFlavor flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
wxString text; wxString text;
switch (usage) { switch (usage) {
case MachineLimitsUsage::EmitToGCode: case MachineLimitsUsage::EmitToGCode:
text = _L("Machine limits will be emitted to G-code and used to estimate print time."); text = _L("Machine limits will be emitted to G-code and used to estimate print time."
" They are also used as safegard when generating gcode");
text += " "+ _L("(even if the acceleration is set to 3000 in the print profile, if this is at 1500, it won't export a gcode that will tell to go over 1500).");
if (flavor != gcfMarlin)
text += "\n" + _L("Grey values means that they can't be send to your firmware (no g-code available).");
break; break;
case MachineLimitsUsage::TimeEstimateOnly: case MachineLimitsUsage::TimeEstimateOnly:
text = _L("Machine limits will NOT be emitted to G-code, however they will be used to estimate print time, " text = _L("Machine limits will NOT be emitted to G-code, however they will be used to estimate print time"
"which may therefore not be accurate as the printer may apply a different set of machine limits."); ", which may therefore not be accurate as the printer may apply a different set of machine limits."
break; " They are also used as safegard when generating gcode");
case MachineLimitsUsage::Ignore: text += " " + _L("(even if the acceleration is set to 3000 in the print profile, if this is at 1500, it won't export a gcode that will tell to go over 1500).");
text = _L("Machine limits are not set, therefore the print time estimate may not be accurate."); break;
break; case MachineLimitsUsage::Limits:
text = _L("Machine limits are used as safegard when generating gcode");
text += " " + _L("(even if the acceleration is set to 3000 in the print profile, if this is at 1500, it won't export a gcode that will tell to go over 1500).");
break;
case MachineLimitsUsage::Ignore:
text = _L("Machine limits are disabled. They are not used for anything.");
break;
default: assert(false); default: assert(false);
} }
m_machine_limits_description_line->SetText(text); m_machine_limits_description_line->SetText(text);
//update fields used
//no need to worry for "silent" version, as it's only for marlin.
if (usage == MachineLimitsUsage::EmitToGCode) {
wxColour greay_color(128, 128, 128);
Field* field;
std::vector<std::string> axes{ "x", "y", "z", "e" };
if (std::set<uint8_t>{gcfKlipper, gcfMach3, gcfMachinekit, gcfMakerWare, gcfSailfish, gcfTeacup}.count(flavor) > 0)
for (const std::string& axis : axes) {
field = m_active_page->get_field("machine_max_feedrate_" + axis, 0);
if (field) dynamic_cast<wxTextCtrl*>(field->getWindow())->SetForegroundColour(greay_color);
}
if (std::set<uint8_t>{gcfKlipper, gcfSmoothie, gcfMach3, gcfMachinekit, gcfMakerWare, gcfSailfish, gcfTeacup}.count(flavor) > 0)
for (const std::string& axis : axes) {
field = m_active_page->get_field("machine_max_acceleration_" + axis, 0);
if (field) dynamic_cast<wxTextCtrl*>(field->getWindow())->SetForegroundColour(greay_color);
}
if (std::set<uint8_t>{gcfSmoothie, gcfMach3, gcfMachinekit, gcfMakerWare, gcfSailfish, gcfTeacup}.count(flavor) > 0)
{
field = m_active_page->get_field("machine_max_acceleration_extruding", 0);
if (field) dynamic_cast<wxTextCtrl*>(field->getWindow())->SetForegroundColour(greay_color);
}
if (flavor != gcfMarlin)
{
field = m_active_page->get_field("machine_max_acceleration_retracting", 0);
if (field) dynamic_cast<wxTextCtrl*>(field->getWindow())->SetForegroundColour(greay_color);
}
if (std::set<uint8_t>{gcfSmoothie, gcfMach3, gcfMachinekit, gcfMakerWare, gcfSailfish, gcfTeacup}.count(flavor) > 0)
{
field = m_active_page->get_field("machine_max_acceleration_travel", 0);
if (field) dynamic_cast<wxTextCtrl*>(field->getWindow())->SetForegroundColour(greay_color);
}
if (std::set<uint8_t>{gcfKlipper, gcfMach3, gcfMachinekit, gcfMakerWare, gcfSailfish, gcfTeacup}.count(flavor) > 0)
for (const std::string& axis : axes) {
field = m_active_page->get_field("machine_max_jerk_" + axis, 0);
if (field) dynamic_cast<wxTextCtrl*>(field->getWindow())->SetForegroundColour(greay_color);
}
if (flavor != gcfMarlin && flavor != gcfRepRap)
{
field = m_active_page->get_field("machine_min_extruding_rate", 0);
if (field) dynamic_cast<wxTextCtrl*>(field->getWindow())->SetForegroundColour(greay_color);
}
if (flavor != gcfMarlin)
{
field = m_active_page->get_field("machine_min_travel_rate", 0);
if (field) dynamic_cast<wxTextCtrl*>(field->getWindow())->SetForegroundColour(greay_color);
}
}
} }
void Tab::compatible_widget_reload(PresetDependencies &deps) void Tab::compatible_widget_reload(PresetDependencies &deps)

View File

@ -426,13 +426,13 @@ class TabPrinter : public Tab
ogStaticText* m_machine_limits_description_line {nullptr}; ogStaticText* m_machine_limits_description_line {nullptr};
void update_machine_limits_description(const MachineLimitsUsage usage); void update_machine_limits_description(const MachineLimitsUsage usage);
ogStaticText* m_fff_print_host_upload_description_line {nullptr};
ogStaticText* m_sla_print_host_upload_description_line {nullptr};
std::vector<PageShp> m_pages_fff; std::vector<PageShp> m_pages_fff;
std::vector<PageShp> m_pages_sla; std::vector<PageShp> m_pages_sla;
public: public:
ogStaticText* m_fff_print_host_upload_description_line{ nullptr };
ogStaticText* m_sla_print_host_upload_description_line{ nullptr };
// void build_printhost(ConfigOptionsGroup *optgroup); // void build_printhost(ConfigOptionsGroup *optgroup);
bool m_has_single_extruder_MM_page = false; bool m_has_single_extruder_MM_page = false;
@ -468,7 +468,6 @@ public:
~TabPrinter() {} ~TabPrinter() {}
void build() override; void build() override;
void build_print_host_upload_group(Page* page);
void build_fff(); void build_fff();
void build_sla(); void build_sla();
void activate_selected_page(std::function<void()> throw_if_canceled) override; void activate_selected_page(std::function<void()> throw_if_canceled) override;