diff --git a/MatterControl.Printing/GCode/GCodeMemoryFile.cs b/MatterControl.Printing/GCode/GCodeMemoryFile.cs
index 8c9137a63..7bf5132a9 100644
--- a/MatterControl.Printing/GCode/GCodeMemoryFile.cs
+++ b/MatterControl.Printing/GCode/GCodeMemoryFile.cs
@@ -942,6 +942,11 @@ namespace MatterControl.Printing
return false;
}
+ ///
+ /// Get the height of this layer (from the top of the previous layer to the top of this layer).
+ ///
+ ///
+ ///
public override double GetLayerHeight(int layerIndex)
{
if (layerHeights.Count > 0)
@@ -962,6 +967,11 @@ namespace MatterControl.Printing
return .5;
}
+ ///
+ /// Get the height of the top of this layer as measure from the bed
+ ///
+ ///
+ ///
public override double GetLayerTop(int layerIndex)
{
double total = 0;
@@ -972,6 +982,21 @@ namespace MatterControl.Printing
return total;
}
+ ///
+ /// Get the height of the bottom of this layer as measure from the bed
+ ///
+ ///
+ ///
+ public double GetLayerBottom(int layerIndex)
+ {
+ double total = 0;
+ for (int i = 0; i < layerIndex; i++)
+ {
+ total += GetLayerHeight(i);
+ }
+ return total;
+ }
+
public override int GetLayerIndex(int instructionIndex)
{
if (instructionIndex >= 0
diff --git a/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs b/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs
index 273cefaa9..1fcfb3277 100644
--- a/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs
+++ b/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs
@@ -461,11 +461,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
{
var bodyRow = new GuiWidget()
{
- HAnchor = HAnchor.Fit | HAnchor.Center,
+ HAnchor = HAnchor.Stretch,
VAnchor = VAnchor.Top | VAnchor.Fit,
//BackgroundColor = new Color(theme.Colors.PrimaryBackgroundColor, 128),
MinimumSize = new Vector2(275, 140),
- Selectable = false
};
// Progress section
@@ -477,9 +476,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
var progressContainer = new FlowLayoutWidget(FlowDirection.TopToBottom)
{
- Margin = new BorderDouble(50, 0),
VAnchor = VAnchor.Center | VAnchor.Fit,
- HAnchor = HAnchor.Center | HAnchor.Fit,
+ HAnchor = HAnchor.Stretch,
};
expandingContainer.AddChild(progressContainer);
@@ -491,12 +489,88 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
};
progressContainer.AddChild(progressDial);
+ var bottomRow = new GuiWidget()
+ {
+ HAnchor = HAnchor.Stretch,
+ VAnchor = VAnchor.Fit
+ };
+ progressContainer.AddChild(bottomRow);
+
var timeContainer = new FlowLayoutWidget()
{
HAnchor = HAnchor.Center | HAnchor.Fit,
Margin = 3
};
- progressContainer.AddChild(timeContainer);
+ bottomRow.AddChild(timeContainer);
+
+ // we can only reslice on 64 bit, because in 64 bit we always have the gcode loaded
+ if (IntPtr.Size == 8)
+ {
+ var resliceButton = new TextButton("Re-Slice", theme)
+ {
+ HAnchor = HAnchor.Right,
+ VAnchor = VAnchor.Center,
+ Margin = new BorderDouble(0, 0, 7, 0)
+ };
+ bool activelySlicing = false;
+ resliceButton.Click += (s, e) =>
+ {
+ resliceButton.Enabled = false;
+ UiThread.RunOnIdle(async () =>
+ {
+ if (!activelySlicing
+ && printer.Settings.IsValid()
+ && printer.Bed.EditContext.SourceItem != null)
+ {
+ activelySlicing = true;
+ if (bottomRow.Name == null)
+ {
+ bottomRow.Name = printer.Bed.EditContext.GCodeFilePath;
+ }
+ await ApplicationController.Instance.Tasks.Execute("Saving".Localize(), printer.Bed.SaveChanges);
+ // start up a new slice on a backgroud thread
+ await ApplicationController.Instance.SliceItemLoadOutput(
+ printer,
+ printer.Bed.Scene,
+ printer.Bed.EditContext.GCodeFilePath);
+ // Switch to the 3D layer view if on Model view
+ if (printer.ViewState.ViewMode == PartViewMode.Model)
+ {
+ printer.ViewState.ViewMode = PartViewMode.Layers3D;
+ }
+ // when it is done queue it to the change to gcode stream
+ var message2 = "Would you like to switch to the new G-Code? Before you switch, check that your are seeing the changes you expect.".Localize();
+ var caption2 = "Switch to new G-Code?".Localize();
+ StyledMessageBox.ShowMessageBox(async (clickedOk2) =>
+ {
+ if (clickedOk2)
+ {
+ if (printer.Connection != null
+ && (printer.Connection.PrinterIsPrinting || printer.Connection.PrinterIsPaused))
+ {
+ printer.Connection.SwitchToGCode(printer.Bed.EditContext.GCodeFilePath);
+ bottomRow.Name = printer.Bed.EditContext.GCodeFilePath;
+ }
+ }
+ else
+ {
+ await ApplicationController.Instance.SliceItemLoadOutput(
+ printer,
+ printer.Bed.Scene,
+ bottomRow.Name);
+ }
+ activelySlicing = false;
+ resliceButton.Enabled = true;
+ }, message2, caption2, StyledMessageBox.MessageType.YES_NO, "Switch".Localize(), "Cancel".Localize());
+ }
+ else
+ {
+ resliceButton.Enabled = true;
+ }
+ });
+ };
+ bottomRow.AddChild(resliceButton);
+ }
timeContainer.AddChild(new ImageWidget(AggContext.StaticData.LoadIcon("fa-clock_24.png", theme.InvertIcons))
{
diff --git a/MatterControlLib/PrinterCommunication/Io/GCodeSwitcher.cs b/MatterControlLib/PrinterCommunication/Io/GCodeSwitcher.cs
new file mode 100644
index 000000000..457b4fdf4
--- /dev/null
+++ b/MatterControlLib/PrinterCommunication/Io/GCodeSwitcher.cs
@@ -0,0 +1,141 @@
+/*
+Copyright (c) 2015, 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 MatterControl.Printing;
+using MatterHackers.VectorMath;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MatterHackers.MatterControl.PrinterCommunication.Io
+{
+ public class GCodeSwitcher : GCodeStream
+ {
+ private GCodeMemoryFile switchToGCode = null;
+ PrinterConnection printerConnection;
+
+ public GCodeSwitcher(string gcodeFilename, PrinterConnection printerConnection, int startLine = 0)
+ {
+ this.printerConnection = printerConnection;
+ var fileStreaming = GCodeFile.Load(gcodeFilename,
+ new Vector4(),
+ new Vector4(),
+ new Vector4(),
+ Vector4.One,
+ CancellationToken.None);
+
+ this.GCodeFile = fileStreaming;
+ LineIndex = startLine;
+ }
+
+ public GCodeFile GCodeFile { get; private set; }
+ public int LineIndex { get; private set; } = -1;
+
+ public override void Dispose()
+ {
+ }
+
+ public override string ReadLine()
+ {
+ if (LineIndex < GCodeFile.LineCount)
+ {
+ if (LineIndex > 1
+ && GCodeFile is GCodeMemoryFile currentMemoryFile)
+ {
+ if (switchToGCode != null)
+ {
+ var prevlayerIndex = currentMemoryFile.GetLayerIndex(LineIndex - 1);
+ var layerIndex = currentMemoryFile.GetLayerIndex(LineIndex);
+ // we only try to switch as we are changing layers
+ if (prevlayerIndex < layerIndex)
+ {
+ var currentBottom = currentMemoryFile.GetLayerBottom(layerIndex);
+ // see if there is a layer height that is compatible in the new gcode
+ for (int i = 0; i < switchToGCode.LayerCount; i++)
+ {
+ // find the first layer in the new code that is greater than or eaqual to our current height
+ var switchBottom = switchToGCode.GetLayerBottom(i);
+ if (switchBottom >= currentBottom)
+ {
+ // is the current gcode the same or bigger than the new gcode
+ if (currentBottom >= switchBottom)
+ {
+ // switch the first time we can
+ GCodeFile = switchToGCode;
+ LineIndex = switchToGCode.GetFirstLayerInstruction(i);
+ printerConnection.QueueLine($"G92 E{switchToGCode.Instruction(LineIndex).EPosition}", true);
+ switchToGCode = null;
+ }
+ else // only switch if we are within one layer height of the new gcode
+ {
+ if(currentBottom - switchBottom < switchToGCode.GetLayerHeight(layerIndex))
+ {
+ GCodeFile = switchToGCode;
+ LineIndex = switchToGCode.GetFirstLayerInstruction(i);
+ printerConnection.QueueLine($"G92 E{switchToGCode.Instruction(LineIndex).EPosition}", true);
+ }
+ }
+ // we are done evaluating after the first found layer
+ break;
+ }
+ }
+ }
+ }
+ }
+ return GCodeFile.Instruction(LineIndex++).Line;
+ }
+
+ return null;
+ }
+
+ public override void SetPrinterPosition(PrinterMove position)
+ {
+ }
+
+ public void SwitchTo(string gcodeFilename)
+ {
+ if (GCodeFile is GCodeMemoryFile)
+ {
+ Task.Run(() =>
+ {
+ var switchToGCode = GCodeFile.Load(gcodeFilename,
+ new Vector4(),
+ new Vector4(),
+ new Vector4(),
+ Vector4.One,
+ CancellationToken.None);
+
+ if (switchToGCode is GCodeMemoryFile memoryFile)
+ {
+ this.switchToGCode = memoryFile;
+ }
+ });
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MatterControlLib/PrinterCommunication/Io/PrintRecoveryStream.cs b/MatterControlLib/PrinterCommunication/Io/PrintRecoveryStream.cs
index d1070623b..5b98b97d4 100644
--- a/MatterControlLib/PrinterCommunication/Io/PrintRecoveryStream.cs
+++ b/MatterControlLib/PrinterCommunication/Io/PrintRecoveryStream.cs
@@ -38,7 +38,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
public class PrintRecoveryStream : GCodeStream
{
- private GCodeFileStream internalStream;
+ private GCodeSwitcher internalStream;
private double percentDone;
double recoverFeedRate;
PrinterMove lastDestination;
@@ -48,7 +48,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
public RecoveryState RecoveryState { get; private set; } = RecoveryState.RemoveHeating;
private PrinterConfig printer;
- public PrintRecoveryStream(PrinterConfig printer, GCodeFileStream internalStream, double percentDone)
+ public PrintRecoveryStream(PrinterConfig printer, GCodeSwitcher internalStream, double percentDone)
{
this.printer = printer;
this.internalStream = internalStream;
diff --git a/MatterControlLib/PrinterCommunication/PrinterConnection.cs b/MatterControlLib/PrinterCommunication/PrinterConnection.cs
index a3d90967b..63555a820 100644
--- a/MatterControlLib/PrinterCommunication/PrinterConnection.cs
+++ b/MatterControlLib/PrinterCommunication/PrinterConnection.cs
@@ -184,7 +184,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication
private PrinterMove lastReportedPosition;
- private GCodeFileStream gCodeFileStream0 = null;
+ private GCodeSwitcher gCodeFileSwitcher0 = null;
private SendProgressStream sendProgressStream1 = null;
private PauseHandlingStream pauseHandlingStream2 = null;
private QueuedCommandsStream queuedCommandStream3 = null;
@@ -513,6 +513,11 @@ namespace MatterHackers.MatterControl.PrinterCommunication
}
}
+ public void SwitchToGCode(string gCodeFilePath)
+ {
+ gCodeFileSwitcher0.SwitchTo(gCodeFilePath);
+ }
+
public string ComPort => printer.Settings?.Helpers.ComPort();
public string DriverType => (this.ComPort == "Emulator") ? "Emulator" : printer.Settings?.GetValue("driver_type");
@@ -542,9 +547,9 @@ namespace MatterHackers.MatterControl.PrinterCommunication
{
get
{
- if (gCodeFileStream0 != null)
+ if (gCodeFileSwitcher0 != null)
{
- return gCodeFileStream0?.GCodeFile?.GetLayerIndex(gCodeFileStream0.LineIndex) ?? -1;
+ return gCodeFileSwitcher0?.GCodeFile?.GetLayerIndex(gCodeFileSwitcher0.LineIndex) ?? -1;
}
return -1;
@@ -597,9 +602,9 @@ namespace MatterHackers.MatterControl.PrinterCommunication
return 100.0;
}
else if (NumberOfLinesInCurrentPrint > 0
- && gCodeFileStream0?.GCodeFile != null)
+ && gCodeFileSwitcher0?.GCodeFile != null)
{
- return gCodeFileStream0.GCodeFile.PercentComplete(gCodeFileStream0.LineIndex);
+ return gCodeFileSwitcher0.GCodeFile.PercentComplete(gCodeFileSwitcher0.LineIndex);
}
else
{
@@ -714,12 +719,12 @@ namespace MatterHackers.MatterControl.PrinterCommunication
{
get
{
- if (gCodeFileStream0?.GCodeFile == null)
+ if (gCodeFileSwitcher0?.GCodeFile == null)
{
return 0;
}
- return gCodeFileStream0.GCodeFile.Ratio0to1IntoContainedLayer(gCodeFileStream0.LineIndex);
+ return gCodeFileSwitcher0.GCodeFile.Ratio0to1IntoContainedLayer(gCodeFileSwitcher0.LineIndex);
}
}
@@ -754,22 +759,22 @@ namespace MatterHackers.MatterControl.PrinterCommunication
}
}
- public int TotalLayersInPrint => gCodeFileStream0?.GCodeFile?.LayerCount ?? -1;
+ public int TotalLayersInPrint => gCodeFileSwitcher0?.GCodeFile?.LayerCount ?? -1;
- private int NumberOfLinesInCurrentPrint => gCodeFileStream0?.GCodeFile?.LineCount ?? -1;
+ private int NumberOfLinesInCurrentPrint => gCodeFileSwitcher0?.GCodeFile?.LineCount ?? -1;
public int TotalSecondsInPrint
{
get
{
- if (gCodeFileStream0?.GCodeFile?.LineCount > 0)
+ if (gCodeFileSwitcher0?.GCodeFile?.LineCount > 0)
{
if (this.FeedRateRatio != 0)
{
- return (int)(gCodeFileStream0.GCodeFile.TotalSecondsInPrint / this.FeedRateRatio);
+ return (int)(gCodeFileSwitcher0.GCodeFile.TotalSecondsInPrint / this.FeedRateRatio);
}
- return (int)(gCodeFileStream0.GCodeFile.TotalSecondsInPrint);
+ return (int)(gCodeFileSwitcher0.GCodeFile.TotalSecondsInPrint);
}
return 0;
@@ -2031,7 +2036,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication
private void ClearQueuedGCode()
{
- gCodeFileStream0?.GCodeFile?.Clear();
+ gCodeFileSwitcher0?.GCodeFile?.Clear();
}
private void DonePrintingSdFile(object sender, FoundStringEventArgs e)
@@ -2096,24 +2101,19 @@ namespace MatterHackers.MatterControl.PrinterCommunication
GCodeStream firstStreamToRead = null;
if (gcodeFilename != null)
{
- gCodeFileStream0 = new GCodeFileStream(GCodeFile.Load(gcodeFilename,
- new Vector4(),
- new Vector4(),
- new Vector4(),
- Vector4.One,
- CancellationToken.None));
+ gCodeFileSwitcher0 = new GCodeSwitcher(gcodeFilename, this);
if (this.RecoveryIsEnabled
&& activePrintTask != null) // We are resuming a failed print (do lots of interesting stuff).
{
- sendProgressStream1 = new SendProgressStream(printer, new PrintRecoveryStream(printer, gCodeFileStream0, activePrintTask.PercentDone));
+ sendProgressStream1 = new SendProgressStream(printer, new PrintRecoveryStream(printer, gCodeFileSwitcher0, activePrintTask.PercentDone));
// And increment the recovery count
activePrintTask.RecoveryCount++;
activePrintTask.Commit();
}
else
{
- sendProgressStream1 = new SendProgressStream(printer, gCodeFileStream0);
+ sendProgressStream1 = new SendProgressStream(printer, gCodeFileSwitcher0);
}
pauseHandlingStream2 = new PauseHandlingStream(printer, sendProgressStream1);
@@ -2121,7 +2121,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication
}
else
{
- gCodeFileStream0 = null;
+ gCodeFileSwitcher0 = null;
firstStreamToRead = new NotPrintingStream();
}
@@ -2167,12 +2167,12 @@ namespace MatterHackers.MatterControl.PrinterCommunication
double secondsSinceStartedPrint = timeSinceStartedPrint.Elapsed.TotalSeconds;
if (timeSinceStartedPrint.Elapsed.TotalSeconds > 0
- && gCodeFileStream0 != null
+ && gCodeFileSwitcher0 != null
&& (secondsSinceUpdateHistory > secondsSinceStartedPrint
|| secondsSinceUpdateHistory + 1 < secondsSinceStartedPrint
- || lineSinceUpdateHistory + 20 < gCodeFileStream0.LineIndex))
+ || lineSinceUpdateHistory + 20 < gCodeFileSwitcher0.LineIndex))
{
- double currentDone = gCodeFileStream0.GCodeFile.PercentComplete(gCodeFileStream0.LineIndex);
+ double currentDone = gCodeFileSwitcher0.GCodeFile.PercentComplete(gCodeFileSwitcher0.LineIndex);
// Only update the amount done if it is greater than what is recorded.
// We don't want to mess up the resume before we actually resume it.
if (activePrintTask != null
@@ -2190,7 +2190,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication
//timer.Restart();
}
secondsSinceUpdateHistory = secondsSinceStartedPrint;
- lineSinceUpdateHistory = gCodeFileStream0.LineIndex;
+ lineSinceUpdateHistory = gCodeFileSwitcher0.LineIndex;
}
Thread.Sleep(5);