public static bool SetupRequired(PrinterConfig printer) { return(LevelingValidation.NeedsToBeRun(printer) || // PrintLevelingWizard ProbeCalibrationWizard.NeedsToBeRun(printer) || FilamentSetupWizard.SetupRequired(printer)); }
/// <summary> /// Validates the printer settings satisfy all requirements /// </summary> /// <param name="printer">The printer to validate</param> /// <returns>A list of all warnings and errors</returns> public static List <ValidationError> ValidateSettings(this PrinterConfig printer, SettingsContext settings = null) { if (settings == null) { settings = new SettingsContext(printer, null, NamedSettingsLayers.All); } var errors = new List <ValidationError>(); var extruderCount = settings.GetValue <int>(SettingsKey.extruder_count); // Check to see if supports are required var supportGenerator = new SupportGenerator(printer.Bed.Scene, .05); if (supportGenerator.RequiresSupport()) { errors.Add(new ValidationError("UnsupportedParts") { Error = "Possible Unsupported Parts Detected".Localize(), Details = "Some parts may require support structures to print correctly".Localize(), ErrorLevel = ValidationErrorLevel.Warning, FixAction = new NamedAction() { Title = "Generate Supports".Localize(), Action = () => { // Find and InvokeClick on the Generate Supports toolbar button var sharedParent = ApplicationController.Instance.DragDropData.View3DWidget.Parents <GuiWidget>().FirstOrDefault(w => w.Name == "View3DContainerParent"); if (sharedParent != null) { var supportsPopup = sharedParent.FindDescendant("Support SplitButton"); supportsPopup.InvokeClick(); } } } }); } if (FilamentSetupWizard.SetupRequired(printer)) { errors.Add(new ValidationError("FilamentSetup") { Error = "Unknown filament loaded".Localize(), Details = "Set active material to continue".Localize(), ErrorLevel = ValidationErrorLevel.Warning, FixAction = new NamedAction() { Title = "Load Filament".Localize(), Action = () => { UiThread.RunOnIdle(() => { DialogWindow.Show( new FilamentSetupWizard(printer, AppContext.Theme), advanceToIncompleteStage: true); }); } } }); } try { if (settings.GetValue <bool>(SettingsKey.validate_layer_height)) { if (settings.GetValue <double>(SettingsKey.layer_height) > settings.GetValue <double>(SettingsKey.nozzle_diameter)) { errors.Add( new SettingsValidationError(SettingsKey.layer_height) { Error = "{0} must be less than or equal to the {1}.".Localize().FormatWith( GetSettingsName(SettingsKey.layer_height), GetSettingsName(SettingsKey.nozzle_diameter)), ValueDetails = "{0} = {1}\n{2} = {3}".FormatWith( GetSettingsName(SettingsKey.layer_height), settings.GetValue <double>(SettingsKey.layer_height), GetSettingsName(SettingsKey.nozzle_diameter), settings.GetValue <double>(SettingsKey.nozzle_diameter)), }); } else if (settings.GetValue <double>(SettingsKey.layer_height) <= 0) { errors.Add( new SettingsValidationError(SettingsKey.layer_height) { Error = "{0} must be greater than 0.".Localize().FormatWith(GetSettingsName(SettingsKey.layer_height)), }); } if (settings.GetValue <double>(SettingsKey.first_layer_height) > settings.GetValue <double>(SettingsKey.nozzle_diameter)) { errors.Add( new SettingsValidationError(SettingsKey.first_layer_height) { Error = "{0} must be less than or equal to the {1}.".Localize().FormatWith( GetSettingsName(SettingsKey.first_layer_height), GetSettingsName(SettingsKey.nozzle_diameter)), ValueDetails = "{0} = {1}\n{2} = {3}".FormatWith( GetSettingsName(SettingsKey.first_layer_height), settings.GetValue <double>(SettingsKey.first_layer_height), GetSettingsName(SettingsKey.nozzle_diameter), settings.GetValue <double>(SettingsKey.nozzle_diameter)), }); } } string[] startGCode = settings.GetValue(SettingsKey.start_gcode).Replace("\\n", "\n").Split('\n'); // Print recovery is incompatible with firmware leveling - ensure not enabled in startGCode if (settings.GetValue <bool>(SettingsKey.recover_is_enabled)) { // Ensure we don't have hardware leveling commands in the start gcode. foreach (string startGCodeLine in startGCode) { if (startGCodeLine.StartsWith("G29")) { errors.Add( new SettingsValidationError(SettingsKey.start_gcode) { Error = "Start G-Code cannot contain G29 if Print Recovery is enabled.".Localize(), Details = "Your Start G-Code should not contain a G29 if you are planning on using Print Recovery. Change your start G-Code or turn off Print Recovery.".Localize(), }); } if (startGCodeLine.StartsWith("G30")) { errors.Add( new SettingsValidationError(SettingsKey.start_gcode) { Error = "Start G-Code cannot contain G30 if Print Leveling is enabled.".Localize(), Details = "Your Start G-Code should not contain a G30 if you are planning on using Print Recovery. Change your start G-Code or turn off Print Recovery.".Localize(), }); } } } var levelingEnabled = printer.Settings.GetValue <bool>(SettingsKey.print_leveling_enabled); var levelingRequired = printer.Settings.GetValue <bool>(SettingsKey.print_leveling_required_to_print); if (levelingEnabled || levelingRequired) { // Ensure we don't have hardware leveling commands in the start gcode. foreach (string startGCodeLine in startGCode) { if (startGCodeLine.StartsWith("G29")) { errors.Add( new SettingsValidationError(SettingsKey.start_gcode) { Error = "Start G-Code cannot contain G29 if Print Leveling is enabled.".Localize(), Details = "Your Start G-Code should not contain a G29 if you are planning on using print leveling. Change your start G-Code or turn off print leveling.".Localize(), }); } if (startGCodeLine.StartsWith("G30")) { errors.Add( new SettingsValidationError(SettingsKey.start_gcode) { Error = "Start G-Code cannot contain G30 if Print Leveling is enabled.".Localize(), Details = "Your Start G-Code should not contain a G30 if you are planning on using print leveling. Change your start G-Code or turn off print leveling.".Localize(), }); } } bool heatedBed = printer.Settings.GetValue <bool>(SettingsKey.has_heated_bed); double bedTemperature = printer.Settings.GetValue <double>(SettingsKey.bed_temperature); PrintLevelingData levelingData = printer.Settings.Helpers.PrintLevelingData; if (heatedBed && !levelingData.IssuedLevelingTempWarning && Math.Abs(bedTemperature - levelingData.BedTemperature) > 10) { errors.Add( new ValidationError("BedLevelingTemperature") { Error = "Bed Leveling Temperature".Localize(), Details = string.Format( "Bed Leveling data created at {0}°C versus current {1}°C".Localize(), levelingData.BedTemperature, bedTemperature), ErrorLevel = ValidationErrorLevel.Warning, FixAction = new NamedAction() { Title = "Recalibrate", Action = () => { UiThread.RunOnIdle(() => { DialogWindow.Show(new PrintLevelingWizard(printer)); }); }, IsEnabled = () => printer.Connection.IsConnected } }); } } // Make sure the z offsets are not too big if (Math.Abs(settings.GetValue <double>(SettingsKey.baby_step_z_offset)) > 2) { // Static path generation for non-SliceSettings value var location = "Location".Localize() + ":" + "\n" + "Controls".Localize() + "\n • " + "Movement".Localize() + "\n • " + "Z Offset".Localize(); errors.Add( new ValidationError("ZOffset0TooLarge") { Error = "Z Offset is too large.".Localize(), Details = string.Format( "{0}\n\n{1}", "The Z Offset for your printer, sometimes called Baby Stepping, is greater than 2mm and invalid. Clear the value and re-level the bed.".Localize(), location) }); } if (settings.GetValue <double>(SettingsKey.first_layer_extrusion_width) > settings.GetValue <double>(SettingsKey.nozzle_diameter) * 4) { errors.Add( new SettingsValidationError(SettingsKey.first_layer_extrusion_width) { Error = "{0} must be less than or equal to the {1} * 4.".Localize().FormatWith( GetSettingsName(SettingsKey.first_layer_extrusion_width), GetSettingsName(SettingsKey.nozzle_diameter)), ValueDetails = "{0} = {1}\n{2} = {3}".FormatWith( GetSettingsName(SettingsKey.first_layer_extrusion_width), settings.GetValue <double>(SettingsKey.first_layer_extrusion_width), GetSettingsName(SettingsKey.nozzle_diameter), settings.GetValue <double>(SettingsKey.nozzle_diameter)) }); } if (settings.GetValue <double>(SettingsKey.first_layer_extrusion_width) <= 0) { errors.Add( new SettingsValidationError(SettingsKey.first_layer_extrusion_width) { Error = "{0} must be greater than 0.".Localize().FormatWith( GetSettingsName(SettingsKey.first_layer_extrusion_width)), ValueDetails = "{0} = {1}".FormatWith( GetSettingsName(SettingsKey.first_layer_extrusion_width), settings.GetValue <double>(SettingsKey.first_layer_extrusion_width)), }); } if (settings.GetValue <double>(SettingsKey.external_perimeter_extrusion_width) > settings.GetValue <double>(SettingsKey.nozzle_diameter) * 4) { errors.Add( new SettingsValidationError(SettingsKey.external_perimeter_extrusion_width) { Error = "{0} must be less than or equal to the {1} * 4.".Localize().FormatWith( GetSettingsName(SettingsKey.external_perimeter_extrusion_width), GetSettingsName(SettingsKey.nozzle_diameter)), ValueDetails = "{0} = {1}\n{2} = {3}".FormatWith( GetSettingsName(SettingsKey.external_perimeter_extrusion_width), settings.GetValue <double>(SettingsKey.external_perimeter_extrusion_width), GetSettingsName(SettingsKey.nozzle_diameter), settings.GetValue <double>(SettingsKey.nozzle_diameter)), }); } if (settings.GetValue <double>(SettingsKey.external_perimeter_extrusion_width) <= 0) { errors.Add( new SettingsValidationError(SettingsKey.external_perimeter_extrusion_width) { Error = "{0} must be greater than 0.".Localize().FormatWith( GetSettingsName(SettingsKey.external_perimeter_extrusion_width)), ValueDetails = "{0} = {1}".FormatWith( GetSettingsName(SettingsKey.external_perimeter_extrusion_width), settings.GetValue <double>(SettingsKey.external_perimeter_extrusion_width)), }); } if (settings.GetValue <double>(SettingsKey.min_fan_speed) > 100) { errors.Add( new SettingsValidationError(SettingsKey.min_fan_speed) { Error = "The {0} can only go as high as 100%.".Localize().FormatWith( GetSettingsName(SettingsKey.min_fan_speed)), ValueDetails = "It is currently set to {0}.".Localize().FormatWith( settings.GetValue <double>(SettingsKey.min_fan_speed)), }); } if (settings.GetValue <double>(SettingsKey.max_fan_speed) > 100) { errors.Add( new SettingsValidationError(SettingsKey.max_fan_speed) { Error = "The {0} can only go as high as 100%.".Localize().FormatWith( GetSettingsName(SettingsKey.max_fan_speed)), ValueDetails = "It is currently set to {0}.".Localize().FormatWith( settings.GetValue <double>(SettingsKey.max_fan_speed)), }); } if (extruderCount < 1) { errors.Add( new SettingsValidationError(SettingsKey.extruder_count) { Error = "The {0} must be at least 1.".Localize().FormatWith( GetSettingsName(SettingsKey.extruder_count)), ValueDetails = "It is currently set to {0}.".Localize().FormatWith(extruderCount), }); } if (settings.GetValue <double>(SettingsKey.fill_density) < 0 || settings.GetValue <double>(SettingsKey.fill_density) > 1) { errors.Add( new SettingsValidationError(SettingsKey.fill_density) { Error = "The {0} must be between 0 and 1.".Localize().FormatWith( GetSettingsName(SettingsKey.fill_density)), ValueDetails = "It is currently set to {0}.".Localize().FormatWith( settings.GetValue <double>(SettingsKey.fill_density)), }); } // marlin firmware can only take a max of 128 bytes in a single instruction, make sure no lines are longer than that ValidateGCodeLinesShortEnough(SettingsKey.cancel_gcode, printer, errors); ValidateGCodeLinesShortEnough(SettingsKey.connect_gcode, printer, errors); ValidateGCodeLinesShortEnough(SettingsKey.end_gcode, printer, errors); ValidateGCodeLinesShortEnough(SettingsKey.layer_gcode, printer, errors); ValidateGCodeLinesShortEnough(SettingsKey.pause_gcode, printer, errors); ValidateGCodeLinesShortEnough(SettingsKey.resume_gcode, printer, errors); ValidateGCodeLinesShortEnough(SettingsKey.start_gcode, printer, errors); // If the given speed is part of the current slice engine then check that it is greater than 0. ValidateGoodSpeedSettingGreaterThan0(SettingsKey.bridge_speed, printer, errors); ValidateGoodSpeedSettingGreaterThan0(SettingsKey.air_gap_speed, printer, errors); ValidateGoodSpeedSettingGreaterThan0(SettingsKey.external_perimeter_speed, printer, errors); ValidateGoodSpeedSettingGreaterThan0(SettingsKey.first_layer_speed, printer, errors); ValidateGoodSpeedSettingGreaterThan0(SettingsKey.infill_speed, printer, errors); ValidateGoodSpeedSettingGreaterThan0(SettingsKey.perimeter_speed, printer, errors); ValidateGoodSpeedSettingGreaterThan0(SettingsKey.small_perimeter_speed, printer, errors); ValidateGoodSpeedSettingGreaterThan0(SettingsKey.solid_infill_speed, printer, errors); ValidateGoodSpeedSettingGreaterThan0(SettingsKey.support_material_speed, printer, errors); ValidateGoodSpeedSettingGreaterThan0(SettingsKey.top_solid_infill_speed, printer, errors); ValidateGoodSpeedSettingGreaterThan0(SettingsKey.travel_speed, printer, errors); ValidateGoodSpeedSettingGreaterThan0(SettingsKey.retract_speed, printer, errors); } catch (Exception e) { errors.Add( new ValidationError("ExceptionDuringSliceSettingsValidation") { Error = "Unexpected error validating settings".Localize(), Details = e.Message }); } return(errors); }