move warning about complete object from pop-up to red foreground message.

This commit is contained in:
supermerill 2020-05-29 22:59:06 +02:00
parent 493dec834b
commit 5b6aaf8c29
11 changed files with 88 additions and 65 deletions

View File

@ -425,9 +425,9 @@ int CLI::run(int argc, char **argv)
fff_print.auto_assign_extruders(mo); fff_print.auto_assign_extruders(mo);
} }
print->apply(model, m_print_config); print->apply(model, m_print_config);
std::string err = print->validate(); std::pair<PrintError, std::string> err = print->validate();
if (! err.empty()) { if (! err.first == PrintError::None) {
boost::nowide::cerr << err << std::endl; boost::nowide::cerr << err.second << std::endl;
return 1; return 1;
} }
if (print->empty()) if (print->empty())

View File

@ -1273,19 +1273,19 @@ static inline bool sequential_print_vertical_clearance_valid(const Print &print)
} }
// Precondition: Print::validate() requires the Print::apply() to be called its invocation. // Precondition: Print::validate() requires the Print::apply() to be called its invocation.
std::string Print::validate() const std::pair<PrintError, std::string> Print::validate() const
{ {
if (m_objects.empty()) if (m_objects.empty())
return L("All objects are outside of the print volume."); return { PrintError::WrongPosition, L("All objects are outside of the print volume.") };
if (extruders().empty()) if (extruders().empty())
return L("The supplied settings will cause an empty print."); return { PrintError::NoPrint, L("The supplied settings will cause an empty print.") };
if (m_config.complete_objects) { if (m_config.complete_objects) {
if (! sequential_print_horizontal_clearance_valid(*this)) if (! sequential_print_horizontal_clearance_valid(*this))
return L("Some objects are too close; your extruder will collide with them."); return { PrintError::WrongPosition, L("Some objects are too close; your extruder will collide with them.") };
if (! sequential_print_vertical_clearance_valid(*this)) if (! sequential_print_vertical_clearance_valid(*this))
return L("Some objects are too tall and cannot be printed without extruder collisions."); return { PrintError::WrongPosition,L("Some objects are too tall and cannot be printed without extruder collisions.") };
} }
if (m_config.spiral_vase) { if (m_config.spiral_vase) {
@ -1294,14 +1294,14 @@ std::string Print::validate() const
total_copies_count += object->instances().size(); total_copies_count += object->instances().size();
// #4043 // #4043
if (total_copies_count > 1 && ! m_config.complete_objects.value) if (total_copies_count > 1 && ! m_config.complete_objects.value)
return L("The Spiral Vase option can only be used when printing a single object."); return { PrintError::WrongSettings,L("The Spiral Vase option can only be used when printing a single object.") };
assert(m_objects.size() == 1 || config().complete_objects.value); assert(m_objects.size() == 1 || config().complete_objects.value);
size_t num_regions = 0; size_t num_regions = 0;
for (const std::vector<std::pair<t_layer_height_range, int>> &volumes_per_region : m_objects.front()->region_volumes) for (const std::vector<std::pair<t_layer_height_range, int>> &volumes_per_region : m_objects.front()->region_volumes)
if (! volumes_per_region.empty()) if (! volumes_per_region.empty())
++ num_regions; ++ num_regions;
if (num_regions > 1) if (num_regions > 1)
return L("The Spiral Vase option can only be used when printing single material objects."); return { PrintError::WrongSettings,L("The Spiral Vase option can only be used when printing single material objects.") };
} }
if (this->has_wipe_tower() && ! m_objects.empty()) { if (this->has_wipe_tower() && ! m_objects.empty()) {
@ -1314,21 +1314,21 @@ std::string Print::validate() const
double filament_diam = m_config.filament_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 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) || std::abs((filament_diam-first_filament_diam)/first_filament_diam) > 0.1)
return L("The wipe tower is only supported if all extruders have the same nozzle diameter " return { PrintError::WrongSettings,L("The wipe tower is only supported if all extruders have the same nozzle diameter "
"and use filaments of the same diameter."); "and use filaments of the same diameter.") };
} }
if (m_config.gcode_flavor != gcfRepRap && m_config.gcode_flavor != gcfRepetier && m_config.gcode_flavor != gcfMarlin if (m_config.gcode_flavor != gcfRepRap && m_config.gcode_flavor != gcfRepetier && m_config.gcode_flavor != gcfMarlin
&& m_config.gcode_flavor != gcfKlipper) && m_config.gcode_flavor != gcfKlipper)
return L("The Wipe Tower is currently only supported for the Marlin, RepRap/Sprinter and Repetier G-code flavors."); return { PrintError::WrongSettings,L("The Wipe Tower is currently only supported for the Marlin, RepRap/Sprinter and Repetier G-code flavors.") };
if (! m_config.use_relative_e_distances) if (! m_config.use_relative_e_distances)
return L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1)."); return { PrintError::WrongSettings,L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).") };
if (m_config.ooze_prevention) if (m_config.ooze_prevention)
return L("Ooze prevention is currently not supported with the wipe tower enabled."); return { PrintError::WrongSettings,L("Ooze prevention is currently not supported with the wipe tower enabled.") };
if (m_config.use_volumetric_e) if (m_config.use_volumetric_e)
return L("The Wipe Tower currently does not support volumetric E (use_volumetric_e=0)."); return { PrintError::WrongSettings,L("The Wipe Tower currently does not support volumetric E (use_volumetric_e=0).") };
if (m_config.complete_objects && extruders().size() > 1) if (m_config.complete_objects && extruders().size() > 1)
return L("The Wipe Tower is currently not supported for multimaterial sequential prints."); return { PrintError::WrongSettings,L("The Wipe Tower is currently not supported for multimaterial sequential prints.") };
if (m_objects.size() > 1) { if (m_objects.size() > 1) {
bool has_custom_layering = false; bool has_custom_layering = false;
@ -1349,15 +1349,15 @@ std::string Print::validate() const
const SlicingParameters &slicing_params = object->slicing_parameters(); const SlicingParameters &slicing_params = object->slicing_parameters();
if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON || if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON) std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON)
return L("The Wipe Tower is only supported for multiple objects if they have equal layer heights"); return { PrintError::WrongSettings,L("The Wipe Tower is only supported for multiple objects if they have equal layer heights") };
if (slicing_params.raft_layers() != slicing_params0.raft_layers()) if (slicing_params.raft_layers() != slicing_params0.raft_layers())
return L("The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers"); return { PrintError::WrongSettings,L("The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers") };
if (object->config().support_material_contact_distance_type != m_objects.front()->config().support_material_contact_distance_type if (object->config().support_material_contact_distance_type != m_objects.front()->config().support_material_contact_distance_type
|| object->config().support_material_contact_distance_top != m_objects.front()->config().support_material_contact_distance_top || object->config().support_material_contact_distance_top != m_objects.front()->config().support_material_contact_distance_top
|| object->config().support_material_contact_distance_bottom != m_objects.front()->config().support_material_contact_distance_bottom) || object->config().support_material_contact_distance_bottom != m_objects.front()->config().support_material_contact_distance_bottom)
return L("The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance"); return { PrintError::WrongSettings,L("The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance") };
if (! equal_layering(slicing_params, slicing_params0)) if (! equal_layering(slicing_params, slicing_params0))
return L("The Wipe Tower is only supported for multiple objects if they are sliced equally."); return { PrintError::WrongSettings,L("The Wipe Tower is only supported for multiple objects if they are sliced equally.") };
if (has_custom_layering) { if (has_custom_layering) {
PrintObject::update_layer_height_profile(*object->model_object(), slicing_params, layer_height_profiles[i]); PrintObject::update_layer_height_profile(*object->model_object(), slicing_params, layer_height_profiles[i]);
if (*(layer_height_profiles[i].end()-2) > *(layer_height_profiles[tallest_object_idx].end()-2)) if (*(layer_height_profiles[i].end()-2) > *(layer_height_profiles[tallest_object_idx].end()-2))
@ -1399,7 +1399,7 @@ std::string Print::validate() const
} while (ref_z == next_ref_z); } while (ref_z == next_ref_z);
} }
if (std::abs(this_height - ref_height) > EPSILON) if (std::abs(this_height - ref_height) > EPSILON)
return L("The Wipe tower is only supported if all objects have the same variable layer height"); return { PrintError::WrongSettings,L("The Wipe tower is only supported if all objects have the same variable layer height") };
i += 2; i += 2;
} }
} }
@ -1448,20 +1448,20 @@ std::string Print::validate() const
// The object has some form of support and either support_material_extruder or support_material_interface_extruder // 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 // will be printed with the current tool without a forced tool change. Play safe, assert that all object nozzles
// are of the same diameter. // are of the same diameter.
return L("Printing with multiple extruders of differing nozzle diameters. " return { PrintError::WrongSettings,L("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), " "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."); "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 == zdNone) {
// Soluble interface // Soluble interface
if (! object->config().support_material_synchronize_layers) if (! object->config().support_material_synchronize_layers)
return L("For the Wipe Tower to work with the soluble supports, the support layers need to be synchronized with the object layers."); return { PrintError::WrongSettings,L("For the Wipe Tower to work with the soluble supports, the support layers need to be synchronized with the object layers.") };
} else { } else {
// Non-soluble interface // Non-soluble interface
if (object->config().support_material_extruder != 0 || object->config().support_material_interface_extruder != 0) if (object->config().support_material_extruder != 0 || object->config().support_material_interface_extruder != 0)
return L("The Wipe Tower currently supports the non-soluble supports only if they are printed with the current extruder without triggering a tool change. " return { PrintError::WrongSettings,L("The Wipe Tower currently supports the non-soluble supports only if they are printed with the current extruder without triggering a tool change. "
"(both support_material_extruder and support_material_interface_extruder need to be set to 0)."); "(both support_material_extruder and support_material_interface_extruder need to be set to 0).") };
} }
} }
} }
@ -1482,27 +1482,27 @@ std::string Print::validate() const
first_layer_min_nozzle_diameter = min_nozzle_diameter; first_layer_min_nozzle_diameter = min_nozzle_diameter;
} }
if (first_layer_height > first_layer_min_nozzle_diameter) if (first_layer_height > first_layer_min_nozzle_diameter)
return L("First layer height can't be greater than nozzle diameter"); return { PrintError::WrongSettings,L("First layer height can't be greater than nozzle diameter") };
// validate layer_height // validate layer_height
double layer_height = object->config().layer_height.value; double layer_height = object->config().layer_height.value;
if (layer_height > min_nozzle_diameter) if (layer_height > min_nozzle_diameter)
return L("Layer height can't be greater than nozzle diameter"); return { PrintError::WrongSettings,L("Layer height can't be greater than nozzle diameter") };
// Validate extrusion widths. // Validate extrusion widths.
std::string err_msg; std::string err_msg;
if (! validate_extrusion_width(object->config(), "extrusion_width", layer_height, err_msg)) if (! validate_extrusion_width(object->config(), "extrusion_width", layer_height, err_msg))
return err_msg; return { PrintError::WrongSettings,err_msg };
if ((object->config().support_material || object->config().raft_layers > 0) && ! validate_extrusion_width(object->config(), "support_material_extrusion_width", layer_height, err_msg)) if ((object->config().support_material || object->config().raft_layers > 0) && ! validate_extrusion_width(object->config(), "support_material_extrusion_width", layer_height, err_msg))
return err_msg; return { PrintError::WrongSettings,err_msg };
for (const char *opt_key : { "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width" }) for (const char *opt_key : { "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width" })
for (size_t i = 0; i < object->region_volumes.size(); ++ i) for (size_t i = 0; i < object->region_volumes.size(); ++ i)
if (! object->region_volumes[i].empty() && ! validate_extrusion_width(this->get_region(i)->config(), opt_key, layer_height, err_msg)) if (! object->region_volumes[i].empty() && ! validate_extrusion_width(this->get_region(i)->config(), opt_key, layer_height, err_msg))
return err_msg; return { PrintError::WrongSettings, err_msg };
} }
} }
return std::string(); return { PrintError::None, std::string() };
} }
#if 0 #if 0

