mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-12 22:19:04 +08:00
Merge branch 'lh_different_nozzle_diameters'
This commit is contained in:
commit
f7a88d4ee1
@ -230,37 +230,64 @@ double Flow::mm3_per_mm() const
|
||||
return res;
|
||||
}
|
||||
|
||||
static float min_nozzle_diameter(const PrintObject &print_object)
|
||||
{
|
||||
const ConfigOptionFloats &nozzle_diameters = print_object.print()->config().nozzle_diameter;
|
||||
float min_nozzle_diameter = std::numeric_limits<float>::max();
|
||||
|
||||
for (const double nozzle_diameter : nozzle_diameters.values) {
|
||||
min_nozzle_diameter = std::min(min_nozzle_diameter, static_cast<float>(nozzle_diameter));
|
||||
}
|
||||
|
||||
return min_nozzle_diameter;
|
||||
}
|
||||
|
||||
Flow support_material_flow(const PrintObject *object, float layer_height)
|
||||
{
|
||||
const PrintConfig &print_config = object->print()->config();
|
||||
const int extruder = object->config().support_material_extruder - 1;
|
||||
|
||||
// If object->config().support_material_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), use the smallest nozzle diameter.
|
||||
const float nozzle_diameter = extruder >= 0 ? static_cast<float>(print_config.nozzle_diameter.get_at(extruder)) : min_nozzle_diameter(*object);
|
||||
|
||||
return Flow::new_from_config_width(
|
||||
frSupportMaterial,
|
||||
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
||||
(object->config().support_material_extrusion_width.value > 0) ? object->config().support_material_extrusion_width : object->config().extrusion_width,
|
||||
// if object->config().support_material_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
|
||||
float(object->print()->config().nozzle_diameter.get_at(object->config().support_material_extruder-1)),
|
||||
nozzle_diameter,
|
||||
(layer_height > 0.f) ? layer_height : float(object->config().layer_height.value));
|
||||
}
|
||||
|
||||
Flow support_material_1st_layer_flow(const PrintObject *object, float layer_height)
|
||||
{
|
||||
const PrintConfig &print_config = object->print()->config();
|
||||
const auto &width = (print_config.first_layer_extrusion_width.value > 0) ? print_config.first_layer_extrusion_width : object->config().support_material_extrusion_width;
|
||||
const int extruder = object->config().support_material_extruder - 1;
|
||||
|
||||
// If object->config().support_material_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), use the smallest nozzle diameter.
|
||||
const float nozzle_diameter = extruder >= 0 ? static_cast<float>(print_config.nozzle_diameter.get_at(extruder)) : min_nozzle_diameter(*object);
|
||||
const auto &width = (print_config.first_layer_extrusion_width.value > 0) ? print_config.first_layer_extrusion_width : object->config().support_material_extrusion_width;
|
||||
|
||||
return Flow::new_from_config_width(
|
||||
frSupportMaterial,
|
||||
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
||||
(width.value > 0) ? width : object->config().extrusion_width,
|
||||
float(print_config.nozzle_diameter.get_at(object->config().support_material_extruder-1)),
|
||||
nozzle_diameter,
|
||||
(layer_height > 0.f) ? layer_height : float(print_config.first_layer_height.get_abs_value(object->config().layer_height.value)));
|
||||
}
|
||||
|
||||
Flow support_material_interface_flow(const PrintObject *object, float layer_height)
|
||||
{
|
||||
const PrintConfig &print_config = object->print()->config();
|
||||
const int extruder = object->config().support_material_interface_extruder - 1;
|
||||
|
||||
// If object->config().support_material_interface_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), use the smallest nozzle diameter.
|
||||
const float nozzle_diameter = extruder >= 0 ? static_cast<float>(print_config.nozzle_diameter.get_at(extruder)) : min_nozzle_diameter(*object);
|
||||
|
||||
return Flow::new_from_config_width(
|
||||
frSupportMaterialInterface,
|
||||
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
||||
(object->config().support_material_extrusion_width > 0) ? object->config().support_material_extrusion_width : object->config().extrusion_width,
|
||||
// if object->config().support_material_interface_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
|
||||
float(object->print()->config().nozzle_diameter.get_at(object->config().support_material_interface_extruder-1)),
|
||||
nozzle_diameter,
|
||||
(layer_height > 0.f) ? layer_height : float(object->config().layer_height.value));
|
||||
}
|
||||
|
||||
|
@ -510,6 +510,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||
"perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
|
||||
"wall_distribution_count", "min_feature_size", "min_bead_width",
|
||||
"top_one_perimeter_type", "only_one_perimeter_first_layer",
|
||||
"automatic_extrusion_widths", "automatic_infill_combination", "automatic_infill_combination_max_layer_height",
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_filament_options {
|
||||
|
@ -283,6 +283,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
steps.emplace_back(psSkirtBrim);
|
||||
} else if (opt_key == "avoid_crossing_curled_overhangs") {
|
||||
osteps.emplace_back(posEstimateCurledExtrusions);
|
||||
} else if (opt_key == "automatic_extrusion_widths") {
|
||||
osteps.emplace_back(posPerimeters);
|
||||
} else {
|
||||
// for legacy, if we can't handle this option let's invalidate all steps
|
||||
//FIXME invalidate all steps of all objects as well?
|
||||
@ -627,15 +629,19 @@ std::string Print::validate(std::vector<std::string>* warnings) const
|
||||
if (this->has_wipe_tower() && ! m_objects.empty()) {
|
||||
// Make sure all extruders use same diameter filament and have the same nozzle diameter
|
||||
// EPSILON comparison is used for nozzles and 10 % tolerance is used for filaments
|
||||
double first_nozzle_diam = m_config.nozzle_diameter.get_at(extruders.front());
|
||||
double first_nozzle_diam = m_config.nozzle_diameter.get_at(extruders.front());
|
||||
double first_filament_diam = m_config.filament_diameter.get_at(extruders.front());
|
||||
|
||||
bool allow_nozzle_diameter_differ_warning = (warnings != nullptr);
|
||||
for (const auto& extruder_idx : extruders) {
|
||||
double nozzle_diam = m_config.nozzle_diameter.get_at(extruder_idx);
|
||||
double nozzle_diam = m_config.nozzle_diameter.get_at(extruder_idx);
|
||||
double filament_diam = m_config.filament_diameter.get_at(extruder_idx);
|
||||
if (nozzle_diam - EPSILON > first_nozzle_diam || nozzle_diam + EPSILON < first_nozzle_diam
|
||||
|| std::abs((filament_diam-first_filament_diam)/first_filament_diam) > 0.1)
|
||||
return _u8L("The wipe tower is only supported if all extruders have the same nozzle diameter "
|
||||
"and use filaments of the same diameter.");
|
||||
if (allow_nozzle_diameter_differ_warning && (nozzle_diam - EPSILON > first_nozzle_diam || nozzle_diam + EPSILON < first_nozzle_diam)) {
|
||||
allow_nozzle_diameter_differ_warning = false;
|
||||
warnings->emplace_back("_WIPE_TOWER_NOZZLE_DIAMETER_DIFFER");
|
||||
} else if (std::abs((filament_diam - first_filament_diam) / first_filament_diam) > 0.1) {
|
||||
return _u8L("The wipe tower is only supported if all extruders use filaments of the same diameter.");
|
||||
}
|
||||
}
|
||||
|
||||
if (m_config.gcode_flavor != gcfRepRapSprinter && m_config.gcode_flavor != gcfRepRapFirmware &&
|
||||
@ -738,13 +744,11 @@ std::string Print::validate(std::vector<std::string>* warnings) const
|
||||
};
|
||||
for (PrintObject *object : m_objects) {
|
||||
if (object->has_support_material()) {
|
||||
if ((object->config().support_material_extruder == 0 || object->config().support_material_interface_extruder == 0) && max_nozzle_diameter - min_nozzle_diameter > EPSILON) {
|
||||
if (warnings != nullptr && (object->config().support_material_extruder == 0 || object->config().support_material_interface_extruder == 0) && max_nozzle_diameter - min_nozzle_diameter > EPSILON) {
|
||||
// The object has some form of support and either support_material_extruder or support_material_interface_extruder
|
||||
// will be printed with the current tool without a forced tool change. Play safe, assert that all object nozzles
|
||||
// are of the same diameter.
|
||||
return _u8L("Printing with multiple extruders of differing nozzle diameters. "
|
||||
"If support is to be printed with the current extruder (support_material_extruder == 0 or support_material_interface_extruder == 0), "
|
||||
"all nozzles have to be of the same diameter.");
|
||||
// will be printed with the current tool without a forced tool change.
|
||||
// Notify the user that printing supports with different nozzle diameters is experimental and requires caution.
|
||||
warnings->emplace_back("_SUPPORT_NOZZLE_DIAMETER_DIFFER");
|
||||
}
|
||||
if (this->has_wipe_tower() && object->config().support_material_style != smsOrganic) {
|
||||
if (object->config().support_material_contact_distance == 0) {
|
||||
|
@ -527,6 +527,31 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<ArcFittingType>(ArcFittingType::Disabled));
|
||||
|
||||
def = this->add("automatic_extrusion_widths", coBool);
|
||||
def->label = L("Automatic extrusion widths calculation");
|
||||
def->category = L("Extrusion Width");
|
||||
def->tooltip = L("Automatically calculates extrusion widths based on the nozzle diameter of the currently used extruder. "
|
||||
"This setting is essential for printing with different nozzle diameters.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("automatic_infill_combination", coBool);
|
||||
def->label = L("Automatic infill combination");
|
||||
def->category = L("Infill");
|
||||
def->tooltip = L("This feature automatically combine infill of several layers and speeds up your print by extruding thicker "
|
||||
"infill layers while preserving thin perimeters, thus accuracy.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("automatic_infill_combination_max_layer_height", coFloatOrPercent);
|
||||
def->label = L("Automatic infill combination - Max layer height");
|
||||
def->category = L("Infill");
|
||||
def->tooltip = L("Maximum layer height for combining infill when automatic infill combining is enabled. "
|
||||
"Maximum layer height could be specified either as an absolute in millimeters value or as a percentage of nozzle diameter. "
|
||||
"For printing with different nozzle diameters, it is recommended to use percentage value over absolute value.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(100., true));
|
||||
|
||||
// Maximum extruder temperature, bumped to 1500 to support printing of glass.
|
||||
const int max_temp = 1500;
|
||||
def = this->add("avoid_crossing_curled_overhangs", coBool);
|
||||
|
@ -685,6 +685,8 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
PRINT_CONFIG_CLASS_DEFINE(
|
||||
PrintRegionConfig,
|
||||
|
||||
((ConfigOptionBool, automatic_infill_combination))
|
||||
((ConfigOptionFloatOrPercent, automatic_infill_combination_max_layer_height))
|
||||
((ConfigOptionFloat, bridge_angle))
|
||||
((ConfigOptionInt, bottom_solid_layers))
|
||||
((ConfigOptionFloat, bottom_solid_min_thickness))
|
||||
@ -898,6 +900,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
||||
PrintConfig,
|
||||
(MachineEnvelopeConfig, GCodeConfig),
|
||||
|
||||
((ConfigOptionBool, automatic_extrusion_widths))
|
||||
((ConfigOptionBool, avoid_crossing_curled_overhangs))
|
||||
((ConfigOptionBool, avoid_crossing_perimeters))
|
||||
((ConfigOptionFloatOrPercent, avoid_crossing_perimeters_max_detour))
|
||||
|
@ -808,6 +808,8 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||
opt_key == "interface_shells"
|
||||
|| opt_key == "infill_only_where_needed"
|
||||
|| opt_key == "infill_every_layers"
|
||||
|| opt_key == "automatic_infill_combination"
|
||||
|| opt_key == "automatic_infill_combination_max_layer_height"
|
||||
|| opt_key == "solid_infill_every_layers"
|
||||
|| opt_key == "ensure_vertical_shell_thickness"
|
||||
|| opt_key == "bottom_solid_min_thickness"
|
||||
@ -3053,16 +3055,24 @@ void PrintObject::discover_horizontal_shells()
|
||||
void PrintObject::combine_infill()
|
||||
{
|
||||
// Work on each region separately.
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||
const PrintRegion ®ion = this->printing_region(region_id);
|
||||
const size_t every = region.config().infill_every_layers.value;
|
||||
if (every < 2 || region.config().fill_density == 0.)
|
||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++region_id) {
|
||||
const PrintRegion ®ion = this->printing_region(region_id);
|
||||
const size_t combine_infill_every_n_layers = region.config().infill_every_layers.value;
|
||||
const bool automatic_infill_combination = region.config().automatic_infill_combination;
|
||||
const bool enable_combine_infill = automatic_infill_combination || combine_infill_every_n_layers >= 2;
|
||||
|
||||
if (!enable_combine_infill || region.config().fill_density == 0.) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Limit the number of combined layers to the maximum height allowed by this regions' nozzle.
|
||||
//FIXME limit the layer height to max_layer_height
|
||||
double nozzle_diameter = std::min(
|
||||
this->print()->config().nozzle_diameter.get_at(region.config().infill_extruder.value - 1),
|
||||
this->print()->config().nozzle_diameter.get_at(region.config().solid_infill_extruder.value - 1));
|
||||
const double nozzle_diameter = std::min(this->print()->config().nozzle_diameter.get_at(region.config().infill_extruder.value - 1),
|
||||
this->print()->config().nozzle_diameter.get_at(region.config().solid_infill_extruder.value - 1));
|
||||
|
||||
const double automatic_infill_combination_max_layer_height = region.config().automatic_infill_combination_max_layer_height.get_abs_value(nozzle_diameter);
|
||||
const double max_combine_layer_height = automatic_infill_combination ? std::min(automatic_infill_combination_max_layer_height, nozzle_diameter) : nozzle_diameter;
|
||||
|
||||
// define the combinations
|
||||
std::vector<size_t> combine(m_layers.size(), 0);
|
||||
{
|
||||
@ -3070,19 +3080,21 @@ void PrintObject::combine_infill()
|
||||
size_t num_layers = 0;
|
||||
for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++ layer_idx) {
|
||||
m_print->throw_if_canceled();
|
||||
const Layer *layer = m_layers[layer_idx];
|
||||
if (layer->id() == 0)
|
||||
const Layer &layer = *m_layers[layer_idx];
|
||||
if (layer.id() == 0)
|
||||
// Skip first print layer (which may not be first layer in array because of raft).
|
||||
continue;
|
||||
|
||||
// Check whether the combination of this layer with the lower layers' buffer
|
||||
// would exceed max layer height or max combined layer count.
|
||||
if (current_height + layer->height >= nozzle_diameter + EPSILON || num_layers >= every) {
|
||||
if (current_height + layer.height >= max_combine_layer_height + EPSILON || (!automatic_infill_combination && num_layers >= combine_infill_every_n_layers)) {
|
||||
// Append combination to lower layer.
|
||||
combine[layer_idx - 1] = num_layers;
|
||||
current_height = 0.;
|
||||
num_layers = 0;
|
||||
}
|
||||
current_height += layer->height;
|
||||
|
||||
current_height += layer.height;
|
||||
++ num_layers;
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,64 @@ void ConfigManipulation::toggle_field(const std::string& opt_key, const bool tog
|
||||
cb_toggle_field(opt_key, toggle, opt_index);
|
||||
}
|
||||
|
||||
std::optional<DynamicPrintConfig> handle_automatic_extrusion_widths(const DynamicPrintConfig &config, const bool is_global_config, wxWindow *msg_dlg_parent)
|
||||
{
|
||||
const std::vector<std::string> extrusion_width_parameters = {"extrusion_width", "external_perimeter_extrusion_width", "first_layer_extrusion_width",
|
||||
"infill_extrusion_width", "perimeter_extrusion_width", "solid_infill_extrusion_width",
|
||||
"support_material_extrusion_width", "top_infill_extrusion_width"};
|
||||
|
||||
auto is_zero_width = [](const ConfigOptionFloatOrPercent &opt) -> bool {
|
||||
return opt.value == 0. && !opt.percent;
|
||||
};
|
||||
|
||||
auto is_parameters_adjustment_needed = [&is_zero_width, &config, &extrusion_width_parameters]() -> bool {
|
||||
if (!config.opt_bool("automatic_extrusion_widths")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const std::string &extrusion_width_parameter : extrusion_width_parameters) {
|
||||
if (!is_zero_width(*config.option<ConfigOptionFloatOrPercent>(extrusion_width_parameter))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
if (is_parameters_adjustment_needed()) {
|
||||
wxString msg_text = _(L("The automatic extrusion widths calculation requires:\n"
|
||||
"- Default extrusion width: 0\n"
|
||||
"- First layer extrusion width: 0\n"
|
||||
"- Perimeter extrusion width: 0\n"
|
||||
"- External perimeter extrusion width: 0\n"
|
||||
"- Infill extrusion width: 0\n"
|
||||
"- Solid infill extrusion width: 0\n"
|
||||
"- Top infill extrusion width: 0\n"
|
||||
"- Support material extrusion width: 0"));
|
||||
|
||||
if (is_global_config) {
|
||||
msg_text += "\n\n" + _(L("Shall I adjust those settings in order to enable automatic extrusion widths calculation?"));
|
||||
}
|
||||
|
||||
MessageDialog dialog(msg_dlg_parent, msg_text, _(L("Automatic extrusion widths calculation")),
|
||||
wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK));
|
||||
|
||||
const int answer = dialog.ShowModal();
|
||||
DynamicPrintConfig new_conf = config;
|
||||
if (!is_global_config || answer == wxID_YES) {
|
||||
for (const std::string &extrusion_width_parameter : extrusion_width_parameters) {
|
||||
new_conf.set_key_value(extrusion_width_parameter, new ConfigOptionFloatOrPercent(0., false));
|
||||
}
|
||||
} else {
|
||||
new_conf.set_key_value("automatic_extrusion_widths", new ConfigOptionBool(false));
|
||||
}
|
||||
|
||||
return new_conf;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, const bool is_global_config)
|
||||
{
|
||||
// #ys_FIXME_to_delete
|
||||
@ -213,6 +271,13 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config->opt_bool("automatic_extrusion_widths")) {
|
||||
std::optional<DynamicPrintConfig> new_config = handle_automatic_extrusion_widths(*config, is_global_config, m_msg_dlg_parent);
|
||||
if (new_config.has_value()) {
|
||||
apply(config, &(*new_config));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
||||
@ -227,11 +292,17 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
||||
toggle_field("overhang_speed_" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds"));
|
||||
}
|
||||
|
||||
bool have_infill = config->option<ConfigOptionPercent>("fill_density")->value > 0;
|
||||
const bool have_infill = config->option<ConfigOptionPercent>("fill_density")->value > 0;
|
||||
const bool has_automatic_infill_combination = config->option<ConfigOptionBool>("automatic_infill_combination")->value;
|
||||
// infill_extruder uses the same logic as in Print::extruders()
|
||||
for (auto el : { "fill_pattern", "infill_every_layers", "infill_only_where_needed",
|
||||
"solid_infill_every_layers", "solid_infill_below_area", "infill_extruder", "infill_anchor_max" })
|
||||
for (auto el : { "fill_pattern","solid_infill_every_layers", "solid_infill_below_area", "infill_extruder",
|
||||
"infill_anchor_max", "automatic_infill_combination" }) {
|
||||
toggle_field(el, have_infill);
|
||||
}
|
||||
|
||||
toggle_field("infill_every_layers", have_infill && !has_automatic_infill_combination);
|
||||
toggle_field("automatic_infill_combination_max_layer_height", have_infill && has_automatic_infill_combination);
|
||||
|
||||
// Only allow configuration of open anchors if the anchoring is enabled.
|
||||
bool has_infill_anchors = have_infill && config->option<ConfigOptionFloatOrPercent>("infill_anchor_max")->value > 0;
|
||||
toggle_field("infill_anchor", has_infill_anchors);
|
||||
|
@ -133,7 +133,7 @@ void NotificationManager::NotificationIDProvider::release_id(int) {}
|
||||
#endif
|
||||
|
||||
//------PopNotification--------
|
||||
NotificationManager::PopNotification::PopNotification(const NotificationData &n, NotificationIDProvider &id_provider, wxEvtHandler* evt_handler) :
|
||||
NotificationManager::PopNotification::PopNotification(const NotificationData &n, NotificationIDProvider &id_provider, wxEvtHandler* evt_handler, const bool multiline) :
|
||||
m_data (n)
|
||||
, m_id_provider (id_provider)
|
||||
, m_text1 (n.text1)
|
||||
@ -141,6 +141,7 @@ NotificationManager::PopNotification::PopNotification(const NotificationData &n,
|
||||
, m_text2 (n.text2)
|
||||
, m_evt_handler (evt_handler)
|
||||
, m_notification_start (GLCanvas3D::timestamp_now())
|
||||
, m_multiline (multiline)
|
||||
{}
|
||||
|
||||
void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width)
|
||||
@ -2157,10 +2158,11 @@ void NotificationManager::push_notification(NotificationType type,
|
||||
const std::string& hypertext,
|
||||
std::function<bool(wxEvtHandler*)> callback,
|
||||
const std::string& text_after,
|
||||
int timestamp)
|
||||
const int timestamp,
|
||||
const bool multiline)
|
||||
{
|
||||
int duration = get_standard_duration(level);
|
||||
push_notification_data({ type, level, duration, text, hypertext, callback, text_after }, timestamp);
|
||||
push_notification_data({ type, level, duration, text, hypertext, callback, text_after }, timestamp, multiline);
|
||||
}
|
||||
|
||||
void NotificationManager::push_delayed_notification(const NotificationType type, std::function<bool(void)> condition_callback, int64_t initial_delay, int64_t delay_interval)
|
||||
@ -2839,9 +2841,9 @@ void NotificationManager::push_updated_item_info_notification(InfoItemType type)
|
||||
}
|
||||
|
||||
}
|
||||
bool NotificationManager::push_notification_data(const NotificationData& notification_data, int timestamp)
|
||||
bool NotificationManager::push_notification_data(const NotificationData& notification_data, int timestamp, const bool multiline)
|
||||
{
|
||||
return push_notification_data(std::make_unique<PopNotification>(notification_data, m_id_provider, m_evt_handler), timestamp);
|
||||
return push_notification_data(std::make_unique<PopNotification>(notification_data, m_id_provider, m_evt_handler, multiline), timestamp);
|
||||
}
|
||||
bool NotificationManager::push_notification_data(std::unique_ptr<NotificationManager::PopNotification> notification, int timestamp)
|
||||
{
|
||||
|
@ -140,6 +140,10 @@ enum class NotificationType
|
||||
BedTemperaturesDiffer,
|
||||
// Notification that shrinkage compensations for the used filaments differ.
|
||||
ShrinkageCompensationsDiffer,
|
||||
// Notification about using wipe tower with different nozzle diameters.
|
||||
WipeTowerNozzleDiameterDiffer,
|
||||
// Notification about using supports with different nozzle diameters.
|
||||
SupportNozzleDiameterDiffer,
|
||||
};
|
||||
|
||||
class NotificationManager
|
||||
@ -179,7 +183,7 @@ public:
|
||||
// Push a NotificationType::CustomNotification with provided notification level and 10s for RegularNotificationLevel.
|
||||
// ErrorNotificationLevel are never faded out.
|
||||
void push_notification(NotificationType type, NotificationLevel level, const std::string& text, const std::string& hypertext = "",
|
||||
std::function<bool(wxEvtHandler*)> callback = std::function<bool(wxEvtHandler*)>(), const std::string& text_after = "", int timestamp = 0);
|
||||
std::function<bool(wxEvtHandler*)> callback = std::function<bool(wxEvtHandler*)>(), const std::string& text_after = "", int timestamp = 0, bool multiline = false);
|
||||
// Pushes basic_notification with delay. See push_delayed_notification_data.
|
||||
void push_delayed_notification(const NotificationType type, std::function<bool(void)> condition_callback, int64_t initial_delay, int64_t delay_interval);
|
||||
// Removes all notifications of type from m_waiting_notifications
|
||||
@ -342,7 +346,7 @@ private:
|
||||
Paused
|
||||
};
|
||||
|
||||
PopNotification(const NotificationData &n, NotificationIDProvider &id_provider, wxEvtHandler* evt_handler);
|
||||
PopNotification(const NotificationData &n, NotificationIDProvider &id_provider, wxEvtHandler* evt_handler, bool multiline = false);
|
||||
virtual ~PopNotification() { if (m_id) m_id_provider.release_id(m_id); }
|
||||
virtual void render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width);
|
||||
// close will dissapear notification on next render
|
||||
@ -853,7 +857,7 @@ private:
|
||||
|
||||
//pushes notification into the queue of notifications that are rendered
|
||||
//can be used to create custom notification
|
||||
bool push_notification_data(const NotificationData& notification_data, int timestamp);
|
||||
bool push_notification_data(const NotificationData& notification_data, int timestamp, bool multiline = false);
|
||||
bool push_notification_data(std::unique_ptr<NotificationManager::PopNotification> notification, int timestamp);
|
||||
// Delayed notifications goes first to the m_waiting_notifications vector and only after remaining time is <= 0
|
||||
// and condition callback is success, notification is regular pushed from update function.
|
||||
|
@ -2098,12 +2098,16 @@ void Plater::priv::process_validation_warning(const std::vector<std::string>& wa
|
||||
if (warnings.empty())
|
||||
notification_manager->close_notification_of_type(NotificationType::ValidateWarning);
|
||||
|
||||
// Always close warnings BedTemperaturesDiffer and ShrinkageCompensationsDiffer before next processing.
|
||||
// Always close warnings BedTemperaturesDiffer, ShrinkageCompensationsDiffer, WipeTowerNozzleDiameterDiffer and SupportNozzleDiameterDiffer before next processing.
|
||||
notification_manager->close_notification_of_type(NotificationType::BedTemperaturesDiffer);
|
||||
notification_manager->close_notification_of_type(NotificationType::ShrinkageCompensationsDiffer);
|
||||
notification_manager->close_notification_of_type(NotificationType::WipeTowerNozzleDiameterDiffer);
|
||||
notification_manager->close_notification_of_type(NotificationType::SupportNozzleDiameterDiffer);
|
||||
|
||||
for (std::string text : warnings) {
|
||||
std::string hypertext = "";
|
||||
std::string text_after = "";
|
||||
bool multiline = false;
|
||||
NotificationType notification_type = NotificationType::ValidateWarning;
|
||||
std::function<bool(wxEvtHandler*)> action_fn = [](wxEvtHandler*){ return false; };
|
||||
|
||||
@ -2128,12 +2132,26 @@ void Plater::priv::process_validation_warning(const std::vector<std::string>& wa
|
||||
text = _u8L("Filament shrinkage will not be used because filament shrinkage "
|
||||
"for the used filaments differs significantly.");
|
||||
notification_type = NotificationType::ShrinkageCompensationsDiffer;
|
||||
} else if (text == "_WIPE_TOWER_NOZZLE_DIAMETER_DIFFER") {
|
||||
text = _u8L("Using the wipe tower for extruders with different nozzle diameters "
|
||||
"is experimental, so proceed with caution.");
|
||||
notification_type = NotificationType::WipeTowerNozzleDiameterDiffer;
|
||||
} else if (text == "_SUPPORT_NOZZLE_DIAMETER_DIFFER") {
|
||||
text = _u8L("Printing supports with different nozzle diameters "
|
||||
"is experimental. For best results, switch to Organic supports and");
|
||||
hypertext = _u8L("assign a specific extruder for supports.");
|
||||
multiline = true;
|
||||
notification_type = NotificationType::SupportNozzleDiameterDiffer;
|
||||
action_fn = [](wxEvtHandler*) {
|
||||
GUI::wxGetApp().jump_to_option("support_material_extruder", Preset::Type::TYPE_PRINT, boost::nowide::widen("Multiple Extruders"));
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
notification_manager->push_notification(
|
||||
notification_type,
|
||||
NotificationManager::NotificationLevel::WarningNotificationLevel,
|
||||
_u8L("WARNING:") + "\n" + text, hypertext, action_fn
|
||||
_u8L("WARNING:") + "\n" + text, hypertext, action_fn, text_after, 0, multiline
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1503,8 +1503,9 @@ void TabPrint::build()
|
||||
|
||||
optgroup = page->new_optgroup(L("Reducing printing time"));
|
||||
category_path = "infill_42#";
|
||||
optgroup->append_single_option_line("automatic_infill_combination");
|
||||
optgroup->append_single_option_line("automatic_infill_combination_max_layer_height");
|
||||
optgroup->append_single_option_line("infill_every_layers", category_path + "combine-infill-every-x-layers");
|
||||
// optgroup->append_single_option_line("infill_only_where_needed", category_path + "only-infill-where-needed");
|
||||
|
||||
optgroup = page->new_optgroup(L("Advanced"));
|
||||
optgroup->append_single_option_line("solid_infill_every_layers", category_path + "solid-infill-every-x-layers");
|
||||
@ -1662,6 +1663,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("solid_infill_extrusion_width");
|
||||
optgroup->append_single_option_line("top_infill_extrusion_width");
|
||||
optgroup->append_single_option_line("support_material_extrusion_width");
|
||||
optgroup->append_single_option_line("automatic_extrusion_widths");
|
||||
|
||||
optgroup = page->new_optgroup(L("Overlap"));
|
||||
optgroup->append_single_option_line("infill_overlap");
|
||||
|
Loading…
x
Reference in New Issue
Block a user