Add some spacing settings at the side of width

- now a setting can be "phony"
 - a phony setting isn't saved in a config file
 - a phony setting should be computed from other settings
 - change/add colors, icons, and callbacks (in PrintConfig.cpp) to make phony settings works
This commit is contained in:
remi durand 2021-04-25 01:55:30 +02:00
parent 1d405304b9
commit 715d58da88
18 changed files with 673 additions and 79 deletions

View File

@ -258,15 +258,40 @@ group:Autospeed (advanced)
page:Width & Flow:width page:Width & Flow:width
group:Extrusion width group:Extrusion width
setting:extrusion_width line:default
setting:first_layer_extrusion_width setting:sidetext_width$10:label$width:extrusion_width
setting:perimeter_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:extrusion_spacing
setting:external_perimeter_extrusion_width end_line
setting:infill_extrusion_width line:first layer
setting:solid_infill_extrusion_width setting:sidetext_width$10:label$width:first_layer_extrusion_width
setting:top_infill_extrusion_width setting:sidetext_width$10:label_width$15:label$spacing:first_layer_extrusion_spacing
setting:support_material_extrusion_width end_line
setting:skirt_extrusion_width line:perimeter
setting:sidetext_width$10:label$width:perimeter_extrusion_width
setting:sidetext_width$10:label_width$15:label$spacing:perimeter_extrusion_spacing
end_line
line:external perimeter
setting:sidetext_width$10:label$width:external_perimeter_extrusion_width
setting:sidetext_width$10:label_width$15:label$width&spacing combo:external_perimeter_extrusion_spacing
end_line
line:infill
setting:sidetext_width$10:label$width:infill_extrusion_width
setting:sidetext_width$10:label_width$15:label$spacing:infill_extrusion_spacing
end_line
line:solid infill
setting:sidetext_width$10:label$width:solid_infill_extrusion_width
setting:sidetext_width$10:label_width$15:label$spacing:solid_infill_extrusion_spacing
end_line
line:top infill
setting:sidetext_width$10:label$width:top_infill_extrusion_width
setting:sidetext_width$10:label_width$15:label$spacing:top_infill_extrusion_spacing
end_line
line:support material
setting:sidetext_width$10:label$width:support_material_extrusion_width
end_line
line:skirt
setting:sidetext_width$10:label$width:skirt_extrusion_width
end_line
recommended_extrusion_width_description recommended_extrusion_width_description
group:Overlap group:Overlap
line:Perimeter overlap line:Perimeter overlap

View File

@ -473,7 +473,9 @@ t_config_option_keys ConfigBase::diff(const ConfigBase &other) const
for (const t_config_option_key &opt_key : this->keys()) { for (const t_config_option_key &opt_key : this->keys()) {
const ConfigOption *this_opt = this->option(opt_key); const ConfigOption *this_opt = this->option(opt_key);
const ConfigOption *other_opt = other.option(opt_key); const ConfigOption *other_opt = other.option(opt_key);
if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt) //dirty if both exist, they aren't both phony and value is different
if (this_opt != nullptr && other_opt != nullptr && !(this_opt->phony && other_opt->phony)
&& ((*this_opt != *other_opt) || (this_opt->phony != other_opt->phony)))
diff.emplace_back(opt_key); diff.emplace_back(opt_key);
} }
return diff; return diff;
@ -495,6 +497,8 @@ std::string ConfigBase::opt_serialize(const t_config_option_key &opt_key) const
{ {
const ConfigOption* opt = this->option(opt_key); const ConfigOption* opt = this->option(opt_key);
assert(opt != nullptr); assert(opt != nullptr);
if (opt->phony)
return "";
return opt->serialize(); return opt->serialize();
} }
@ -584,7 +588,19 @@ bool ConfigBase::set_deserialize_raw(const t_config_option_key &opt_key_src, con
ConfigOption *opt = this->option(opt_key, true); ConfigOption *opt = this->option(opt_key, true);
if (opt == nullptr) if (opt == nullptr)
throw new UnknownOptionException(opt_key); throw new UnknownOptionException(opt_key);
bool ok= opt->deserialize(value, append);
bool ok = true;
if (!optdef->can_phony || value != "")
ok = opt->deserialize(value, append);
//set phony status
if (optdef->can_phony)
if(value == "")
opt->phony = true;
else
opt->phony = false;
else
opt->phony = false;
return ok; return ok;
} }

View File

@ -214,6 +214,12 @@ inline OutputFormat operator&=(OutputFormat& a, OutputFormat b) {
// A generic value of a configuration option. // A generic value of a configuration option.
class ConfigOption { class ConfigOption {
public: public:
// if true, this option doesn't need to be saved, it's a computed value from an other configOption.
bool phony;
ConfigOption() : phony(false) {}
ConfigOption(bool phony) : phony(phony) {}
virtual ~ConfigOption() {} virtual ~ConfigOption() {}
virtual ConfigOptionType type() const = 0; virtual ConfigOptionType type() const = 0;
@ -258,6 +264,7 @@ class ConfigOptionSingle : public ConfigOption {
public: public:
T value; T value;
explicit ConfigOptionSingle(T value) : value(value) {} explicit ConfigOptionSingle(T value) : value(value) {}
explicit ConfigOptionSingle(T value, bool phony) : ConfigOption(phony), value(value) {}
operator T() const { return this->value; } operator T() const { return this->value; }
void set(const ConfigOption *rhs) override void set(const ConfigOption *rhs) override
@ -266,6 +273,7 @@ public:
throw Slic3r::RuntimeError("ConfigOptionSingle: Assigning an incompatible type"); throw Slic3r::RuntimeError("ConfigOptionSingle: Assigning an incompatible type");
assert(dynamic_cast<const ConfigOptionSingle<T>*>(rhs)); assert(dynamic_cast<const ConfigOptionSingle<T>*>(rhs));
this->value = static_cast<const ConfigOptionSingle<T>*>(rhs)->value; this->value = static_cast<const ConfigOptionSingle<T>*>(rhs)->value;
this->phony = rhs->phony;
} }
bool operator==(const ConfigOption &rhs) const override bool operator==(const ConfigOption &rhs) const override
@ -340,6 +348,7 @@ public:
throw Slic3r::RuntimeError("ConfigOptionVector: Assigning an incompatible type"); throw Slic3r::RuntimeError("ConfigOptionVector: Assigning an incompatible type");
assert(dynamic_cast<const ConfigOptionVector<T>*>(rhs)); assert(dynamic_cast<const ConfigOptionVector<T>*>(rhs));
this->values = static_cast<const ConfigOptionVector<T>*>(rhs)->values; this->values = static_cast<const ConfigOptionVector<T>*>(rhs)->values;
this->phony = rhs->phony;
} }
// Set from a vector of ConfigOptions. // Set from a vector of ConfigOptions.
@ -504,6 +513,7 @@ class ConfigOptionFloat : public ConfigOptionSingle<double>
public: public:
ConfigOptionFloat() : ConfigOptionSingle<double>(0) {} ConfigOptionFloat() : ConfigOptionSingle<double>(0) {}
explicit ConfigOptionFloat(double _value) : ConfigOptionSingle<double>(_value) {} explicit ConfigOptionFloat(double _value) : ConfigOptionSingle<double>(_value) {}
explicit ConfigOptionFloat(double _value, bool _phony) : ConfigOptionSingle<double>(_value, _phony) {}
static ConfigOptionType static_type() { return coFloat; } static ConfigOptionType static_type() { return coFloat; }
ConfigOptionType type() const override { return static_type(); } ConfigOptionType type() const override { return static_type(); }
@ -850,6 +860,7 @@ class ConfigOptionPercent : public ConfigOptionFloat
public: public:
ConfigOptionPercent() : ConfigOptionFloat(0) {} ConfigOptionPercent() : ConfigOptionFloat(0) {}
explicit ConfigOptionPercent(double _value) : ConfigOptionFloat(_value) {} explicit ConfigOptionPercent(double _value) : ConfigOptionFloat(_value) {}
explicit ConfigOptionPercent(double _value, bool _phony) : ConfigOptionFloat(_value, _phony) {}
static ConfigOptionType static_type() { return coPercent; } static ConfigOptionType static_type() { return coPercent; }
ConfigOptionType type() const override { return static_type(); } ConfigOptionType type() const override { return static_type(); }
@ -943,6 +954,7 @@ public:
bool percent; bool percent;
ConfigOptionFloatOrPercent() : ConfigOptionPercent(0), percent(false) {} ConfigOptionFloatOrPercent() : ConfigOptionPercent(0), percent(false) {}
explicit ConfigOptionFloatOrPercent(double _value, bool _percent) : ConfigOptionPercent(_value), percent(_percent) {} explicit ConfigOptionFloatOrPercent(double _value, bool _percent) : ConfigOptionPercent(_value), percent(_percent) {}
explicit ConfigOptionFloatOrPercent(double _value, bool _percent, bool _phony) : ConfigOptionPercent(_value, _phony), percent(_percent) {}
static ConfigOptionType static_type() { return coFloatOrPercent; } static ConfigOptionType static_type() { return coFloatOrPercent; }
ConfigOptionType type() const override { return static_type(); } ConfigOptionType type() const override { return static_type(); }
@ -1427,6 +1439,7 @@ public:
throw Slic3r::RuntimeError("ConfigOptionEnum<T>: Assigning an incompatible type"); throw Slic3r::RuntimeError("ConfigOptionEnum<T>: Assigning an incompatible type");
// rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T> // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
this->value = (T)rhs->getInt(); this->value = (T)rhs->getInt();
this->phony = rhs->phony;
} }
std::string serialize() const override std::string serialize() const override
@ -1511,6 +1524,7 @@ public:
throw Slic3r::RuntimeError("ConfigOptionEnumGeneric: Assigning an incompatible type"); throw Slic3r::RuntimeError("ConfigOptionEnumGeneric: Assigning an incompatible type");
// rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T> // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
this->value = rhs->getInt(); this->value = rhs->getInt();
this->phony = rhs->phony;
} }
std::string serialize() const override std::string serialize() const override
@ -1658,7 +1672,9 @@ public:
// For text input: If true, the GUI formats text as code (fixed-width) // For text input: If true, the GUI formats text as code (fixed-width)
bool is_code = false; bool is_code = false;
// Not editable. Currently only used for the display of the number of threads. // Not editable. Currently only used for the display of the number of threads.
bool readonly = false; bool readonly = false;
// Can be phony. if not present at laoding, mark it as phony. Also adapt the gui to look for phony status.
bool can_phony = false;
// Height of a multiline GUI text box. // Height of a multiline GUI text box.
int height = -1; int height = -1;
// Optional width of an input field. // Optional width of an input field.