View File

@ -399,7 +399,7 @@ public:
bool has_skirt() const; bool has_skirt() const;
// Returns an empty string if valid, otherwise returns an error message. // Returns an empty string if valid, otherwise returns an error message.
std::string validate() const override; std::pair<PrintError, std::string> validate() const override;
double skirt_first_layer_height() const; double skirt_first_layer_height() const;
Flow brim_flow(size_t extruder_id) const; Flow brim_flow(size_t extruder_id) const;
Flow skirt_flow(size_t extruder_id) const; Flow skirt_flow(size_t extruder_id) const;

View File

@ -203,6 +203,13 @@ protected:
ModelObject *m_model_object; ModelObject *m_model_object;
}; };
enum PrintError {
None,
WrongPosition,
NoPrint,
WrongSettings,
};
/** /**
* @brief Printing involves slicing and export of device dependent instructions. * @brief Printing involves slicing and export of device dependent instructions.
* *
@ -229,7 +236,7 @@ public:
virtual bool empty() const = 0; virtual bool empty() const = 0;
// Validate the print, return empty string if valid, return error if process() cannot (or should not) be started. // Validate the print, return empty string if valid, return error if process() cannot (or should not) be started.
virtual std::string validate() const { return std::string(); } virtual std::pair<PrintError, std::string> validate() const { return { PrintError::None, std::string() }; }
enum ApplyStatus { enum ApplyStatus {
// No change after the Print::apply() call. // No change after the Print::apply() call.

View File

@ -602,7 +602,7 @@ std::string SLAPrint::output_filename(const std::string &filename_base) const
return this->PrintBase::output_filename(m_print_config.output_filename_format.value, ".sl1", filename_base, &config); return this->PrintBase::output_filename(m_print_config.output_filename_format.value, ".sl1", filename_base, &config);
} }
std::string SLAPrint::validate() const std::pair<PrintError, std::string>SLAPrint::validate() const
{ {
for(SLAPrintObject * po : m_objects) { for(SLAPrintObject * po : m_objects) {
@ -612,8 +612,8 @@ std::string SLAPrint::validate() const
if(supports_en && if(supports_en &&
mo->sla_points_status == sla::PointsStatus::UserModified && mo->sla_points_status == sla::PointsStatus::UserModified &&
mo->sla_support_points.empty()) mo->sla_support_points.empty())
return L("Cannot proceed without support points! " return { PrintError::WrongSettings, L("Cannot proceed without support points! "
"Add support points or disable support generation."); "Add support points or disable support generation.") };
sla::SupportConfig cfg = make_support_cfg(po->config()); sla::SupportConfig cfg = make_support_cfg(po->config());
@ -623,21 +623,21 @@ std::string SLAPrint::validate() const
sla::PadConfig::EmbedObject &builtinpad = padcfg.embed_object; sla::PadConfig::EmbedObject &builtinpad = padcfg.embed_object;
if(supports_en && !builtinpad.enabled && elv < cfg.head_fullwidth()) if(supports_en && !builtinpad.enabled && elv < cfg.head_fullwidth())
return L( return { PrintError::WrongSettings, L(
"Elevation is too low for object. Use the \"Pad around " "Elevation is too low for object. Use the \"Pad around "
"object\" feature to print the object without elevation."); "object\" feature to print the object without elevation.") };
if(supports_en && builtinpad.enabled && if(supports_en && builtinpad.enabled &&
cfg.pillar_base_safety_distance_mm < builtinpad.object_gap_mm) { cfg.pillar_base_safety_distance_mm < builtinpad.object_gap_mm) {
return L( return { PrintError::WrongSettings, L(
"The endings of the support pillars will be deployed on the " "The endings of the support pillars will be deployed on the "
"gap between the object and the pad. 'Support base safety " "gap between the object and the pad. 'Support base safety "
"distance' has to be greater than the 'Pad object gap' " "distance' has to be greater than the 'Pad object gap' "
"parameter to avoid this."); "parameter to avoid this.") };
} }
std::string pval = padcfg.validate(); std::string pval = padcfg.validate();
if (!pval.empty()) return pval; if (!pval.empty()) return { PrintError::WrongSettings, pval };
} }
double expt_max = m_printer_config.max_exposure_time.getFloat(); double expt_max = m_printer_config.max_exposure_time.getFloat();
@ -645,16 +645,16 @@ std::string SLAPrint::validate() const
double expt_cur = m_material_config.exposure_time.getFloat(); double expt_cur = m_material_config.exposure_time.getFloat();
if (expt_cur < expt_min || expt_cur > expt_max) if (expt_cur < expt_min || expt_cur > expt_max)
return L("Exposition time is out of printer profile bounds."); return { PrintError::WrongSettings, L("Exposition time is out of printer profile bounds.") };
double iexpt_max = m_printer_config.max_initial_exposure_time.getFloat(); double iexpt_max = m_printer_config.max_initial_exposure_time.getFloat();
double iexpt_min = m_printer_config.min_initial_exposure_time.getFloat(); double iexpt_min = m_printer_config.min_initial_exposure_time.getFloat();
double iexpt_cur = m_material_config.initial_exposure_time.getFloat(); double iexpt_cur = m_material_config.initial_exposure_time.getFloat();
if (iexpt_cur < iexpt_min || iexpt_cur > iexpt_max) if (iexpt_cur < iexpt_min || iexpt_cur > iexpt_max)
return L("Initial exposition time is out of printer profile bounds."); return { PrintError::WrongSettings, L("Initial exposition time is out of printer profile bounds.") };
return ""; return { PrintError::None, "" };
} }
bool SLAPrint::invalidate_step(SLAPrintStep step) bool SLAPrint::invalidate_step(SLAPrintStep step)

View File

@ -432,7 +432,7 @@ public:
const SLAPrintStatistics& print_statistics() const { return m_print_statistics; } const SLAPrintStatistics& print_statistics() const { return m_print_statistics; }
std::string validate() const override; std::pair<PrintError, std::string> validate() const override;
// An aggregation of SliceRecord-s from all the print objects for each // An aggregation of SliceRecord-s from all the print objects for each
// occupied layer. Slice record levels dont have to match exactly. // occupied layer. Slice record levels dont have to match exactly.

View File

@ -373,7 +373,7 @@ bool BackgroundSlicingProcess::empty() const
return m_print->empty(); return m_print->empty();
} }
std::string BackgroundSlicingProcess::validate() std::pair<PrintError, std::string> BackgroundSlicingProcess::validate()
{ {
assert(m_print != nullptr); assert(m_print != nullptr);
return m_print->validate(); return m_print->validate();

View File

@ -92,9 +92,9 @@ public:
void set_task(const PrintBase::TaskParams &params); void set_task(const PrintBase::TaskParams &params);
// After calling apply, the empty() call will report whether there is anything to slice. // After calling apply, the empty() call will report whether there is anything to slice.
bool empty() const; bool empty() const;
// Validate the print. Returns an empty string if valid, returns an error message if invalid. // Validate the print. Returns a {PrintError::None,empty string} if valid, returns an error message if invalid.
// Call validate before calling start(). // Call validate before calling start().
std::string validate(); std::pair<PrintError, std::string> validate();
// Set the export path of the G-code. // Set the export path of the G-code.
// Once the path is set, the G-code // Once the path is set, the G-code

View File

@ -658,7 +658,7 @@ GLCanvas3D::WarningTexture::WarningTexture()
{ {
} }
void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool state, const GLCanvas3D& canvas) void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool state, const GLCanvas3D& canvas, std::string str_override)
{ {
auto it = std::find(m_warnings.begin(), m_warnings.end(), warning); auto it = std::find(m_warnings.begin(), m_warnings.end(), warning);
@ -682,8 +682,9 @@ void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool
} }
// Look at the end of our vector and generate proper texture. // Look at the end of our vector and generate proper texture.
std::string text; std::string text = str_override;
bool red_colored = false; bool red_colored = false;
if (text.empty()) {
switch (m_warnings.back()) { switch (m_warnings.back()) {
case ObjectOutside: text = L("An object outside the print area was detected"); break; case ObjectOutside: text = L("An object outside the print area was detected"); break;
case ToolpathOutside: text = L("A toolpath outside the print area was detected"); break; case ToolpathOutside: text = L("A toolpath outside the print area was detected"); break;
@ -695,6 +696,10 @@ void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool
red_colored = true; red_colored = true;
break; break;
} }
default: text = L("An error occured");
}
} else {
red_colored = true;
} }
generate(text, canvas, true, red_colored); // GUI::GLTexture::reset() is called at the beginning of generate(...) generate(text, canvas, true, red_colored); // GUI::GLTexture::reset() is called at the beginning of generate(...)

View File

@ -314,12 +314,13 @@ private:
ToolpathOutside, ToolpathOutside,
SlaSupportsOutside, SlaSupportsOutside,
SomethingNotShown, SomethingNotShown,
PrintWarning,
ObjectClashed ObjectClashed
}; };
// Sets a warning of the given type to be active/inactive. If several warnings are active simultaneously, // Sets a warning of the given type to be active/inactive. If several warnings are active simultaneously,
// only the last one is shown (decided by the order in the enum above). // only the last one is shown (decided by the order in the enum above).
void activate(WarningTexture::Warning warning, bool state, const GLCanvas3D& canvas); void activate(WarningTexture::Warning warning, bool state, const GLCanvas3D& canvas, std::string str_override = "");
void render(const GLCanvas3D& canvas) const; void render(const GLCanvas3D& canvas) const;
// function used to get an information for rescaling of the warning // function used to get an information for rescaling of the warning
@ -699,6 +700,13 @@ public:
bool are_labels_shown() const { return m_labels.is_shown(); } bool are_labels_shown() const { return m_labels.is_shown(); }
void show_labels(bool show) { m_labels.show(show); } void show_labels(bool show) { m_labels.show(show); }
void show_print_warning(std::string str) {
if (str.empty())
m_warning_texture.activate(WarningTexture::Warning::PrintWarning, false, *this);
else
m_warning_texture.activate(WarningTexture::Warning::PrintWarning, true, *this, str);
}
private: private:
bool _is_shown_on_screen() const; bool _is_shown_on_screen() const;

View File

@ -3165,8 +3165,9 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
// The delayed error message is no more valid. // The delayed error message is no more valid.
this->delayed_error_message.clear(); this->delayed_error_message.clear();
// The state of the Print changed, and it is non-zero. Let's validate it and give the user feedback on errors. // The state of the Print changed, and it is non-zero. Let's validate it and give the user feedback on errors.
std::string err = this->background_process.validate(); std::pair<PrintError, std::string> err = this->background_process.validate();
if (err.empty()) { this->get_current_canvas3D()->show_print_warning("");
if (err.first == PrintError::None) {
if (invalidated != Print::APPLY_STATUS_UNCHANGED && this->background_processing_enabled()) if (invalidated != Print::APPLY_STATUS_UNCHANGED && this->background_processing_enabled())
return_state |= UPDATE_BACKGROUND_PROCESS_RESTART; return_state |= UPDATE_BACKGROUND_PROCESS_RESTART;
} else { } else {
@ -3176,12 +3177,14 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
while (p->GetParent()) while (p->GetParent())
p = p->GetParent(); p = p->GetParent();
auto *top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p); auto *top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p);
if (! postpone_error_messages && top_level_wnd && top_level_wnd->IsActive()) { if ( (err.first == PrintError::WrongPosition || err.first == PrintError::NoPrint) && top_level_wnd && top_level_wnd->IsActive()) {
this->get_current_canvas3D()->show_print_warning(err.second);
} else if (!postpone_error_messages && top_level_wnd && top_level_wnd->IsActive()) {
// The error returned from the Print needs to be translated into the local language. // The error returned from the Print needs to be translated into the local language.
GUI::show_error(this->q, err); GUI::show_error(this->q, err.second);
} else { } else {
// Show the error message once the main window gets activated. // Show the error message once the main window gets activated.
this->delayed_error_message = err; this->delayed_error_message = err.second;
} }
return_state |= UPDATE_BACKGROUND_PROCESS_INVALID; return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
} }