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);
}