From b0fa37b2a435437582d620bbc880a67698df3603 Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Mon, 30 Oct 2017 13:08:28 -0700 Subject: [PATCH] Added first pass at support for SLA printers Took out unused slice settings --- PrinterControls/ManualPrinterControls.cs | 2 +- .../Settings/PrinterSettings.cs | 1 - .../Settings/SettingsHelpers.cs | 4 + .../SlicerMapping/EngineMapingBase.cs | 3 +- .../SlicerMapping/EngineMappingMatterSlice.cs | 14 +- .../SlicerMapping/MappingClasses.cs | 31 ++ .../OEMSettings/SampleParts/MH Logo.stl | Bin 0 -> 62284 bytes StaticData/SliceSettings/Layouts.txt | 30 +- StaticData/SliceSettings/Properties.json | 300 +++++++----------- Submodules/agg-sharp | 2 +- .../PartPreviewTests.cs | 45 +++ 11 files changed, 218 insertions(+), 214 deletions(-) create mode 100644 StaticData/OEMSettings/SampleParts/MH Logo.stl diff --git a/PrinterControls/ManualPrinterControls.cs b/PrinterControls/ManualPrinterControls.cs index 6cf71dbf0..48ef94c91 100644 --- a/PrinterControls/ManualPrinterControls.cs +++ b/PrinterControls/ManualPrinterControls.cs @@ -55,7 +55,7 @@ namespace MatterHackers.MatterControl public override void OnLoad(EventArgs args) { - if (!pluginsQueuedToAdd && printer.Settings.GetValue("include_firmware_updater") == "Simple Arduino") + if (!pluginsQueuedToAdd && printer.Settings.GetValue(SettingsKey.include_firmware_updater) == "Simple Arduino") { UiThread.RunOnIdle(() => { diff --git a/SlicerConfiguration/Settings/PrinterSettings.cs b/SlicerConfiguration/Settings/PrinterSettings.cs index 8fc6365b3..2a64449a4 100644 --- a/SlicerConfiguration/Settings/PrinterSettings.cs +++ b/SlicerConfiguration/Settings/PrinterSettings.cs @@ -1088,7 +1088,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration if (!ValidateGoodSpeedSettingGreaterThan0("bridge_speed", normalSpeedLocation)) return false; if (!ValidateGoodSpeedSettingGreaterThan0("external_perimeter_speed", normalSpeedLocation)) return false; if (!ValidateGoodSpeedSettingGreaterThan0(SettingsKey.first_layer_speed, normalSpeedLocation)) return false; - if (!ValidateGoodSpeedSettingGreaterThan0("gap_fill_speed", normalSpeedLocation)) return false; if (!ValidateGoodSpeedSettingGreaterThan0("infill_speed", normalSpeedLocation)) return false; if (!ValidateGoodSpeedSettingGreaterThan0("perimeter_speed", normalSpeedLocation)) return false; if (!ValidateGoodSpeedSettingGreaterThan0("small_perimeter_speed", normalSpeedLocation)) return false; diff --git a/SlicerConfiguration/Settings/SettingsHelpers.cs b/SlicerConfiguration/Settings/SettingsHelpers.cs index cbc6441b3..4431b8797 100644 --- a/SlicerConfiguration/Settings/SettingsHelpers.cs +++ b/SlicerConfiguration/Settings/SettingsHelpers.cs @@ -85,6 +85,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public const string has_power_control = nameof(has_power_control); public const string has_sd_card_reader = nameof(has_sd_card_reader); public const string heat_extruder_before_homing = nameof(heat_extruder_before_homing); + public const string include_firmware_updater = nameof(include_firmware_updater); public const string ip_address = nameof(ip_address); public const string ip_port = nameof(ip_port); public const string layer_gcode = nameof(layer_gcode); @@ -101,6 +102,8 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public const string oem_profile_token = nameof(oem_profile_token); public const string pause_gcode = nameof(pause_gcode); public const string perimeter_start_end_overlap = nameof(perimeter_start_end_overlap); + public const string laser_speed_025 = nameof(laser_speed_025); + public const string laser_speed_100 = nameof(laser_speed_100); public const string print_center = nameof(print_center); public const string print_leveling_data = nameof(print_leveling_data); public const string print_leveling_enabled = nameof(print_leveling_enabled); @@ -115,6 +118,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public const string recover_position_before_z_home = nameof(recover_position_before_z_home); public const string resume_gcode = nameof(resume_gcode); public const string show_reset_connection = nameof(show_reset_connection); + public const string sla_printer = nameof(sla_printer); public const string validate_layer_height = nameof(validate_layer_height); public const string spiral_vase = nameof(spiral_vase); public const string start_gcode = nameof(start_gcode); diff --git a/SlicerConfiguration/SlicerMapping/EngineMapingBase.cs b/SlicerConfiguration/SlicerMapping/EngineMapingBase.cs index d33f12f0e..39e97f042 100644 --- a/SlicerConfiguration/SlicerMapping/EngineMapingBase.cs +++ b/SlicerConfiguration/SlicerMapping/EngineMapingBase.cs @@ -86,7 +86,8 @@ namespace MatterHackers.MatterControl.SlicerConfiguration SettingsKey.bed_remove_part_temperature, "extruder_wipe_temperature", SettingsKey.heat_extruder_before_homing, - "include_firmware_updater", + SettingsKey.include_firmware_updater, + SettingsKey.sla_printer, "layer_to_pause", SettingsKey.show_reset_connection, SettingsKey.validate_layer_height, diff --git a/SlicerConfiguration/SlicerMapping/EngineMappingMatterSlice.cs b/SlicerConfiguration/SlicerMapping/EngineMappingMatterSlice.cs index 404126db5..c421938ed 100644 --- a/SlicerConfiguration/SlicerMapping/EngineMappingMatterSlice.cs +++ b/SlicerConfiguration/SlicerMapping/EngineMappingMatterSlice.cs @@ -57,11 +57,11 @@ namespace MatterHackers.MatterControl.SlicerConfiguration new AsCountOrDistance("top_solid_layers", "numberOfTopLayers", SettingsKey.layer_height), new AsCountOrDistance("brims", "numberOfBrimLoops", SettingsKey.nozzle_diameter), new AsPercentOfReferenceOrDirect(SettingsKey.external_perimeter_extrusion_width, "outsidePerimeterExtrusionWidth", SettingsKey.nozzle_diameter), - new AsPercentOfReferenceOrDirect("external_perimeter_speed", "outsidePerimeterSpeed", "perimeter_speed"), + new OverrideSpeedOnSlaPrinters("external_perimeter_speed", "outsidePerimeterSpeed", "perimeter_speed"), new AsPercentOfReferenceOrDirect(SettingsKey.first_layer_speed, "firstLayerSpeed", "infill_speed"), new AsCountOrDistance(SettingsKey.number_of_first_layers, "numberOfFirstLayers", SettingsKey.layer_height), new AsPercentOfReferenceOrDirect("raft_print_speed", "raftPrintSpeed", "infill_speed"), - new AsPercentOfReferenceOrDirect("top_solid_infill_speed", "topInfillSpeed", "infill_speed"), + new OverrideSpeedOnSlaPrinters("top_solid_infill_speed", "topInfillSpeed", "infill_speed"), new AsPercentOfReferenceOrDirect(SettingsKey.first_layer_extrusion_width, "firstLayerExtrusionWidth", SettingsKey.nozzle_diameter), new AsPercentOfReferenceOrDirect(SettingsKey.first_layer_height, "firstLayerThickness", SettingsKey.layer_height), new ExtruderOffsets("extruder_offset", "extruderOffsets"), @@ -75,18 +75,18 @@ namespace MatterHackers.MatterControl.SlicerConfiguration new MapFirstValue("retract_restart_extra_time_to_apply", "retractRestartExtraTimeToApply"), new MapFirstValue("retract_speed", "retractionSpeed"), new MappedSetting("bridge_fan_speed", "bridgeFanSpeedPercent"), - new MappedSetting("bridge_speed", "bridgeSpeed"), + new OverrideSpeedOnSlaPrinters("bridge_speed", "bridgeSpeed", "infill_speed"), new MappedSetting("disable_fan_first_layers", "firstLayerToAllowFan"), new MappedSetting("extrusion_multiplier", "extrusionMultiplier"), new MappedSetting("fill_angle", "infillStartingAngle"), new MappedSetting("infill_overlap_perimeter", "infillExtendIntoPerimeter"), - new MappedSetting("infill_speed", "infillSpeed"), + new OverrideSpeedOnSlaPrinters("infill_speed", "infillSpeed", "infill_speed"), new MappedSetting("infill_type", "infillType"), new MappedSetting("max_fan_speed", "fanSpeedMaxPercent"), new MappedSetting("min_extrusion_before_retract", "minimumExtrusionBeforeRetraction"), new MappedSetting("min_fan_speed", "fanSpeedMinPercent"), new MappedSetting("min_print_speed", "minimumPrintingSpeed"), - new MappedSetting("perimeter_speed", "insidePerimetersSpeed"), + new OverrideSpeedOnSlaPrinters("perimeter_speed", "insidePerimetersSpeed", "infill_speed"), new MappedSetting("raft_air_gap", "raftAirGap"), new MappedSetting("raft_fan_speed_percent", "raftFanSpeedPercent"), new MappedSetting("retract_length_tool_change", "retractionOnExtruderSwitch"), @@ -97,7 +97,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration new MappedSetting("support_material_infill_angle", "supportInfillStartingAngle"), new MappedSetting("support_material_percent", "supportPercent"), new MappedSetting("support_material_spacing", "supportLineSpacing"), - new MappedSetting("support_material_speed", "supportMaterialSpeed"), + new OverrideSpeedOnSlaPrinters("support_material_speed", "supportMaterialSpeed", "infill_speed"), new MappedSetting("support_material_xy_distance", "supportXYDistanceFromObject"), new MappedSetting("support_type", "supportType"), new MappedSetting("travel_speed", "travelSpeed"), @@ -133,6 +133,8 @@ namespace MatterHackers.MatterControl.SlicerConfiguration new VisibleButNotMappedToEngine("extruders_share_temperature"), new VisibleButNotMappedToEngine("g0"), new VisibleButNotMappedToEngine("solid_shell"), + new VisibleButNotMappedToEngine(SettingsKey.laser_speed_025), + new VisibleButNotMappedToEngine(SettingsKey.laser_speed_100), }; matterSliceSettingNames = new HashSet(mappedSettings.Select(m => m.CanonicalSettingsName)); diff --git a/SlicerConfiguration/SlicerMapping/MappingClasses.cs b/SlicerConfiguration/SlicerMapping/MappingClasses.cs index 7995ba208..090ae2b97 100644 --- a/SlicerConfiguration/SlicerMapping/MappingClasses.cs +++ b/SlicerConfiguration/SlicerMapping/MappingClasses.cs @@ -520,6 +520,37 @@ namespace MatterHackers.MatterControl.SlicerConfiguration } } + public class OverrideSpeedOnSlaPrinters : AsPercentOfReferenceOrDirect + { + public OverrideSpeedOnSlaPrinters(string canonicalSettingsName, string exportedName, string originalReference, double scale = 1) + : base(canonicalSettingsName, exportedName, originalReference, scale) + { + } + + public override string Value + { + get + { + if (ActiveSliceSettings.Instance.GetValue(SettingsKey.sla_printer)) + { + // return the speed based on the layer height + var speedAt025 = ActiveSliceSettings.Instance.GetValue(SettingsKey.laser_speed_025); + var speedAt100 = ActiveSliceSettings.Instance.GetValue(SettingsKey.laser_speed_100); + var deltaSpeed = speedAt100 - speedAt025; + + var layerHeight = ActiveSliceSettings.Instance.GetValue(SettingsKey.layer_height); + var deltaHeight = .1 - .025; + var heightRatio = (layerHeight - .025) / deltaHeight; + return (speedAt025 + deltaSpeed * heightRatio).ToString(); + } + else + { + return base.Value; + } + } + } + } + public class AsPercentOfReferenceOrDirect : MappedSetting { string originalReference; diff --git a/StaticData/OEMSettings/SampleParts/MH Logo.stl b/StaticData/OEMSettings/SampleParts/MH Logo.stl new file mode 100644 index 0000000000000000000000000000000000000000..d12d717ef0e251bf7ef290cc78b676495d24b3c9 GIT binary patch literal 62284 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 + { + testRunner.AddItemToBedplate(partName: "Row Item MH Logo.stl"); + testRunner.Delay(.1); + testRunner.ClickByName("MH Logo.stl"); + Assert.IsNotNull(scene.SelectedItem); + }, + (scene) => + { + testRunner.ClickByName("View3DWidget"); // place focus back in the scene + testRunner.Type("^a"); // select all + testRunner.ClickByName("3D View Ungroup"); + testRunner.ClickByName("View3DWidget"); // place focus back in the scene + testRunner.Type(" "); // select none + testRunner.Delay(() => scene1.Children.Count() == 3, .5); + Assert.AreEqual(3, scene1.Children.Count()); + }); + */ + // test group 2 objects RunDoUndoTest(testRunner, scene1, (scene) => { @@ -265,6 +286,30 @@ namespace MatterHackers.MatterControl.Tests.Automation testRunner.Delay(() => scene.SelectedItem == null, .5); }); + // test un-group 2 grouped objects + RunDoUndoTest(testRunner, scene1, (scene) => + { + AddBoxABoxBToBed(testRunner, scene); + Assert.AreEqual(2, scene1.Children.Count()); + testRunner.ClickByName("View3DWidget"); // place focus back in the scene + testRunner.Type("^a"); // select all + testRunner.ClickByName("3D View Group"); + testRunner.ClickByName("View3DWidget"); // place focus back in the scene + testRunner.Type(" "); // select none + testRunner.Delay(() => scene1.Children.Count() == 1, .5); + Assert.AreEqual(1, scene1.Children.Count()); + }, + (scene) => + { + testRunner.ClickByName("View3DWidget"); // place focus back in the scene + testRunner.Type("^a"); // select all + testRunner.ClickByName("3D View Ungroup"); + testRunner.ClickByName("View3DWidget"); // place focus back in the scene + testRunner.Type(" "); // select none + testRunner.Delay(() => scene1.Children.Count() == 2, .5); + Assert.AreEqual(2, scene1.Children.Count()); + }); + // test mirror operations TestMirrorDoUndo(testRunner, scene1, "Mirror Button X"); TestMirrorDoUndo(testRunner, scene1, "Mirror Button Y");