View File

@ -299,8 +299,8 @@ std::pair<double, double> adaptive_fill_line_spacing(const PrintObject &print_ob
for (const PrintRegion *region : print_object.print()->regions()) { for (const PrintRegion *region : print_object.print()->regions()) {
const PrintRegionConfig &config = region->config(); const PrintRegionConfig &config = region->config();
bool nonempty = config.fill_density > 0; bool nonempty = config.fill_density > 0;
bool has_adaptive_infill = nonempty && config.fill_pattern == ipAdaptiveCubic; bool has_adaptive_infill = nonempty && config.fill_pattern.value == ipAdaptiveCubic;
bool has_support_infill = nonempty && config.fill_pattern == ipSupportCubic; bool has_support_infill = nonempty && config.fill_pattern.value == ipSupportCubic;
double infill_extrusion_width = config.infill_extrusion_width.get_abs_value(max_nozzle_diameter); double infill_extrusion_width = config.infill_extrusion_width.get_abs_value(max_nozzle_diameter);
region_fill_data.push_back(RegionFillData({ region_fill_data.push_back(RegionFillData({
has_adaptive_infill ? Tristate::Maybe : Tristate::No, has_adaptive_infill ? Tristate::Maybe : Tristate::No,

View File

@ -743,7 +743,7 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re
namespace DoExport { namespace DoExport {
static void init_gcode_processor(const PrintConfig& config, GCodeProcessor& processor, bool& silent_time_estimator_enabled) static void init_gcode_processor(const PrintConfig& config, GCodeProcessor& processor, bool& silent_time_estimator_enabled)
{ {
silent_time_estimator_enabled = (config.gcode_flavor == gcfMarlin) && config.silent_mode; silent_time_estimator_enabled = (config.gcode_flavor.value == gcfMarlin) && config.silent_mode;
processor.reset(); processor.reset();
processor.apply_config(config); processor.apply_config(config);
processor.enable_stealth_time_estimator(silent_time_estimator_enabled); processor.enable_stealth_time_estimator(silent_time_estimator_enabled);
@ -1490,7 +1490,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
bbox_prime.offset(0.5f); bbox_prime.offset(0.5f);
bool overlap = bbox_prime.overlap(bbox_print); bool overlap = bbox_prime.overlap(bbox_print);
if (print.config().gcode_flavor == gcfMarlin) { if (print.config().gcode_flavor.value == gcfMarlin) {
_write(file, this->retract()); _write(file, this->retract());
_write(file, "M300 S800 P500\n"); // Beep for 500ms, tone 800Hz. _write(file, "M300 S800 P500\n"); // Beep for 500ms, tone 800Hz.
if (overlap) { if (overlap) {
@ -1727,14 +1727,14 @@ void GCode::print_machine_envelope(FILE *file, Print &print)
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, 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, (print.config().gcode_flavor == gcfMarlin || print.config().gcode_flavor == gcfSmoothie) fprintf(file, (print.config().gcode_flavor.value == gcfMarlin || print.config().gcode_flavor.value == 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/sec\n"
: "M203 X%d Y%d Z%d E%d ; sets maximum feedrates, mm/min\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) { if (print.config().gcode_flavor.value == gcfRepRap) {
fprintf(file, "M203 X%d Y%d Z%d E%d I%d; sets maximum feedrates, mm/min\n", 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_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),
@ -1806,7 +1806,7 @@ void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, c
{ {
// Is the bed temperature set by the provided custom G-code? // Is the bed temperature set by the provided custom G-code?
int temp_by_gcode = -1; int temp_by_gcode = -1;
bool include_g10 = print.config().gcode_flavor == gcfRepRap; bool include_g10 = print.config().gcode_flavor.value == gcfRepRap;
if (custom_gcode_sets_temperature(gcode, 104, 109, include_g10, temp_by_gcode)) { if (custom_gcode_sets_temperature(gcode, 104, 109, include_g10, temp_by_gcode)) {
// Set the extruder temperature at m_writer, but throw away the generated G-code as it will be written with the custom G-code. // Set the extruder temperature at m_writer, but throw away the generated G-code as it will be written with the custom G-code.
int temp = print.config().first_layer_temperature.get_at(first_printing_extruder_id); int temp = print.config().first_layer_temperature.get_at(first_printing_extruder_id);

View File

@ -6,9 +6,9 @@
#include <map> #include <map>
#include <assert.h> #include <assert.h>
#define FLAVOR_IS(val) this->config.gcode_flavor == val #define FLAVOR_IS(val) this->config.gcode_flavor.value == val
#define FLAVOR_IS_NOT(val) this->config.gcode_flavor != val #define FLAVOR_IS_NOT(val) this->config.gcode_flavor.value != val
#define COMMENT(comment) if (this->config.gcode_comments && !comment.empty()) gcode << " ; " << comment; #define COMMENT(comment) if (this->config.gcode_comments.value && !comment.empty()) gcode << " ; " << comment;
#define PRECISION(val, precision) std::fixed << std::setprecision(precision) << (val) #define PRECISION(val, precision) std::fixed << std::setprecision(precision) << (val)
#define XYZF_NUM(val) PRECISION(val, this->config.gcode_precision_xyz.value) #define XYZF_NUM(val) PRECISION(val, this->config.gcode_precision_xyz.value)
#define E_NUM(val) PRECISION(val, this->config.gcode_precision_e.get_at(m_tool->id())) #define E_NUM(val) PRECISION(val, this->config.gcode_precision_e.get_at(m_tool->id()))

View File

@ -156,7 +156,7 @@ void PerimeterGenerator::process()
ExPolygons bridgeable = union_ex(detector.coverage(-1, true)); ExPolygons bridgeable = union_ex(detector.coverage(-1, true));
if (!bridgeable.empty()) { if (!bridgeable.empty()) {
//check if we get everything or just the bridgeable area //check if we get everything or just the bridgeable area
if (this->config->no_perimeter_unsupported_algo == npuaNoPeri || this->config->no_perimeter_unsupported_algo == npuaFilled) { if (this->config->no_perimeter_unsupported_algo.value == npuaNoPeri || this->config->no_perimeter_unsupported_algo.value == npuaFilled) {
//we bridge everything, even the not-bridgeable bits //we bridge everything, even the not-bridgeable bits
for (size_t i = 0; i < unsupported_filtered.size();) { for (size_t i = 0; i < unsupported_filtered.size();) {
ExPolygon &poly_unsupp = *(unsupported_filtered.begin() + i); ExPolygon &poly_unsupp = *(unsupported_filtered.begin() + i);
@ -177,7 +177,7 @@ void PerimeterGenerator::process()
} }
unsupported_filtered = intersection_ex(last, unsupported_filtered = intersection_ex(last,
offset2_ex(unsupported_filtered, double(-perimeter_spacing / 2), double(perimeter_spacing * 3 / 2))); offset2_ex(unsupported_filtered, double(-perimeter_spacing / 2), double(perimeter_spacing * 3 / 2)));
if (this->config->no_perimeter_unsupported_algo == npuaFilled) { if (this->config->no_perimeter_unsupported_algo.value == npuaFilled) {
for (ExPolygon &expol : unsupported_filtered) { for (ExPolygon &expol : unsupported_filtered) {
//check if the holes won't be covered by the upper layer //check if the holes won't be covered by the upper layer
//TODO: if we want to do that, we must modify the geometry before making perimeters. //TODO: if we want to do that, we must modify the geometry before making perimeters.
@ -227,7 +227,7 @@ void PerimeterGenerator::process()
} }
//TODO: add other polys as holes inside this one (-margin) //TODO: add other polys as holes inside this one (-margin)
} else if (this->config->no_perimeter_unsupported_algo == npuaBridgesOverhangs || this->config->no_perimeter_unsupported_algo == npuaBridges){ } else if (this->config->no_perimeter_unsupported_algo.value == npuaBridgesOverhangs || this->config->no_perimeter_unsupported_algo.value == npuaBridges){
//simplify to avoid most of artefacts from printing lines. //simplify to avoid most of artefacts from printing lines.
ExPolygons bridgeable_simplified; ExPolygons bridgeable_simplified;
for (ExPolygon &poly : bridgeable) { for (ExPolygon &poly : bridgeable) {
@ -246,7 +246,7 @@ void PerimeterGenerator::process()
//unbridgeable = offset2_ex(unbridgeable, -ext_perimeter_width, ext_perimeter_width); //unbridgeable = offset2_ex(unbridgeable, -ext_perimeter_width, ext_perimeter_width);
if (this->config->no_perimeter_unsupported_algo == npuaBridges) { if (this->config->no_perimeter_unsupported_algo.value == npuaBridges) {
ExPolygons unbridgeable = unsupported_filtered; ExPolygons unbridgeable = unsupported_filtered;
for (ExPolygon &expol : unbridgeable) for (ExPolygon &expol : unbridgeable)
expol.holes.clear(); expol.holes.clear();

View File

@ -535,9 +535,23 @@ const std::vector<std::string>& Preset::print_options()
"extruder_clearance_radius", "extruder_clearance_radius",
"extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "perimeter_extruder", "extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "perimeter_extruder",
"infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder", "infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder",
"ooze_prevention", "standby_temperature_delta", "interface_shells", "extrusion_width", "first_layer_extrusion_width", "ooze_prevention", "standby_temperature_delta", "interface_shells",
"perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "extrusion_spacing",
"top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "extrusion_width",
"first_layer_extrusion_spacing",
"first_layer_extrusion_width",
"perimeter_extrusion_spacing",
"perimeter_extrusion_width",
"external_perimeter_extrusion_spacing",
"external_perimeter_extrusion_width",
"infill_extrusion_spacing",
"infill_extrusion_width",
"solid_infill_extrusion_spacing",
"solid_infill_extrusion_width",
"top_infill_extrusion_spacing",
"top_infill_extrusion_width",
"support_material_extrusion_width",
"infill_overlap", "bridge_flow_ratio",
"infill_anchor", "infill_anchor",
"infill_anchor_max", "infill_anchor_max",
"clip_multipart_objects", "clip_multipart_objects",
@ -1373,7 +1387,9 @@ inline t_config_option_keys deep_diff(const ConfigBase &config_this, const Confi
for (const t_config_option_key &opt_key : config_this.keys()) { for (const t_config_option_key &opt_key : config_this.keys()) {
const ConfigOption *this_opt = config_this.option(opt_key); const ConfigOption *this_opt = config_this.option(opt_key);
const ConfigOption *other_opt = config_other.option(opt_key); const ConfigOption *other_opt = config_other.option(opt_key);
if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt) //dirty if both exist, they aren't both phony and value is different
if (this_opt != nullptr && other_opt != nullptr && !(this_opt->phony && other_opt->phony)
&& ((*this_opt != *other_opt) || (this_opt->phony != other_opt->phony)))
{ {
if (opt_key == "bed_shape" || opt_key == "thumbnails" || opt_key == "compatible_prints" || opt_key == "compatible_printers") { if (opt_key == "bed_shape" || opt_key == "thumbnails" || opt_key == "compatible_prints" || opt_key == "compatible_printers") {
// Scalar variable, or a vector variable, which is independent from number of extruders, // Scalar variable, or a vector variable, which is independent from number of extruders,

View File

@ -1535,7 +1535,7 @@ std::pair<PrintBase::PrintValidationError, std::string> Print::validate() const
"all nozzles have to be of the same diameter.") }; "all nozzles have to be of the same diameter.") };
} }
if (this->has_wipe_tower()) { if (this->has_wipe_tower()) {
if (object->config().support_material_contact_distance_type == zdNone) { if (object->config().support_material_contact_distance_type.value == zdNone) {
// Soluble interface // Soluble interface
if (! object->config().support_material_synchronize_layers) if (! object->config().support_material_synchronize_layers)
return { PrintBase::PrintValidationError::pveWrongSettings,L("For the Wipe Tower to work with the soluble supports, the support layers need to be synchronized with the object layers.") }; return { PrintBase::PrintValidationError::pveWrongSettings,L("For the Wipe Tower to work with the soluble supports, the support layers need to be synchronized with the object layers.") };

View File

@ -830,9 +830,23 @@ void PrintConfigDef::init_fff_params()
def->sidetext = L("mm or %"); def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter"; def->ratio_over = "nozzle_diameter";
def->min = 0; def->min = 0;
def->can_phony = true;
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
def = this->add("external_perimeter_extrusion_spacing", coFloatOrPercent);
def->label = L("External perimeters");
def->full_label = L("External perimeters spacing");
def->category = OptionCategory::width;
def->tooltip = L("Like the External perimeters width, but this value is the distance between the edge and the 'frontier' to the next perimeter."
"\nSetting the spacing will deactivate the width setting, and vice versa.");
def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter";
def->min = 0;
def->can_phony = true;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false, true));
def = this->add("external_perimeter_cut_corners", coPercent); def = this->add("external_perimeter_cut_corners", coPercent);
def->label = L("Cutting corners"); def->label = L("Cutting corners");
def->full_label = L("Ext. peri. cut corners"); def->full_label = L("Ext. peri. cut corners");
@ -1140,16 +1154,30 @@ void PrintConfigDef::init_fff_params()
def->label = L("Default extrusion width"); def->label = L("Default extrusion width");
def->category = OptionCategory::width; def->category = OptionCategory::width;
def->tooltip = L("Set this to a non-zero value to allow a manual extrusion width. " def->tooltip = L("Set this to a non-zero value to allow a manual extrusion width. "
"If left to zero, Slic3r derives extrusion widths from the nozzle diameter " "If left to zero, Slic3r derives extrusion widths from the nozzle diameter "
"(see the tooltips for perimeter extrusion width, infill extrusion width etc). " "(see the tooltips for perimeter extrusion width, infill extrusion width etc). "
"If expressed as percentage (for example: 105%), it will be computed over nozzle diameter."); "If expressed as percentage (for example: 105%), it will be computed over nozzle diameter.");
def->sidetext = L("mm or %"); def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter"; def->ratio_over = "nozzle_diameter";
def->min = 0; def->min = 0;
def->max = 1000; def->max = 1000;
def->can_phony = true;
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
def = this->add("extrusion_spacing", coFloatOrPercent);
def->label = L("Default extrusion spacing");
def->category = OptionCategory::width;
def->tooltip = L("Like Default extrusion width but spacing is the distance between two lines (as they overlap a bit, it's not the same)."
"\nSetting the spacing will deactivate the width setting, and vice versa.");
def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter";
def->min = 0;
def->max = 1000;
def->can_phony = true;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false, true));
def = this->add("fan_always_on", coBools); def = this->add("fan_always_on", coBools);
def->label = L("Keep fan always on"); def->label = L("Keep fan always on");
def->category = OptionCategory::cooling; def->category = OptionCategory::cooling;
@ -1709,16 +1737,32 @@ void PrintConfigDef::init_fff_params()
def->full_label = L("First layer width"); def->full_label = L("First layer width");
def->category = OptionCategory::width; def->category = OptionCategory::width;
def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for first layer. " def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for first layer. "
"You can use this to force fatter extrudates for better adhesion. If expressed " "You can use this to force fatter extrudates for better adhesion. If expressed "
"as percentage (for example 140%) it will be computed over the nozzle diameter " "as percentage (for example 140%) it will be computed over the nozzle diameter "
"of the nozzle used for the type of extrusion. " "of the nozzle used for the type of extrusion. "
"If set to zero, it will use the default extrusion width."); "If set to zero, it will use the default extrusion width.");
def->sidetext = L("mm or %"); def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter"; def->ratio_over = "nozzle_diameter";
def->min = 0; def->min = 0;
def->max = 1000;
def->can_phony = true;
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(140, true)); def->set_default_value(new ConfigOptionFloatOrPercent(140, true));
def = this->add("first_layer_extrusion_spacing", coFloatOrPercent);
def->label = L("First layer");
def->full_label = L("First layer spacing");
def->category = OptionCategory::width;
def->tooltip = L("Like First layer width but spacing is the distance between two lines (as they overlap a bit, it's not the same)."
"\nSetting the spacing will deactivate the width setting, and vice versa.");
def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter";
def->min = 0;
def->max = 1000;
def->can_phony = true;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false, true));
def = this->add("first_layer_height", coFloatOrPercent); def = this->add("first_layer_height", coFloatOrPercent);
def->label = L("First layer height"); def->label = L("First layer height");
def->category = OptionCategory::perimeter; def->category = OptionCategory::perimeter;
@ -2086,17 +2130,34 @@ void PrintConfigDef::init_fff_params()
def = this->add("infill_extrusion_width", coFloatOrPercent); def = this->add("infill_extrusion_width", coFloatOrPercent);
def->label = L("Infill"); def->label = L("Infill");
def->full_label = L("Infill width");
def->category = OptionCategory::width; def->category = OptionCategory::width;
def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for infill. " def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for infill. "
"If left zero, default extrusion width will be used if set, otherwise 1.125 x nozzle diameter will be used. " "If left zero, default extrusion width will be used if set, otherwise 1.125 x nozzle diameter will be used. "
"You may want to use fatter extrudates to speed up the infill and make your parts stronger. " "You may want to use fatter extrudates to speed up the infill and make your parts stronger. "
"If expressed as percentage (for example 110%) it will be computed over nozzle diameter."); "If expressed as percentage (for example 110%) it will be computed over nozzle diameter.");
def->sidetext = L("mm or %"); def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter"; def->ratio_over = "nozzle_diameter";
def->min = 0; def->min = 0;
def->max = 1000;
def->can_phony = true;
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
def = this->add("infill_extrusion_spacing", coFloatOrPercent);
def->label = L("Infill");
def->full_label = L("Infill spacing");
def->category = OptionCategory::width;
def->tooltip = L("Like First layer width but spacing is the distance between two lines (as they overlap a bit, it's not the same)."
"\nSetting the spacing will deactivate the width setting, and vice versa.");
def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter";
def->min = 0;
def->max = 1000;
def->can_phony = true;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false, true));
def = this->add("infill_first", coBool); def = this->add("infill_first", coBool);
def->label = L("Infill before perimeters"); def->label = L("Infill before perimeters");
def->category = OptionCategory::infill; def->category = OptionCategory::infill;
@ -2799,15 +2860,31 @@ void PrintConfigDef::init_fff_params()
def->full_label = ("Perimeter width"); def->full_label = ("Perimeter width");
def->category = OptionCategory::width; def->category = OptionCategory::width;
def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for perimeters. " def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for perimeters. "
"You may want to use thinner extrudates to get more accurate surfaces. " "You may want to use thinner extrudates to get more accurate surfaces. "
"If left zero, default extrusion width will be used if set, otherwise 1.125 x nozzle diameter will be used. " "If left zero, default extrusion width will be used if set, otherwise 1.125 x nozzle diameter will be used. "
"If expressed as percentage (for example 105%) it will be computed over nozzle diameter."); "If expressed as percentage (for example 105%) it will be computed over nozzle diameter.");
def->sidetext = L("mm or %"); def->sidetext = L("mm or %");
def->aliases = { "perimeters_extrusion_width" }; def->aliases = { "perimeters_extrusion_width" };
def->min = 0; def->min = 0;
def->max = 1000;
def->can_phony = true;
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
def = this->add("perimeter_extrusion_spacing", coFloatOrPercent);
def->label = L("Perimeters");
def->full_label = ("Perimeter spacing");
def->category = OptionCategory::width;
def->tooltip = L("Like Perimeter width but spacing is the distance between two perimeter lines (as they overlap a bit, it's not the same)."
"\nSetting the spacing will deactivate the width setting, and vice versa.");
def->sidetext = L("mm or %");
def->aliases = { "perimeters_extrusion_width" };
def->min = 0;
def->max = 1000;
def->can_phony = true;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false, true));
def = this->add("perimeter_speed", coFloat); def = this->add("perimeter_speed", coFloat);
def->label = L("Default"); def->label = L("Default");
def->full_label = ("Default speed"); def->full_label = ("Default speed");
@ -3141,10 +3218,12 @@ void PrintConfigDef::init_fff_params()
def = this->add("skirt_extrusion_width", coFloatOrPercent); def = this->add("skirt_extrusion_width", coFloatOrPercent);
def->label = L("Skirt"); def->label = L("Skirt");
def->full_label = L("Skirt width");
def->category = OptionCategory::width; def->category = OptionCategory::width;
def->tooltip = L("Horizontal width of the skirt that will be printed around each object."); def->tooltip = L("Horizontal width of the skirt that will be printed around each object.");
def->sidetext = L("mm"); def->sidetext = L("mm");
def->min = 0; def->min = 0;
def->max = 1000;
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
@ -3306,14 +3385,30 @@ void PrintConfigDef::init_fff_params()
def->full_label = ("Solid infill width"); def->full_label = ("Solid infill width");
def->category = OptionCategory::width; def->category = OptionCategory::width;
def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for infill for solid surfaces. " def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for infill for solid surfaces. "
"If left zero, default extrusion width will be used if set, otherwise 1.125 x nozzle diameter will be used. " "If left zero, default extrusion width will be used if set, otherwise 1.125 x nozzle diameter will be used. "
"If expressed as percentage (for example 110%) it will be computed over nozzle diameter."); "If expressed as percentage (for example 110%) it will be computed over nozzle diameter.");
def->sidetext = L("mm or %"); def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter"; def->ratio_over = "nozzle_diameter";
def->min = 0; def->min = 0;
def->max = 1000;
def->can_phony = true;
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
def = this->add("solid_infill_extrusion_spacing", coFloatOrPercent);
def->label = L("Solid spacing");
def->full_label = ("Solid infill spacing");
def->category = OptionCategory::width;
def->tooltip = L("Like Solid infill width but spacing is the distance between two lines (as they overlap a bit, it's not the same)."
"\nSetting the spacing will deactivate the width setting, and vice versa.");
def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter";
def->min = 0;
def->max = 1000;
def->can_phony = true;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false, true));
def = this->add("solid_infill_speed", coFloatOrPercent); def = this->add("solid_infill_speed", coFloatOrPercent);
def->label = L("Solid"); def->label = L("Solid");
def->full_label = ("Solid infill speed"); def->full_label = ("Solid infill speed");
@ -3577,11 +3672,12 @@ void PrintConfigDef::init_fff_params()
def->full_label = L("Support material width"); def->full_label = L("Support material width");
def->category = OptionCategory::width; def->category = OptionCategory::width;
def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for support material. " def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for support material. "
"If left zero, default extrusion width will be used if set, otherwise nozzle diameter will be used. " "If left zero, default extrusion width will be used if set, otherwise nozzle diameter will be used. "
"If expressed as percentage (for example 110%) it will be computed over nozzle diameter."); "If expressed as percentage (for example 110%) it will be computed over nozzle diameter.");
def->sidetext = L("mm or %"); def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter"; def->ratio_over = "nozzle_diameter";
def->min = 0; def->min = 0;
def->max = 1000;
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
@ -3857,15 +3953,30 @@ void PrintConfigDef::init_fff_params()
def->label = L("Top solid infill"); def->label = L("Top solid infill");
def->category = OptionCategory::width; def->category = OptionCategory::width;
def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for infill for top surfaces. " def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for infill for top surfaces. "
"You may want to use thinner extrudates to fill all narrow regions and get a smoother finish. " "You may want to use thinner extrudates to fill all narrow regions and get a smoother finish. "
"If left zero, default extrusion width will be used if set, otherwise nozzle diameter will be used. " "If left zero, default extrusion width will be used if set, otherwise nozzle diameter will be used. "
"If expressed as percentage (for example 110%) it will be computed over nozzle diameter."); "If expressed as percentage (for example 110%) it will be computed over nozzle diameter.");
def->sidetext = L("mm or %"); def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter"; def->ratio_over = "nozzle_diameter";
def->min = 0; def->min = 0;
def->max = 1000;
def->can_phony = true;
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); def->set_default_value(new ConfigOptionFloatOrPercent(0, false));
def = this->add("top_infill_extrusion_spacing", coFloatOrPercent);
def->label = L("Top solid spacing");
def->category = OptionCategory::width;
def->tooltip = L("Like Top solid infill width but spacing is the distance between two lines (as they overlap a bit, it's not the same)."
"\nSetting the spacing will deactivate the width setting, and vice versa.");
def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter";
def->min = 0;
def->max = 1000;
def->can_phony = true;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false, true));
def = this->add("top_solid_infill_speed", coFloatOrPercent); def = this->add("top_solid_infill_speed", coFloatOrPercent);
def->label = L("Top solid"); def->label = L("Top solid");
def->full_label = L("Top solid speed"); def->full_label = L("Top solid speed");
@ -5141,6 +5252,12 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
// In PrusaSlicer 2.3.0-alpha0 the "monotonic" infill was introduced, which was later renamed to "monotonous". // In PrusaSlicer 2.3.0-alpha0 the "monotonic" infill was introduced, which was later renamed to "monotonous".
if (value == "monotonous" && (opt_key == "top_fill_pattern" || opt_key == "bottom_fill_pattern" || opt_key == "fill_pattern" || opt_key == "solid_fill_pattern" || opt_key == "support_material_interface_pattern")) if (value == "monotonous" && (opt_key == "top_fill_pattern" || opt_key == "bottom_fill_pattern" || opt_key == "fill_pattern" || opt_key == "solid_fill_pattern" || opt_key == "support_material_interface_pattern"))
value = "monotonic"; value = "monotonic";
// some changes has occurs between rectilineargapfill and monotonicgapfill. Set them at the right value for each type
if (value == "rectilineargapfill" && (opt_key == "top_fill_pattern" || opt_key == "bottom_fill_pattern" || opt_key == "fill_pattern" || opt_key == "support_material_interface_pattern"))
value = "monotonicgapfill";
if (value == "monotonicgapfill" && (opt_key == "solid_fill_pattern"))
value = "rectilineargapfill";
if (ignore.find(opt_key) != ignore.end()) { if (ignore.find(opt_key) != ignore.end()) {
opt_key = ""; opt_key = "";
@ -5292,7 +5409,14 @@ void PrintConfigDef::to_prusa(t_config_option_key& opt_key, std::string& value,
"milling_post_process", "milling_post_process",
"milling_extra_size", "milling_extra_size",
"milling_after_z", "milling_after_z",
"milling_speed" "milling_speed",
"extrusion_spacing",
"first_layer_extrusion_spacing",
"perimeter_extrusion_spacing",
"external_perimeter_extrusion_spacing",
"infill_extrusion_spacing",
"solid_infill_extrusion_spacing",
"top_infill_extrusion_spacing"
}; };
//looks if it's to be removed, or have to be transformed //looks if it's to be removed, or have to be transformed
@ -5360,6 +5484,15 @@ void PrintConfigDef::to_prusa(t_config_option_key& opt_key, std::string& value,
value = "marlin"; value = "marlin";
else if ("klipper" == value) else if ("klipper" == value)
value = "reprap"; value = "reprap";
} else if (opt_key.find("extrusion_width") != std::string::npos) {
if (std::set<std::string>{"extrusion_width", "first_layer_extrusion_width", "perimeter_extrusion_width", "external_perimeter_extrusion_width",
"infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width"}.count(opt_key) > 0) {
const ConfigOptionFloatOrPercent* opt = all_conf.option<ConfigOptionFloatOrPercent>(opt_key);
if (opt->phony) {
//bypass the phony kill switch from Config::opt_serialize
value = opt->serialize();
}
}
} }
} }
@ -5592,6 +5725,7 @@ std::string DynamicPrintConfig::validate()
{ {
FullPrintConfig fpc; FullPrintConfig fpc;
fpc.apply(*this, true); fpc.apply(*this, true);
// Verify this print options through the FullPrintConfig. // Verify this print options through the FullPrintConfig.
return fpc.validate(); return fpc.validate();
} }
@ -5601,6 +5735,261 @@ std::string DynamicPrintConfig::validate()
} }
} }
template<typename TYPE>
const TYPE* find_option(const t_config_option_key &opt_key, DynamicPrintConfig* default_config, const std::vector<const DynamicPrintConfig*> &other_config) {
const TYPE* option = default_config->option<TYPE>(opt_key);
if (option)
return option;
for (const DynamicPrintConfig* conf : other_config) {
option = conf->option<TYPE>(opt_key);
if (option)
return option;
}
return nullptr;
}
bool DynamicPrintConfig::update_phony(const std::vector<const DynamicPrintConfig*> config_collection) {
bool something_changed = false;
//update width/spacing links
const char* widths[] = { "", "external_perimeter_", "perimeter_", "infill_", "solid_infill_", "top_infill_", "support_material_", "first_layer_", "skirt_" };
for (size_t i = 0; i < sizeof(widths) / sizeof(widths[i]); ++i) {
std::string key_width(widths[i]);
key_width += "extrusion_width";
std::string key_spacing(widths[i]);
key_spacing += "extrusion_spacing";
ConfigOptionFloatOrPercent* width_option = this->option<ConfigOptionFloatOrPercent>(key_width);
ConfigOptionFloatOrPercent* spacing_option = this->option<ConfigOptionFloatOrPercent>(key_spacing);
if (width_option && spacing_option)
if (!spacing_option->phony && width_option->phony)
something_changed |= value_changed(key_spacing, config_collection);
else
something_changed |= value_changed(key_width, config_collection);
}
return something_changed;
}
bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const std::vector<const DynamicPrintConfig*> config_collection) {
if (opt_key == "layer_height") {
update_phony(config_collection);
}
bool something_changed = false;
// width -> spacing
if (opt_key.find("extrusion_spacing") != std::string::npos) {
const ConfigOptionFloats* nozzle_diameter_option = find_option<ConfigOptionFloats>("nozzle_diameter", this, config_collection);
const ConfigOptionFloat* layer_height_option = find_option<ConfigOptionFloat>("layer_height", this, config_collection);
ConfigOptionFloatOrPercent* spacing_option = this->option<ConfigOptionFloatOrPercent>(opt_key);
if (layer_height_option && spacing_option && nozzle_diameter_option) {
//compute spacing with current height and change the width
double max_nozzle_diameter = 0;
for (double dmr : nozzle_diameter_option->values)
max_nozzle_diameter = std::max(max_nozzle_diameter, dmr);
Flow flow = Flow::new_from_spacing(spacing_option->get_abs_value(max_nozzle_diameter), max_nozzle_diameter, layer_height_option->value, false);
if (opt_key == "extrusion_spacing") {
ConfigOptionFloatOrPercent* width_option = this->option<ConfigOptionFloatOrPercent>("extrusion_width");
if (width_option) {
width_option->phony = true;
spacing_option->phony = false;
width_option->value = (spacing_option->percent) ? std::round(100 * flow.width / max_nozzle_diameter) : (std::round(flow.width * 10000) / 10000);
width_option->percent = spacing_option->percent;
something_changed = true;
}
}
if (opt_key == "first_layer_extrusion_spacing") {
ConfigOptionFloatOrPercent* width_option = this->option<ConfigOptionFloatOrPercent>("first_layer_extrusion_width");
if (width_option) {
width_option->phony = true;
spacing_option->phony = false;
width_option->value = (spacing_option->percent) ? std::round(100 * flow.width / max_nozzle_diameter) : (std::round(flow.width * 10000) / 10000);
width_option->percent = spacing_option->percent;
something_changed = true;
}
}
if (opt_key == "perimeter_extrusion_spacing") {
const ConfigOptionPercent* perimeter_overlap_option = find_option<ConfigOptionPercent>("perimeter_overlap", this, config_collection);
ConfigOptionFloatOrPercent* width_option = this->option<ConfigOptionFloatOrPercent>("perimeter_extrusion_width");
if (width_option && perimeter_overlap_option) {
width_option->phony = true;
spacing_option->phony = false;
flow.spacing_ratio = perimeter_overlap_option->get_abs_value(1);
flow.width = spacing_option->get_abs_value(max_nozzle_diameter) + layer_height_option->value * (1. - 0.25 * PI) * flow.spacing_ratio;
width_option->value = (spacing_option->percent) ? std::round(100 * flow.width / max_nozzle_diameter) : (std::round(flow.width * 10000) / 10000);
width_option->percent = spacing_option->percent;
something_changed = true;
}
}
if (opt_key == "external_perimeter_extrusion_spacing") {
const ConfigOptionPercent* external_perimeter_overlap_option = find_option<ConfigOptionPercent>("external_perimeter_overlap", this, config_collection);
ConfigOptionFloatOrPercent* width_option = this->option<ConfigOptionFloatOrPercent>("external_perimeter_extrusion_width");
if (width_option && external_perimeter_overlap_option) {
width_option->phony = true;
spacing_option->phony = false;
flow.spacing_ratio = external_perimeter_overlap_option->get_abs_value(0.5);
flow.width = spacing_option->get_abs_value(max_nozzle_diameter) + layer_height_option->value * (1. - 0.25 * PI) * flow.spacing_ratio;
width_option->value = (spacing_option->percent) ? std::round(100 * flow.width / max_nozzle_diameter) : (std::round(flow.width * 10000) / 10000);
width_option->percent = spacing_option->percent;
something_changed = true;
}
}
if (opt_key == "infill_extrusion_spacing") {
ConfigOptionFloatOrPercent* width_option = this->option<ConfigOptionFloatOrPercent>("infill_extrusion_width");
if (width_option) {
width_option->phony = true;
spacing_option->phony = false;
width_option->value = (spacing_option->percent) ? std::round(100 * flow.width / max_nozzle_diameter) : (std::round(flow.width * 10000) / 10000);
width_option->percent = spacing_option->percent;
something_changed = true;
}
}
if (opt_key == "solid_infill_extrusion_spacing") {
ConfigOptionFloatOrPercent* width_option = this->option<ConfigOptionFloatOrPercent>("solid_infill_extrusion_width");
if (width_option) {
width_option->phony = true;
spacing_option->phony = false;
width_option->value = (spacing_option->percent) ? std::round(100 * flow.width / max_nozzle_diameter) : (std::round(flow.width * 10000) / 10000);
width_option->percent = spacing_option->percent;
something_changed = true;
}
}
if (opt_key == "top_infill_extrusion_spacing") {
ConfigOptionFloatOrPercent* width_option = this->option<ConfigOptionFloatOrPercent>("top_infill_extrusion_width");
if (width_option) {
width_option->phony = true;
spacing_option->phony = false;
width_option->value = (spacing_option->percent) ? std::round(100 * flow.width / max_nozzle_diameter) : (std::round(flow.width * 10000) / 10000);
width_option->percent = spacing_option->percent;
something_changed = true;
}
}
/*if (opt_key == "support_material_extrusion_spacing") {
if (spacing_option->percent)
this->set_key_value("support_material_extrusion_width", new ConfigOptionFloatOrPercent(std::round(100 * flow.width / max_nozzle_diameter), true));
else
this->set_key_value("support_material_extrusion_width", new ConfigOptionFloatOrPercent(std::round(flow.width * 10000) / 10000, false));
something_changed = true;
}
if (opt_key == "skirt_extrusion_spacing") {
if (spacing_option->percent)
this->set_key_value("skirt_extrusion_width", new ConfigOptionFloatOrPercent(std::round(100 * flow.width / max_nozzle_diameter), true));
else
this->set_key_value("skirt_extrusion_width", new ConfigOptionFloatOrPercent(std::round(flow.width * 10000) / 10000, false));
something_changed = true;
}*/
}
}
if (opt_key.find("extrusion_width") != std::string::npos) {
const ConfigOptionFloats* nozzle_diameter_option = find_option<ConfigOptionFloats>("nozzle_diameter", this, config_collection);
const ConfigOptionFloat* layer_height_option = find_option<ConfigOptionFloat>("layer_height", this, config_collection);
ConfigOptionFloatOrPercent* width_option = this->option<ConfigOptionFloatOrPercent>(opt_key);
if (layer_height_option && width_option && nozzle_diameter_option) {
//compute spacing with current height and change the width
double max_nozzle_diameter = 0;
for (double dmr : nozzle_diameter_option->values)
max_nozzle_diameter = std::max(max_nozzle_diameter, dmr);
if (opt_key == "extrusion_width") {
ConfigOptionFloatOrPercent* spacing_option = this->option<ConfigOptionFloatOrPercent>("extrusion_spacing");
if (width_option) {
width_option->phony = false;
spacing_option->phony = true;
Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
something_changed = true;
}
}
if (opt_key == "first_layer_extrusion_width") {
ConfigOptionFloatOrPercent* spacing_option = this->option<ConfigOptionFloatOrPercent>("first_layer_extrusion_spacing");
if (width_option) {
width_option->phony = false;
spacing_option->phony = true;
Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
something_changed = true;
}
}
if (opt_key == "perimeter_extrusion_width") {
const ConfigOptionPercent* perimeter_overlap_option = find_option<ConfigOptionPercent>("perimeter_overlap", this, config_collection);
ConfigOptionFloatOrPercent* spacing_option = this->option<ConfigOptionFloatOrPercent>("perimeter_extrusion_spacing");
if (width_option && perimeter_overlap_option) {
width_option->phony = false;
spacing_option->phony = true;
Flow flow = Flow::new_from_config_width(FlowRole::frExternalPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
flow.spacing_ratio = perimeter_overlap_option->get_abs_value(1);
spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
something_changed = true;
}
}
if (opt_key == "external_perimeter_extrusion_width") {
const ConfigOptionPercent* external_perimeter_overlap_option = find_option<ConfigOptionPercent>("external_perimeter_overlap", this, config_collection);
ConfigOptionFloatOrPercent* spacing_option = this->option<ConfigOptionFloatOrPercent>("external_perimeter_extrusion_spacing");
if (width_option && external_perimeter_overlap_option) {
width_option->phony = false;
spacing_option->phony = true;
Flow ext_perimeter_flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
ext_perimeter_flow.spacing_ratio = external_perimeter_overlap_option->get_abs_value(0.5);
spacing_option->value = (width_option->percent) ? std::round(100 * ext_perimeter_flow.spacing() / max_nozzle_diameter) : (std::round(ext_perimeter_flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
something_changed = true;
}
}
if (opt_key == "infill_extrusion_width") {
ConfigOptionFloatOrPercent* spacing_option = this->option<ConfigOptionFloatOrPercent>("infill_extrusion_spacing");
if (width_option) {
width_option->phony = false;
spacing_option->phony = true;
Flow flow = Flow::new_from_config_width(FlowRole::frInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
something_changed = true;
}
}
if (opt_key == "solid_infill_extrusion_width") {
ConfigOptionFloatOrPercent* spacing_option = this->option<ConfigOptionFloatOrPercent>("solid_infill_extrusion_spacing");
if (width_option) {
width_option->phony = false;
spacing_option->phony = true;
Flow flow = Flow::new_from_config_width(FlowRole::frSolidInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
something_changed = true;
}
}
if (opt_key == "top_infill_extrusion_width") {
ConfigOptionFloatOrPercent* spacing_option = this->option<ConfigOptionFloatOrPercent>("top_infill_extrusion_spacing");
if (width_option) {
width_option->phony = false;
spacing_option->phony = true;
Flow flow = Flow::new_from_config_width(FlowRole::frTopSolidInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
something_changed = true;
}
}
//if (opt_key == "support_material_extrusion_width") {
// Flow flow = Flow::new_from_config_width(FlowRole::frSupportMaterial, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
// if (width_option->percent)
// this->set_key_value("support_material_extrusion_spacing", new ConfigOptionFloatOrPercent(std::round(100 * flow.spacing() / max_nozzle_diameter), true));
// else
// this->set_key_value("support_material_extrusion_spacing", new ConfigOptionFloatOrPercent(std::round(flow.spacing() * 10000) / 10000, false));
// something_changed = true;
//}
//if (opt_key == "skirt_extrusion_width") {
// Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
// if (width_option->percent)
// this->set_key_value("skirt_extrusion_spacing", new ConfigOptionFloatOrPercent(std::round(100 * flow.spacing() / max_nozzle_diameter), true));
// else
// this->set_key_value("skirt_extrusion_spacing", new ConfigOptionFloatOrPercent(std::round(flow.spacing() * 10000) / 10000, false));
// something_changed = true;
//}
}
}
return something_changed;
}
//FIXME localize this function. //FIXME localize this function.
std::string FullPrintConfig::validate() std::string FullPrintConfig::validate()
{ {
@ -5701,8 +6090,8 @@ std::string FullPrintConfig::validate()
return "Invalid value for --extrusion-multiplier"; return "Invalid value for --extrusion-multiplier";
// --default-acceleration // --default-acceleration
if ((this->perimeter_acceleration != 0. || this->infill_acceleration != 0. || this->bridge_acceleration != 0. || this->first_layer_acceleration != 0.) && if ((this->perimeter_acceleration.value != 0. || this->infill_acceleration.value != 0. || this->bridge_acceleration.value != 0. || this->first_layer_acceleration.value != 0.) &&
this->default_acceleration == 0.) this->default_acceleration.value == 0.)
return "Invalid zero value for --default-acceleration when using other acceleration settings"; return "Invalid zero value for --default-acceleration when using other acceleration settings";
// --spiral-vase // --spiral-vase
@ -5732,10 +6121,10 @@ std::string FullPrintConfig::validate()
double max_nozzle_diameter = 0.; double max_nozzle_diameter = 0.;
for (double dmr : this->nozzle_diameter.values) for (double dmr : this->nozzle_diameter.values)
max_nozzle_diameter = std::max(max_nozzle_diameter, dmr); max_nozzle_diameter = std::max(max_nozzle_diameter, dmr);
const char *widths[] = { "external_perimeter", "perimeter", "infill", "solid_infill", "top_infill", "support_material", "first_layer" }; const char *widths[] = { "", "external_perimeter_", "perimeter_", "infill_", "solid_infill_", "top_infill_", "support_material_", "first_layer_", "skirt_" };
for (size_t i = 0; i < sizeof(widths) / sizeof(widths[i]); ++ i) { for (size_t i = 0; i < sizeof(widths) / sizeof(widths[i]); ++ i) {
std::string key(widths[i]); std::string key(widths[i]);
key += "_extrusion_width"; key += "extrusion_width";
if (this->get_abs_value(key, max_nozzle_diameter) > 10. * max_nozzle_diameter) if (this->get_abs_value(key, max_nozzle_diameter) > 10. * max_nozzle_diameter)
return std::string("Invalid extrusion width (too large): ") + key; return std::string("Invalid extrusion width (too large): ") + key;
} }

View File

@ -456,6 +456,13 @@ public:
void to_prusa(t_config_option_key& opt_key, std::string& value) const override void to_prusa(t_config_option_key& opt_key, std::string& value) const override
{ PrintConfigDef::to_prusa(opt_key, value, *this); } { PrintConfigDef::to_prusa(opt_key, value, *this); }
/// <summary>
/// callback to changed other settings that are linked (like width & spacing)
/// </summary>
/// <param name="opt_key">name of the changed option</param>
bool value_changed(const t_config_option_key& opt_key, const std::vector<const DynamicPrintConfig*> config_collection);
bool update_phony(const std::vector<const DynamicPrintConfig*> config_collection);
}; };
class StaticPrintConfig : public StaticConfig class StaticPrintConfig : public StaticConfig

View File

@ -725,7 +725,7 @@ namespace Slic3r {
steps.emplace_back(posSlice); steps.emplace_back(posSlice);
} else if (opt_key == "support_material") { } else if (opt_key == "support_material") {
steps.emplace_back(posSupportMaterial); steps.emplace_back(posSupportMaterial);
if (m_config.support_material_contact_distance_top == 0. || m_config.support_material_contact_distance_bottom == 0.) { if (m_config.support_material_contact_distance_top.value == 0. || m_config.support_material_contact_distance_bottom.value == 0.) {
// Enabling / disabling supports while soluble support interface is enabled. // Enabling / disabling supports while soluble support interface is enabled.
// This changes the bridging logic (bridging enabled without supports, disabled with supports). // This changes the bridging logic (bridging enabled without supports, disabled with supports).
// Reset everything. // Reset everything.
@ -1091,20 +1091,20 @@ namespace Slic3r {
if (!intersect.empty()) { if (!intersect.empty()) {
double area_intersect = 0; double area_intersect = 0;
// calculate area to decide if area is small enough for autofill // calculate area to decide if area is small enough for autofill
if (layerm->region()->config().infill_dense_algo == dfaAutoNotFull || layerm->region()->config().infill_dense_algo == dfaAutoOrEnlarged) if (layerm->region()->config().infill_dense_algo.value == dfaAutoNotFull || layerm->region()->config().infill_dense_algo.value == dfaAutoOrEnlarged)
for (ExPolygon poly_inter : intersect) for (ExPolygon poly_inter : intersect)
area_intersect += poly_inter.area(); area_intersect += poly_inter.area();
if (layerm->region()->config().infill_dense_algo == dfaEnlarged if (layerm->region()->config().infill_dense_algo.value == dfaEnlarged
|| (layerm->region()->config().infill_dense_algo == dfaAutoOrEnlarged && surf.area() <= area_intersect * COEFF_SPLIT)) { || (layerm->region()->config().infill_dense_algo.value == dfaAutoOrEnlarged && surf.area() <= area_intersect * COEFF_SPLIT)) {
//expand the area a bit //expand the area a bit
intersect = offset_ex(intersect, double(scale_(layerm->region()->config().external_infill_margin.get_abs_value( intersect = offset_ex(intersect, double(scale_(layerm->region()->config().external_infill_margin.get_abs_value(
region->config().perimeters == 0 ? 0 : (layerm->flow(frExternalPerimeter).width + layerm->flow(frPerimeter).spacing() * (region->config().perimeters - 1)))))); region->config().perimeters == 0 ? 0 : (layerm->flow(frExternalPerimeter).width + layerm->flow(frPerimeter).spacing() * (region->config().perimeters - 1))))));
} else if (layerm->region()->config().infill_dense_algo == dfaAutoNotFull } else if (layerm->region()->config().infill_dense_algo.value == dfaAutoNotFull
|| layerm->region()->config().infill_dense_algo == dfaAutomatic) { || layerm->region()->config().infill_dense_algo.value == dfaAutomatic) {
//like intersect.empty() but more resilient //like intersect.empty() but more resilient
if (layerm->region()->config().infill_dense_algo == dfaAutomatic if (layerm->region()->config().infill_dense_algo.value == dfaAutomatic
|| surf.area() > area_intersect * COEFF_SPLIT) { || surf.area() > area_intersect * COEFF_SPLIT) {
ExPolygons cover_intersect; ExPolygons cover_intersect;
@ -1237,7 +1237,7 @@ namespace Slic3r {
Polygons layerm_slices_surfaces = to_polygons(layerm->slices().surfaces); Polygons layerm_slices_surfaces = to_polygons(layerm->slices().surfaces);
// no_perimeter_full_bridge allow to put bridges where there are nothing, hence adding area to slice, that's why we need to start from the result of PerimeterGenerator. // no_perimeter_full_bridge allow to put bridges where there are nothing, hence adding area to slice, that's why we need to start from the result of PerimeterGenerator.
if (layerm->region()->config().no_perimeter_unsupported_algo == npuaFilled) { if (layerm->region()->config().no_perimeter_unsupported_algo.value == npuaFilled) {
layerm_slices_surfaces = union_(layerm_slices_surfaces, to_polygons(layerm->fill_surfaces)); layerm_slices_surfaces = union_(layerm_slices_surfaces, to_polygons(layerm->fill_surfaces));
} }
@ -3512,11 +3512,11 @@ namespace Slic3r {
0.5f * layerms.back()->flow(frPerimeter).scaled_width() + 0.5f * layerms.back()->flow(frPerimeter).scaled_width() +
// Because fill areas for rectilinear and honeycomb are grown // Because fill areas for rectilinear and honeycomb are grown
// later to overlap perimeters, we need to counteract that too. // later to overlap perimeters, we need to counteract that too.
((region->config().fill_pattern == ipRectilinear || ((region->config().fill_pattern.value == ipRectilinear ||
region->config().fill_pattern == ipMonotonic || region->config().fill_pattern.value == ipMonotonic ||
region->config().fill_pattern == ipGrid || region->config().fill_pattern.value == ipGrid ||
region->config().fill_pattern == ipLine || region->config().fill_pattern.value == ipLine ||
region->config().fill_pattern == ipHoneycomb) ? 1.5f : 0.5f) * region->config().fill_pattern.value == ipHoneycomb) ? 1.5f : 0.5f) *
layerms.back()->flow(frSolidInfill).scaled_width(); layerms.back()->flow(frSolidInfill).scaled_width();
for (ExPolygon& expoly : intersection) for (ExPolygon& expoly : intersection)
polygons_append(intersection_with_clearance, offset(expoly, clearance_offset)); polygons_append(intersection_with_clearance, offset(expoly, clearance_offset));

View File

@ -1242,7 +1242,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
// it will support layers printed with a bridging flow. // it will support layers printed with a bridging flow.
if (SupportMaterialInternal::has_bridging_extrusions(layer)) { if (SupportMaterialInternal::has_bridging_extrusions(layer)) {
coordf_t bridging_height = layer.height; coordf_t bridging_height = layer.height;
if (m_object_config->support_material_contact_distance_type == zdFilament) { if (m_object_config->support_material_contact_distance_type.value == zdFilament) {
bridging_height = 0.; bridging_height = 0.;
for (const LayerRegion *region : layer.regions()) for (const LayerRegion *region : layer.regions())
bridging_height += region->region()->bridging_height_avg(*m_print_config); bridging_height += region->region()->bridging_height_avg(*m_print_config);
@ -1513,7 +1513,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
// According to Jindrich the bottom surfaces work well. // According to Jindrich the bottom surfaces work well.
//FIXME test the bridging flow instead? //FIXME test the bridging flow instead?
m_support_material_interface_flow.nozzle_diameter; m_support_material_interface_flow.nozzle_diameter;
layer_new.height_block = ((m_object_config->support_material_contact_distance_type == zdPlane) ? object.layers()[layer_id + 1]->height : layer_new.height); layer_new.height_block = ((m_object_config->support_material_contact_distance_type.value == zdPlane) ? object.layers()[layer_id + 1]->height : layer_new.height);
layer_new.print_z = m_slicing_params.soluble_interface ? object.layers()[layer_id + 1]->print_z : layer_new.print_z = m_slicing_params.soluble_interface ? object.layers()[layer_id + 1]->print_z :
(layer.print_z + layer_new.height_block + this->m_slicing_params.gap_object_support); (layer.print_z + layer_new.height_block + this->m_slicing_params.gap_object_support);
layer_new.bottom_z = layer.print_z; layer_new.bottom_z = layer.print_z;
@ -2135,7 +2135,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
const Layer &object_layer = *object.layers()[i]; const Layer &object_layer = *object.layers()[i];
bool some_region_overlaps = false; bool some_region_overlaps = false;
for (LayerRegion *region : object_layer.regions()) { for (LayerRegion *region : object_layer.regions()) {
coordf_t bridging_height = m_object_config->support_material_contact_distance_type == zdFilament coordf_t bridging_height = m_object_config->support_material_contact_distance_type.value == zdFilament
? region->region()->bridging_height_avg(*this->m_print_config) ? region->region()->bridging_height_avg(*this->m_print_config)
: object_layer.height; : object_layer.height;
if (object_layer.print_z - bridging_height > support_layer.print_z + gap_extra_above - EPSILON) if (object_layer.print_z - bridging_height > support_layer.print_z + gap_extra_above - EPSILON)

View File

@ -50,6 +50,18 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, const std::vector<Entry
grid_sizer->Add(sys_colour, -1, wxALIGN_CENTRE_VERTICAL); grid_sizer->Add(sys_colour, -1, wxALIGN_CENTRE_VERTICAL);
grid_sizer->Add(sys_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND); grid_sizer->Add(sys_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
auto default_label = new wxStaticText(this, wxID_ANY, _(L("Value is the same as the last saved preset, but is not the system value")));
default_label->SetForegroundColour(wxGetApp().get_label_clr_default());
auto default_colour = new wxColourPickerCtrl(this, wxID_ANY, wxGetApp().get_label_clr_default());
default_colour->Bind(wxEVT_COLOURPICKER_CHANGED, ([default_colour, default_label](wxCommandEvent e)
{
default_label->SetForegroundColour(default_colour->GetColour());
default_label->Refresh();
}));
grid_sizer->Add(0, -1, wxALIGN_CENTRE_VERTICAL);
grid_sizer->Add(default_colour, -1, wxALIGN_CENTRE_VERTICAL);
grid_sizer->Add(default_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
auto mod_label = new wxStaticText(this, wxID_ANY, _(L("Value was changed and is not equal to the system value or the last saved preset"))); auto mod_label = new wxStaticText(this, wxID_ANY, _(L("Value was changed and is not equal to the system value or the last saved preset")));
mod_label->SetForegroundColour(wxGetApp().get_label_clr_modified()); mod_label->SetForegroundColour(wxGetApp().get_label_clr_modified());
auto mod_colour = new wxColourPickerCtrl(this, wxID_ANY, wxGetApp().get_label_clr_modified()); auto mod_colour = new wxColourPickerCtrl(this, wxID_ANY, wxGetApp().get_label_clr_modified());
@ -62,14 +74,28 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, const std::vector<Entry
grid_sizer->Add(mod_colour, -1, wxALIGN_CENTRE_VERTICAL); grid_sizer->Add(mod_colour, -1, wxALIGN_CENTRE_VERTICAL);
grid_sizer->Add(mod_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND); grid_sizer->Add(mod_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
auto phony_label = new wxStaticText(this, wxID_ANY, _(L("Value isn't taken into account, it's computed over an other field.")));
phony_label->SetForegroundColour(wxGetApp().get_label_clr_phony());
auto phony_colour = new wxColourPickerCtrl(this, wxID_ANY, wxGetApp().get_label_clr_phony());
phony_colour->Bind(wxEVT_COLOURPICKER_CHANGED, ([phony_colour, phony_label](wxCommandEvent e)
{
phony_label->SetForegroundColour(phony_colour->GetColour());
phony_label->Refresh();
}));
grid_sizer->Add(0, -1, wxALIGN_CENTRE_VERTICAL);
grid_sizer->Add(phony_colour, -1, wxALIGN_CENTRE_VERTICAL);
grid_sizer->Add(phony_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
auto buttons = CreateStdDialogButtonSizer(wxOK|wxCANCEL); auto buttons = CreateStdDialogButtonSizer(wxOK|wxCANCEL);
main_sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); main_sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10);
wxButton* btn = static_cast<wxButton*>(FindWindowById(wxID_OK, this)); wxButton* btn = static_cast<wxButton*>(FindWindowById(wxID_OK, this));
btn->Bind(wxEVT_BUTTON, [sys_colour, mod_colour, this](wxCommandEvent&) { btn->Bind(wxEVT_BUTTON, [sys_colour, mod_colour, default_colour, phony_colour, this](wxCommandEvent&) {
wxGetApp().set_label_clr_sys(sys_colour->GetColour()); wxGetApp().set_label_clr_sys(sys_colour->GetColour());
wxGetApp().set_label_clr_modified(mod_colour->GetColour()); wxGetApp().set_label_clr_modified(mod_colour->GetColour());
wxGetApp().set_label_clr_default(default_colour->GetColour());
wxGetApp().set_label_clr_phony(phony_colour->GetColour());
EndModal(wxID_OK); EndModal(wxID_OK);
}); });

View File

@ -1033,6 +1033,7 @@ void GUI_App::init_label_colours()
m_color_label_sys = wxColour(26, 132, 57); m_color_label_sys = wxColour(26, 132, 57);
} }
m_color_label_default = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); m_color_label_default = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
m_color_label_phony = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
} }
void GUI_App::update_label_colours_from_appconfig() void GUI_App::update_label_colours_from_appconfig()
@ -1048,6 +1049,18 @@ void GUI_App::update_label_colours_from_appconfig()
if (str != "") if (str != "")
m_color_label_modified = wxColour(str); m_color_label_modified = wxColour(str);
} }
if (app_config->has("label_clr_default")) {
auto str = app_config->get("label_clr_default");
if (str != "")
m_color_label_default = wxColour(str);
}
if (app_config->has("label_clr_phony")) {
auto str = app_config->get("label_clr_phony");
if (str != "")
m_color_label_phony = wxColour(str);
}
} }
void GUI_App::init_fonts() void GUI_App::init_fonts()
@ -1099,6 +1112,22 @@ void GUI_App::set_label_clr_sys(const wxColour& clr) {
app_config->save(); app_config->save();
} }
void GUI_App::set_label_clr_default(const wxColour& clr) {
m_color_label_default = clr;
auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue());
std::string str = clr_str.ToStdString();
app_config->set("label_clr_default", str);
app_config->save();
}
void GUI_App::set_label_clr_phony(const wxColour& clr) {
m_color_label_phony = clr;
auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue());
std::string str = clr_str.ToStdString();
app_config->set("label_clr_phony", str);
app_config->save();
}
wxSize GUI_App::get_min_size() const wxSize GUI_App::get_min_size() const
{ {
return wxSize(76*m_em_unit, 49 * m_em_unit); return wxSize(76*m_em_unit, 49 * m_em_unit);
@ -1154,7 +1183,7 @@ void GUI_App::check_printer_presets()
for (const std::string& preset_name : preset_names) for (const std::string& preset_name : preset_names)
msg_text += "\n \"" + from_u8(preset_name) + "\","; msg_text += "\n \"" + from_u8(preset_name) + "\",";
msg_text.RemoveLast(); msg_text.RemoveLast();
msg_text += "\n\n" + _L("But since this version of PrusaSlicer we don't show this information in Printer Settings anymore.\n" msg_text += "\n\n" + _L("But since this version of " SLIC3R_APP_NAME " we don't show this information in Printer Settings anymore.\n"
"Settings will be available in physical printers settings.") + "\n\n" + "Settings will be available in physical printers settings.") + "\n\n" +
_L("By default new Printer devices will be named as \"Printer N\" during its creation.\n" _L("By default new Printer devices will be named as \"Printer N\" during its creation.\n"
"Note: This name can be changed later from the physical printers settings"); "Note: This name can be changed later from the physical printers settings");

View File

@ -116,6 +116,7 @@ private:
wxColour m_color_label_modified; wxColour m_color_label_modified;
wxColour m_color_label_sys; wxColour m_color_label_sys;
wxColour m_color_label_default; wxColour m_color_label_default;
wxColour m_color_label_phony;
wxFont m_small_font; wxFont m_small_font;
wxFont m_bold_font; wxFont m_bold_font;
@ -171,10 +172,13 @@ public:
void update_fonts(const MainFrame *main_frame = nullptr); void update_fonts(const MainFrame *main_frame = nullptr);
void set_label_clr_modified(const wxColour& clr); void set_label_clr_modified(const wxColour& clr);
void set_label_clr_sys(const wxColour& clr); void set_label_clr_sys(const wxColour& clr);
void set_label_clr_default(const wxColour& clr);
void set_label_clr_phony(const wxColour& clr);
const wxColour& get_label_clr_modified(){ return m_color_label_modified; } const wxColour& get_label_clr_modified(){ return m_color_label_modified; }
const wxColour& get_label_clr_sys() { return m_color_label_sys; } const wxColour& get_label_clr_sys() { return m_color_label_sys; }
const wxColour& get_label_clr_default() { return m_color_label_default; } const wxColour& get_label_clr_default() { return m_color_label_default; }
const wxColour& get_label_clr_phony() { return m_color_label_phony; }
const wxFont& small_font() { return m_small_font; } const wxFont& small_font() { return m_small_font; }
const wxFont& bold_font() { return m_bold_font; } const wxFont& bold_font() { return m_bold_font; }

View File

@ -251,6 +251,8 @@ void Tab::create_preset_tab()
for (Tab *tab : wxGetApp().tabs_list) { for (Tab *tab : wxGetApp().tabs_list) {
tab->m_sys_label_clr = wxGetApp().get_label_clr_sys(); tab->m_sys_label_clr = wxGetApp().get_label_clr_sys();
tab->m_modified_label_clr = wxGetApp().get_label_clr_modified(); tab->m_modified_label_clr = wxGetApp().get_label_clr_modified();
tab->m_default_text_clr = wxGetApp().get_label_clr_default();
tab->m_phony_text_clr = wxGetApp().get_label_clr_phony();
tab->update_labels_colour(); tab->update_labels_colour();
} }
} }
@ -260,7 +262,8 @@ void Tab::create_preset_tab()
// Colors for ui "decoration" // Colors for ui "decoration"
m_sys_label_clr = wxGetApp().get_label_clr_sys(); m_sys_label_clr = wxGetApp().get_label_clr_sys();
m_modified_label_clr = wxGetApp().get_label_clr_modified(); m_modified_label_clr = wxGetApp().get_label_clr_modified();
m_default_text_clr = wxGetApp().get_label_clr_default(); m_default_text_clr = wxGetApp().get_label_clr_default();
m_phony_text_clr = wxGetApp().get_label_clr_phony();
// Sizer with buttons for mode changing // Sizer with buttons for mode changing
m_mode_sizer = new ModeSizer(panel); m_mode_sizer = new ModeSizer(panel);
@ -513,6 +516,15 @@ void Tab::update_labels_colour()
else else
color = &m_modified_label_clr; color = &m_modified_label_clr;
} }
if ((opt.second & osCurrentPhony) != 0)
color = &m_phony_text_clr;
else {
if ((opt.second & osInitPhony) != 0)
color = &m_modified_label_clr;
else if ((opt.second & osSystemPhony) != 0)
color = &m_default_text_clr;
}
if (opt.first == "bed_shape" || opt.first == "filament_ramming_parameters" || if (opt.first == "bed_shape" || opt.first == "filament_ramming_parameters" ||
opt.first == "compatible_prints" || opt.first == "compatible_printers" ) { opt.first == "compatible_prints" || opt.first == "compatible_printers" ) {
if (m_colored_Label_colors.find(opt.first) != m_colored_Label_colors.end()) if (m_colored_Label_colors.find(opt.first) != m_colored_Label_colors.end())
@ -592,6 +604,16 @@ void Tab::decorate()
tt = &m_tt_white_bullet; tt = &m_tt_white_bullet;
} }
//color for phony things
if ((opt.second & osCurrentPhony) != 0)
color = &m_phony_text_clr;
else {
if ((opt.second & osInitPhony) != 0)
color = &m_modified_label_clr;
else if ((opt.second & osSystemPhony) != 0)
color = &m_default_text_clr;
}
if (colored_label_clr) { if (colored_label_clr) {
*colored_label_clr = *color; *colored_label_clr = *color;
continue; continue;
@ -634,8 +656,28 @@ void Tab::update_changed_ui()
for (auto& it : m_options_list) for (auto& it : m_options_list)
it.second = m_opt_status_value; it.second = m_opt_status_value;
for (auto opt_key : dirty_options) m_options_list[opt_key] &= ~osInitValue;
for (auto opt_key : nonsys_options) m_options_list[opt_key] &= ~osSystemValue; const Preset& edited_preset = m_presets->get_edited_preset();
const Preset& selected_preset = m_presets->get_selected_preset();
const Preset* system_preset = m_presets->get_selected_preset_parent();
for (auto& opt_key : m_presets->get_edited_preset().config.keys()) {
if (edited_preset.config.option(opt_key)->phony)
//ensure that osCurrentPhony is in the bitmask
m_options_list[opt_key] |= osCurrentPhony;
if (selected_preset.config.option(opt_key)->phony)
m_options_list[opt_key] |= osInitPhony;
if (system_preset && system_preset->config.option(opt_key)->phony)
m_options_list[opt_key] |= osSystemPhony;
}
//don't let option that were phony be resetable.
for (auto opt_key : dirty_options)
if( (m_options_list[opt_key] & osInitPhony) == 0)
//ensure that osInitValue is not in the bitmask
m_options_list[opt_key] &= ~osInitValue;
for (auto opt_key : nonsys_options)
if ((m_options_list[opt_key] & osSystemPhony) == 0)
m_options_list[opt_key] &= ~osSystemValue;
decorate(); decorate();
@ -1141,6 +1183,13 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
wxGetApp().plater()->on_extruders_change(boost::any_cast<int>(value)); wxGetApp().plater()->on_extruders_change(boost::any_cast<int>(value));
} }
//wxGetApp().preset_bundle->value_changed(opt_key);
if (m_config->value_changed(opt_key, { wxGetApp().plater()->config() })) {
update_dirty();
//# Initialize UI components with the config values.
reload_config();
}
update(); update();
} }
@ -2956,6 +3005,7 @@ void Tab::load_current_preset()
update_tab_ui(); update_tab_ui();
// update show/hide tabs // update show/hide tabs
//merill note: this is a bit of anti-inheritance pattern
if (m_type == Slic3r::Preset::TYPE_PRINTER) { if (m_type == Slic3r::Preset::TYPE_PRINTER) {
const PrinterTechnology printer_technology = m_presets->get_edited_preset().printer_technology(); const PrinterTechnology printer_technology = m_presets->get_edited_preset().printer_technology();
if (printer_technology != static_cast<TabPrinter*>(this)->m_printer_technology) if (printer_technology != static_cast<TabPrinter*>(this)->m_printer_technology)
@ -3002,6 +3052,15 @@ void Tab::load_current_preset()
on_presets_changed(); on_presets_changed();
if (m_type == Preset::TYPE_SLA_PRINT || m_type == Preset::TYPE_PRINT) if (m_type == Preset::TYPE_SLA_PRINT || m_type == Preset::TYPE_PRINT)
update_frequently_changed_parameters(); update_frequently_changed_parameters();
//update width/spacing links
if (m_type == Preset::TYPE_PRINT) {
//verify that spacings are set
if (m_config->update_phony({ wxGetApp().plater()->config() })) {
update_dirty();
reload_config();
}
}
} }
m_opt_status_value = (m_presets->get_selected_preset_parent() ? osSystemValue : 0) | osInitValue; m_opt_status_value = (m_presets->get_selected_preset_parent() ? osSystemValue : 0) | osInitValue;

View File

@ -170,6 +170,7 @@ protected:
wxColour m_sys_label_clr; wxColour m_sys_label_clr;
wxColour m_modified_label_clr; wxColour m_modified_label_clr;
wxColour m_default_text_clr; wxColour m_default_text_clr;
wxColour m_phony_text_clr;
// Tooltip text for reset buttons (for whole options group) // Tooltip text for reset buttons (for whole options group)
wxString m_ttg_value_lock; wxString m_ttg_value_lock;
@ -199,7 +200,13 @@ protected:
bool m_show_incompatible_presets; bool m_show_incompatible_presets;
std::vector<Preset::Type> m_dependent_tabs; std::vector<Preset::Type> m_dependent_tabs;
enum OptStatus { osSystemValue = 1, osInitValue = 2 }; enum OptStatus {
osSystemValue = 1,
osInitValue = 2,
osSystemPhony = 4,
osInitPhony = 8,
osCurrentPhony = 16,
};
std::map<std::string, int> m_options_list; std::map<std::string, int> m_options_list;
int m_opt_status_value = 0; int m_opt_status_value = 0;