From 0babdab806b1f01e07495d08cf361bcb77320b52 Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Tue, 13 Nov 2018 18:43:27 -0800 Subject: [PATCH] cleaning up MappedSetting --- .../ApplicationView/AppViewState.cs | 39 + MatterControlLib/ApplicationView/BedConfig.cs | 588 +++++++ .../ApplicationView/EditContext.cs | 94 ++ .../ApplicationView/PrinterConfig.cs | 460 ++++++ .../ApplicationView/PrinterModels.cs | 1404 ----------------- .../ApplicationView/PrinterViewState.cs | 182 +++ .../ApplicationView/SceneContextViewState.cs | 117 ++ .../ApplicationView/View3DConfig.cs | 202 +++ .../Io/PauseHandlingStream.cs | 2 +- .../Io/QueuedCommandsStream.cs | 2 +- .../EngineMappingMatterSlice.cs | 267 ++++ .../MappingClasses/AsCountOrDistance.cs | 61 + .../AsPercentOfReferenceOrDirect.cs | 76 + .../MappingClasses/ExtruderOffsets.cs | 84 + .../MappingClasses/FanTranslator.cs | 49 + .../MappingClasses/GCodeForSlicer.cs | 41 + .../MappingClasses/InfillTranslator.cs | 57 + .../MappingClasses/InjectGCodeCommands.cs | 60 + .../MappingClasses/MapFirstValue.cs | 41 + .../MappingClasses/MapLayerChangeGCode.cs | 56 + .../MappingClasses/MapStartGCode.cs | 210 +++ .../MappingClasses/MappedBrimLoopsSetting.cs | 52 + .../MappingClasses/MappedFanSpeedSetting.cs | 52 + .../MappingClasses/MappedSetting.cs | 60 + .../MappingClasses/MappedSkirtLoopsSetting.cs | 52 + .../MappingClasses/MappedToBoolString.cs | 41 + .../OverrideSpeedOnSlaPrinters.cs | 63 + .../MappingClasses/RetractionLength.cs | 54 + .../MappingClasses/ScaledSingleNumber.cs | 61 + .../MappingClasses/SkirtLengthMapping.cs | 55 + .../MappingClasses/Slice3rBedShape.cs | 86 + .../MappingClasses/SupportExtrusionWidth.cs | 68 + .../UnescapeNewlineCharacters.cs | 42 + .../MappingClasses/ValuePlusConstant.cs | 44 + .../Settings/PrinterSettings.cs | 9 +- .../SliceSettingsWidget.cs | 2 +- .../SlicerConfiguration/Slicer.cs | 2 +- .../SlicerMapping/EngineMappingMatterSlice.cs | 446 ------ .../SlicerMapping/MappingClasses.cs | 665 -------- Submodules/agg-sharp | 2 +- .../MatterControl/GCodeProcessingTests.cs | 4 +- 41 files changed, 3427 insertions(+), 2525 deletions(-) create mode 100644 MatterControlLib/ApplicationView/AppViewState.cs create mode 100644 MatterControlLib/ApplicationView/BedConfig.cs create mode 100644 MatterControlLib/ApplicationView/EditContext.cs create mode 100644 MatterControlLib/ApplicationView/PrinterConfig.cs delete mode 100644 MatterControlLib/ApplicationView/PrinterModels.cs create mode 100644 MatterControlLib/ApplicationView/PrinterViewState.cs create mode 100644 MatterControlLib/ApplicationView/SceneContextViewState.cs create mode 100644 MatterControlLib/ApplicationView/View3DConfig.cs create mode 100644 MatterControlLib/SlicerConfiguration/EngineMappingMatterSlice.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/AsCountOrDistance.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/AsPercentOfReferenceOrDirect.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/ExtruderOffsets.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/FanTranslator.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/GCodeForSlicer.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/InfillTranslator.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/InjectGCodeCommands.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/MapFirstValue.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/MapLayerChangeGCode.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/MapStartGCode.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/MappedBrimLoopsSetting.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/MappedFanSpeedSetting.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/MappedSetting.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/MappedSkirtLoopsSetting.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/MappedToBoolString.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/OverrideSpeedOnSlaPrinters.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/RetractionLength.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/ScaledSingleNumber.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/SkirtLengthMapping.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/Slice3rBedShape.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/SupportExtrusionWidth.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/UnescapeNewlineCharacters.cs create mode 100644 MatterControlLib/SlicerConfiguration/MappingClasses/ValuePlusConstant.cs delete mode 100644 MatterControlLib/SlicerConfiguration/SlicerMapping/EngineMappingMatterSlice.cs delete mode 100644 MatterControlLib/SlicerConfiguration/SlicerMapping/MappingClasses.cs diff --git a/MatterControlLib/ApplicationView/AppViewState.cs b/MatterControlLib/ApplicationView/AppViewState.cs new file mode 100644 index 000000000..704255096 --- /dev/null +++ b/MatterControlLib/ApplicationView/AppViewState.cs @@ -0,0 +1,39 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + + +namespace MatterHackers.MatterControl +{ + using MatterHackers.MatterControl.PrintLibrary; + + public class AppViewState + { + public PrintLibraryWidget.ListViewModes LibraryViewMode { get; set; } = PrintLibraryWidget.ListViewModes.IconListView; + } +} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/BedConfig.cs b/MatterControlLib/ApplicationView/BedConfig.cs new file mode 100644 index 000000000..00697f7b9 --- /dev/null +++ b/MatterControlLib/ApplicationView/BedConfig.cs @@ -0,0 +1,588 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using MatterControl.Printing; +using MatterHackers.Agg.UI; +using MatterHackers.MatterControl.SlicerConfiguration; +using Newtonsoft.Json; + +namespace MatterHackers.MatterControl +{ + using System.Collections.Generic; + using System.Threading; + using MatterHackers.Agg; + using MatterHackers.DataConverters3D; + using MatterHackers.GCodeVisualizer; + using MatterHackers.Localizations; + using MatterHackers.MatterControl.Library; + using MatterHackers.MatterControl.PartPreviewWindow; + using MatterHackers.MeshVisualizer; + using MatterHackers.PolygonMesh; + using MatterHackers.VectorMath; + + public class BedConfig + { + public event EventHandler ActiveLayerChanged; + + public event EventHandler LoadedGCodeChanged; + + public event EventHandler SceneLoaded; + + public View3DConfig RendererOptions { get; } = new View3DConfig(); + + public PrinterConfig Printer { get; set; } + + public EditContext EditContext { get; private set; } + + public Mesh PrinterShape { get; private set; } + + public SceneContextViewState ViewState { get; } + + private HistoryContainerBase historyContainer; + + public BedConfig(HistoryContainerBase historyContainer, PrinterConfig printer = null) + { + this.historyContainer = historyContainer; + this.Printer = printer; + this.ViewState = new SceneContextViewState(this); + } + + public void LoadEmptyContent(EditContext editContext) + { + // Make sure we don't have a selection + this.Scene.SelectedItem = null; + + this.EditContext = editContext; + this.ContentType = "mcx"; + + this.Scene.Children.Modify(children => children.Clear()); + + this.Scene.Load(new Object3D()); + + // Notify + this.SceneLoaded?.Invoke(this, null); + } + + public Task LoadLibraryContent(ILibraryItem libraryItem) + { + return this.LoadContent( + new EditContext() + { + ContentStore = ApplicationController.Instance.Library.PlatingHistory, + SourceItem = libraryItem + }); + } + + public async Task LoadContent(EditContext editContext) + { + // Make sure we don't have a selection + this.Scene.SelectedItem = null; + + // Store + this.EditContext = editContext; + + var contentInfo = editContext.SourceItem as ILibraryAsset; + if (contentInfo != null) + { + this.ContentType = contentInfo.ContentType; + } + + await this.LoadIntoCurrent(editContext); + } + + /// + /// Load content from the given EditContext into the current one + /// + /// + /// + public async Task LoadIntoCurrent(EditContext editContext) + { + // Load + if (editContext.SourceItem is ILibraryAssetStream contentStream + && contentStream.ContentType == "gcode") + { + using (var task = await contentStream.GetStream(null)) + { + await LoadGCodeContent(task.Stream); + } + + this.Scene.Children.Modify(children => children.Clear()); + + editContext.FreezeGCode = true; + } + else + { + // Load last item or fall back to empty if unsuccessful + var content = await editContext.SourceItem.CreateContent(null) ?? new Object3D(); + this.Scene.Load(content); + } + + // Notify + this.SceneLoaded?.Invoke(this, null); + } + + public async Task LoadGCodeContent(Stream stream) + { + await ApplicationController.Instance.Tasks.Execute("Loading G-Code".Localize(), (reporter, cancellationToken) => + { + var progressStatus = new ProgressStatus(); + reporter.Report(progressStatus); + + this.LoadGCode(stream, cancellationToken, (progress0To1, status) => + { + progressStatus.Status = status; + progressStatus.Progress0To1 = progress0To1; + reporter.Report(progressStatus); + }); + + return Task.CompletedTask; + }); + } + + internal void ClearPlate() + { + // Clear existing + this.LoadedGCode = null; + this.GCodeRenderer = null; + + // Switch back to Model view on ClearPlate + if (this.Printer != null) + { + this.Printer.ViewState.ViewMode = PartViewMode.Model; + } + + // Load + this.LoadEmptyContent( + new EditContext() + { + ContentStore = historyContainer, + SourceItem = historyContainer.NewPlatingItem() + }); + } + + public InsertionGroupObject3D AddToPlate(IEnumerable itemsToAdd) + { + InsertionGroupObject3D insertionGroup = null; + + var context = ApplicationController.Instance.DragDropData; + var scene = context.SceneContext.Scene; + scene.Children.Modify(list => + { + list.Add( + insertionGroup = new InsertionGroupObject3D( + itemsToAdd, + context.View3DWidget, + scene, + (Printer != null) ? Printer.Bed.BedCenter : Vector2.Zero, + (item, itemsToAvoid) => + { + PlatingHelper.MoveToOpenPositionRelativeGroup(item, itemsToAvoid); + })); + }); + + return insertionGroup; + } + + /// + /// Loads content to the bed and prepares edit/persistence context for use + /// + /// + /// + public async Task LoadPlateFromHistory() + { + await this.LoadContent(new EditContext() + { + ContentStore = historyContainer, + SourceItem = historyContainer.GetLastPlateOrNew() + }); + } + + public async Task StashAndPrintGCode(ILibraryItem libraryItem) + { + // Clear plate + this.ClearPlate(); + + // Add content + await this.LoadContent( + new EditContext() + { + SourceItem = libraryItem, + // No content store for GCode + ContentStore = null + }); + + // Slice and print + await ApplicationController.Instance.PrintPart( + this.EditContext, + this.Printer, + null, + CancellationToken.None); + } + + public async Task StashAndPrint(IEnumerable selectedLibraryItems) + { + // Clear plate + this.ClearPlate(); + + // Add content + var insertionGroup = this.AddToPlate(selectedLibraryItems); + await insertionGroup.LoadingItemsTask; + + // Persist changes + await this.SaveChanges(null, CancellationToken.None); + + // Slice and print + await ApplicationController.Instance.PrintPart( + this.EditContext, + this.Printer, + null, + CancellationToken.None); + } + + private GCodeFile loadedGCode; + public GCodeFile LoadedGCode + { + get => loadedGCode; + private set + { + if (loadedGCode != value) + { + loadedGCode = value; + LoadedGCodeChanged?.Invoke(null, null); + } + } + } + + internal void EnsureGCodeLoaded() + { + if (this.LoadedGCode == null + && File.Exists(this.EditContext?.GCodeFilePath)) + { + UiThread.RunOnIdle(async () => + { + using (var stream = File.OpenRead(this.EditContext.GCodeFilePath)) + { + await LoadGCodeContent(stream); + } + }); + } + } + + public WorldView World { get; } = new WorldView(0, 0); + + public double BuildHeight { get; internal set; } + public Vector3 ViewerVolume { get; internal set; } + public Vector2 BedCenter { get; internal set; } = Vector2.Zero; + public BedShape BedShape { get; internal set; } + + // TODO: Make assignment private, wire up post slicing initialization here + public GCodeRenderer GCodeRenderer { get; set; } + + private int _activeLayerIndex; + public int ActiveLayerIndex + { + get => _activeLayerIndex; + set + { + if (_activeLayerIndex != value) + { + _activeLayerIndex = value; + + // Clamp activeLayerIndex to valid range + if (this.GCodeRenderer == null || _activeLayerIndex < 0) + { + _activeLayerIndex = 0; + } + else if (_activeLayerIndex >= this.LoadedGCode.LayerCount) + { + _activeLayerIndex = this.LoadedGCode.LayerCount - 1; + } + + // When the active layer changes we update the selected range accordingly - constrain to applicable values + if (this.RenderInfo != null) + { + // TODO: Unexpected that rendering layer 2 requires that we set the range to 0-3. Seems like model should be updated to allow 0-2 to mean render up to layer 2 + this.RenderInfo.EndLayerIndex = Math.Min(this.LoadedGCode == null ? 0 : this.LoadedGCode.LayerCount, Math.Max(_activeLayerIndex + 1, 1)); + } + + ActiveLayerChanged?.Invoke(this, null); + } + } + } + + public InteractiveScene Scene { get; } = new InteractiveScene(); + + public GCodeRenderInfo RenderInfo { get; set; } + + private Mesh _bedMesh; + public Mesh Mesh + { + get + { + if (_bedMesh == null) + { + + // Load bed and build volume meshes + (_bedMesh, _buildVolumeMesh) = BedMeshGenerator.CreatePrintBedAndVolume(Printer); + + Task.Run(() => + { + try + { + string url = Printer.Settings.GetValue("PrinterShapeUrl"); + string extension = Printer.Settings.GetValue("PrinterShapeExtension"); + + if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(extension)) + { + return; + } + + using (var stream = ApplicationController.Instance.LoadHttpAsset(url)) + { + var mesh = Object3D.Load(stream, extension, CancellationToken.None).Mesh; + + BspNode bspTree = null; + + // if there is a cached bsp tree load it + var meshHashCode = mesh.GetLongHashCode(); + string cachePath = ApplicationController.CacheablePath("MeshBspData", $"{meshHashCode}.bsp"); + if (File.Exists(cachePath)) + { + JsonConvert.DeserializeObject(File.ReadAllText(cachePath)); + } + else + { + // else calculate it + bspTree = FaceBspTree.Create(mesh, 20, true); + // and save it + File.WriteAllText(cachePath, JsonConvert.SerializeObject(bspTree)); + } + + // set the mesh to use the new tree + UiThread.RunOnIdle(() => + { + mesh.FaceBspTree = bspTree; + this.PrinterShape = mesh; + + // TODO: Need to send a notification that the mesh changed so the UI can pickup and render + }); + } + } + catch { } + }); + } + + return _bedMesh; + } + } + + private Mesh _buildVolumeMesh; + + public Mesh BuildVolumeMesh => _buildVolumeMesh; + + public bool EditableScene + { + get => this.EditContext?.FreezeGCode != true; + } + + public string ContentType { get; private set; } + + internal void RenderGCode3D(DrawEventArgs e) + { + if (this.RenderInfo != null) + { + // If needed, update the RenderType flags to match to current user selection + if (RendererOptions.IsDirty) + { + this.RenderInfo.RefreshRenderType(); + RendererOptions.IsDirty = false; + } + + this.GCodeRenderer.Render3D(this.RenderInfo, e); + } + } + + public void LoadGCode(string filePath, CancellationToken cancellationToken, Action progressReporter) + { + if (File.Exists(filePath)) + { + using (var stream = File.OpenRead(filePath)) + { + this.LoadGCode(stream, cancellationToken, progressReporter); + } + } + } + + private RenderType GetRenderType() + { + var options = this.RendererOptions; + + RenderType renderType = RenderType.Extrusions; + + if (options.RenderMoves) + { + renderType |= RenderType.Moves; + } + if (options.RenderRetractions) + { + renderType |= RenderType.Retractions; + } + + if (options.GCodeLineColorStyle == "Speeds") + { + renderType |= RenderType.SpeedColors; + } + else if (options.GCodeLineColorStyle != "Materials") + { + renderType |= RenderType.GrayColors; + } + + if (options.SimulateExtrusion) + { + renderType |= RenderType.SimulateExtrusion; + } + if (options.TransparentExtrusion) + { + renderType |= RenderType.TransparentExtrusion; + } + if (options.HideExtruderOffsets) + { + renderType |= RenderType.HideExtruderOffsets; + } + + return renderType; + } + + public void LoadGCode(Stream stream, CancellationToken cancellationToken, Action progressReporter) + { + var settings = this.Printer.Settings; + var maxAcceleration = settings.GetValue(SettingsKey.max_acceleration); + var maxVelocity = settings.GetValue(SettingsKey.max_velocity); + var jerkVelocity = settings.GetValue(SettingsKey.jerk_velocity); + var multiplier = settings.GetValue(SettingsKey.print_time_estimate_multiplier) / 100.0; + + var loadedGCode = GCodeMemoryFile.Load(stream, + new Vector4(maxAcceleration, maxAcceleration, maxAcceleration, maxAcceleration), + new Vector4(maxVelocity, maxVelocity, maxVelocity, maxVelocity), + new Vector4(jerkVelocity, jerkVelocity, jerkVelocity, jerkVelocity), + new Vector4(multiplier, multiplier, multiplier, multiplier), + cancellationToken, progressReporter); + + this.GCodeRenderer = new GCodeRenderer(loadedGCode) + { + Gray = AppContext.Theme.IsDarkTheme ? Color.DarkGray : Color.Gray + }; + + this.RenderInfo = new GCodeRenderInfo( + 0, + // Renderer requires endLayerIndex to be desiredLayer+1: to render layer zero we set endLayerIndex to 1 + Math.Max(1, this.ActiveLayerIndex + 1), + Agg.Transform.Affine.NewIdentity(), + 1, + 0, + 1, + new Vector2[] + { + settings.Helpers.ExtruderOffset(0), + settings.Helpers.ExtruderOffset(1) + }, + this.GetRenderType, + MeshViewerWidget.GetExtruderColor); + + GCodeRenderer.ExtruderWidth = this.Printer.Settings.GetValue(SettingsKey.nozzle_diameter); + + try + { + // TODO: After loading we reprocess the entire document just to compute filament used. If it's a feature we need, seems like it should just be normal step during load and result stored in a property + GCodeRenderer.GCodeFileToDraw?.GetFilamentUsedMm(this.Printer.Settings.GetValue(SettingsKey.filament_diameter)); + } + catch (Exception ex) + { + Debug.Print(ex.Message); + } + + // Assign property causing event and UI load + this.LoadedGCode = loadedGCode; + + // Constrain to max layers + if (this.ActiveLayerIndex > loadedGCode.LayerCount) + { + this.ActiveLayerIndex = loadedGCode.LayerCount; + } + + ActiveLayerChanged?.Invoke(this, null); + } + + public void InvalidateBedMesh() + { + // Invalidate bed mesh cache + _bedMesh = null; + } + + /// + /// Persists modified meshes to assets and saves pending changes back to the EditContext + /// + /// + /// + /// + public async Task SaveChanges(IProgress progress, CancellationToken cancellationToken) + { + var progressStatus = new ProgressStatus() + { + Status = "Saving Changes" + }; + + progress?.Report(progressStatus); + + if (this.Scene.Persistable) + { + await this.Scene.PersistAssets((progress0to1, status) => + { + if (progress != null) + { + progressStatus.Status = status; + progressStatus.Progress0To1 = progress0to1; + progress.Report(progressStatus); + } + }); + + this.EditContext?.Save(this.Scene); + } + } + + public List GetBaseViewOptions() + { + return new List(); + } + } +} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/EditContext.cs b/MatterControlLib/ApplicationView/EditContext.cs new file mode 100644 index 000000000..9ed6fda13 --- /dev/null +++ b/MatterControlLib/ApplicationView/EditContext.cs @@ -0,0 +1,94 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System; +using System.IO; +using MatterControl.Printing; +using MatterHackers.MatterControl.DataStorage; +using MatterHackers.MatterControl.PrintQueue; + +namespace MatterHackers.MatterControl +{ + using MatterHackers.DataConverters3D; + using MatterHackers.MatterControl.Library; + + public class EditContext + { + private ILibraryItem _sourceItem; + + public IContentStore ContentStore { get; set; } + + public ILibraryItem SourceItem + { + get => _sourceItem; + set + { + if (_sourceItem != value) + { + _sourceItem = value; + + if (_sourceItem is FileSystemFileItem fileItem) + { + printItem = new PrintItemWrapper(new PrintItem(fileItem.FileName, fileItem.Path)); + } + } + } + } + + // Natural path + private string gcodePath => printItem?.GetGCodePathAndFileName(); + + // Override path + public string GCodeOverridePath => Path.ChangeExtension(gcodePath, GCodeFile.PostProcessedExtension); + + // Override or natural path + public string GCodeFilePath => (File.Exists(this.GCodeOverridePath)) ? this.GCodeOverridePath : gcodePath; + + public string SourceFilePath => printItem?.FileLocation; + + public bool FreezeGCode { get; set; } + + /// + /// Short term stop gap that should only be used until GCode path helpers, hash code and print recovery components can be extracted + /// + [Obsolete] + internal PrintItemWrapper printItem { get; set; } + + internal void Save(IObject3D scene) + { + if (!this.FreezeGCode) + { + ApplicationController.Instance.Thumbnails.DeleteCache(this.SourceItem); + + // Call save on the provider + this.ContentStore?.Save(this.SourceItem, scene); + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/PrinterConfig.cs b/MatterControlLib/ApplicationView/PrinterConfig.cs new file mode 100644 index 000000000..360c0b97c --- /dev/null +++ b/MatterControlLib/ApplicationView/PrinterConfig.cs @@ -0,0 +1,460 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System; +using System.Threading.Tasks; +using MatterHackers.Agg.UI; +using MatterHackers.MatterControl.SlicerConfiguration; + +namespace MatterHackers.MatterControl +{ + using System.Threading; + using MatterHackers.Agg; + using MatterHackers.Localizations; + using MatterHackers.MatterControl.PrinterCommunication; + using MatterHackers.MatterControl.SlicerConfiguration.MappingClasses; + using MatterHackers.MeshVisualizer; + using MatterHackers.VectorMath; + + public class PrinterConfig : IDisposable + { + MappedSetting[] replaceWithSettingsStrings = null; + + public event EventHandler Disposed; + + public BedConfig Bed { get; } + + public static PrinterConfig EmptyPrinter { get; } = new PrinterConfig(); + + public EngineMappingsMatterSlice EngineMappingsMatterSlice { get; } + + private PrinterConfig() + { + this.Connection = new PrinterConnection(this); + var printer = this; + replaceWithSettingsStrings = new MappedSetting[] + { + // Have a mapping so that MatterSlice while always use a setting that can be set. (the user cannot set first_layer_bedTemperature in MatterSlice) + new AsPercentOfReferenceOrDirect(printer, SettingsKey.first_layer_speed, "first_layer_speed", "infill_speed", 60), + new AsPercentOfReferenceOrDirect(printer, "external_perimeter_speed","external_perimeter_speed", "perimeter_speed", 60), + new AsPercentOfReferenceOrDirect(printer, "raft_print_speed", "raft_print_speed", "infill_speed", 60), + new MappedSetting(printer, SettingsKey.bed_remove_part_temperature,SettingsKey.bed_remove_part_temperature), + new MappedSetting(printer, "bridge_fan_speed","bridge_fan_speed"), + new MappedSetting(printer, "bridge_speed","bridge_speed"), + new MappedSetting(printer, "air_gap_speed", "air_gap_speed"), + new MappedSetting(printer, "extruder_wipe_temperature","extruder_wipe_temperature"), + new MappedSetting(printer, SettingsKey.filament_diameter,SettingsKey.filament_diameter), + new MappedSetting(printer, "first_layer_bed_temperature", SettingsKey.bed_temperature), + new MappedSetting(printer, "first_layer_temperature", SettingsKey.temperature), + new MappedSetting(printer, SettingsKey.max_fan_speed,"max_fan_speed"), + new MappedSetting(printer, SettingsKey.min_fan_speed,"min_fan_speed"), + new MappedSetting(printer, "retract_length","retract_length"), + new MappedSetting(printer, SettingsKey.temperature,SettingsKey.temperature), + new MappedSetting(printer, "z_offset","z_offset"), + new MappedSetting(printer, SettingsKey.bed_temperature,SettingsKey.bed_temperature), + new ScaledSingleNumber(printer, "infill_speed", "infill_speed", 60), + new ScaledSingleNumber(printer, "min_print_speed", "min_print_speed", 60), + new ScaledSingleNumber(printer, "perimeter_speed","perimeter_speed", 60), + new ScaledSingleNumber(printer, "retract_speed","retract_speed", 60), + new ScaledSingleNumber(printer, "support_material_speed","support_material_speed", 60), + new ScaledSingleNumber(printer, "travel_speed", "travel_speed", 60), + new ScaledSingleNumber(printer, SettingsKey.load_filament_speed, SettingsKey.load_filament_speed, 60), + new MappedSetting(printer, SettingsKey.trim_filament_markdown, SettingsKey.trim_filament_markdown), + new MappedSetting(printer, SettingsKey.insert_filament_markdown2, SettingsKey.insert_filament_markdown2), + new MappedSetting(printer, SettingsKey.running_clean_markdown2, SettingsKey.running_clean_markdown2), + }; + + EngineMappingsMatterSlice = new EngineMappingsMatterSlice(this); + } + + public PrinterConfig(PrinterSettings settings) + : this() + { + this.Bed = new BedConfig(ApplicationController.Instance.Library.PlatingHistory, this); + this.ViewState = new PrinterViewState(); + + // Need a way to hook up all the callbacks that exist on a given connection + DoConnectionBinding(); + + this.Settings = settings; + this.Settings.printer = this; + + this.Settings.SettingChanged += Printer_SettingChanged; + this.Disposed -= Printer_SettingChanged; + + void PrintFinished(object s, EventArgs e) + { + // clear single use setting on print completion + foreach (var keyValue in this.Settings.BaseLayer) + { + string currentValue = this.Settings.GetValue(keyValue.Key); + + bool valueIsClear = currentValue == "0" | currentValue == ""; + + SliceSettingData data = SettingsOrganizer.Instance.GetSettingsData(keyValue.Key); + if (data?.ResetAtEndOfPrint == true && !valueIsClear) + { + this.Settings.ClearValue(keyValue.Key); + } + } + } + this.Connection.PrintFinished += PrintFinished; + this.Disposed += (s, e) => this.Connection.PrintFinished -= PrintFinished; + + + if (!string.IsNullOrEmpty(this.Settings.GetValue(SettingsKey.baud_rate))) + { + this.Connection.BaudRate = this.Settings.GetValue(SettingsKey.baud_rate); + } + this.Connection.ConnectGCode = this.Settings.GetValue(SettingsKey.connect_gcode); + this.Connection.CancelGCode = this.Settings.GetValue(SettingsKey.cancel_gcode); + this.Connection.EnableNetworkPrinting = this.Settings.GetValue(SettingsKey.enable_network_printing); + this.Connection.AutoReleaseMotors = this.Settings.GetValue(SettingsKey.auto_release_motors); + this.Connection.RecoveryIsEnabled = this.Settings.GetValue(SettingsKey.recover_is_enabled); + this.Connection.ExtruderCount = this.Settings.GetValue(SettingsKey.extruder_count); + this.Connection.SendWithChecksum = this.Settings.GetValue(SettingsKey.send_with_checksum); + this.Connection.ReadLineReplacementString = this.Settings.GetValue(SettingsKey.read_regex); + } + + public string ReplaceMacroValues(string gcodeWithMacros) + { + foreach (MappedSetting mappedSetting in replaceWithSettingsStrings) + { + // first check if this setting is anywhere in the line + if (gcodeWithMacros.Contains(mappedSetting.CanonicalSettingsName)) + { + { + // do the replacement with {} (curly brackets) + string thingToReplace = "{" + "{0}".FormatWith(mappedSetting.CanonicalSettingsName) + "}"; + gcodeWithMacros = gcodeWithMacros.Replace(thingToReplace, mappedSetting.Value); + } + // do the replacement with [] (square brackets) Slic3r uses only square brackets + { + string thingToReplace = "[" + "{0}".FormatWith(mappedSetting.CanonicalSettingsName) + "]"; + gcodeWithMacros = gcodeWithMacros.Replace(thingToReplace, mappedSetting.Value); + } + } + } + + return gcodeWithMacros; + } + + private void DoConnectionBinding() + { + // show countdown for turning off heat if required + this.Connection.TemporarilyHoldingTemp += ApplicationController.Instance.Connection_TemporarilyHoldingTemp; + this.Disposed += (s, e) => this.Connection.TemporarilyHoldingTemp -= ApplicationController.Instance.Connection_TemporarilyHoldingTemp; + + // hook up error reporting feedback + this.Connection.ErrorReported += ApplicationController.Instance.Connection_ErrorReported; + this.Disposed += (s, e) => this.Connection.ErrorReported -= ApplicationController.Instance.Connection_ErrorReported; + + // show ui for setup if needed + void ConnectionSucceeded(object s, EventArgs e) + { + if (s is PrinterConfig printer) + { + ApplicationController.Instance.RunAnyRequiredPrinterSetup(printer, ApplicationController.Instance.Theme); + } + } + this.Connection.ConnectionSucceeded += ConnectionSucceeded; + this.Disposed += (s, e) => this.Connection.ConnectionSucceeded -= ConnectionSucceeded; + + // show heating status messages + bool waitingForBedHeat = false; + bool waitingForExtruderHeat = false; + double heatDistance = 0; + double heatStart = 0; + + void CommunicationStateChanged(object s, EventArgs e) + { + var printerConnection = this.Connection; + + if (printerConnection.PrinterIsPrinting || printerConnection.PrinterIsPaused) + { + switch (printerConnection.DetailedPrintingState) + { + case DetailedPrintingState.HeatingBed: + ApplicationController.Instance.Tasks.Execute( + "Heating Bed".Localize(), + (reporter, cancellationToken) => + { + waitingForBedHeat = true; + waitingForExtruderHeat = false; + + var progressStatus = new ProgressStatus(); + heatStart = printerConnection.ActualBedTemperature; + heatDistance = Math.Abs(printerConnection.TargetBedTemperature - heatStart); + + while (heatDistance > 0 && waitingForBedHeat) + { + var remainingDistance = Math.Abs(printerConnection.TargetBedTemperature - printerConnection.ActualBedTemperature); + progressStatus.Status = $"Heating Bed ({printerConnection.ActualBedTemperature:0}/{printerConnection.TargetBedTemperature:0})"; + progressStatus.Progress0To1 = (heatDistance - remainingDistance) / heatDistance; + reporter.Report(progressStatus); + Thread.Sleep(10); + } + + return Task.CompletedTask; + }, + new RunningTaskOptions() + { + ReadOnlyReporting = true + }); + break; + + case DetailedPrintingState.HeatingExtruder: + ApplicationController.Instance.Tasks.Execute( + "Heating Extruder".Localize(), + (reporter, cancellationToken) => + { + waitingForBedHeat = false; + waitingForExtruderHeat = true; + + var progressStatus = new ProgressStatus(); + + heatStart = printerConnection.GetActualHotendTemperature(0); + heatDistance = Math.Abs(printerConnection.GetTargetHotendTemperature(0) - heatStart); + + while (heatDistance > 0 && waitingForExtruderHeat) + { + var currentDistance = Math.Abs(printerConnection.GetTargetHotendTemperature(0) - printerConnection.GetActualHotendTemperature(0)); + progressStatus.Progress0To1 = (heatDistance - currentDistance) / heatDistance; + progressStatus.Status = $"Heating Extruder ({printerConnection.GetActualHotendTemperature(0):0}/{printerConnection.GetTargetHotendTemperature(0):0})"; + reporter.Report(progressStatus); + Thread.Sleep(1000); + } + + return Task.CompletedTask; + }, + new RunningTaskOptions() + { + ReadOnlyReporting = true + }); + break; + + case DetailedPrintingState.HomingAxis: + case DetailedPrintingState.Printing: + default: + // clear any existing waiting states + waitingForBedHeat = false; + waitingForExtruderHeat = false; + break; + } + } + else + { + // turn of any running temp feedback tasks + waitingForBedHeat = false; + waitingForExtruderHeat = false; + } + } + this.Connection.CommunicationStateChanged += CommunicationStateChanged; + this.Disposed += (s, e) => this.Connection.CommunicationStateChanged -= CommunicationStateChanged; + + + void Printer_SettingChanged(object s, EventArgs e) + { + if (e is StringEventArgs stringArg + && SettingsOrganizer.SettingsData.TryGetValue(stringArg.Data, out SliceSettingData settingsData) + && settingsData.ReloadUiWhenChanged) + { + UiThread.RunOnIdle(ApplicationController.Instance.ReloadAll); + } + + // clean up profile manager InventoryTreeView + ProfileManager.SettingsChanged(s, e); + } + this.Settings.SettingChanged += Printer_SettingChanged; + this.Disposed += (s, e) => this.Settings.SettingChanged -= Printer_SettingChanged; + } + + public PrinterViewState ViewState { get; } + + private PrinterSettings _settings = PrinterSettings.Empty; + public PrinterSettings Settings + { + get => _settings; + private set + { + if (_settings != value) + { + _settings = value; + this.ReloadSettings(); + this.Bed.InvalidateBedMesh(); + } + } + } + + public PrinterConnection Connection { get; private set; } + + public string PrinterConnectionStatus + { + get + { + switch (this.Connection.CommunicationState) + { + case CommunicationStates.Disconnected: + return "Not Connected".Localize(); + + case CommunicationStates.Disconnecting: + return "Disconnecting".Localize(); + + case CommunicationStates.AttemptingToConnect: + return "Connecting".Localize() + "..."; + + case CommunicationStates.ConnectionLost: + return "Connection Lost".Localize(); + + case CommunicationStates.FailedToConnect: + return "Unable to Connect".Localize(); + + case CommunicationStates.Connected: + return "Connected".Localize(); + + case CommunicationStates.PreparingToPrint: + return "Preparing To Print".Localize(); + + case CommunicationStates.Printing: + switch (this.Connection.DetailedPrintingState) + { + case DetailedPrintingState.HomingAxis: + return "Homing".Localize(); + + case DetailedPrintingState.HeatingBed: + return "Waiting for Bed to Heat to".Localize() + $" {this.Connection.TargetBedTemperature}°C"; + + case DetailedPrintingState.HeatingExtruder: + return "Waiting for Extruder to Heat to".Localize() + $" {this.Connection.GetTargetHotendTemperature(0)}°C"; + + case DetailedPrintingState.Printing: + default: + return "Printing".Localize(); + } + + case CommunicationStates.PrintingFromSd: + return "Printing From SD Card".Localize(); + + case CommunicationStates.Paused: + return "Paused".Localize(); + + case CommunicationStates.FinishedPrint: + return "Finished Print".Localize(); + + default: + throw new NotImplementedException("Make sure every status returns the correct connected state."); + } + } + } + + public void SwapToSettings(PrinterSettings printerSettings) + { + _settings = printerSettings; + + // TODO: Why reload all after swap? We need to rebuild the printer tab only and should have messaging to do so... + ApplicationController.Instance.ReloadAll(); + } + + private void ReloadSettings() + { + this.Bed.BuildHeight = this.Settings.GetValue(SettingsKey.build_height); + this.Bed.ViewerVolume = new Vector3(this.Settings.GetValue(SettingsKey.bed_size), this.Bed.BuildHeight); + this.Bed.BedCenter = this.Settings.GetValue(SettingsKey.print_center); + this.Bed.BedShape = this.Settings.GetValue(SettingsKey.bed_shape); + } + + private void Printer_SettingChanged(object sender, EventArgs e) + { + if (e is StringEventArgs stringEvent) + { + if (stringEvent.Data == SettingsKey.bed_size + || stringEvent.Data == SettingsKey.print_center + || stringEvent.Data == SettingsKey.build_height + || stringEvent.Data == SettingsKey.bed_shape) + { + this.ReloadSettings(); + this.Bed.InvalidateBedMesh(); + } + + // Sync settings changes to printer connection + switch(stringEvent.Data) + { + case SettingsKey.feedrate_ratio: + this.Connection.FeedRateRatio = this.Settings.GetValue(SettingsKey.feedrate_ratio); + break; + + case SettingsKey.baud_rate: + if (!string.IsNullOrEmpty(this.Settings.GetValue(SettingsKey.baud_rate))) + { + this.Connection.BaudRate = this.Settings.GetValue(SettingsKey.baud_rate); + } + break; + + case SettingsKey.connect_gcode: + this.Connection.ConnectGCode = this.Settings.GetValue(SettingsKey.connect_gcode); + break; + + case SettingsKey.cancel_gcode: + this.Connection.CancelGCode = this.Settings.GetValue(SettingsKey.cancel_gcode); + break; + + case SettingsKey.enable_network_printing: + this.Connection.EnableNetworkPrinting = this.Settings.GetValue(SettingsKey.enable_network_printing); + break; + + case SettingsKey.auto_release_motors: + this.Connection.AutoReleaseMotors = this.Settings.GetValue(SettingsKey.auto_release_motors); + break; + + case SettingsKey.recover_is_enabled: + this.Connection.RecoveryIsEnabled = this.Settings.GetValue(SettingsKey.recover_is_enabled); + break; + + case SettingsKey.extruder_count: + this.Connection.ExtruderCount = this.Settings.GetValue(SettingsKey.extruder_count); + break; + + case SettingsKey.send_with_checksum: + this.Connection.SendWithChecksum = this.Settings.GetValue(SettingsKey.send_with_checksum); + break; + + case SettingsKey.read_regex: + this.Connection.ReadLineReplacementString = this.Settings.GetValue(SettingsKey.read_regex); + break; + } + } + } + + public void Dispose() + { + Connection.Dispose(); + Disposed?.Invoke(this, null); + } + } +} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/PrinterModels.cs b/MatterControlLib/ApplicationView/PrinterModels.cs deleted file mode 100644 index 5b6333715..000000000 --- a/MatterControlLib/ApplicationView/PrinterModels.cs +++ /dev/null @@ -1,1404 +0,0 @@ -/* -Copyright (c) 2018, Lars Brubaker, John Lewin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those -of the authors and should not be interpreted as representing official policies, -either expressed or implied, of the FreeBSD Project. -*/ - -using System; -using System.Diagnostics; -using System.IO; -using System.Threading.Tasks; -using MatterControl.Printing; -using MatterHackers.Agg.UI; -using MatterHackers.MatterControl.DataStorage; -using MatterHackers.MatterControl.PrintQueue; -using MatterHackers.MatterControl.SlicerConfiguration; -using Newtonsoft.Json; - -namespace MatterHackers.MatterControl -{ - using System.Collections.Generic; - using System.ComponentModel; - using System.Threading; - using MatterHackers.Agg; - using MatterHackers.DataConverters3D; - using MatterHackers.GCodeVisualizer; - using MatterHackers.Localizations; - using MatterHackers.MatterControl.Library; - using MatterHackers.MatterControl.PartPreviewWindow; - using MatterHackers.MatterControl.PrinterCommunication; - using MatterHackers.MatterControl.PrintLibrary; - using MatterHackers.MeshVisualizer; - using MatterHackers.PolygonMesh; - using MatterHackers.RenderOpenGl; - using MatterHackers.VectorMath; - - public class BedConfig - { - public event EventHandler ActiveLayerChanged; - - public event EventHandler LoadedGCodeChanged; - - public event EventHandler SceneLoaded; - - public View3DConfig RendererOptions { get; } = new View3DConfig(); - - public PrinterConfig Printer { get; set; } - - public EditContext EditContext { get; private set; } - - public Mesh PrinterShape { get; private set; } - - public SceneContextViewState ViewState { get; } - - private HistoryContainerBase historyContainer; - - public BedConfig(HistoryContainerBase historyContainer, PrinterConfig printer = null) - { - this.historyContainer = historyContainer; - this.Printer = printer; - this.ViewState = new SceneContextViewState(this); - } - - public void LoadEmptyContent(EditContext editContext) - { - // Make sure we don't have a selection - this.Scene.SelectedItem = null; - - this.EditContext = editContext; - this.ContentType = "mcx"; - - this.Scene.Children.Modify(children => children.Clear()); - - this.Scene.Load(new Object3D()); - - // Notify - this.SceneLoaded?.Invoke(this, null); - } - - public Task LoadLibraryContent(ILibraryItem libraryItem) - { - return this.LoadContent( - new EditContext() - { - ContentStore = ApplicationController.Instance.Library.PlatingHistory, - SourceItem = libraryItem - }); - } - - public async Task LoadContent(EditContext editContext) - { - // Make sure we don't have a selection - this.Scene.SelectedItem = null; - - // Store - this.EditContext = editContext; - - var contentInfo = editContext.SourceItem as ILibraryAsset; - if (contentInfo != null) - { - this.ContentType = contentInfo.ContentType; - } - - await this.LoadIntoCurrent(editContext); - } - - /// - /// Load content from the given EditContext into the current one - /// - /// - /// - public async Task LoadIntoCurrent(EditContext editContext) - { - // Load - if (editContext.SourceItem is ILibraryAssetStream contentStream - && contentStream.ContentType == "gcode") - { - using (var task = await contentStream.GetStream(null)) - { - await LoadGCodeContent(task.Stream); - } - - this.Scene.Children.Modify(children => children.Clear()); - - editContext.FreezeGCode = true; - } - else - { - // Load last item or fall back to empty if unsuccessful - var content = await editContext.SourceItem.CreateContent(null) ?? new Object3D(); - this.Scene.Load(content); - } - - // Notify - this.SceneLoaded?.Invoke(this, null); - } - - public async Task LoadGCodeContent(Stream stream) - { - await ApplicationController.Instance.Tasks.Execute("Loading G-Code".Localize(), (reporter, cancellationToken) => - { - var progressStatus = new ProgressStatus(); - reporter.Report(progressStatus); - - this.LoadGCode(stream, cancellationToken, (progress0To1, status) => - { - progressStatus.Status = status; - progressStatus.Progress0To1 = progress0To1; - reporter.Report(progressStatus); - }); - - return Task.CompletedTask; - }); - } - - internal void ClearPlate() - { - // Clear existing - this.LoadedGCode = null; - this.GCodeRenderer = null; - - // Switch back to Model view on ClearPlate - if (this.Printer != null) - { - this.Printer.ViewState.ViewMode = PartViewMode.Model; - } - - // Load - this.LoadEmptyContent( - new EditContext() - { - ContentStore = historyContainer, - SourceItem = historyContainer.NewPlatingItem() - }); - } - - public InsertionGroupObject3D AddToPlate(IEnumerable itemsToAdd) - { - InsertionGroupObject3D insertionGroup = null; - - var context = ApplicationController.Instance.DragDropData; - var scene = context.SceneContext.Scene; - scene.Children.Modify(list => - { - list.Add( - insertionGroup = new InsertionGroupObject3D( - itemsToAdd, - context.View3DWidget, - scene, - (Printer != null) ? Printer.Bed.BedCenter : Vector2.Zero, - (item, itemsToAvoid) => - { - PlatingHelper.MoveToOpenPositionRelativeGroup(item, itemsToAvoid); - })); - }); - - return insertionGroup; - } - - /// - /// Loads content to the bed and prepares edit/persistence context for use - /// - /// - /// - public async Task LoadPlateFromHistory() - { - await this.LoadContent(new EditContext() - { - ContentStore = historyContainer, - SourceItem = historyContainer.GetLastPlateOrNew() - }); - } - - public async Task StashAndPrintGCode(ILibraryItem libraryItem) - { - // Clear plate - this.ClearPlate(); - - // Add content - await this.LoadContent( - new EditContext() - { - SourceItem = libraryItem, - // No content store for GCode - ContentStore = null - }); - - // Slice and print - await ApplicationController.Instance.PrintPart( - this.EditContext, - this.Printer, - null, - CancellationToken.None); - } - - public async Task StashAndPrint(IEnumerable selectedLibraryItems) - { - // Clear plate - this.ClearPlate(); - - // Add content - var insertionGroup = this.AddToPlate(selectedLibraryItems); - await insertionGroup.LoadingItemsTask; - - // Persist changes - await this.SaveChanges(null, CancellationToken.None); - - // Slice and print - await ApplicationController.Instance.PrintPart( - this.EditContext, - this.Printer, - null, - CancellationToken.None); - } - - private GCodeFile loadedGCode; - public GCodeFile LoadedGCode - { - get => loadedGCode; - private set - { - if (loadedGCode != value) - { - loadedGCode = value; - LoadedGCodeChanged?.Invoke(null, null); - } - } - } - - internal void EnsureGCodeLoaded() - { - if (this.LoadedGCode == null - && File.Exists(this.EditContext?.GCodeFilePath)) - { - UiThread.RunOnIdle(async () => - { - using (var stream = File.OpenRead(this.EditContext.GCodeFilePath)) - { - await LoadGCodeContent(stream); - } - }); - } - } - - public WorldView World { get; } = new WorldView(0, 0); - - public double BuildHeight { get; internal set; } - public Vector3 ViewerVolume { get; internal set; } - public Vector2 BedCenter { get; internal set; } = Vector2.Zero; - public BedShape BedShape { get; internal set; } - - // TODO: Make assignment private, wire up post slicing initialization here - public GCodeRenderer GCodeRenderer { get; set; } - - private int _activeLayerIndex; - public int ActiveLayerIndex - { - get => _activeLayerIndex; - set - { - if (_activeLayerIndex != value) - { - _activeLayerIndex = value; - - // Clamp activeLayerIndex to valid range - if (this.GCodeRenderer == null || _activeLayerIndex < 0) - { - _activeLayerIndex = 0; - } - else if (_activeLayerIndex >= this.LoadedGCode.LayerCount) - { - _activeLayerIndex = this.LoadedGCode.LayerCount - 1; - } - - // When the active layer changes we update the selected range accordingly - constrain to applicable values - if (this.RenderInfo != null) - { - // TODO: Unexpected that rendering layer 2 requires that we set the range to 0-3. Seems like model should be updated to allow 0-2 to mean render up to layer 2 - this.RenderInfo.EndLayerIndex = Math.Min(this.LoadedGCode == null ? 0 : this.LoadedGCode.LayerCount, Math.Max(_activeLayerIndex + 1, 1)); - } - - ActiveLayerChanged?.Invoke(this, null); - } - } - } - - public InteractiveScene Scene { get; } = new InteractiveScene(); - - public GCodeRenderInfo RenderInfo { get; set; } - - private Mesh _bedMesh; - public Mesh Mesh - { - get - { - if (_bedMesh == null) - { - - // Load bed and build volume meshes - (_bedMesh, _buildVolumeMesh) = BedMeshGenerator.CreatePrintBedAndVolume(Printer); - - Task.Run(() => - { - try - { - string url = Printer.Settings.GetValue("PrinterShapeUrl"); - string extension = Printer.Settings.GetValue("PrinterShapeExtension"); - - if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(extension)) - { - return; - } - - using (var stream = ApplicationController.Instance.LoadHttpAsset(url)) - { - var mesh = Object3D.Load(stream, extension, CancellationToken.None).Mesh; - - BspNode bspTree = null; - - // if there is a cached bsp tree load it - var meshHashCode = mesh.GetLongHashCode(); - string cachePath = ApplicationController.CacheablePath("MeshBspData", $"{meshHashCode}.bsp"); - if (File.Exists(cachePath)) - { - JsonConvert.DeserializeObject(File.ReadAllText(cachePath)); - } - else - { - // else calculate it - bspTree = FaceBspTree.Create(mesh, 20, true); - // and save it - File.WriteAllText(cachePath, JsonConvert.SerializeObject(bspTree)); - } - - // set the mesh to use the new tree - UiThread.RunOnIdle(() => - { - mesh.FaceBspTree = bspTree; - this.PrinterShape = mesh; - - // TODO: Need to send a notification that the mesh changed so the UI can pickup and render - }); - } - } - catch { } - }); - } - - return _bedMesh; - } - } - - private Mesh _buildVolumeMesh; - - public Mesh BuildVolumeMesh => _buildVolumeMesh; - - public bool EditableScene - { - get => this.EditContext?.FreezeGCode != true; - } - - public string ContentType { get; private set; } - - internal void RenderGCode3D(DrawEventArgs e) - { - if (this.RenderInfo != null) - { - // If needed, update the RenderType flags to match to current user selection - if (RendererOptions.IsDirty) - { - this.RenderInfo.RefreshRenderType(); - RendererOptions.IsDirty = false; - } - - this.GCodeRenderer.Render3D(this.RenderInfo, e); - } - } - - public void LoadGCode(string filePath, CancellationToken cancellationToken, Action progressReporter) - { - if (File.Exists(filePath)) - { - using (var stream = File.OpenRead(filePath)) - { - this.LoadGCode(stream, cancellationToken, progressReporter); - } - } - } - - private RenderType GetRenderType() - { - var options = this.RendererOptions; - - RenderType renderType = RenderType.Extrusions; - - if (options.RenderMoves) - { - renderType |= RenderType.Moves; - } - if (options.RenderRetractions) - { - renderType |= RenderType.Retractions; - } - - if (options.GCodeLineColorStyle == "Speeds") - { - renderType |= RenderType.SpeedColors; - } - else if (options.GCodeLineColorStyle != "Materials") - { - renderType |= RenderType.GrayColors; - } - - if (options.SimulateExtrusion) - { - renderType |= RenderType.SimulateExtrusion; - } - if (options.TransparentExtrusion) - { - renderType |= RenderType.TransparentExtrusion; - } - if (options.HideExtruderOffsets) - { - renderType |= RenderType.HideExtruderOffsets; - } - - return renderType; - } - - public void LoadGCode(Stream stream, CancellationToken cancellationToken, Action progressReporter) - { - var settings = this.Printer.Settings; - var maxAcceleration = settings.GetValue(SettingsKey.max_acceleration); - var maxVelocity = settings.GetValue(SettingsKey.max_velocity); - var jerkVelocity = settings.GetValue(SettingsKey.jerk_velocity); - var multiplier = settings.GetValue(SettingsKey.print_time_estimate_multiplier) / 100.0; - - var loadedGCode = GCodeMemoryFile.Load(stream, - new Vector4(maxAcceleration, maxAcceleration, maxAcceleration, maxAcceleration), - new Vector4(maxVelocity, maxVelocity, maxVelocity, maxVelocity), - new Vector4(jerkVelocity, jerkVelocity, jerkVelocity, jerkVelocity), - new Vector4(multiplier, multiplier, multiplier, multiplier), - cancellationToken, progressReporter); - - this.GCodeRenderer = new GCodeRenderer(loadedGCode) - { - Gray = AppContext.Theme.IsDarkTheme ? Color.DarkGray : Color.Gray - }; - - this.RenderInfo = new GCodeRenderInfo( - 0, - // Renderer requires endLayerIndex to be desiredLayer+1: to render layer zero we set endLayerIndex to 1 - Math.Max(1, this.ActiveLayerIndex + 1), - Agg.Transform.Affine.NewIdentity(), - 1, - 0, - 1, - new Vector2[] - { - settings.Helpers.ExtruderOffset(0), - settings.Helpers.ExtruderOffset(1) - }, - this.GetRenderType, - MeshViewerWidget.GetExtruderColor); - - GCodeRenderer.ExtruderWidth = this.Printer.Settings.GetValue(SettingsKey.nozzle_diameter); - - try - { - // TODO: After loading we reprocess the entire document just to compute filament used. If it's a feature we need, seems like it should just be normal step during load and result stored in a property - GCodeRenderer.GCodeFileToDraw?.GetFilamentUsedMm(this.Printer.Settings.GetValue(SettingsKey.filament_diameter)); - } - catch (Exception ex) - { - Debug.Print(ex.Message); - } - - // Assign property causing event and UI load - this.LoadedGCode = loadedGCode; - - // Constrain to max layers - if (this.ActiveLayerIndex > loadedGCode.LayerCount) - { - this.ActiveLayerIndex = loadedGCode.LayerCount; - } - - ActiveLayerChanged?.Invoke(this, null); - } - - public void InvalidateBedMesh() - { - // Invalidate bed mesh cache - _bedMesh = null; - } - - /// - /// Persists modified meshes to assets and saves pending changes back to the EditContext - /// - /// - /// - /// - public async Task SaveChanges(IProgress progress, CancellationToken cancellationToken) - { - var progressStatus = new ProgressStatus() - { - Status = "Saving Changes" - }; - - progress?.Report(progressStatus); - - if (this.Scene.Persistable) - { - await this.Scene.PersistAssets((progress0to1, status) => - { - if (progress != null) - { - progressStatus.Status = status; - progressStatus.Progress0To1 = progress0to1; - progress.Report(progressStatus); - } - }); - - this.EditContext?.Save(this.Scene); - } - } - - public List GetBaseViewOptions() - { - return new List(); - } - } - - public class EditContext - { - private ILibraryItem _sourceItem; - - public IContentStore ContentStore { get; set; } - - public ILibraryItem SourceItem - { - get => _sourceItem; - set - { - if (_sourceItem != value) - { - _sourceItem = value; - - if (_sourceItem is FileSystemFileItem fileItem) - { - printItem = new PrintItemWrapper(new PrintItem(fileItem.FileName, fileItem.Path)); - } - } - } - } - - // Natural path - private string gcodePath => printItem?.GetGCodePathAndFileName(); - - // Override path - public string GCodeOverridePath => Path.ChangeExtension(gcodePath, GCodeFile.PostProcessedExtension); - - // Override or natural path - public string GCodeFilePath => (File.Exists(this.GCodeOverridePath)) ? this.GCodeOverridePath : gcodePath; - - public string SourceFilePath => printItem?.FileLocation; - - public bool FreezeGCode { get; set; } - - /// - /// Short term stop gap that should only be used until GCode path helpers, hash code and print recovery components can be extracted - /// - [Obsolete] - internal PrintItemWrapper printItem { get; set; } - - internal void Save(IObject3D scene) - { - if (!this.FreezeGCode) - { - ApplicationController.Instance.Thumbnails.DeleteCache(this.SourceItem); - - // Call save on the provider - this.ContentStore?.Save(this.SourceItem, scene); - } - } - } - - public class AppViewState - { - public PrintLibraryWidget.ListViewModes LibraryViewMode { get; set; } = PrintLibraryWidget.ListViewModes.IconListView; - } - - public class SceneContextViewState - { - private BedConfig sceneContext; - private RenderTypes renderType = RenderTypes.Outlines; - - public SceneContextViewState(BedConfig sceneContext) - { - this.sceneContext = sceneContext; - - // Make sure the render mode is set correctly - string renderTypeString = UserSettings.Instance.get(UserSettingsKey.defaultRenderSetting); - if (renderTypeString == null) - { - renderTypeString = "Outlines"; - UserSettings.Instance.set(UserSettingsKey.defaultRenderSetting, renderTypeString); - } - - if (Enum.TryParse(renderTypeString, out renderType)) - { - this.RenderType = renderType; - } - } - - public bool ModelView { get; set; } = true; - - public RenderTypes RenderType - { - get => this.ModelView ? renderType : RenderTypes.Shaded; - set - { - if (renderType != value) - { - renderType = value; - - // Persist value - UserSettings.Instance.set(UserSettingsKey.defaultRenderSetting, renderType.ToString()); - - foreach (var renderTransfrom in sceneContext.Scene.VisibleMeshes()) - { - renderTransfrom.Mesh.MarkAsChanged(); - } - } - } - } - - public double SceneTreeRatio - { - get - { - if (double.TryParse(UserSettings.Instance.get(UserSettingsKey.SceneTreeRatio), out double treeRatio)) - { - return treeRatio; - } - - return .75; - } - set - { - UserSettings.Instance.set(UserSettingsKey.SceneTreeRatio, value.ToString()); - } - } - - public double SelectedObjectEditorHeight - { - get - { - if (double.TryParse(UserSettings.Instance.get(UserSettingsKey.SelectedObjectEditorHeight), out double controlHeight)) - { - return Math.Max(controlHeight, 35); - } - - return 120; - } - set - { - var minimumValue = Math.Max(value, 35); - UserSettings.Instance.set(UserSettingsKey.SelectedObjectEditorHeight, minimumValue.ToString()); - } - } - } - - public class PrinterViewState - { - public event EventHandler ViewModeChanged; - - public event EventHandler VisibilityChanged; - - public bool SliceSettingsTabPinned - { - get => UserSettings.Instance.get(UserSettingsKey.SliceSettingsTabPinned) == "true"; - set => UserSettings.Instance.set(UserSettingsKey.SliceSettingsTabPinned, value ? "true" : "false"); - } - - public string SliceSettingsTabKey - { - get => UserSettings.Instance.get(UserSettingsKey.SliceSettingsTabIndex); - set => UserSettings.Instance.set(UserSettingsKey.SliceSettingsTabIndex, value); - } - - public bool DockWindowFloating { get; internal set; } - - double DefaultSliceSettingsWidth => 450; - public double SliceSettingsWidth - { - get - { - double.TryParse(UserSettings.Instance.get(UserSettingsKey.SliceSettingsWidth), out double controlWidth); - if(controlWidth == 0) - { - controlWidth = DefaultSliceSettingsWidth; - } - return controlWidth; - } - set - { - UserSettings.Instance.set(UserSettingsKey.SliceSettingsWidth, value.ToString()); - } - } - - private PartViewMode viewMode = PartViewMode.Model; - public PartViewMode ViewMode - { - get => viewMode; - set - { - if (viewMode != value) - { - // Capture before/after state - var eventArgs = new ViewModeChangedEventArgs() - { - ViewMode = value, - PreviousMode = viewMode - }; - - viewMode = value; - - this.ViewModeChanged?.Invoke(this, eventArgs); - } - } - } - - public bool _configurePrinterVisible = UserSettings.Instance.get(UserSettingsKey.ConfigurePrinterTabVisible) == "true"; - // set the controls to default to visible - public bool _controlsVisible = UserSettings.Instance.get(UserSettingsKey.ControlsTabVisible) != "false"; - public bool _terminalVisible = UserSettings.Instance.get(UserSettingsKey.TerminalTabVisible) == "true"; - - public bool ConfigurePrinterVisible - { - get => _configurePrinterVisible; - set - { - if (_configurePrinterVisible != value) - { - if (value) - { - this.SliceSettingsTabKey = "Printer"; - } - - _configurePrinterVisible = value; - - UserSettings.Instance.set(UserSettingsKey.ConfigurePrinterTabVisible, _configurePrinterVisible ? "true" : "false"); - - VisibilityChanged?.Invoke(this, null); - } - } - } - - public bool ControlsVisible - { - get => _controlsVisible; - set - { - if (_controlsVisible != value) - { - if (value) - { - this.SliceSettingsTabKey = "Controls"; - } - - _controlsVisible = value; - - UserSettings.Instance.set(UserSettingsKey.ControlsTabVisible, _controlsVisible ? "true" : "false"); - - VisibilityChanged?.Invoke(this, null); - } - } - } - - public bool TerminalVisible - { - get => _terminalVisible; - set - { - if (_terminalVisible != value) - { - if (value) - { - this.SliceSettingsTabKey = "Terminal"; - } - - _terminalVisible = value; - - UserSettings.Instance.set(UserSettingsKey.TerminalTabVisible, _terminalVisible ? "true" : "false"); - - VisibilityChanged?.Invoke(this, null); - } - } - } - - public double SelectedObjectPanelWidth - { - get - { - if (double.TryParse(UserSettings.Instance.get(UserSettingsKey.SelectedObjectPanelWidth), out double controlWidth)) - { - return Math.Max(controlWidth, 150); - } - - return 200; - } - set - { - var minimumValue = Math.Max(value, 150); - UserSettings.Instance.set(UserSettingsKey.SelectedObjectPanelWidth, minimumValue.ToString()); - } - } - } - - public class PrinterConfig : IDisposable - { - public event EventHandler Disposed; - - public BedConfig Bed { get; } - - public static PrinterConfig EmptyPrinter { get; } = new PrinterConfig(); - - private PrinterConfig() - { - this.Connection = new PrinterConnection(this); - } - - public PrinterConfig(PrinterSettings settings) - { - this.Bed = new BedConfig(ApplicationController.Instance.Library.PlatingHistory, this); - this.ViewState = new PrinterViewState(); - this.Connection = new PrinterConnection(this); - - // Need a way to hook up all the callbacks that exist on a given connection - DoConnectionBinding(); - - this.Settings = settings; - this.Settings.printer = this; - - this.Settings.SettingChanged += Printer_SettingChanged; - this.Disposed -= Printer_SettingChanged; - - void PrintFinished(object s, EventArgs e) - { - // clear single use setting on print completion - foreach (var keyValue in this.Settings.BaseLayer) - { - string currentValue = this.Settings.GetValue(keyValue.Key); - - bool valueIsClear = currentValue == "0" | currentValue == ""; - - SliceSettingData data = SettingsOrganizer.Instance.GetSettingsData(keyValue.Key); - if (data?.ResetAtEndOfPrint == true && !valueIsClear) - { - this.Settings.ClearValue(keyValue.Key); - } - } - } - this.Connection.PrintFinished += PrintFinished; - this.Disposed += (s, e) => this.Connection.PrintFinished -= PrintFinished; - - - if (!string.IsNullOrEmpty(this.Settings.GetValue(SettingsKey.baud_rate))) - { - this.Connection.BaudRate = this.Settings.GetValue(SettingsKey.baud_rate); - } - this.Connection.ConnectGCode = this.Settings.GetValue(SettingsKey.connect_gcode); - this.Connection.CancelGCode = this.Settings.GetValue(SettingsKey.cancel_gcode); - this.Connection.EnableNetworkPrinting = this.Settings.GetValue(SettingsKey.enable_network_printing); - this.Connection.AutoReleaseMotors = this.Settings.GetValue(SettingsKey.auto_release_motors); - this.Connection.RecoveryIsEnabled = this.Settings.GetValue(SettingsKey.recover_is_enabled); - this.Connection.ExtruderCount = this.Settings.GetValue(SettingsKey.extruder_count); - this.Connection.SendWithChecksum = this.Settings.GetValue(SettingsKey.send_with_checksum); - this.Connection.ReadLineReplacementString = this.Settings.GetValue(SettingsKey.read_regex); - } - - private void DoConnectionBinding() - { - // show countdown for turning off heat if required - this.Connection.TemporarilyHoldingTemp += ApplicationController.Instance.Connection_TemporarilyHoldingTemp; - this.Disposed += (s, e) => this.Connection.TemporarilyHoldingTemp -= ApplicationController.Instance.Connection_TemporarilyHoldingTemp; - - // hook up error reporting feedback - this.Connection.ErrorReported += ApplicationController.Instance.Connection_ErrorReported; - this.Disposed += (s, e) => this.Connection.ErrorReported -= ApplicationController.Instance.Connection_ErrorReported; - - // show ui for setup if needed - void ConnectionSucceeded(object s, EventArgs e) - { - if (s is PrinterConfig printer) - { - ApplicationController.Instance.RunAnyRequiredPrinterSetup(printer, ApplicationController.Instance.Theme); - } - } - this.Connection.ConnectionSucceeded += ConnectionSucceeded; - this.Disposed += (s, e) => this.Connection.ConnectionSucceeded -= ConnectionSucceeded; - - // show heating status messages - bool waitingForBedHeat = false; - bool waitingForExtruderHeat = false; - double heatDistance = 0; - double heatStart = 0; - - void CommunicationStateChanged(object s, EventArgs e) - { - var printerConnection = this.Connection; - - if (printerConnection.PrinterIsPrinting || printerConnection.PrinterIsPaused) - { - switch (printerConnection.DetailedPrintingState) - { - case DetailedPrintingState.HeatingBed: - ApplicationController.Instance.Tasks.Execute( - "Heating Bed".Localize(), - (reporter, cancellationToken) => - { - waitingForBedHeat = true; - waitingForExtruderHeat = false; - - var progressStatus = new ProgressStatus(); - heatStart = printerConnection.ActualBedTemperature; - heatDistance = Math.Abs(printerConnection.TargetBedTemperature - heatStart); - - while (heatDistance > 0 && waitingForBedHeat) - { - var remainingDistance = Math.Abs(printerConnection.TargetBedTemperature - printerConnection.ActualBedTemperature); - progressStatus.Status = $"Heating Bed ({printerConnection.ActualBedTemperature:0}/{printerConnection.TargetBedTemperature:0})"; - progressStatus.Progress0To1 = (heatDistance - remainingDistance) / heatDistance; - reporter.Report(progressStatus); - Thread.Sleep(10); - } - - return Task.CompletedTask; - }, - new RunningTaskOptions() - { - ReadOnlyReporting = true - }); - break; - - case DetailedPrintingState.HeatingExtruder: - ApplicationController.Instance.Tasks.Execute( - "Heating Extruder".Localize(), - (reporter, cancellationToken) => - { - waitingForBedHeat = false; - waitingForExtruderHeat = true; - - var progressStatus = new ProgressStatus(); - - heatStart = printerConnection.GetActualHotendTemperature(0); - heatDistance = Math.Abs(printerConnection.GetTargetHotendTemperature(0) - heatStart); - - while (heatDistance > 0 && waitingForExtruderHeat) - { - var currentDistance = Math.Abs(printerConnection.GetTargetHotendTemperature(0) - printerConnection.GetActualHotendTemperature(0)); - progressStatus.Progress0To1 = (heatDistance - currentDistance) / heatDistance; - progressStatus.Status = $"Heating Extruder ({printerConnection.GetActualHotendTemperature(0):0}/{printerConnection.GetTargetHotendTemperature(0):0})"; - reporter.Report(progressStatus); - Thread.Sleep(1000); - } - - return Task.CompletedTask; - }, - new RunningTaskOptions() - { - ReadOnlyReporting = true - }); - break; - - case DetailedPrintingState.HomingAxis: - case DetailedPrintingState.Printing: - default: - // clear any existing waiting states - waitingForBedHeat = false; - waitingForExtruderHeat = false; - break; - } - } - else - { - // turn of any running temp feedback tasks - waitingForBedHeat = false; - waitingForExtruderHeat = false; - } - } - this.Connection.CommunicationStateChanged += CommunicationStateChanged; - this.Disposed += (s, e) => this.Connection.CommunicationStateChanged -= CommunicationStateChanged; - - - void Printer_SettingChanged(object s, EventArgs e) - { - if (e is StringEventArgs stringArg - && SettingsOrganizer.SettingsData.TryGetValue(stringArg.Data, out SliceSettingData settingsData) - && settingsData.ReloadUiWhenChanged) - { - UiThread.RunOnIdle(ApplicationController.Instance.ReloadAll); - } - - // clean up profile manager InventoryTreeView - ProfileManager.SettingsChanged(s, e); - } - this.Settings.SettingChanged += Printer_SettingChanged; - this.Disposed += (s, e) => this.Settings.SettingChanged -= Printer_SettingChanged; - } - - public PrinterViewState ViewState { get; } - - private PrinterSettings _settings = PrinterSettings.Empty; - public PrinterSettings Settings - { - get => _settings; - private set - { - if (_settings != value) - { - _settings = value; - this.ReloadSettings(); - this.Bed.InvalidateBedMesh(); - } - } - } - - public PrinterConnection Connection { get; private set; } - - public string PrinterConnectionStatus - { - get - { - switch (this.Connection.CommunicationState) - { - case CommunicationStates.Disconnected: - return "Not Connected".Localize(); - - case CommunicationStates.Disconnecting: - return "Disconnecting".Localize(); - - case CommunicationStates.AttemptingToConnect: - return "Connecting".Localize() + "..."; - - case CommunicationStates.ConnectionLost: - return "Connection Lost".Localize(); - - case CommunicationStates.FailedToConnect: - return "Unable to Connect".Localize(); - - case CommunicationStates.Connected: - return "Connected".Localize(); - - case CommunicationStates.PreparingToPrint: - return "Preparing To Print".Localize(); - - case CommunicationStates.Printing: - switch (this.Connection.DetailedPrintingState) - { - case DetailedPrintingState.HomingAxis: - return "Homing".Localize(); - - case DetailedPrintingState.HeatingBed: - return "Waiting for Bed to Heat to".Localize() + $" {this.Connection.TargetBedTemperature}°C"; - - case DetailedPrintingState.HeatingExtruder: - return "Waiting for Extruder to Heat to".Localize() + $" {this.Connection.GetTargetHotendTemperature(0)}°C"; - - case DetailedPrintingState.Printing: - default: - return "Printing".Localize(); - } - - case CommunicationStates.PrintingFromSd: - return "Printing From SD Card".Localize(); - - case CommunicationStates.Paused: - return "Paused".Localize(); - - case CommunicationStates.FinishedPrint: - return "Finished Print".Localize(); - - default: - throw new NotImplementedException("Make sure every status returns the correct connected state."); - } - } - } - - public void SwapToSettings(PrinterSettings printerSettings) - { - _settings = printerSettings; - - // TODO: Why reload all after swap? We need to rebuild the printer tab only and should have messaging to do so... - ApplicationController.Instance.ReloadAll(); - } - - private void ReloadSettings() - { - this.Bed.BuildHeight = this.Settings.GetValue(SettingsKey.build_height); - this.Bed.ViewerVolume = new Vector3(this.Settings.GetValue(SettingsKey.bed_size), this.Bed.BuildHeight); - this.Bed.BedCenter = this.Settings.GetValue(SettingsKey.print_center); - this.Bed.BedShape = this.Settings.GetValue(SettingsKey.bed_shape); - } - - private void Printer_SettingChanged(object sender, EventArgs e) - { - if (e is StringEventArgs stringEvent) - { - if (stringEvent.Data == SettingsKey.bed_size - || stringEvent.Data == SettingsKey.print_center - || stringEvent.Data == SettingsKey.build_height - || stringEvent.Data == SettingsKey.bed_shape) - { - this.ReloadSettings(); - this.Bed.InvalidateBedMesh(); - } - - // Sync settings changes to printer connection - switch(stringEvent.Data) - { - case SettingsKey.feedrate_ratio: - this.Connection.FeedRateRatio = this.Settings.GetValue(SettingsKey.feedrate_ratio); - break; - - case SettingsKey.baud_rate: - if (!string.IsNullOrEmpty(this.Settings.GetValue(SettingsKey.baud_rate))) - { - this.Connection.BaudRate = this.Settings.GetValue(SettingsKey.baud_rate); - } - break; - - case SettingsKey.connect_gcode: - this.Connection.ConnectGCode = this.Settings.GetValue(SettingsKey.connect_gcode); - break; - - case SettingsKey.cancel_gcode: - this.Connection.CancelGCode = this.Settings.GetValue(SettingsKey.cancel_gcode); - break; - - case SettingsKey.enable_network_printing: - this.Connection.EnableNetworkPrinting = this.Settings.GetValue(SettingsKey.enable_network_printing); - break; - - case SettingsKey.auto_release_motors: - this.Connection.AutoReleaseMotors = this.Settings.GetValue(SettingsKey.auto_release_motors); - break; - - case SettingsKey.recover_is_enabled: - this.Connection.RecoveryIsEnabled = this.Settings.GetValue(SettingsKey.recover_is_enabled); - break; - - case SettingsKey.extruder_count: - this.Connection.ExtruderCount = this.Settings.GetValue(SettingsKey.extruder_count); - break; - - case SettingsKey.send_with_checksum: - this.Connection.SendWithChecksum = this.Settings.GetValue(SettingsKey.send_with_checksum); - break; - - case SettingsKey.read_regex: - this.Connection.ReadLineReplacementString = this.Settings.GetValue(SettingsKey.read_regex); - break; - } - } - } - - public void Dispose() - { - Connection.Dispose(); - Disposed?.Invoke(this, null); - } - } - - public class View3DConfig : INotifyPropertyChanged - { - public event PropertyChangedEventHandler PropertyChanged; - - public bool IsDirty { get; internal set; } - - public bool RenderBed - { - get - { - string value = UserSettings.Instance.get(UserSettingsKey.GcodeViewerRenderGrid); - if (value == null) - { - return true; - } - return (value == "True"); - } - set - { - if (this.RenderBed != value) - { - UserSettings.Instance.set(UserSettingsKey.GcodeViewerRenderGrid, value.ToString()); - this.IsDirty = true; - this.OnPropertyChanged(nameof(RenderBed)); - } - } - } - - public bool RenderMoves - { - get => UserSettings.Instance.get(UserSettingsKey.GcodeViewerRenderMoves) == "True"; - set - { - if (this.RenderMoves != value) - { - UserSettings.Instance.set(UserSettingsKey.GcodeViewerRenderMoves, value.ToString()); - this.IsDirty = true; - this.OnPropertyChanged(nameof(RenderMoves)); - } - } - } - - public bool RenderRetractions - { - get => UserSettings.Instance.get(UserSettingsKey.GcodeViewerRenderRetractions) == "True"; - set - { - if (this.RenderRetractions != value) - { - UserSettings.Instance.set(UserSettingsKey.GcodeViewerRenderRetractions, value.ToString()); - this.IsDirty = true; - this.OnPropertyChanged(nameof(RenderRetractions)); - } - } - } - - public string GCodeModelView - { - get => UserSettings.Instance.get(UserSettingsKey.GcodeModelView); - set - { - if (this.GCodeModelView != value) - { - UserSettings.Instance.set(UserSettingsKey.GcodeModelView, value); - this.IsDirty = true; - this.OnPropertyChanged(nameof(GCodeModelView)); - } - } - } - - public string GCodeLineColorStyle - { - get => UserSettings.Instance.get(UserSettingsKey.GCodeLineColorStyle); - set - { - if (this.GCodeLineColorStyle != value) - { - UserSettings.Instance.set(UserSettingsKey.GCodeLineColorStyle, value); - this.IsDirty = true; - this.OnPropertyChanged(nameof(GCodeLineColorStyle)); - } - } - } - - public bool SimulateExtrusion - { - get => UserSettings.Instance.get(UserSettingsKey.GcodeViewerSimulateExtrusion) == "True"; - set - { - if (this.SimulateExtrusion != value) - { - UserSettings.Instance.set(UserSettingsKey.GcodeViewerSimulateExtrusion, value.ToString()); - this.IsDirty = true; - this.OnPropertyChanged(nameof(SimulateExtrusion)); - } - } - } - - public bool TransparentExtrusion - { - get => UserSettings.Instance.get(UserSettingsKey.GcodeViewerTransparentExtrusion) == "True"; - set - { - if (this.TransparentExtrusion != value) - { - UserSettings.Instance.set(UserSettingsKey.GcodeViewerTransparentExtrusion, value.ToString()); - this.IsDirty = true; - this.OnPropertyChanged(nameof(TransparentExtrusion)); - } - } - } - - public bool HideExtruderOffsets - { - get - { - string value = UserSettings.Instance.get(UserSettingsKey.GcodeViewerHideExtruderOffsets); - if (value == null) - { - return true; - } - return (value == "True"); - } - set - { - if (this.HideExtruderOffsets != value) - { - UserSettings.Instance.set(UserSettingsKey.GcodeViewerHideExtruderOffsets, value.ToString()); - this.IsDirty = true; - this.OnPropertyChanged(nameof(HideExtruderOffsets)); - } - } - } - - public bool SyncToPrint - { - get => UserSettings.Instance.get(UserSettingsKey.LayerViewSyncToPrint) == "True"; - set - { - if (this.SyncToPrint != value) - { - UserSettings.Instance.set(UserSettingsKey.LayerViewSyncToPrint, value.ToString()); - this.IsDirty = true; - this.OnPropertyChanged(nameof(SyncToPrint)); - } - } - } - - private bool _renderBuildVolume; - public bool RenderBuildVolume - { - get => _renderBuildVolume; - set - { - if (_renderBuildVolume != value) - { - _renderBuildVolume = value; - this.OnPropertyChanged(nameof(RenderBuildVolume)); - } - } - } - - protected void OnPropertyChanged(string name) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); - } - } -} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/PrinterViewState.cs b/MatterControlLib/ApplicationView/PrinterViewState.cs new file mode 100644 index 000000000..a6d26ea43 --- /dev/null +++ b/MatterControlLib/ApplicationView/PrinterViewState.cs @@ -0,0 +1,182 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System; + +namespace MatterHackers.MatterControl +{ + using MatterHackers.MatterControl.PartPreviewWindow; + + public class PrinterViewState + { + public event EventHandler ViewModeChanged; + + public event EventHandler VisibilityChanged; + + public bool SliceSettingsTabPinned + { + get => UserSettings.Instance.get(UserSettingsKey.SliceSettingsTabPinned) == "true"; + set => UserSettings.Instance.set(UserSettingsKey.SliceSettingsTabPinned, value ? "true" : "false"); + } + + public string SliceSettingsTabKey + { + get => UserSettings.Instance.get(UserSettingsKey.SliceSettingsTabIndex); + set => UserSettings.Instance.set(UserSettingsKey.SliceSettingsTabIndex, value); + } + + public bool DockWindowFloating { get; internal set; } + + double DefaultSliceSettingsWidth => 450; + public double SliceSettingsWidth + { + get + { + double.TryParse(UserSettings.Instance.get(UserSettingsKey.SliceSettingsWidth), out double controlWidth); + if(controlWidth == 0) + { + controlWidth = DefaultSliceSettingsWidth; + } + return controlWidth; + } + set + { + UserSettings.Instance.set(UserSettingsKey.SliceSettingsWidth, value.ToString()); + } + } + + private PartViewMode viewMode = PartViewMode.Model; + public PartViewMode ViewMode + { + get => viewMode; + set + { + if (viewMode != value) + { + // Capture before/after state + var eventArgs = new ViewModeChangedEventArgs() + { + ViewMode = value, + PreviousMode = viewMode + }; + + viewMode = value; + + this.ViewModeChanged?.Invoke(this, eventArgs); + } + } + } + + public bool _configurePrinterVisible = UserSettings.Instance.get(UserSettingsKey.ConfigurePrinterTabVisible) == "true"; + // set the controls to default to visible + public bool _controlsVisible = UserSettings.Instance.get(UserSettingsKey.ControlsTabVisible) != "false"; + public bool _terminalVisible = UserSettings.Instance.get(UserSettingsKey.TerminalTabVisible) == "true"; + + public bool ConfigurePrinterVisible + { + get => _configurePrinterVisible; + set + { + if (_configurePrinterVisible != value) + { + if (value) + { + this.SliceSettingsTabKey = "Printer"; + } + + _configurePrinterVisible = value; + + UserSettings.Instance.set(UserSettingsKey.ConfigurePrinterTabVisible, _configurePrinterVisible ? "true" : "false"); + + VisibilityChanged?.Invoke(this, null); + } + } + } + + public bool ControlsVisible + { + get => _controlsVisible; + set + { + if (_controlsVisible != value) + { + if (value) + { + this.SliceSettingsTabKey = "Controls"; + } + + _controlsVisible = value; + + UserSettings.Instance.set(UserSettingsKey.ControlsTabVisible, _controlsVisible ? "true" : "false"); + + VisibilityChanged?.Invoke(this, null); + } + } + } + + public bool TerminalVisible + { + get => _terminalVisible; + set + { + if (_terminalVisible != value) + { + if (value) + { + this.SliceSettingsTabKey = "Terminal"; + } + + _terminalVisible = value; + + UserSettings.Instance.set(UserSettingsKey.TerminalTabVisible, _terminalVisible ? "true" : "false"); + + VisibilityChanged?.Invoke(this, null); + } + } + } + + public double SelectedObjectPanelWidth + { + get + { + if (double.TryParse(UserSettings.Instance.get(UserSettingsKey.SelectedObjectPanelWidth), out double controlWidth)) + { + return Math.Max(controlWidth, 150); + } + + return 200; + } + set + { + var minimumValue = Math.Max(value, 150); + UserSettings.Instance.set(UserSettingsKey.SelectedObjectPanelWidth, minimumValue.ToString()); + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/SceneContextViewState.cs b/MatterControlLib/ApplicationView/SceneContextViewState.cs new file mode 100644 index 000000000..070d092f0 --- /dev/null +++ b/MatterControlLib/ApplicationView/SceneContextViewState.cs @@ -0,0 +1,117 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System; + +namespace MatterHackers.MatterControl +{ + using MatterHackers.DataConverters3D; + using MatterHackers.RenderOpenGl; + + public class SceneContextViewState + { + private BedConfig sceneContext; + private RenderTypes renderType = RenderTypes.Outlines; + + public SceneContextViewState(BedConfig sceneContext) + { + this.sceneContext = sceneContext; + + // Make sure the render mode is set correctly + string renderTypeString = UserSettings.Instance.get(UserSettingsKey.defaultRenderSetting); + if (renderTypeString == null) + { + renderTypeString = "Outlines"; + UserSettings.Instance.set(UserSettingsKey.defaultRenderSetting, renderTypeString); + } + + if (Enum.TryParse(renderTypeString, out renderType)) + { + this.RenderType = renderType; + } + } + + public bool ModelView { get; set; } = true; + + public RenderTypes RenderType + { + get => this.ModelView ? renderType : RenderTypes.Shaded; + set + { + if (renderType != value) + { + renderType = value; + + // Persist value + UserSettings.Instance.set(UserSettingsKey.defaultRenderSetting, renderType.ToString()); + + foreach (var renderTransfrom in sceneContext.Scene.VisibleMeshes()) + { + renderTransfrom.Mesh.MarkAsChanged(); + } + } + } + } + + public double SceneTreeRatio + { + get + { + if (double.TryParse(UserSettings.Instance.get(UserSettingsKey.SceneTreeRatio), out double treeRatio)) + { + return treeRatio; + } + + return .75; + } + set + { + UserSettings.Instance.set(UserSettingsKey.SceneTreeRatio, value.ToString()); + } + } + + public double SelectedObjectEditorHeight + { + get + { + if (double.TryParse(UserSettings.Instance.get(UserSettingsKey.SelectedObjectEditorHeight), out double controlHeight)) + { + return Math.Max(controlHeight, 35); + } + + return 120; + } + set + { + var minimumValue = Math.Max(value, 35); + UserSettings.Instance.set(UserSettingsKey.SelectedObjectEditorHeight, minimumValue.ToString()); + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/View3DConfig.cs b/MatterControlLib/ApplicationView/View3DConfig.cs new file mode 100644 index 000000000..bd8b8606a --- /dev/null +++ b/MatterControlLib/ApplicationView/View3DConfig.cs @@ -0,0 +1,202 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + + +namespace MatterHackers.MatterControl +{ + using System.ComponentModel; + + public class View3DConfig : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + public bool IsDirty { get; internal set; } + + public bool RenderBed + { + get + { + string value = UserSettings.Instance.get(UserSettingsKey.GcodeViewerRenderGrid); + if (value == null) + { + return true; + } + return (value == "True"); + } + set + { + if (this.RenderBed != value) + { + UserSettings.Instance.set(UserSettingsKey.GcodeViewerRenderGrid, value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(RenderBed)); + } + } + } + + public bool RenderMoves + { + get => UserSettings.Instance.get(UserSettingsKey.GcodeViewerRenderMoves) == "True"; + set + { + if (this.RenderMoves != value) + { + UserSettings.Instance.set(UserSettingsKey.GcodeViewerRenderMoves, value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(RenderMoves)); + } + } + } + + public bool RenderRetractions + { + get => UserSettings.Instance.get(UserSettingsKey.GcodeViewerRenderRetractions) == "True"; + set + { + if (this.RenderRetractions != value) + { + UserSettings.Instance.set(UserSettingsKey.GcodeViewerRenderRetractions, value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(RenderRetractions)); + } + } + } + + public string GCodeModelView + { + get => UserSettings.Instance.get(UserSettingsKey.GcodeModelView); + set + { + if (this.GCodeModelView != value) + { + UserSettings.Instance.set(UserSettingsKey.GcodeModelView, value); + this.IsDirty = true; + this.OnPropertyChanged(nameof(GCodeModelView)); + } + } + } + + public string GCodeLineColorStyle + { + get => UserSettings.Instance.get(UserSettingsKey.GCodeLineColorStyle); + set + { + if (this.GCodeLineColorStyle != value) + { + UserSettings.Instance.set(UserSettingsKey.GCodeLineColorStyle, value); + this.IsDirty = true; + this.OnPropertyChanged(nameof(GCodeLineColorStyle)); + } + } + } + + public bool SimulateExtrusion + { + get => UserSettings.Instance.get(UserSettingsKey.GcodeViewerSimulateExtrusion) == "True"; + set + { + if (this.SimulateExtrusion != value) + { + UserSettings.Instance.set(UserSettingsKey.GcodeViewerSimulateExtrusion, value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(SimulateExtrusion)); + } + } + } + + public bool TransparentExtrusion + { + get => UserSettings.Instance.get(UserSettingsKey.GcodeViewerTransparentExtrusion) == "True"; + set + { + if (this.TransparentExtrusion != value) + { + UserSettings.Instance.set(UserSettingsKey.GcodeViewerTransparentExtrusion, value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(TransparentExtrusion)); + } + } + } + + public bool HideExtruderOffsets + { + get + { + string value = UserSettings.Instance.get(UserSettingsKey.GcodeViewerHideExtruderOffsets); + if (value == null) + { + return true; + } + return (value == "True"); + } + set + { + if (this.HideExtruderOffsets != value) + { + UserSettings.Instance.set(UserSettingsKey.GcodeViewerHideExtruderOffsets, value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(HideExtruderOffsets)); + } + } + } + + public bool SyncToPrint + { + get => UserSettings.Instance.get(UserSettingsKey.LayerViewSyncToPrint) == "True"; + set + { + if (this.SyncToPrint != value) + { + UserSettings.Instance.set(UserSettingsKey.LayerViewSyncToPrint, value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(SyncToPrint)); + } + } + } + + private bool _renderBuildVolume; + public bool RenderBuildVolume + { + get => _renderBuildVolume; + set + { + if (_renderBuildVolume != value) + { + _renderBuildVolume = value; + this.OnPropertyChanged(nameof(RenderBuildVolume)); + } + } + } + + protected void OnPropertyChanged(string name) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); + } + } +} \ No newline at end of file diff --git a/MatterControlLib/PrinterCommunication/Io/PauseHandlingStream.cs b/MatterControlLib/PrinterCommunication/Io/PauseHandlingStream.cs index 7a9223e78..89c25d735 100644 --- a/MatterControlLib/PrinterCommunication/Io/PauseHandlingStream.cs +++ b/MatterControlLib/PrinterCommunication/Io/PauseHandlingStream.cs @@ -258,7 +258,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io private void InjectPauseGCode(string codeToInject) { - codeToInject = GCodeProcessing.ReplaceMacroValues(codeToInject); + codeToInject = printer.ReplaceMacroValues(codeToInject); codeToInject = codeToInject.Replace("\\n", "\n"); string[] lines = codeToInject.Split('\n'); diff --git a/MatterControlLib/PrinterCommunication/Io/QueuedCommandsStream.cs b/MatterControlLib/PrinterCommunication/Io/QueuedCommandsStream.cs index dd24d870f..96cc55bcc 100644 --- a/MatterControlLib/PrinterCommunication/Io/QueuedCommandsStream.cs +++ b/MatterControlLib/PrinterCommunication/Io/QueuedCommandsStream.cs @@ -114,7 +114,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io if (commandQueue.Count > 0) { lineToSend = commandQueue[0]; - lineToSend = GCodeProcessing.ReplaceMacroValues(lineToSend); + lineToSend = printer.ReplaceMacroValues(lineToSend); commandQueue.RemoveAt(0); } } diff --git a/MatterControlLib/SlicerConfiguration/EngineMappingMatterSlice.cs b/MatterControlLib/SlicerConfiguration/EngineMappingMatterSlice.cs new file mode 100644 index 000000000..c92a1d803 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/EngineMappingMatterSlice.cs @@ -0,0 +1,267 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.Agg; +using MatterHackers.MatterControl.SlicerConfiguration.MappingClasses; +using MatterHackers.VectorMath; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace MatterHackers.MatterControl.SlicerConfiguration +{ + public class EngineMappingsMatterSlice + { + /// + /// Application level settings control MatterControl behaviors but aren't used or passed through to the slice engine. Putting settings + /// in this list ensures they show up for all slice engines and the lack of a MappedSetting for the engine guarantees that it won't pass + /// through into the slicer config file + /// + protected HashSet applicationLevelSettings = new HashSet() + { + "enable_fan", + "extruder_wipe_temperature", + "extruders_share_temperature", + "g0", + "layer_to_pause", + "selector_ip_address", + "solid_shell", + "z_homes_to_max", + // TODO: merge the items below into the list above after some validation - setting that weren't previously mapped to Cura but probably should be. + SettingsKey.auto_connect, + SettingsKey.auto_release_motors, + SettingsKey.backup_firmware_before_update, + SettingsKey.baud_rate, + SettingsKey.bed_remove_part_temperature, + SettingsKey.bed_shape, + SettingsKey.bed_size, + SettingsKey.bed_temperature, + SettingsKey.build_height, + SettingsKey.cancel_gcode, + SettingsKey.com_port, + SettingsKey.connect_gcode, + SettingsKey.created_date, + SettingsKey.enable_line_splitting, + SettingsKey.enable_network_printing, + SettingsKey.enable_retractions, + SettingsKey.enable_sailfish_communication, + SettingsKey.filament_cost, + SettingsKey.filament_density, + SettingsKey.filament_has_been_loaded, + SettingsKey.filament_runout_sensor, + SettingsKey.has_fan, + SettingsKey.has_hardware_leveling, + SettingsKey.has_heated_bed, + SettingsKey.has_power_control, + SettingsKey.has_sd_card_reader, + SettingsKey.has_z_probe, + SettingsKey.has_z_servo, + SettingsKey.heat_extruder_before_homing, + SettingsKey.include_firmware_updater, + SettingsKey.insert_filament_markdown2, + SettingsKey.ip_address, + SettingsKey.ip_port, + SettingsKey.laser_speed_025, + SettingsKey.laser_speed_100, + SettingsKey.leveling_sample_points, + SettingsKey.load_filament_length, + SettingsKey.load_filament_speed, + SettingsKey.make, + SettingsKey.model, + SettingsKey.number_of_first_layers, + SettingsKey.pause_gcode, + SettingsKey.print_center, + SettingsKey.print_leveling_probe_start, + SettingsKey.print_leveling_required_to_print, + SettingsKey.print_leveling_solution, + SettingsKey.print_time_estimate_multiplier, + SettingsKey.printer_name, + SettingsKey.probe_has_been_calibrated, + SettingsKey.probe_offset_sample_point, + SettingsKey.progress_reporting, + SettingsKey.read_regex, + SettingsKey.recover_first_layer_speed, + SettingsKey.recover_is_enabled, + SettingsKey.recover_position_before_z_home, + SettingsKey.resume_gcode, + SettingsKey.running_clean_markdown2, + SettingsKey.send_with_checksum, + SettingsKey.show_reset_connection, + SettingsKey.sla_printer, + SettingsKey.temperature, + SettingsKey.trim_filament_markdown, + SettingsKey.unload_filament_length, + SettingsKey.use_z_probe, + SettingsKey.validate_layer_height, + SettingsKey.write_regex, + SettingsKey.z_probe_samples, + SettingsKey.z_probe_xy_offset, + SettingsKey.z_probe_z_offset, + SettingsKey.z_servo_depolyed_angle, + SettingsKey.z_servo_retracted_angle, + }; + + public List MappedSettings { get; private set; } + private HashSet matterSliceSettingNames; + + // Singleton use only - prevent external construction + public EngineMappingsMatterSlice(PrinterConfig printer) + { + MappedSettings = new List() + { + new AsCountOrDistance(printer, "bottom_solid_layers", "numberOfBottomLayers", SettingsKey.layer_height), + new AsCountOrDistance(printer, "perimeters", "numberOfPerimeters", SettingsKey.nozzle_diameter), + new AsCountOrDistance(printer, "raft_extra_distance_around_part", "raftExtraDistanceAroundPart", SettingsKey.nozzle_diameter), + new AsCountOrDistance(printer, "support_material_interface_layers", "supportInterfaceLayers", SettingsKey.layer_height), + new AsCountOrDistance(printer, "top_solid_layers", "numberOfTopLayers", SettingsKey.layer_height), + new AsPercentOfReferenceOrDirect(printer, SettingsKey.external_perimeter_extrusion_width, "outsidePerimeterExtrusionWidth", SettingsKey.nozzle_diameter), + new OverrideSpeedOnSlaPrinters(printer, "external_perimeter_speed", "outsidePerimeterSpeed", "perimeter_speed"), + new AsPercentOfReferenceOrDirect(printer, SettingsKey.first_layer_speed, "firstLayerSpeed", "infill_speed"), + new AsCountOrDistance(printer, SettingsKey.number_of_first_layers, "numberOfFirstLayers", SettingsKey.layer_height), + new AsPercentOfReferenceOrDirect(printer, "raft_print_speed", "raftPrintSpeed", "infill_speed"), + new OverrideSpeedOnSlaPrinters(printer, SettingsKey.top_solid_infill_speed, "topInfillSpeed", "infill_speed"), + new AsPercentOfReferenceOrDirect(printer, SettingsKey.first_layer_extrusion_width, "firstLayerExtrusionWidth", SettingsKey.nozzle_diameter), + new AsPercentOfReferenceOrDirect(printer, SettingsKey.first_layer_height, "firstLayerThickness", SettingsKey.layer_height), + new ExtruderOffsets(printer, "extruder_offset", "extruderOffsets"), + new GCodeForSlicer(printer, SettingsKey.end_gcode, "endCode"), + new GCodeForSlicer(printer, "before_toolchange_gcode", "beforeToolchangeCode"), + new GCodeForSlicer(printer, "toolchange_gcode", "toolChangeCode"), + new GCodeForSlicer(printer, "before_toolchange_gcode_1", "beforeToolchangeCode1"), + new GCodeForSlicer(printer, "toolchange_gcode_1", "toolChangeCode1"), + new MapFirstValue(printer, "retract_before_travel", "minimumTravelToCauseRetraction"), + new RetractionLength(printer, "retract_length", "retractionOnTravel"), + new MapFirstValue(printer, "retract_lift", "retractionZHop"), + new MapFirstValue(printer, "retract_restart_extra", "unretractExtraExtrusion"), + new MapFirstValue(printer, "retract_restart_extra_time_to_apply", "retractRestartExtraTimeToApply"), + new MapFirstValue(printer, "retract_speed", "retractionSpeed"), + new OverrideSpeedOnSlaPrinters(printer, "bridge_speed", "bridgeSpeed", "infill_speed"), + new OverrideSpeedOnSlaPrinters(printer, "air_gap_speed", "airGapSpeed", "infill_speed"), + new OverrideSpeedOnSlaPrinters(printer, "bottom_infill_speed", "bottomInfillSpeed", "infill_speed"), + new MappedToBoolString(printer, "bridge_over_infill", "bridgeOverInfill"), + new MappedSetting(printer, "extrusion_multiplier", "extrusionMultiplier"), + new MappedSetting(printer, "fill_angle", "infillStartingAngle"), + new AsPercentOfReferenceOrDirect(printer, SettingsKey.infill_overlap_perimeter, "infillExtendIntoPerimeter", SettingsKey.nozzle_diameter, change0ToReference: false), + new OverrideSpeedOnSlaPrinters(printer, "infill_speed", "infillSpeed", "infill_speed"), + new MappedSetting(printer, SettingsKey.infill_type, "infillType"), + new MappedSetting(printer, "min_extrusion_before_retract", "minimumExtrusionBeforeRetraction"), + new MappedSetting(printer, "min_print_speed", "minimumPrintingSpeed"), + new OverrideSpeedOnSlaPrinters(printer, "perimeter_speed", "insidePerimetersSpeed", "infill_speed"), + new MappedSetting(printer, "raft_air_gap", "raftAirGap"), + new MappedSetting(printer, SettingsKey.max_acceleration, "maxAcceleration"), + new MappedSetting(printer, SettingsKey.max_velocity, "maxVelocity"), + new MappedSetting(printer, SettingsKey.jerk_velocity, "jerkVelocity"), + new ScaledSingleNumber(printer, SettingsKey.print_time_estimate_multiplier, "printTimeEstimateMultiplier", .01), + // fan settings + new MappedFanSpeedSetting(printer, SettingsKey.min_fan_speed, "fanSpeedMinPercent"), + new MappedSetting(printer, "coast_at_end_distance", "coastAtEndDistance"), + new MappedSetting(printer, "min_fan_speed_layer_time", "minFanSpeedLayerTime"), + new MappedFanSpeedSetting(printer, SettingsKey.max_fan_speed, "fanSpeedMaxPercent"), + new MappedSetting(printer, "max_fan_speed_layer_time", "maxFanSpeedLayerTime"), + new MappedFanSpeedSetting(printer, "bridge_fan_speed", "bridgeFanSpeedPercent"), + new MappedSetting(printer, "disable_fan_first_layers", "firstLayerToAllowFan"), + // end fan + new MappedSetting(printer, "retract_length_tool_change", "retractionOnExtruderSwitch"), + new MappedSetting(printer, "retract_restart_extra_toolchange", "unretractExtraOnExtruderSwitch"), + new MappedToBoolString(printer, "reset_long_extrusion", "resetLongExtrusion"), + new MappedSetting(printer, "slowdown_below_layer_time", "minimumLayerTimeSeconds"), + new MappedSetting(printer, "support_air_gap", "supportAirGap"), + new MappedSetting(printer, "support_material_infill_angle", "supportInfillStartingAngle"), + new MappedSetting(printer, "support_material_percent", "supportPercent"), + new MappedSetting(printer, "support_material_spacing", "supportLineSpacing"), + new OverrideSpeedOnSlaPrinters(printer, "support_material_speed", "supportMaterialSpeed", "infill_speed"), + new MappedSetting(printer, "support_material_xy_distance", "supportXYDistanceFromObject"), + new MappedSetting(printer, "support_type", "supportType"), + new MappedSetting(printer, "travel_speed", "travelSpeed"), + new MappedSetting(printer, "wipe_shield_distance", "wipeShieldDistanceFromObject"), + new MappedSetting(printer, "wipe_tower_size", "wipeTowerSize"), + new MappedSetting(printer, "z_offset", "zOffset"), + new MappedSetting(printer, SettingsKey.filament_diameter, "filamentDiameter"), + new MappedSetting(printer, SettingsKey.layer_height, "layerThickness"), + new MappedSetting(printer, SettingsKey.nozzle_diameter, "extrusionWidth"), + new MappedSetting(printer, "extruder_count", "extruderCount"), + new MappedToBoolString(printer, "avoid_crossing_perimeters", "avoidCrossingPerimeters"), + new MappedToBoolString(printer, "create_raft", "enableRaft"), + new MappedToBoolString(printer, "external_perimeters_first", "outsidePerimetersFirst"), + new MappedToBoolString(printer, "output_only_first_layer", "outputOnlyFirstLayer"), + new MappedToBoolString(printer, "retract_when_changing_islands", "retractWhenChangingIslands"), + new MappedToBoolString(printer, "support_material", "generateSupport"), + new MappedToBoolString(printer, "support_material_create_internal_support", "generateInternalSupport"), + new MappedToBoolString(printer, "support_material_create_perimeter", "generateSupportPerimeter"), + new MappedToBoolString(printer, SettingsKey.expand_thin_walls, "expandThinWalls"), + new MappedToBoolString(printer, SettingsKey.merge_overlapping_lines, "MergeOverlappingLines"), + new MappedToBoolString(printer, SettingsKey.fill_thin_gaps, "fillThinGaps"), + new MappedToBoolString(printer, SettingsKey.spiral_vase, "continuousSpiralOuterPerimeter"), + new MapStartGCode(printer, SettingsKey.start_gcode, "startCode", true), + new MapLayerChangeGCode(printer, "layer_gcode", "layerChangeCode"), + new ScaledSingleNumber(printer, "fill_density", "infillPercent", 100), + new ScaledSingleNumber(printer, SettingsKey.perimeter_start_end_overlap, "perimeterStartEndOverlapRatio", .01), + new SupportExtrusionWidth(printer, "support_material_extrusion_width","supportExtrusionPercent"), + new ValuePlusConstant(printer, "raft_extruder", "raftExtruder", -1), + new ValuePlusConstant(printer, "support_material_extruder", "supportExtruder", -1), + new ValuePlusConstant(printer, "support_material_interface_extruder", "supportInterfaceExtruder", -1), + // Skirt settings + new MappedSkirtLoopsSetting(printer, "skirts", "numberOfSkirtLoops", SettingsKey.nozzle_diameter), + new MappedSetting(printer, "skirt_distance", "skirtDistanceFromObject"), + new SkirtLengthMapping(printer, "min_skirt_length", "skirtMinLength"), + // Brim settings + new MappedBrimLoopsSetting(printer, "brims", "numberOfBrimLoops", SettingsKey.nozzle_diameter), + }; + + matterSliceSettingNames = new HashSet(MappedSettings.Select(m => m.CanonicalSettingsName)); + } + + public string Name => "MatterSlice"; + + public void WriteSliceSettingsFile(string outputFilename, IEnumerable rawLines) + { + using (var sliceSettingsFile = new StreamWriter(outputFilename)) + { + foreach (MappedSetting mappedSetting in MappedSettings) + { + if (mappedSetting.Value != null) + { + sliceSettingsFile.WriteLine("{0} = {1}".FormatWith(mappedSetting.ExportedName, mappedSetting.Value)); + } + } + + foreach(var line in rawLines) + { + sliceSettingsFile.WriteLine(line); + } + } + } + + public bool MapContains(string canonicalSettingsName) + { + return matterSliceSettingNames.Contains(canonicalSettingsName) + || applicationLevelSettings.Contains(canonicalSettingsName); + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/AsCountOrDistance.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/AsCountOrDistance.cs new file mode 100644 index 000000000..c30b5fd25 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/AsCountOrDistance.cs @@ -0,0 +1,61 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class AsCountOrDistance : MappedSetting + { + private string keyToUseAsDenominatorForCount; + + public AsCountOrDistance(PrinterConfig printer, string canonicalSettingsName, string exportedName, string keyToUseAsDenominatorForCount) + : base(printer, canonicalSettingsName, exportedName) + { + this.keyToUseAsDenominatorForCount = keyToUseAsDenominatorForCount; + } + + public override string Value + { + get + { + // When the state is store in mm, determine and use the value in (counted) units i.e. round distance up to layer count + if (base.Value.Contains("mm")) + { + string withoutMm = base.Value.Replace("mm", ""); + string distanceString = printer.Settings.GetValue(keyToUseAsDenominatorForCount); + double denominator = ParseDouble(distanceString, 1); + + int layers = (int)(ParseDouble(withoutMm) / denominator + .5); + return layers.ToString(); + } + + return base.Value; + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/AsPercentOfReferenceOrDirect.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/AsPercentOfReferenceOrDirect.cs new file mode 100644 index 000000000..e34c429c5 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/AsPercentOfReferenceOrDirect.cs @@ -0,0 +1,76 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class AsPercentOfReferenceOrDirect : MappedSetting + { + private bool change0ToReference; + private string originalReference; + private double scale; + + public AsPercentOfReferenceOrDirect(PrinterConfig printer, string canonicalSettingsName, string exportedName, string originalReference, double scale = 1, bool change0ToReference = true) + : base(printer, canonicalSettingsName, exportedName) + { + this.change0ToReference = change0ToReference; + this.scale = scale; + this.originalReference = originalReference; + } + + public override string Value + { + get + { + double finalValue = 0; + if (base.Value.Contains("%")) + { + string withoutPercent = base.Value.Replace("%", ""); + double ratio = ParseDouble(withoutPercent) / 100.0; + string originalReferenceString = printer.Settings.GetValue(originalReference); + double valueToModify = ParseDouble(originalReferenceString); + finalValue = valueToModify * ratio; + } + else + { + finalValue = ParseDouble(base.Value); + } + + if (change0ToReference + && finalValue == 0) + { + finalValue = ParseDouble(printer.Settings.GetValue(originalReference)); + } + + finalValue *= scale; + + return finalValue.ToString(); + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/ExtruderOffsets.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/ExtruderOffsets.cs new file mode 100644 index 000000000..430302316 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/ExtruderOffsets.cs @@ -0,0 +1,84 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System.Text; + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class ExtruderOffsets : MappedSetting + { + public ExtruderOffsets(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + public override string Value + { + get + { + // map from 0x0,0x0,0x0 + // to [[0,0],[0,0]] + StringBuilder final = new StringBuilder("["); + string[] offsets = base.Value.Split(','); + bool first = true; + int count = 0; + foreach (string offset in offsets) + { + if (!first) + { + final.Append(","); + } + string[] xy = offset.Split('x'); + if (xy.Length == 2) + { + double x = 0; + double.TryParse(xy[0], out x); + double y = 0; + double.TryParse(xy[1], out y); + final.Append($"[{x},{y}]"); + first = false; + count++; + } + else + { + final.Append("[0,0]"); + } + } + while (count < 16) + { + final.Append(",[0,0]"); + count++; + } + final.Append("]"); + + return final.ToString(); + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/FanTranslator.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/FanTranslator.cs new file mode 100644 index 000000000..91b039ae0 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/FanTranslator.cs @@ -0,0 +1,49 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class FanTranslator : MappedSetting + { + public FanTranslator(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + public override string Value + { + get + { + int numLayersFanIsDisabledOn = int.Parse(base.Value); + int layerToEnableFanOn = numLayersFanIsDisabledOn + 1; + return layerToEnableFanOn.ToString(); + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/GCodeForSlicer.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/GCodeForSlicer.cs new file mode 100644 index 000000000..9927b9879 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/GCodeForSlicer.cs @@ -0,0 +1,41 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class GCodeForSlicer : InjectGCodeCommands + { + public GCodeForSlicer(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + public override string Value => printer.ReplaceMacroValues(base.Value.Replace("\n", "\\n")); + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/InfillTranslator.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/InfillTranslator.cs new file mode 100644 index 000000000..284553978 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/InfillTranslator.cs @@ -0,0 +1,57 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class InfillTranslator : MappedSetting + { + public InfillTranslator(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + public override string Value + { + get + { + double infillRatio0To1 = ParseDouble(base.Value); + // 400 = solid (extruder width) + + double nozzle_diameter = printer.Settings.GetValue(SettingsKey.nozzle_diameter); + double linespacing = 1000; + if (infillRatio0To1 > .01) + { + linespacing = nozzle_diameter / infillRatio0To1; + } + + return ((int)(linespacing * 1000)).ToString(); + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/InjectGCodeCommands.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/InjectGCodeCommands.cs new file mode 100644 index 000000000..b72912977 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/InjectGCodeCommands.cs @@ -0,0 +1,60 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System.Collections.Generic; + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class InjectGCodeCommands : UnescapeNewlineCharacters + { + public InjectGCodeCommands(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + protected void AddDefaultIfNotPresent(List linesAdded, string commandToAdd, string[] linesToCheckIfAlreadyPresent, string comment) + { + string command = commandToAdd.Split(' ')[0].Trim(); + bool foundCommand = false; + foreach (string line in linesToCheckIfAlreadyPresent) + { + if (line.StartsWith(command)) + { + foundCommand = true; + break; + } + } + + if (!foundCommand) + { + linesAdded.Add(string.Format("{0} ; {1}", commandToAdd, comment)); + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/MapFirstValue.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/MapFirstValue.cs new file mode 100644 index 000000000..461956e6d --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/MapFirstValue.cs @@ -0,0 +1,41 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class MapFirstValue : MappedSetting + { + public MapFirstValue(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + public override string Value => base.Value.Contains(",") ? base.Value.Split(',')[0] : base.Value; + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/MapLayerChangeGCode.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/MapLayerChangeGCode.cs new file mode 100644 index 000000000..476179ba1 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/MapLayerChangeGCode.cs @@ -0,0 +1,56 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class MapLayerChangeGCode : InjectGCodeCommands + { + public MapLayerChangeGCode(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + public override string Value + { + get + { + string macroReplaced = base.Value; + if (!macroReplaced.Contains("; LAYER:") + && !macroReplaced.Contains(";LAYER:")) + { + macroReplaced += "; LAYER:[layer_num]\n"; + } + + macroReplaced = printer.ReplaceMacroValues(macroReplaced.Replace("\n", "\\n")); + + return macroReplaced; + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/MapStartGCode.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/MapStartGCode.cs new file mode 100644 index 000000000..a46b24ba8 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/MapStartGCode.cs @@ -0,0 +1,210 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.Agg; +using System; +using System.Collections.Generic; +using System.Text; + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class MapStartGCode : InjectGCodeCommands + { + private bool escapeNewlineCharacters; + + public MapStartGCode(PrinterConfig printer, string canonicalSettingsName, string exportedName, bool escapeNewlineCharacters) + : base(printer, canonicalSettingsName, exportedName) + { + this.escapeNewlineCharacters = escapeNewlineCharacters; + } + + public override string Value + { + get + { + StringBuilder newStartGCode = new StringBuilder(); + foreach (string line in PreStartGCode(Slicer.extrudersUsed)) + { + newStartGCode.Append(line + "\n"); + } + + newStartGCode.Append(printer.ReplaceMacroValues(base.Value)); + + foreach (string line in PostStartGCode(Slicer.extrudersUsed)) + { + newStartGCode.Append("\n"); + newStartGCode.Append(line); + } + + if (escapeNewlineCharacters) + { + return newStartGCode.ToString().Replace("\n", "\\n"); + } + + return newStartGCode.ToString(); + } + } + + public List PostStartGCode(List extrudersUsed) + { + string startGCode = printer.Settings.GetValue(SettingsKey.start_gcode); + string[] postStartGCodeLines = startGCode.Split(new string[] { "\\n" }, StringSplitOptions.RemoveEmptyEntries); + + List postStartGCode = new List(); + postStartGCode.Add("; automatic settings after start_gcode"); + + int numberOfHeatedExtruders = printer.Settings.GetValue(SettingsKey.extruder_count); + + // don't set extruder 0 to heating if we already waited for it to reach temp + if (printer.Settings.GetValue(SettingsKey.heat_extruder_before_homing) != "1") + { + if (extrudersUsed[0]) + { + double materialTemperature = printer.Settings.Helpers.ExtruderTemperature(0); + if (materialTemperature != 0) + { + string setTempString = $"M109 T0 S{materialTemperature}"; + AddDefaultIfNotPresent(postStartGCode, setTempString, postStartGCodeLines, string.Format("wait for extruder {0} to reach temperature", 1)); + } + } + } + + if (extrudersUsed.Count > 1) + { + // start all the extruders heating + for (int extruderIndex0Based = 1; extruderIndex0Based < numberOfHeatedExtruders; extruderIndex0Based++) + { + if (extruderIndex0Based < extrudersUsed.Count + && extrudersUsed[extruderIndex0Based]) + { + double materialTemperature = printer.Settings.Helpers.ExtruderTemperature(extruderIndex0Based); + if (materialTemperature != 0) + { + // always heat the extruders that are used beyond extruder 0 + postStartGCode.Add($"M104 T{extruderIndex0Based} S{materialTemperature} ; Start heating extruder{extruderIndex0Based + 1}"); + } + } + } + + // wait for them to finish + for (int extruderIndex0Based = 1; extruderIndex0Based < numberOfHeatedExtruders; extruderIndex0Based++) + { + if (extruderIndex0Based < extrudersUsed.Count + && extrudersUsed[extruderIndex0Based]) + { + double materialTemperature = printer.Settings.Helpers.ExtruderTemperature(extruderIndex0Based); + if (materialTemperature != 0) + { + // always heat the extruders that are used beyond extruder 0 + postStartGCode.Add($"M109 T{extruderIndex0Based} S{materialTemperature} ; Finish heating extruder{extruderIndex0Based + 1}"); + } + } + } + } + + SwitchToFirstActiveExtruder(extrudersUsed, postStartGCodeLines, postStartGCode); + AddDefaultIfNotPresent(postStartGCode, "G90", postStartGCodeLines, "use absolute coordinates"); + postStartGCode.Add(string.Format("{0} ; {1}", "G92 E0", "reset the expected extruder position")); + AddDefaultIfNotPresent(postStartGCode, "M82", postStartGCodeLines, "use absolute distance for extrusion"); + + return postStartGCode; + } + + public List PreStartGCode(List extrudersUsed) + { + string startGCode = printer.Settings.GetValue(SettingsKey.start_gcode); + string[] preStartGCodeLines = startGCode.Split(new string[] { "\\n" }, StringSplitOptions.RemoveEmptyEntries); + + List preStartGCode = new List(); + preStartGCode.Add("; automatic settings before start_gcode"); + AddDefaultIfNotPresent(preStartGCode, "G21", preStartGCodeLines, "set units to millimeters"); + AddDefaultIfNotPresent(preStartGCode, "M107", preStartGCodeLines, "fan off"); + double bed_temperature = printer.Settings.GetValue(SettingsKey.bed_temperature); + if (bed_temperature > 0) + { + string setBedTempString = string.Format("M190 S{0}", bed_temperature); + AddDefaultIfNotPresent(preStartGCode, setBedTempString, preStartGCodeLines, "wait for bed temperature to be reached"); + } + + int numberOfHeatedExtruders = printer.Settings.Helpers.NumberOfHotends(); + + // Start heating all the extruder that we are going to use. + for (int extruderIndex0Based = 0; extruderIndex0Based < numberOfHeatedExtruders; extruderIndex0Based++) + { + if (extrudersUsed.Count > extruderIndex0Based + && extrudersUsed[extruderIndex0Based]) + { + double materialTemperature = printer.Settings.Helpers.ExtruderTemperature(extruderIndex0Based); + if (materialTemperature != 0) + { + string setTempString = "M104 T{0} S{1}".FormatWith(extruderIndex0Based, materialTemperature); + AddDefaultIfNotPresent(preStartGCode, setTempString, preStartGCodeLines, string.Format("start heating extruder {0}", extruderIndex0Based + 1)); + } + } + } + + // If we need to wait for the heaters to heat up before homing then set them to M109 (heat and wait). + if (printer.Settings.GetValue(SettingsKey.heat_extruder_before_homing) == "1") + { + for (int extruderIndex0Based = 0; extruderIndex0Based < numberOfHeatedExtruders; extruderIndex0Based++) + { + if (extrudersUsed.Count > extruderIndex0Based + && extrudersUsed[extruderIndex0Based]) + { + double materialTemperature = printer.Settings.Helpers.ExtruderTemperature(extruderIndex0Based); + if (materialTemperature != 0) + { + string setTempString = "M109 T{0} S{1}".FormatWith(extruderIndex0Based, materialTemperature); + AddDefaultIfNotPresent(preStartGCode, setTempString, preStartGCodeLines, string.Format("wait for extruder {0}", extruderIndex0Based + 1)); + } + } + } + } + + SwitchToFirstActiveExtruder(extrudersUsed, preStartGCodeLines, preStartGCode); + preStartGCode.Add("; settings from start_gcode"); + + return preStartGCode; + } + + private void SwitchToFirstActiveExtruder(List extrudersUsed, string[] preStartGCodeLines, List preStartGCode) + { + // make sure we are on the first active extruder + for (int extruderIndex = 0; extruderIndex < extrudersUsed.Count; extruderIndex++) + { + if (extrudersUsed[extruderIndex]) + { + // set the active extruder to the first one that will be printing + AddDefaultIfNotPresent(preStartGCode, "T{0}".FormatWith(extruderIndex), preStartGCodeLines, "set the active extruder to {0}".FormatWith(extruderIndex)); + break; // then break so we don't set it to a different ones + } + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/MappedBrimLoopsSetting.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/MappedBrimLoopsSetting.cs new file mode 100644 index 000000000..ca76a3373 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/MappedBrimLoopsSetting.cs @@ -0,0 +1,52 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class MappedBrimLoopsSetting : AsCountOrDistance + { + public MappedBrimLoopsSetting(PrinterConfig printer, string canonicalSettingsName, string exportedName, string keyToUseAsDenominatorForCount) + : base(printer, canonicalSettingsName, exportedName, keyToUseAsDenominatorForCount) + { + } + + public override string Value + { + get + { + if (printer.Settings.GetValue("create_brim")) + { + return base.Value; + } + + return "0"; + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/MappedFanSpeedSetting.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/MappedFanSpeedSetting.cs new file mode 100644 index 000000000..3cf9fcd83 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/MappedFanSpeedSetting.cs @@ -0,0 +1,52 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class MappedFanSpeedSetting : MappedSetting + { + public MappedFanSpeedSetting(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + public override string Value + { + get + { + if (printer.Settings.GetValue("enable_fan")) + { + return base.Value; + } + + return "0"; + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/MappedSetting.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/MappedSetting.cs new file mode 100644 index 000000000..3e6fdaaa0 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/MappedSetting.cs @@ -0,0 +1,60 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class MappedSetting + { + protected PrinterConfig printer; + + public MappedSetting(PrinterConfig printer, string canonicalSettingsName, string exportedName) + { + this.printer = printer; + this.CanonicalSettingsName = canonicalSettingsName; + this.ExportedName = exportedName; + } + + public string CanonicalSettingsName { get; } + + public string ExportedName { get; } + + public virtual string Value => printer.Settings.GetValue(CanonicalSettingsName); + + public double ParseDouble(string textValue, double valueOnError = 0) + { + double value; + if (!double.TryParse(textValue, out value)) + { + return valueOnError; + } + + return value; + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/MappedSkirtLoopsSetting.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/MappedSkirtLoopsSetting.cs new file mode 100644 index 000000000..c14b01a88 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/MappedSkirtLoopsSetting.cs @@ -0,0 +1,52 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class MappedSkirtLoopsSetting : AsCountOrDistance + { + public MappedSkirtLoopsSetting(PrinterConfig printer, string canonicalSettingsName, string exportedName, string keyToUseAsDenominatorForCount) + : base(printer, canonicalSettingsName, exportedName, keyToUseAsDenominatorForCount) + { + } + + public override string Value + { + get + { + if (printer.Settings.GetValue("create_skirt")) + { + return base.Value; + } + + return "0"; + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/MappedToBoolString.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/MappedToBoolString.cs new file mode 100644 index 000000000..7fbc2ab87 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/MappedToBoolString.cs @@ -0,0 +1,41 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class MappedToBoolString : MappedSetting + { + public MappedToBoolString(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + public override string Value => (base.Value == "1") ? "True" : "False"; + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/OverrideSpeedOnSlaPrinters.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/OverrideSpeedOnSlaPrinters.cs new file mode 100644 index 000000000..88d9d4c80 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/OverrideSpeedOnSlaPrinters.cs @@ -0,0 +1,63 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class OverrideSpeedOnSlaPrinters : AsPercentOfReferenceOrDirect + { + public OverrideSpeedOnSlaPrinters(PrinterConfig printer, string canonicalSettingsName, string exportedName, string originalReference, double scale = 1) + : base(printer, canonicalSettingsName, exportedName, originalReference, scale) + { + } + + public override string Value + { + get + { + if (printer.Settings.GetValue(SettingsKey.sla_printer)) + { + // return the speed based on the layer height + var speedAt025 = printer.Settings.GetValue(SettingsKey.laser_speed_025); + var speedAt100 = printer.Settings.GetValue(SettingsKey.laser_speed_100); + var deltaSpeed = speedAt100 - speedAt025; + + var layerHeight = printer.Settings.GetValue(SettingsKey.layer_height); + var deltaHeight = .1 - .025; + var heightRatio = (layerHeight - .025) / deltaHeight; + var ajustedSpeed = speedAt025 + deltaSpeed * heightRatio; + return ajustedSpeed.ToString(); + } + else + { + return base.Value; + } + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/RetractionLength.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/RetractionLength.cs new file mode 100644 index 000000000..351d01214 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/RetractionLength.cs @@ -0,0 +1,54 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class RetractionLength : MappedSetting + { + public RetractionLength(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + public override string Value + { + get + { + if (printer.Settings.GetValue(SettingsKey.enable_retractions)) + { + return base.Value; + } + else + { + return 0.ToString(); + } + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/ScaledSingleNumber.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/ScaledSingleNumber.cs new file mode 100644 index 000000000..ea3796125 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/ScaledSingleNumber.cs @@ -0,0 +1,61 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class ScaledSingleNumber : MapFirstValue + { + internal double scale; + + internal ScaledSingleNumber(PrinterConfig printer, string matterControlName, string exportedName, double scale = 1) + : base(printer, matterControlName, exportedName) + { + this.scale = scale; + } + + public override string Value + { + get + { + double ratio = 0; + if (base.Value.Contains("%")) + { + string withoutPercent = base.Value.Replace("%", ""); + ratio = ParseDouble(withoutPercent) / 100.0; + } + else + { + ratio = ParseDouble(base.Value); + } + + return (ratio * scale).ToString(); + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/SkirtLengthMapping.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/SkirtLengthMapping.cs new file mode 100644 index 000000000..a6c1568a3 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/SkirtLengthMapping.cs @@ -0,0 +1,55 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class SkirtLengthMapping : MappedSetting + { + public SkirtLengthMapping(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + public override string Value + { + get + { + double lengthToExtrudeMm = ParseDouble(base.Value); + // we need to convert mm of filament to mm of extrusion path + double amountOfFilamentCubicMms = printer.Settings.GetValue(SettingsKey.filament_diameter) * MathHelper.Tau * lengthToExtrudeMm; + double extrusionSquareSize = printer.Settings.GetValue(SettingsKey.first_layer_height) * printer.Settings.GetValue(SettingsKey.nozzle_diameter); + double lineLength = amountOfFilamentCubicMms / extrusionSquareSize; + + return lineLength.ToString(); + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/Slice3rBedShape.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/Slice3rBedShape.cs new file mode 100644 index 000000000..d0d62f538 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/Slice3rBedShape.cs @@ -0,0 +1,86 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.MeshVisualizer; +using MatterHackers.VectorMath; +using System; + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class Slice3rBedShape : MappedSetting + { + public Slice3rBedShape(PrinterConfig printer, string canonicalSettingsName) + : base(printer, canonicalSettingsName, canonicalSettingsName) + { + } + + public override string Value + { + get + { + Vector2 printCenter = printer.Settings.GetValue(SettingsKey.print_center); + Vector2 bedSize = printer.Settings.GetValue(SettingsKey.bed_size); + switch (printer.Settings.GetValue(SettingsKey.bed_shape)) + { + case BedShape.Circular: + { + int numPoints = 10; + double angle = MathHelper.Tau / numPoints; + string bedString = ""; + bool first = true; + for (int i = 0; i < numPoints; i++) + { + if (!first) + { + bedString += ","; + } + double x = Math.Cos(angle * i); + double y = Math.Sin(angle * i); + bedString += $"{printCenter.X + x * bedSize.X / 2:0.####}x{printCenter.Y + y * bedSize.Y / 2:0.####}"; + first = false; + } + return bedString; + } + //bed_shape = 99.4522x10.4528,97.8148x20.7912,95.1057x30.9017,91.3545x40.6737,86.6025x50,80.9017x58.7785,74.3145x66.9131,66.9131x74.3145,58.7785x80.9017,50x86.6025,40.6737x91.3545,30.9017x95.1057,20.7912x97.8148,10.4528x99.4522,0x100,-10.4528x99.4522,-20.7912x97.8148,-30.9017x95.1057,-40.6737x91.3545,-50x86.6025,-58.7785x80.9017,-66.9131x74.3145,-74.3145x66.9131,-80.9017x58.7785,-86.6025x50,-91.3545x40.6737,-95.1057x30.9017,-97.8148x20.7912,-99.4522x10.4528,-100x0,-99.4522x - 10.4528,-97.8148x - 20.7912,-95.1057x - 30.9017,-91.3545x - 40.6737,-86.6025x - 50,-80.9017x - 58.7785,-74.3145x - 66.9131,-66.9131x - 74.3145,-58.7785x - 80.9017,-50x - 86.6025,-40.6737x - 91.3545,-30.9017x - 95.1057,-20.7912x - 97.8148,-10.4528x - 99.4522,0x - 100,10.4528x - 99.4522,20.7912x - 97.8148,30.9017x - 95.1057,40.6737x - 91.3545,50x - 86.6025,58.7785x - 80.9017,66.9131x - 74.3145,74.3145x - 66.9131,80.9017x - 58.7785,86.6025x - 50,91.3545x - 40.6737,95.1057x - 30.9017,97.8148x - 20.7912,99.4522x - 10.4528,100x0 + + case BedShape.Rectangular: + default: + { + //bed_shape = 0x0,200x0,200x200,0x200 + string bedString = $"{printCenter.X - bedSize.X / 2}x{printCenter.Y - bedSize.Y / 2}"; + bedString += $",{printCenter.X + bedSize.X / 2}x{printCenter.Y - bedSize.Y / 2}"; + bedString += $",{printCenter.X + bedSize.X / 2}x{printCenter.Y + bedSize.Y / 2}"; + bedString += $",{printCenter.X - bedSize.X / 2}x{printCenter.Y + bedSize.Y / 2}"; + return bedString; + } + } + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/SupportExtrusionWidth.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/SupportExtrusionWidth.cs new file mode 100644 index 000000000..7a9b0a5f2 --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/SupportExtrusionWidth.cs @@ -0,0 +1,68 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class SupportExtrusionWidth : MappedSetting + { + public SupportExtrusionWidth(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + public override string Value + { + get + { + double nozzleDiameter = printer.Settings.GetValue(SettingsKey.nozzle_diameter); + + string extrusionWidth = base.Value; + + if (extrusionWidth == "0") + { + return "100"; + } + + if (extrusionWidth.Contains("%")) + { + string withoutPercent = extrusionWidth.Replace("%", ""); + return withoutPercent; + } + + double originalValue; + if (!double.TryParse(extrusionWidth, out originalValue)) + { + originalValue = nozzleDiameter; + } + + return (originalValue / nozzleDiameter * 100).ToString(); + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/UnescapeNewlineCharacters.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/UnescapeNewlineCharacters.cs new file mode 100644 index 000000000..476a8053c --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/UnescapeNewlineCharacters.cs @@ -0,0 +1,42 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + // Replaces escaped newline characters with unescaped newline characters + public class UnescapeNewlineCharacters : MappedSetting + { + public UnescapeNewlineCharacters(PrinterConfig printer, string canonicalSettingsName, string exportedName) + : base(printer, canonicalSettingsName, exportedName) + { + } + + public override string Value => base.Value.Replace("\\n", "\n"); + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/MappingClasses/ValuePlusConstant.cs b/MatterControlLib/SlicerConfiguration/MappingClasses/ValuePlusConstant.cs new file mode 100644 index 000000000..62bee106f --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/MappingClasses/ValuePlusConstant.cs @@ -0,0 +1,44 @@ +/* +Copyright (c) 2016, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +namespace MatterHackers.MatterControl.SlicerConfiguration.MappingClasses +{ + public class ValuePlusConstant : MappedSetting + { + private double constant; + + public ValuePlusConstant(PrinterConfig printer, string canonicalSettingsName, string exportedName, double constant) + : base(printer, canonicalSettingsName, exportedName) + { + this.constant = constant; + } + + public override string Value => (ParseDouble(base.Value) + constant).ToString(); + } +} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/Settings/PrinterSettings.cs b/MatterControlLib/SlicerConfiguration/Settings/PrinterSettings.cs index 13414d644..1e037e48f 100644 --- a/MatterControlLib/SlicerConfiguration/Settings/PrinterSettings.cs +++ b/MatterControlLib/SlicerConfiguration/Settings/PrinterSettings.cs @@ -62,7 +62,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public static EventHandler AnyPrinterSettingChanged; - public EventHandler SettingChanged; + public event EventHandler SettingChanged; public event EventHandler MaterialPresetChanged; @@ -97,6 +97,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public PrinterSettingsLayer StagedUserSettings { get; set; } = new PrinterSettingsLayer(); + [JsonIgnore] internal PrinterConfig printer { get; set; } static PrinterSettings() @@ -768,8 +769,8 @@ namespace MatterHackers.MatterControl.SlicerConfiguration return false; } - [JsonIgnore] PrinterSettingsLayer _baseLayer; + [JsonIgnore] public PrinterSettingsLayer BaseLayer { get @@ -1354,7 +1355,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration } if (!valueWasNumber - || (EngineMappingsMatterSlice.Instance.MapContains(speedSetting) + || (printer.EngineMappingsMatterSlice.MapContains(speedSetting) && speedToCheck <= 0)) { SliceSettingData data = SettingsOrganizer.Instance.GetSettingsData(speedSetting); @@ -1373,8 +1374,8 @@ namespace MatterHackers.MatterControl.SlicerConfiguration #endregion - [JsonIgnore] private static HashSet knownSettings; + [JsonIgnore] public static HashSet KnownSettings { get diff --git a/MatterControlLib/SlicerConfiguration/SliceSettingsWidget.cs b/MatterControlLib/SlicerConfiguration/SliceSettingsWidget.cs index 6bedc696c..9a5f6c20f 100644 --- a/MatterControlLib/SlicerConfiguration/SliceSettingsWidget.cs +++ b/MatterControlLib/SlicerConfiguration/SliceSettingsWidget.cs @@ -439,7 +439,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration // settingShouldBeShown / addedSettingToSubGroup / needToAddSubGroup bool settingShouldBeShown = CheckIfShouldBeShown(settingData, settingsContext); - if (EngineMappingsMatterSlice.Instance.MapContains(settingData.SlicerConfigName) + if (printer.EngineMappingsMatterSlice.MapContains(settingData.SlicerConfigName) && settingShouldBeShown) { settingsRow = CreateItemRow(settingData); diff --git a/MatterControlLib/SlicerConfiguration/Slicer.cs b/MatterControlLib/SlicerConfiguration/Slicer.cs index 8c4256034..f513c5d68 100644 --- a/MatterControlLib/SlicerConfiguration/Slicer.cs +++ b/MatterControlLib/SlicerConfiguration/Slicer.cs @@ -255,7 +255,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration matrixAndMeshArgs.Append($" \"{matrixAndFile.fileName}\" "); } - EngineMappingsMatterSlice.WriteSliceSettingsFile(configFilePath, rawLines: new[] + printer.EngineMappingsMatterSlice.WriteSliceSettingsFile(configFilePath, rawLines: new[] { $"booleanOperations = {mergeRules}", $"additionalArgsToProcess ={matrixAndMeshArgs}" diff --git a/MatterControlLib/SlicerConfiguration/SlicerMapping/EngineMappingMatterSlice.cs b/MatterControlLib/SlicerConfiguration/SlicerMapping/EngineMappingMatterSlice.cs deleted file mode 100644 index 7787a7d5c..000000000 --- a/MatterControlLib/SlicerConfiguration/SlicerMapping/EngineMappingMatterSlice.cs +++ /dev/null @@ -1,446 +0,0 @@ -/* -Copyright (c) 2016, Lars Brubaker -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those -of the authors and should not be interpreted as representing official policies, -either expressed or implied, of the FreeBSD Project. -*/ - -using MatterHackers.Agg; -using MatterHackers.VectorMath; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -namespace MatterHackers.MatterControl.SlicerConfiguration -{ - public class EngineMappingsMatterSlice - { - public static readonly EngineMappingsMatterSlice Instance = new EngineMappingsMatterSlice(); - - /// - /// Application level settings control MatterControl behaviors but aren't used or passed through to the slice engine. Putting settings - /// in this list ensures they show up for all slice engines and the lack of a MappedSetting for the engine guarantees that it won't pass - /// through into the slicer config file - /// - protected HashSet applicationLevelSettings = new HashSet() - { - SettingsKey.bed_shape, - SettingsKey.bed_size, - SettingsKey.print_center, - SettingsKey.send_with_checksum, - SettingsKey.bed_temperature, - SettingsKey.build_height, - SettingsKey.cancel_gcode, - SettingsKey.connect_gcode, - SettingsKey.write_regex, - SettingsKey.read_regex, - SettingsKey.has_fan, - SettingsKey.has_hardware_leveling, - SettingsKey.has_heated_bed, - SettingsKey.has_power_control, - SettingsKey.has_sd_card_reader, - SettingsKey.printer_name, - SettingsKey.auto_connect, - SettingsKey.backup_firmware_before_update, - SettingsKey.baud_rate, - SettingsKey.com_port, - SettingsKey.filament_cost, - SettingsKey.filament_density, - SettingsKey.filament_runout_sensor, - SettingsKey.z_probe_z_offset, - SettingsKey.use_z_probe, - SettingsKey.z_probe_samples, - SettingsKey.has_z_probe, - SettingsKey.has_z_servo, - SettingsKey.z_probe_xy_offset, - SettingsKey.z_servo_depolyed_angle, - SettingsKey.z_servo_retracted_angle, - SettingsKey.pause_gcode, - SettingsKey.print_leveling_probe_start, - SettingsKey.probe_has_been_calibrated, - SettingsKey.filament_has_been_loaded, - SettingsKey.print_leveling_required_to_print, - SettingsKey.print_leveling_solution, - SettingsKey.leveling_sample_points, - SettingsKey.probe_offset_sample_point, - SettingsKey.recover_first_layer_speed, - SettingsKey.number_of_first_layers, - SettingsKey.recover_is_enabled, - SettingsKey.recover_position_before_z_home, - SettingsKey.auto_release_motors, - SettingsKey.resume_gcode, - SettingsKey.temperature, - SettingsKey.enable_retractions, - "z_homes_to_max", - - // TODO: merge the items below into the list above after some validation - setting that weren't previously mapped to Cura but probably should be. - SettingsKey.bed_remove_part_temperature, - "extruder_wipe_temperature", - SettingsKey.heat_extruder_before_homing, - SettingsKey.include_firmware_updater, - SettingsKey.sla_printer, - "layer_to_pause", - SettingsKey.show_reset_connection, - SettingsKey.validate_layer_height, - SettingsKey.make, - SettingsKey.created_date, - SettingsKey.model, - SettingsKey.enable_network_printing, - SettingsKey.enable_line_splitting, - SettingsKey.enable_sailfish_communication, - SettingsKey.print_time_estimate_multiplier, - SettingsKey.ip_address, - SettingsKey.ip_port, - SettingsKey.progress_reporting, - SettingsKey.load_filament_length, - SettingsKey.trim_filament_markdown, - SettingsKey.insert_filament_markdown2, - SettingsKey.running_clean_markdown2, - SettingsKey.unload_filament_length, - SettingsKey.load_filament_speed, - }; - - public List MappedSettings { get; private set; } - private HashSet matterSliceSettingNames; - - // Singleton use only - prevent external construction - private EngineMappingsMatterSlice() - { - MappedSettings = new List() - { - new AsCountOrDistance("bottom_solid_layers", "numberOfBottomLayers", SettingsKey.layer_height), - new AsCountOrDistance("perimeters", "numberOfPerimeters", SettingsKey.nozzle_diameter), - new AsCountOrDistance("raft_extra_distance_around_part", "raftExtraDistanceAroundPart", SettingsKey.nozzle_diameter), - new AsCountOrDistance("support_material_interface_layers", "supportInterfaceLayers", SettingsKey.layer_height), - new AsCountOrDistance("top_solid_layers", "numberOfTopLayers", SettingsKey.layer_height), - new AsPercentOfReferenceOrDirect(SettingsKey.external_perimeter_extrusion_width, "outsidePerimeterExtrusionWidth", SettingsKey.nozzle_diameter), - 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 OverrideSpeedOnSlaPrinters(SettingsKey.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"), - new GCodeForSlicer(SettingsKey.end_gcode, "endCode"), - new GCodeForSlicer("before_toolchange_gcode", "beforeToolchangeCode"), - new GCodeForSlicer("toolchange_gcode", "toolChangeCode"), - new GCodeForSlicer("before_toolchange_gcode_1", "beforeToolchangeCode1"), - new GCodeForSlicer("toolchange_gcode_1", "toolChangeCode1"), - new MapFirstValue("retract_before_travel", "minimumTravelToCauseRetraction"), - new RetractionLength("retract_length", "retractionOnTravel"), - new MapFirstValue("retract_lift", "retractionZHop"), - new MapFirstValue("retract_restart_extra", "unretractExtraExtrusion"), - new MapFirstValue("retract_restart_extra_time_to_apply", "retractRestartExtraTimeToApply"), - new MapFirstValue("retract_speed", "retractionSpeed"), - new OverrideSpeedOnSlaPrinters("bridge_speed", "bridgeSpeed", "infill_speed"), - new OverrideSpeedOnSlaPrinters("air_gap_speed", "airGapSpeed", "infill_speed"), - new OverrideSpeedOnSlaPrinters("bottom_infill_speed", "bottomInfillSpeed", "infill_speed"), - new MappedToBoolString("bridge_over_infill", "bridgeOverInfill"), - new MappedSetting("extrusion_multiplier", "extrusionMultiplier"), - new MappedSetting("fill_angle", "infillStartingAngle"), - new AsPercentOfReferenceOrDirect(SettingsKey.infill_overlap_perimeter, "infillExtendIntoPerimeter", SettingsKey.nozzle_diameter, change0ToReference: false), - new OverrideSpeedOnSlaPrinters("infill_speed", "infillSpeed", "infill_speed"), - new MappedSetting(SettingsKey.infill_type, "infillType"), - new MappedSetting("min_extrusion_before_retract", "minimumExtrusionBeforeRetraction"), - new MappedSetting("min_print_speed", "minimumPrintingSpeed"), - new OverrideSpeedOnSlaPrinters("perimeter_speed", "insidePerimetersSpeed", "infill_speed"), - new MappedSetting("raft_air_gap", "raftAirGap"), - new MappedSetting(SettingsKey.max_acceleration, "maxAcceleration"), - new MappedSetting(SettingsKey.max_velocity, "maxVelocity"), - new MappedSetting(SettingsKey.jerk_velocity, "jerkVelocity"), - new ScaledSingleNumber(SettingsKey.print_time_estimate_multiplier, "printTimeEstimateMultiplier", .01), - // fan settings - new VisibleButNotMappedToEngine("enable_fan"), // this is considered when sending fan speeds to slicing - new MappedFanSpeedSetting(SettingsKey.min_fan_speed, "fanSpeedMinPercent"), - new MappedSetting("coast_at_end_distance", "coastAtEndDistance"), - new MappedSetting("min_fan_speed_layer_time", "minFanSpeedLayerTime"), - new MappedFanSpeedSetting(SettingsKey.max_fan_speed, "fanSpeedMaxPercent"), - new MappedSetting("max_fan_speed_layer_time", "maxFanSpeedLayerTime"), - new MappedFanSpeedSetting("bridge_fan_speed", "bridgeFanSpeedPercent"), - new MappedSetting("disable_fan_first_layers", "firstLayerToAllowFan"), - // end fan - new MappedSetting("retract_length_tool_change", "retractionOnExtruderSwitch"), - new MappedSetting("retract_restart_extra_toolchange", "unretractExtraOnExtruderSwitch"), - new MappedToBoolString("reset_long_extrusion", "resetLongExtrusion"), - new MappedSetting("slowdown_below_layer_time", "minimumLayerTimeSeconds"), - new MappedSetting("support_air_gap", "supportAirGap"), - new MappedSetting("support_material_infill_angle", "supportInfillStartingAngle"), - new MappedSetting("support_material_percent", "supportPercent"), - new MappedSetting("support_material_spacing", "supportLineSpacing"), - 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"), - new MappedSetting("wipe_shield_distance", "wipeShieldDistanceFromObject"), - new MappedSetting("wipe_tower_size", "wipeTowerSize"), - new MappedSetting("z_offset", "zOffset"), - new MappedSetting(SettingsKey.filament_diameter, "filamentDiameter"), - new MappedSetting(SettingsKey.layer_height, "layerThickness"), - new MappedSetting(SettingsKey.nozzle_diameter, "extrusionWidth"), - new MappedSetting("extruder_count", "extruderCount"), - new MappedToBoolString("avoid_crossing_perimeters", "avoidCrossingPerimeters"), - new MappedToBoolString("create_raft", "enableRaft"), - new MappedToBoolString("external_perimeters_first", "outsidePerimetersFirst"), - new MappedToBoolString("output_only_first_layer", "outputOnlyFirstLayer"), - new MappedToBoolString("retract_when_changing_islands", "retractWhenChangingIslands"), - new MappedToBoolString("support_material", "generateSupport"), - new MappedToBoolString("support_material_create_internal_support", "generateInternalSupport"), - new MappedToBoolString("support_material_create_perimeter", "generateSupportPerimeter"), - new MappedToBoolString(SettingsKey.expand_thin_walls, "expandThinWalls"), - new MappedToBoolString(SettingsKey.merge_overlapping_lines, "MergeOverlappingLines"), - new MappedToBoolString(SettingsKey.fill_thin_gaps, "fillThinGaps"), - new MappedToBoolString(SettingsKey.spiral_vase, "continuousSpiralOuterPerimeter"), - new MapStartGCode(SettingsKey.start_gcode, "startCode", true), - new MapLayerChangeGCode("layer_gcode", "layerChangeCode"), - new ScaledSingleNumber("fill_density", "infillPercent", 100), - new ScaledSingleNumber(SettingsKey.perimeter_start_end_overlap, "perimeterStartEndOverlapRatio", .01), - new SupportExtrusionWidth("support_material_extrusion_width","supportExtrusionPercent"), - new ValuePlusConstant("raft_extruder", "raftExtruder", -1), - new ValuePlusConstant("support_material_extruder", "supportExtruder", -1), - new ValuePlusConstant("support_material_interface_extruder", "supportInterfaceExtruder", -1), - new VisibleButNotMappedToEngine("extruders_share_temperature"), - new VisibleButNotMappedToEngine("g0"), - new VisibleButNotMappedToEngine("solid_shell"), - new VisibleButNotMappedToEngine(SettingsKey.laser_speed_025), - new VisibleButNotMappedToEngine(SettingsKey.laser_speed_100), - new VisibleButNotMappedToEngine("selector_ip_address"), - // Skirt settings - new MappedSkirtLoopsSetting("skirts", "numberOfSkirtLoops", SettingsKey.nozzle_diameter), - new MappedSetting("skirt_distance", "skirtDistanceFromObject"), - new SkirtLengthMapping("min_skirt_length", "skirtMinLength"), - // Brim settings - new MappedBrimLoopsSetting("brims", "numberOfBrimLoops", SettingsKey.nozzle_diameter), - }; - - matterSliceSettingNames = new HashSet(MappedSettings.Select(m => m.CanonicalSettingsName)); - } - - public string Name => "MatterSlice"; - - public static void WriteSliceSettingsFile(string outputFilename, IEnumerable rawLines) - { - using (var sliceSettingsFile = new StreamWriter(outputFilename)) - { - foreach (MappedSetting mappedSetting in Instance.MappedSettings) - { - if (mappedSetting.Value != null) - { - sliceSettingsFile.WriteLine("{0} = {1}".FormatWith(mappedSetting.ExportedName, mappedSetting.Value)); - } - } - - foreach(var line in rawLines) - { - sliceSettingsFile.WriteLine(line); - } - } - } - - public bool MapContains(string canonicalSettingsName) - { - return matterSliceSettingNames.Contains(canonicalSettingsName) - || applicationLevelSettings.Contains(canonicalSettingsName); - } - - public class ExtruderOffsets : MappedSetting - { - public ExtruderOffsets(string canonicalSettingsName, string exportedName) - : base(canonicalSettingsName, exportedName) - { - } - - public override string Value - { - get - { - // map from 0x0,0x0,0x0 - // to [[0,0],[0,0]] - StringBuilder final = new StringBuilder("["); - string[] offsets = base.Value.Split(','); - bool first = true; - int count = 0; - foreach (string offset in offsets) - { - if (!first) - { - final.Append(","); - } - string[] xy = offset.Split('x'); - if (xy.Length == 2) - { - double x = 0; - double.TryParse(xy[0], out x); - double y = 0; - double.TryParse(xy[1], out y); - final.Append($"[{x},{y}]"); - first = false; - count++; - } - else - { - final.Append("[0,0]"); - } - } - while (count < 16) - { - final.Append(",[0,0]"); - count++; - } - final.Append("]"); - - return final.ToString(); - } - } - } - - public class FanTranslator : MappedSetting - { - public FanTranslator(string canonicalSettingsName, string exportedName) - : base(canonicalSettingsName, exportedName) - { - } - - public override string Value - { - get - { - int numLayersFanIsDisabledOn = int.Parse(base.Value); - int layerToEnableFanOn = numLayersFanIsDisabledOn + 1; - return layerToEnableFanOn.ToString(); - } - } - } - - public class GCodeForSlicer : InjectGCodeCommands - { - public GCodeForSlicer(string canonicalSettingsName, string exportedName) - : base(canonicalSettingsName, exportedName) - { - } - - public override string Value => GCodeProcessing.ReplaceMacroValues(base.Value.Replace("\n", "\\n")); - } - - public class InfillTranslator : MappedSetting - { - public InfillTranslator(string canonicalSettingsName, string exportedName) - : base(canonicalSettingsName, exportedName) - { - } - - public override string Value - { - get - { - double infillRatio0To1 = ParseDouble(base.Value); - // 400 = solid (extruder width) - - double nozzle_diameter = printer.Settings.GetValue(SettingsKey.nozzle_diameter); - double linespacing = 1000; - if (infillRatio0To1 > .01) - { - linespacing = nozzle_diameter / infillRatio0To1; - } - - return ((int)(linespacing * 1000)).ToString(); - } - } - } - - public class SkirtLengthMapping : MappedSetting - { - public SkirtLengthMapping(string canonicalSettingsName, string exportedName) - : base(canonicalSettingsName, exportedName) - { - } - - public override string Value - { - get - { - double lengthToExtrudeMm = ParseDouble(base.Value); - // we need to convert mm of filament to mm of extrusion path - double amountOfFilamentCubicMms = printer.Settings.GetValue(SettingsKey.filament_diameter) * MathHelper.Tau * lengthToExtrudeMm; - double extrusionSquareSize = printer.Settings.GetValue(SettingsKey.first_layer_height) * printer.Settings.GetValue(SettingsKey.nozzle_diameter); - double lineLength = amountOfFilamentCubicMms / extrusionSquareSize; - - return lineLength.ToString(); - } - } - } - - public class SupportExtrusionWidth : MappedSetting - { - public SupportExtrusionWidth(string canonicalSettingsName, string exportedName) - : base(canonicalSettingsName, exportedName) - { - } - - public override string Value - { - get - { - double nozzleDiameter = printer.Settings.GetValue(SettingsKey.nozzle_diameter); - - string extrusionWidth = base.Value; - - if (extrusionWidth == "0") - { - return "100"; - } - - if (extrusionWidth.Contains("%")) - { - string withoutPercent = extrusionWidth.Replace("%", ""); - return withoutPercent; - } - - double originalValue; - if (!double.TryParse(extrusionWidth, out originalValue)) - { - originalValue = nozzleDiameter; - } - - return (originalValue / nozzleDiameter * 100).ToString(); - } - } - } - - public class ValuePlusConstant : MappedSetting - { - private double constant; - - public ValuePlusConstant(string canonicalSettingsName, string exportedName, double constant) - : base(canonicalSettingsName, exportedName) - { - this.constant = constant; - } - - public override string Value => (ParseDouble(base.Value) + constant).ToString(); - } - } -} \ No newline at end of file diff --git a/MatterControlLib/SlicerConfiguration/SlicerMapping/MappingClasses.cs b/MatterControlLib/SlicerConfiguration/SlicerMapping/MappingClasses.cs deleted file mode 100644 index fbac63e09..000000000 --- a/MatterControlLib/SlicerConfiguration/SlicerMapping/MappingClasses.cs +++ /dev/null @@ -1,665 +0,0 @@ -/* -Copyright (c) 2016, Lars Brubaker -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those -of the authors and should not be interpreted as representing official policies, -either expressed or implied, of the FreeBSD Project. -*/ - -using System; -using System.Collections.Generic; -using System.Text; -using MatterHackers.Agg; -using MatterHackers.MeshVisualizer; -using MatterHackers.VectorMath; - -namespace MatterHackers.MatterControl.SlicerConfiguration -{ - public static class GCodeProcessing - { - private static MappedSetting[] replaceWithSettingsStrings = new MappedSetting[] - { - // Have a mapping so that MatterSlice while always use a setting that can be set. (the user cannot set first_layer_bedTemperature in MatterSlice) - new AsPercentOfReferenceOrDirect(SettingsKey.first_layer_speed, "first_layer_speed", "infill_speed", 60), - new AsPercentOfReferenceOrDirect("external_perimeter_speed","external_perimeter_speed", "perimeter_speed", 60), - new AsPercentOfReferenceOrDirect("raft_print_speed", "raft_print_speed", "infill_speed", 60), - new MappedSetting(SettingsKey.bed_remove_part_temperature,SettingsKey.bed_remove_part_temperature), - new MappedSetting("bridge_fan_speed","bridge_fan_speed"), - new MappedSetting("bridge_speed","bridge_speed"), - new MappedSetting("air_gap_speed", "air_gap_speed"), - new MappedSetting("extruder_wipe_temperature","extruder_wipe_temperature"), - new MappedSetting(SettingsKey.filament_diameter,SettingsKey.filament_diameter), - new MappedSetting("first_layer_bed_temperature", SettingsKey.bed_temperature), - new MappedSetting("first_layer_temperature", SettingsKey.temperature), - new MappedSetting(SettingsKey.max_fan_speed,"max_fan_speed"), - new MappedSetting(SettingsKey.min_fan_speed,"min_fan_speed"), - new MappedSetting("retract_length","retract_length"), - new MappedSetting(SettingsKey.temperature,SettingsKey.temperature), - new MappedSetting("z_offset","z_offset"), - new MappedSetting(SettingsKey.bed_temperature,SettingsKey.bed_temperature), - new ScaledSingleNumber("infill_speed", "infill_speed", 60), - new ScaledSingleNumber("min_print_speed", "min_print_speed", 60), - new ScaledSingleNumber("perimeter_speed","perimeter_speed", 60), - new ScaledSingleNumber("retract_speed","retract_speed", 60), - new ScaledSingleNumber("support_material_speed","support_material_speed", 60), - new ScaledSingleNumber("travel_speed", "travel_speed", 60), - new ScaledSingleNumber(SettingsKey.load_filament_speed, SettingsKey.load_filament_speed, 60), - new MappedSetting(SettingsKey.trim_filament_markdown, SettingsKey.trim_filament_markdown), - new MappedSetting(SettingsKey.insert_filament_markdown2, SettingsKey.insert_filament_markdown2), - new MappedSetting(SettingsKey.running_clean_markdown2, SettingsKey.running_clean_markdown2), - }; - - public static string ReplaceMacroValues(string gcodeWithMacros) - { - foreach (MappedSetting mappedSetting in replaceWithSettingsStrings) - { - // first check if this setting is anywhere in the line - if (gcodeWithMacros.Contains(mappedSetting.CanonicalSettingsName)) - { - { - // do the replacement with {} (curly brackets) - string thingToReplace = "{" + "{0}".FormatWith(mappedSetting.CanonicalSettingsName) + "}"; - gcodeWithMacros = gcodeWithMacros.Replace(thingToReplace, mappedSetting.Value); - } - // do the replacement with [] (square brackets) Slic3r uses only square brackets - { - string thingToReplace = "[" + "{0}".FormatWith(mappedSetting.CanonicalSettingsName) + "]"; - gcodeWithMacros = gcodeWithMacros.Replace(thingToReplace, mappedSetting.Value); - } - } - } - - return gcodeWithMacros; - } - } - - public class MappedSetting - { - protected PrinterConfig printer => ApplicationController.Instance.ActivePrinter; - - public MappedSetting(string canonicalSettingsName, string exportedName) - { - this.CanonicalSettingsName = canonicalSettingsName; - this.ExportedName = exportedName; - } - - public double ParseDouble(string textValue, double valueOnError = 0) - { - double value; - if (!double.TryParse(textValue, out value)) - { - return valueOnError; - } - - return value; - } - - public string ExportedName { get; } - - public string CanonicalSettingsName { get; } - - public virtual string Value => printer.Settings.GetValue(CanonicalSettingsName); - } - - public class MappedFanSpeedSetting : MappedSetting - { - public MappedFanSpeedSetting(string canonicalSettingsName, string exportedName) - : base(canonicalSettingsName, exportedName) - { - } - public override string Value - { - get - { - if (printer.Settings.GetValue("enable_fan")) - { - return base.Value; - } - - return "0"; - } - } - } - - public class MappedBrimLoopsSetting : AsCountOrDistance - { - public MappedBrimLoopsSetting(string canonicalSettingsName, string exportedName, string keyToUseAsDenominatorForCount) - : base(canonicalSettingsName, exportedName, keyToUseAsDenominatorForCount) - { - } - public override string Value - { - get - { - if (printer.Settings.GetValue("create_brim")) - { - return base.Value; - } - - return "0"; - } - } - } - - public class MappedSkirtLoopsSetting : AsCountOrDistance - { - public MappedSkirtLoopsSetting(string canonicalSettingsName, string exportedName, string keyToUseAsDenominatorForCount) - : base(canonicalSettingsName, exportedName, keyToUseAsDenominatorForCount) - { - } - public override string Value - { - get - { - if (printer.Settings.GetValue("create_skirt")) - { - return base.Value; - } - - return "0"; - } - } - } - - public class Slice3rBedShape : MappedSetting - { - public Slice3rBedShape(string canonicalSettingsName) - : base(canonicalSettingsName, canonicalSettingsName) - { - } - - public override string Value - { - get - { - Vector2 printCenter = printer.Settings.GetValue(SettingsKey.print_center); - Vector2 bedSize = printer.Settings.GetValue(SettingsKey.bed_size); - switch (printer.Settings.GetValue(SettingsKey.bed_shape)) - { - case BedShape.Circular: - { - int numPoints = 10; - double angle = MathHelper.Tau / numPoints; - string bedString = ""; - bool first = true; - for (int i = 0; i < numPoints; i++) - { - if (!first) - { - bedString += ","; - } - double x = Math.Cos(angle * i); - double y = Math.Sin(angle * i); - bedString += $"{printCenter.X + x * bedSize.X / 2:0.####}x{printCenter.Y + y * bedSize.Y / 2:0.####}"; - first = false; - } - return bedString; - } - //bed_shape = 99.4522x10.4528,97.8148x20.7912,95.1057x30.9017,91.3545x40.6737,86.6025x50,80.9017x58.7785,74.3145x66.9131,66.9131x74.3145,58.7785x80.9017,50x86.6025,40.6737x91.3545,30.9017x95.1057,20.7912x97.8148,10.4528x99.4522,0x100,-10.4528x99.4522,-20.7912x97.8148,-30.9017x95.1057,-40.6737x91.3545,-50x86.6025,-58.7785x80.9017,-66.9131x74.3145,-74.3145x66.9131,-80.9017x58.7785,-86.6025x50,-91.3545x40.6737,-95.1057x30.9017,-97.8148x20.7912,-99.4522x10.4528,-100x0,-99.4522x - 10.4528,-97.8148x - 20.7912,-95.1057x - 30.9017,-91.3545x - 40.6737,-86.6025x - 50,-80.9017x - 58.7785,-74.3145x - 66.9131,-66.9131x - 74.3145,-58.7785x - 80.9017,-50x - 86.6025,-40.6737x - 91.3545,-30.9017x - 95.1057,-20.7912x - 97.8148,-10.4528x - 99.4522,0x - 100,10.4528x - 99.4522,20.7912x - 97.8148,30.9017x - 95.1057,40.6737x - 91.3545,50x - 86.6025,58.7785x - 80.9017,66.9131x - 74.3145,74.3145x - 66.9131,80.9017x - 58.7785,86.6025x - 50,91.3545x - 40.6737,95.1057x - 30.9017,97.8148x - 20.7912,99.4522x - 10.4528,100x0 - - case BedShape.Rectangular: - default: - { - //bed_shape = 0x0,200x0,200x200,0x200 - string bedString = $"{printCenter.X - bedSize.X / 2}x{printCenter.Y - bedSize.Y / 2}"; - bedString += $",{printCenter.X + bedSize.X / 2}x{printCenter.Y - bedSize.Y / 2}"; - bedString += $",{printCenter.X + bedSize.X / 2}x{printCenter.Y + bedSize.Y / 2}"; - bedString += $",{printCenter.X - bedSize.X / 2}x{printCenter.Y + bedSize.Y / 2}"; - return bedString; - } - } - } - } - } - - public class MapFirstValue : MappedSetting - { - public MapFirstValue(string canonicalSettingsName, string exportedName) - : base(canonicalSettingsName, exportedName) - { - } - - public override string Value => base.Value.Contains(",") ? base.Value.Split(',')[0] : base.Value; - } - - // Replaces escaped newline characters with unescaped newline characters - public class UnescapeNewlineCharacters : MappedSetting - { - public UnescapeNewlineCharacters(string canonicalSettingsName, string exportedName) - : base(canonicalSettingsName, exportedName) - { - } - - public override string Value => base.Value.Replace("\\n", "\n"); - } - - /// - /// Setting will appear in the editor, but it will not be passed to the slicing engine. - /// These values are used in other parts of MatterControl, not slicing, but are held in the slicing data. - /// - /// - public class VisibleButNotMappedToEngine : MappedSetting - { - public VisibleButNotMappedToEngine(string canonicalSettingsName) - : base(canonicalSettingsName, "") - { - } - - public override string Value => null; - } - - public class MapLayerChangeGCode : InjectGCodeCommands - { - public MapLayerChangeGCode(string canonicalSettingsName, string exportedName) - : base(canonicalSettingsName, exportedName) - { - } - - public override string Value - { - get - { - string macroReplaced = base.Value; - if (!macroReplaced.Contains("; LAYER:") - && !macroReplaced.Contains(";LAYER:")) - { - macroReplaced += "; LAYER:[layer_num]\n"; - } - - macroReplaced = GCodeProcessing.ReplaceMacroValues(macroReplaced.Replace("\n", "\\n")); - - return macroReplaced; - } - } - } - - public class MapStartGCode : InjectGCodeCommands - { - private bool escapeNewlineCharacters; - - public MapStartGCode(string canonicalSettingsName, string exportedName, bool escapeNewlineCharacters) - : base(canonicalSettingsName, exportedName) - { - this.escapeNewlineCharacters = escapeNewlineCharacters; - } - - public override string Value - { - get - { - StringBuilder newStartGCode = new StringBuilder(); - foreach (string line in PreStartGCode(Slicer.extrudersUsed)) - { - newStartGCode.Append(line + "\n"); - } - - newStartGCode.Append(GCodeProcessing.ReplaceMacroValues(base.Value)); - - foreach (string line in PostStartGCode(Slicer.extrudersUsed)) - { - newStartGCode.Append("\n"); - newStartGCode.Append(line); - } - - if (escapeNewlineCharacters) - { - return newStartGCode.ToString().Replace("\n", "\\n"); - } - - return newStartGCode.ToString(); - } - } - - public List PreStartGCode(List extrudersUsed) - { - string startGCode = printer.Settings.GetValue(SettingsKey.start_gcode); - string[] preStartGCodeLines = startGCode.Split(new string[] { "\\n" }, StringSplitOptions.RemoveEmptyEntries); - - List preStartGCode = new List(); - preStartGCode.Add("; automatic settings before start_gcode"); - AddDefaultIfNotPresent(preStartGCode, "G21", preStartGCodeLines, "set units to millimeters"); - AddDefaultIfNotPresent(preStartGCode, "M107", preStartGCodeLines, "fan off"); - double bed_temperature = printer.Settings.GetValue(SettingsKey.bed_temperature); - if (bed_temperature > 0) - { - string setBedTempString = string.Format("M190 S{0}", bed_temperature); - AddDefaultIfNotPresent(preStartGCode, setBedTempString, preStartGCodeLines, "wait for bed temperature to be reached"); - } - - int numberOfHeatedExtruders = printer.Settings.Helpers.NumberOfHotends(); - - // Start heating all the extruder that we are going to use. - for (int extruderIndex0Based = 0; extruderIndex0Based < numberOfHeatedExtruders; extruderIndex0Based++) - { - if (extrudersUsed.Count > extruderIndex0Based - && extrudersUsed[extruderIndex0Based]) - { - double materialTemperature = printer.Settings.Helpers.ExtruderTemperature(extruderIndex0Based); - if (materialTemperature != 0) - { - string setTempString = "M104 T{0} S{1}".FormatWith(extruderIndex0Based, materialTemperature); - AddDefaultIfNotPresent(preStartGCode, setTempString, preStartGCodeLines, string.Format("start heating extruder {0}", extruderIndex0Based + 1)); - } - } - } - - // If we need to wait for the heaters to heat up before homing then set them to M109 (heat and wait). - if (printer.Settings.GetValue(SettingsKey.heat_extruder_before_homing) == "1") - { - for (int extruderIndex0Based = 0; extruderIndex0Based < numberOfHeatedExtruders; extruderIndex0Based++) - { - if (extrudersUsed.Count > extruderIndex0Based - && extrudersUsed[extruderIndex0Based]) - { - double materialTemperature = printer.Settings.Helpers.ExtruderTemperature(extruderIndex0Based); - if (materialTemperature != 0) - { - string setTempString = "M109 T{0} S{1}".FormatWith(extruderIndex0Based, materialTemperature); - AddDefaultIfNotPresent(preStartGCode, setTempString, preStartGCodeLines, string.Format("wait for extruder {0}", extruderIndex0Based + 1)); - } - } - } - } - - SwitchToFirstActiveExtruder(extrudersUsed, preStartGCodeLines, preStartGCode); - preStartGCode.Add("; settings from start_gcode"); - - return preStartGCode; - } - - private void SwitchToFirstActiveExtruder(List extrudersUsed, string[] preStartGCodeLines, List preStartGCode) - { - // make sure we are on the first active extruder - for (int extruderIndex = 0; extruderIndex < extrudersUsed.Count; extruderIndex++) - { - if (extrudersUsed[extruderIndex]) - { - // set the active extruder to the first one that will be printing - AddDefaultIfNotPresent(preStartGCode, "T{0}".FormatWith(extruderIndex), preStartGCodeLines, "set the active extruder to {0}".FormatWith(extruderIndex)); - break; // then break so we don't set it to a different ones - } - } - } - - public List PostStartGCode(List extrudersUsed) - { - string startGCode = printer.Settings.GetValue(SettingsKey.start_gcode); - string[] postStartGCodeLines = startGCode.Split(new string[] { "\\n" }, StringSplitOptions.RemoveEmptyEntries); - - List postStartGCode = new List(); - postStartGCode.Add("; automatic settings after start_gcode"); - - int numberOfHeatedExtruders = printer.Settings.GetValue(SettingsKey.extruder_count); - - // don't set extruder 0 to heating if we already waited for it to reach temp - if (printer.Settings.GetValue(SettingsKey.heat_extruder_before_homing) != "1") - { - if (extrudersUsed[0]) - { - double materialTemperature = printer.Settings.Helpers.ExtruderTemperature(0); - if (materialTemperature != 0) - { - string setTempString = $"M109 T0 S{materialTemperature}"; - AddDefaultIfNotPresent(postStartGCode, setTempString, postStartGCodeLines, string.Format("wait for extruder {0} to reach temperature", 1)); - } - } - } - - if (extrudersUsed.Count > 1) - { - // start all the extruders heating - for (int extruderIndex0Based = 1; extruderIndex0Based < numberOfHeatedExtruders; extruderIndex0Based++) - { - if (extruderIndex0Based < extrudersUsed.Count - && extrudersUsed[extruderIndex0Based]) - { - double materialTemperature = printer.Settings.Helpers.ExtruderTemperature(extruderIndex0Based); - if (materialTemperature != 0) - { - // always heat the extruders that are used beyond extruder 0 - postStartGCode.Add($"M104 T{extruderIndex0Based} S{materialTemperature} ; Start heating extruder{extruderIndex0Based + 1}"); - } - } - } - - // wait for them to finish - for (int extruderIndex0Based = 1; extruderIndex0Based < numberOfHeatedExtruders; extruderIndex0Based++) - { - if (extruderIndex0Based < extrudersUsed.Count - && extrudersUsed[extruderIndex0Based]) - { - double materialTemperature = printer.Settings.Helpers.ExtruderTemperature(extruderIndex0Based); - if (materialTemperature != 0) - { - // always heat the extruders that are used beyond extruder 0 - postStartGCode.Add($"M109 T{extruderIndex0Based} S{materialTemperature} ; Finish heating extruder{extruderIndex0Based + 1}"); - } - } - } - } - - SwitchToFirstActiveExtruder(extrudersUsed, postStartGCodeLines, postStartGCode); - AddDefaultIfNotPresent(postStartGCode, "G90", postStartGCodeLines, "use absolute coordinates"); - postStartGCode.Add(string.Format("{0} ; {1}", "G92 E0", "reset the expected extruder position")); - AddDefaultIfNotPresent(postStartGCode, "M82", postStartGCodeLines, "use absolute distance for extrusion"); - - return postStartGCode; - } - } - - public class MappedToBoolString : MappedSetting - { - public MappedToBoolString(string canonicalSettingsName, string exportedName) : base(canonicalSettingsName, exportedName) - { - } - - public override string Value => (base.Value == "1") ? "True" : "False"; - } - - public class ScaledSingleNumber : MapFirstValue - { - internal double scale; - - internal ScaledSingleNumber(string matterControlName, string exportedName, double scale = 1) : base(matterControlName, exportedName) - { - this.scale = scale; - } - - public override string Value - { - get - { - double ratio = 0; - if (base.Value.Contains("%")) - { - string withoutPercent = base.Value.Replace("%", ""); - ratio = ParseDouble(withoutPercent) / 100.0; - } - else - { - ratio = ParseDouble(base.Value); - } - - return (ratio * scale).ToString(); - } - } - } - - public class InjectGCodeCommands : UnescapeNewlineCharacters - { - public InjectGCodeCommands(string canonicalSettingsName, string exportedName) - : base(canonicalSettingsName, exportedName) - { - } - - protected void AddDefaultIfNotPresent(List linesAdded, string commandToAdd, string[] linesToCheckIfAlreadyPresent, string comment) - { - string command = commandToAdd.Split(' ')[0].Trim(); - bool foundCommand = false; - foreach (string line in linesToCheckIfAlreadyPresent) - { - if (line.StartsWith(command)) - { - foundCommand = true; - break; - } - } - - if (!foundCommand) - { - linesAdded.Add(string.Format("{0} ; {1}", commandToAdd, comment)); - } - } - } - - public class AsCountOrDistance : MappedSetting - { - private string keyToUseAsDenominatorForCount; - - public AsCountOrDistance(string canonicalSettingsName, string exportedName, string keyToUseAsDenominatorForCount) - : base(canonicalSettingsName, exportedName) - { - this.keyToUseAsDenominatorForCount = keyToUseAsDenominatorForCount; - } - - public override string Value - { - get - { - // When the state is store in mm, determine and use the value in (counted) units i.e. round distance up to layer count - if (base.Value.Contains("mm")) - { - string withoutMm = base.Value.Replace("mm", ""); - string distanceString = printer.Settings.GetValue(keyToUseAsDenominatorForCount); - double denominator = ParseDouble(distanceString, 1); - - int layers = (int)(ParseDouble(withoutMm) / denominator + .5); - return layers.ToString(); - } - - return base.Value; - } - } - } - - public class RetractionLength : MappedSetting - { - public RetractionLength(string canonicalSettingsName, string exportedName) - : base(canonicalSettingsName, exportedName) - { - } - - public override string Value - { - get - { - if (printer.Settings.GetValue(SettingsKey.enable_retractions)) - { - return base.Value; - } - else - { - return 0.ToString(); - } - } - } - } - - 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 (printer.Settings.GetValue(SettingsKey.sla_printer)) - { - // return the speed based on the layer height - var speedAt025 = printer.Settings.GetValue(SettingsKey.laser_speed_025); - var speedAt100 = printer.Settings.GetValue(SettingsKey.laser_speed_100); - var deltaSpeed = speedAt100 - speedAt025; - - var layerHeight = printer.Settings.GetValue(SettingsKey.layer_height); - var deltaHeight = .1 - .025; - var heightRatio = (layerHeight - .025) / deltaHeight; - var ajustedSpeed = speedAt025 + deltaSpeed * heightRatio; - return ajustedSpeed.ToString(); - } - else - { - return base.Value; - } - } - } - } - - public class AsPercentOfReferenceOrDirect : MappedSetting - { - bool change0ToReference; - string originalReference; - double scale; - - public AsPercentOfReferenceOrDirect(string canonicalSettingsName, string exportedName, string originalReference, double scale = 1, bool change0ToReference = true) - : base(canonicalSettingsName, exportedName) - { - this.change0ToReference = change0ToReference; - this.scale = scale; - this.originalReference = originalReference; - } - - public override string Value - { - get - { - double finalValue = 0; - if (base.Value.Contains("%")) - { - string withoutPercent = base.Value.Replace("%", ""); - double ratio = ParseDouble(withoutPercent) / 100.0; - string originalReferenceString = printer.Settings.GetValue(originalReference); - double valueToModify = ParseDouble(originalReferenceString); - finalValue = valueToModify * ratio; - } - else - { - finalValue = ParseDouble(base.Value); - } - - if (change0ToReference - && finalValue == 0) - { - finalValue = ParseDouble(printer.Settings.GetValue(originalReference)); - } - - finalValue *= scale; - - return finalValue.ToString(); - } - } - } -} diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index b118a6cbf..8c636b2c0 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit b118a6cbf254179ec6e6e70b394c4ca29cadf883 +Subproject commit 8c636b2c051acf182e56ba6973e663c6f5c4a76e diff --git a/Tests/MatterControl.Tests/MatterControl/GCodeProcessingTests.cs b/Tests/MatterControl.Tests/MatterControl/GCodeProcessingTests.cs index a3452264c..5fae853f3 100644 --- a/Tests/MatterControl.Tests/MatterControl/GCodeProcessingTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/GCodeProcessingTests.cs @@ -29,6 +29,7 @@ either expressed or implied, of the FreeBSD Project. using MatterHackers.Agg; using MatterHackers.Agg.Platform; +using MatterHackers.MatterControl; using MatterHackers.MatterControl.PrinterCommunication; using MatterHackers.MatterControl.SlicerConfiguration; using MatterHackers.MatterControl.Tests.Automation; @@ -92,7 +93,8 @@ namespace MatterControl.Tests.MatterControl private void TestMacroReplacement(string inputText, string outputControl) { - string outputTest = GCodeProcessing.ReplaceMacroValues(inputText); + var printer = new PrinterConfig(new PrinterSettings()); + string outputTest = printer.ReplaceMacroValues(inputText); Assert.IsTrue(outputTest == outputControl); }