From c2d2509195e06d68ef5fb6bb303cf626e60a05fb Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Tue, 8 May 2018 15:19:06 -0700 Subject: [PATCH] Got the per layer info to show up in gcode view Fixed bugs with gcode parsing Moved classes into separate files --- .../GCodeRenderer/GCodeRenderer.cs | 6 +- MatterControl.Printing/GCode/GCodeFile.cs | 8 +- .../GCode/GCodeFileStreamed.cs | 4 +- .../GCode/GCodeMemoryFile.cs | 86 +++++++------ MatterControl.csproj | 8 +- PartPreviewWindow/GCode3DWidget.cs | 46 ++++--- PartPreviewWindow/GCodeDetails/BoolOption.cs | 57 +++++++++ .../{ => GCodeDetails}/GCodeDetails.cs | 100 +++++++++++++-- .../GCodeDetails/GCodeDetailsView.cs | 120 ++++++++++++++++++ .../GCodeDetails/GCodeLayerDetailsView.cs | 107 ++++++++++++++++ .../GCodeOptionsPanel.cs} | 114 ----------------- .../GCodeDetails/IToggleOption.cs | 40 ++++++ Submodules/MatterSlice | 2 +- Submodules/agg-sharp | 2 +- 14 files changed, 500 insertions(+), 200 deletions(-) create mode 100644 PartPreviewWindow/GCodeDetails/BoolOption.cs rename PartPreviewWindow/{ => GCodeDetails}/GCodeDetails.cs (57%) create mode 100644 PartPreviewWindow/GCodeDetails/GCodeDetailsView.cs create mode 100644 PartPreviewWindow/GCodeDetails/GCodeLayerDetailsView.cs rename PartPreviewWindow/{GCodeDetailsView.cs => GCodeDetails/GCodeOptionsPanel.cs} (73%) create mode 100644 PartPreviewWindow/GCodeDetails/IToggleOption.cs diff --git a/MatterControl.OpenGL/GCodeRenderer/GCodeRenderer.cs b/MatterControl.OpenGL/GCodeRenderer/GCodeRenderer.cs index d3f0dcd0a..5b9752be2 100644 --- a/MatterControl.OpenGL/GCodeRenderer/GCodeRenderer.cs +++ b/MatterControl.OpenGL/GCodeRenderer/GCodeRenderer.cs @@ -130,11 +130,7 @@ namespace MatterHackers.GCodeVisualizer { if (gCodeFileToDraw.IsExtruding(instructionIndex)) { - double layerThickness = gCodeFileToDraw.GetLayerHeight(); - if (layerToCreate == 0) - { - layerThickness = gCodeFileToDraw.GetFirstLayerHeight(); - } + double layerThickness = gCodeFileToDraw.GetLayerHeight(layerToCreate); Color extrusionColor = ExtrusionColors.GetColorForSpeed((float)currentInstruction.FeedRate); renderFeaturesForLayer.Add(new RenderFeatureExtrusion(previousInstruction.Position, currentInstruction.Position, currentInstruction.ExtruderIndex, currentInstruction.FeedRate, currentInstruction.EPosition - previousInstruction.EPosition, gCodeFileToDraw.GetFilamentDiameter(), layerThickness, extrusionColor)); diff --git a/MatterControl.Printing/GCode/GCodeFile.cs b/MatterControl.Printing/GCode/GCodeFile.cs index 912e64158..066272677 100644 --- a/MatterControl.Printing/GCode/GCodeFile.cs +++ b/MatterControl.Printing/GCode/GCodeFile.cs @@ -68,11 +68,11 @@ namespace MatterControl.Printing public abstract double GetFilamentWeightGrams(double filamentDiameterMm, double density); - public abstract double GetFirstLayerHeight(); - public abstract int GetInstructionIndexAtLayer(int layerIndex); - public abstract double GetLayerHeight(); + public abstract double GetLayerHeight(int layerIndex); + + public abstract double GetLayerZOffset(int layerIndex); public abstract int GetLayerIndex(int instructionIndex); @@ -142,7 +142,7 @@ namespace MatterControl.Printing int stringPos = stringWithNumber.IndexOf(stringToCheckAfter, startIndex); int stopPos = stringWithNumber.IndexOf(stopCheckingString); if (stringPos != -1 - && (stopPos == -1 || stringPos < stopPos)) + && (stopPos == -1 || stringPos < stopPos || string.IsNullOrEmpty(stopCheckingString))) { stringPos += stringToCheckAfter.Length; readValue = agg_basics.ParseDouble(stringWithNumber, ref stringPos, true); diff --git a/MatterControl.Printing/GCode/GCodeFileStreamed.cs b/MatterControl.Printing/GCode/GCodeFileStreamed.cs index cb2dde4ad..d19dbd151 100644 --- a/MatterControl.Printing/GCode/GCodeFileStreamed.cs +++ b/MatterControl.Printing/GCode/GCodeFileStreamed.cs @@ -144,12 +144,12 @@ namespace MatterControl.Printing throw new NotImplementedException(); } - public override double GetLayerHeight() + public override double GetLayerHeight(int layerIndex) { throw new NotImplementedException(); } - public override double GetFirstLayerHeight() + public override double GetLayerZOffset(int layerIndex) { throw new NotImplementedException(); } diff --git a/MatterControl.Printing/GCode/GCodeMemoryFile.cs b/MatterControl.Printing/GCode/GCodeMemoryFile.cs index d5a93f23c..627792b86 100644 --- a/MatterControl.Printing/GCode/GCodeMemoryFile.cs +++ b/MatterControl.Printing/GCode/GCodeMemoryFile.cs @@ -42,16 +42,15 @@ namespace MatterControl.Printing { private double amountOfAccumulatedEWhileParsing = 0; - private List indexOfChangeInZ = new List(); - private MatterHackers.VectorMath.Vector2 center = Vector2.Zero; + private Vector2 center = Vector2.Zero; private double parsingLastZ; private bool gcodeHasExplicitLayerChangeInfo = false; - private double firstLayerThickness; - private double layerThickness; - private double filamentUsedMmCache = 0; - private double diameterOfFilamentUsedMmCache = 0; + private double filamentUsedMmCache = 0; + private double diameterOfFilamentUsedMmCache = 0; + private List layerZOffset = new List(); + private List layerHeights = new List(); private List GCodeCommandQueue = new List(); public GCodeMemoryFile(bool gcodeHasExplicitLayerChangeInfo = false) @@ -76,7 +75,7 @@ namespace MatterControl.Printing cancellationToken, null); if (loadedFile != null) { - this.indexOfChangeInZ = loadedFile.indexOfChangeInZ; + this.IndexOfChangeInZ = loadedFile.IndexOfChangeInZ; this.center = loadedFile.center; this.parsingLastZ = loadedFile.parsingLastZ; this.GCodeCommandQueue = loadedFile.GCodeCommandQueue; @@ -92,7 +91,7 @@ namespace MatterControl.Printing public override void Clear() { - indexOfChangeInZ.Clear(); + IndexOfChangeInZ.Clear(); GCodeCommandQueue.Clear(); } @@ -105,11 +104,11 @@ namespace MatterControl.Printing public void Insert(int insertIndex, PrinterMachineInstruction printerMachineInstruction) { - for (int i = 0; i < indexOfChangeInZ.Count; i++) + for (int i = 0; i < IndexOfChangeInZ.Count; i++) { - if (insertIndex < indexOfChangeInZ[i]) + if (insertIndex < IndexOfChangeInZ[i]) { - indexOfChangeInZ[i]++; + IndexOfChangeInZ[i]++; } } @@ -271,7 +270,10 @@ namespace MatterControl.Printing case ';': if (gcodeHasExplicitLayerChangeInfo && IsLayerChange(lineString)) { - if (lineString.EndsWith("LAYER:0")) + // if we just found the start of the file and we have not added any layers yet + // Make sure we start at the beginging + if (lineString.EndsWith("LAYER:0") + && loadedGCodeFile.IndexOfChangeInZ.Count == 0) { loadedGCodeFile.IndexOfChangeInZ.Add(0); break; @@ -279,13 +281,13 @@ namespace MatterControl.Printing loadedGCodeFile.IndexOfChangeInZ.Add(loadedGCodeFile.GCodeCommandQueue.Count); } - if (lineString.StartsWith("; layerThickness")) + else if (lineString.StartsWith("; LAYER_HEIGHT:")) { - loadedGCodeFile.layerThickness = double.Parse(lineString.Split('=')[1]); - } - else if (lineString.StartsWith("; firstLayerThickness") && loadedGCodeFile.firstLayerThickness == 0) - { - loadedGCodeFile.firstLayerThickness = double.Parse(lineString.Split('=')[1]); + double layerWidth = 0; + if (GetFirstNumberAfter("LAYER_HEIGHT:", lineString, ref layerWidth, 0, "")) + { + loadedGCodeFile.layerHeights.Add(layerWidth); + } } break; @@ -437,20 +439,22 @@ namespace MatterControl.Printing public override int GetInstructionIndexAtLayer(int layerIndex) { - return IndexOfChangeInZ[layerIndex]; - } + if (layerIndex < IndexOfChangeInZ.Count - 1) + { + return IndexOfChangeInZ[layerIndex]; + } - private List IndexOfChangeInZ - { - get { return indexOfChangeInZ; } + // else return the last instruction + return GCodeCommandQueue.Count - 1; } public override int LayerCount { - get { return indexOfChangeInZ.Count; } + get { return IndexOfChangeInZ.Count; } } public HashSet Speeds { get; private set; } + public List IndexOfChangeInZ { get; set; } = new List(); private void ParseMLine(string lineString, PrinterMachineInstruction processingMachineState) { @@ -688,10 +692,10 @@ namespace MatterControl.Printing if (!gcodeHasExplicitLayerChangeInfo) { - if (processingMachineState.Z != parsingLastZ || indexOfChangeInZ.Count == 0) + if (processingMachineState.Z != parsingLastZ || IndexOfChangeInZ.Count == 0) { // if we changed z or there is a movement and we have never started a layer index - indexOfChangeInZ.Add(GCodeCommandQueue.Count); + IndexOfChangeInZ.Add(GCodeCommandQueue.Count); } } parsingLastZ = processingMachineState.Position.Z; @@ -903,14 +907,19 @@ namespace MatterControl.Printing return filamentDiameterCache; } - public override double GetLayerHeight() + public override double GetLayerHeight(int layerIndex) { - if (layerThickness > 0) + if (layerHeights.Count > 0) { - return layerThickness; + if (layerIndex < layerHeights.Count) + { + return layerHeights[layerIndex]; + } + + return 0; } - if (indexOfChangeInZ.Count > 2) + if (IndexOfChangeInZ.Count > 2) { return GCodeCommandQueue[IndexOfChangeInZ[2]].Z - GCodeCommandQueue[IndexOfChangeInZ[1]].Z; } @@ -918,19 +927,14 @@ namespace MatterControl.Printing return .5; } - public override double GetFirstLayerHeight() + public override double GetLayerZOffset(int layerIndex) { - if (firstLayerThickness > 0) + double total = 0; + for (int i = 0; i <= layerIndex; i++) { - return firstLayerThickness; + total += GetLayerHeight(i); } - - if (indexOfChangeInZ.Count > 1) - { - return GCodeCommandQueue[IndexOfChangeInZ[1]].Z - GCodeCommandQueue[IndexOfChangeInZ[0]].Z; - } - - return .5; + return total; } public override int GetLayerIndex(int instructionIndex) @@ -940,7 +944,7 @@ namespace MatterControl.Printing { for(var i = IndexOfChangeInZ.Count - 1; i >=0; i--) { - var lineStart = indexOfChangeInZ[i]; + var lineStart = IndexOfChangeInZ[i]; if (instructionIndex >= lineStart) { diff --git a/MatterControl.csproj b/MatterControl.csproj index da9c2e737..162f42cee 100644 --- a/MatterControl.csproj +++ b/MatterControl.csproj @@ -83,6 +83,10 @@ + + + + @@ -294,8 +298,8 @@ - - + + diff --git a/PartPreviewWindow/GCode3DWidget.cs b/PartPreviewWindow/GCode3DWidget.cs index 7d5205bd7..43d3915d3 100644 --- a/PartPreviewWindow/GCode3DWidget.cs +++ b/PartPreviewWindow/GCode3DWidget.cs @@ -100,23 +100,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow if (sceneContext.LoadedGCode?.LineCount > 0) { - loadedGCodeSection.AddChild( - new SectionWidget( - "Details".Localize(), - new GCodeDetailsView(new GCodeDetails(printer, printer.Bed.LoadedGCode), theme.FontSize12, theme.FontSize9) - { - HAnchor = HAnchor.Stretch, - Margin = new BorderDouble(bottom: 3), - Padding = new BorderDouble(15, 4) - }, - theme) - { - HAnchor = HAnchor.Stretch, - VAnchor = VAnchor.Fit - }); - bool renderSpeeds = printer.Bed.RendererOptions.GCodeLineColorStyle == "Speeds"; - loadedGCodeSection.AddChild( speedsWidget = new SectionWidget( "Speeds".Localize(), @@ -133,6 +117,36 @@ namespace MatterHackers.MatterControl.PartPreviewWindow }); speedsWidget.Visible = renderSpeeds; + + loadedGCodeSection.AddChild( + new SectionWidget( + "Details".Localize(), + new GCodeDetailsView(new GCodeDetails(printer, printer.Bed.LoadedGCode), theme.FontSize12, theme.FontSize9) + { + HAnchor = HAnchor.Stretch, + Margin = new BorderDouble(bottom: 3), + Padding = new BorderDouble(15, 4) + }, + theme) + { + HAnchor = HAnchor.Stretch, + VAnchor = VAnchor.Fit + }); + + loadedGCodeSection.AddChild( + new SectionWidget( + "Layer".Localize(), + new GCodeLayerDetailsView(new GCodeDetails(printer, printer.Bed.LoadedGCode), sceneContext, theme.FontSize12, theme.FontSize9) + { + HAnchor = HAnchor.Stretch, + Margin = new BorderDouble(bottom: 3), + Padding = new BorderDouble(15, 4) + }, + theme) + { + HAnchor = HAnchor.Stretch, + VAnchor = VAnchor.Fit + }); } // Enforce panel padding in sidebar diff --git a/PartPreviewWindow/GCodeDetails/BoolOption.cs b/PartPreviewWindow/GCodeDetails/BoolOption.cs new file mode 100644 index 000000000..77b9550da --- /dev/null +++ b/PartPreviewWindow/GCodeDetails/BoolOption.cs @@ -0,0 +1,57 @@ +/* +Copyright (c) 2017, 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.PartPreviewWindow +{ + public class BoolOption : IToggleOption + { + public string Title { get; } + + public Func IsChecked { get; } + + public Func IsVisible { get; } + + public Action SetValue { get; } + + public BoolOption(string title, Func isChecked, Action setValue) + : this(title, isChecked, setValue, () => true) + { + } + + public BoolOption(string title, Func isChecked, Action setValue, Func isVisible) + { + this.Title = title; + this.IsChecked = isChecked; + this.SetValue = setValue; + this.IsVisible = isVisible; + } + } +} diff --git a/PartPreviewWindow/GCodeDetails.cs b/PartPreviewWindow/GCodeDetails/GCodeDetails.cs similarity index 57% rename from PartPreviewWindow/GCodeDetails.cs rename to PartPreviewWindow/GCodeDetails/GCodeDetails.cs index 3070a64e8..cee3559c2 100644 --- a/PartPreviewWindow/GCodeDetails.cs +++ b/PartPreviewWindow/GCodeDetails/GCodeDetails.cs @@ -27,6 +27,7 @@ of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ +using System; using MatterControl.Printing; using MatterHackers.MatterControl.SlicerConfiguration; @@ -43,6 +44,28 @@ namespace MatterHackers.MatterControl.PartPreviewWindow this.loadedGCode = loadedGCode; } + public string SecondsToTime(double seconds) + { + int secondsRemaining = (int)seconds; + int hoursRemaining = (int)(secondsRemaining / (60 * 60)); + int minutesRemaining = (int)((secondsRemaining + 30) / 60 - hoursRemaining * 60); // +30 for rounding + + secondsRemaining = secondsRemaining % 60; + + if (hoursRemaining > 0) + { + return $"{hoursRemaining} h, {minutesRemaining} min"; + } + else if(minutesRemaining > 10) + { + return $"{minutesRemaining} min"; + } + else + { + return $"{minutesRemaining} min {secondsRemaining} s"; + } + } + public string EstimatedPrintTime { get @@ -52,20 +75,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow return "---"; } - int secondsRemaining = (int)loadedGCode.Instruction(0).secondsToEndFromHere; - int hoursRemaining = (int)(secondsRemaining / (60 * 60)); - int minutesRemaining = (int)((secondsRemaining + 30) / 60 - hoursRemaining * 60); // +30 for rounding - - secondsRemaining = secondsRemaining % 60; - - if (hoursRemaining > 0) - { - return $"{hoursRemaining} h, {minutesRemaining} min"; - } - else - { - return $"{minutesRemaining} min"; - } + return SecondsToTime(loadedGCode.Instruction(0).secondsToEndFromHere); } } @@ -88,6 +98,68 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } } + public double GetLayerHeight(int layerIndex) + { + return loadedGCode.GetLayerHeight(layerIndex); + } + + internal object GetLayerZOffset(int layerIndex) + { + return loadedGCode.GetLayerZOffset(layerIndex); + } + + public string LayerTime(int activeLayerIndex) + { + if (loadedGCode == null) + { + return "---"; + } + + int startInstruction = Math.Min(loadedGCode.LayerCount - 1, loadedGCode.GetInstructionIndexAtLayer(activeLayerIndex)); + int endInstruction = loadedGCode.GetInstructionIndexAtLayer(activeLayerIndex + 1); + var secondsToEndFromStart = loadedGCode.Instruction(startInstruction).secondsToEndFromHere; + var secondsToEndFromEnd = loadedGCode.Instruction(endInstruction).secondsToEndFromHere; + return SecondsToTime(secondsToEndFromStart - secondsToEndFromEnd); + } + + internal string GetLayerFanSpeeds(int activeLayerIndex) + { + if (loadedGCode == null) + { + return "---"; + } + + int startInstruction = loadedGCode.GetInstructionIndexAtLayer(activeLayerIndex); + if(activeLayerIndex == 0) + { + startInstruction = 0; + } + int endInstruction = loadedGCode.GetInstructionIndexAtLayer(activeLayerIndex + 1); + + string separator = ""; + string fanSpeeds = ""; + for (int i = startInstruction; i < endInstruction; i++) + { + var line = loadedGCode.Instruction(i).Line; + if (line.StartsWith("M107")) // fan off + { + fanSpeeds += separator + "Off"; + separator = ", "; + } + else if(line.StartsWith("M106")) // fan on + { + double speed = 0; + if (GCodeFile.GetFirstNumberAfter("M106", line, ref speed, 0, "")) + { + fanSpeeds += separator + $"{speed/255*100:0}%"; + separator = ", "; + } + } + } + + return fanSpeeds; + } + public double TotalCost { get diff --git a/PartPreviewWindow/GCodeDetails/GCodeDetailsView.cs b/PartPreviewWindow/GCodeDetails/GCodeDetailsView.cs new file mode 100644 index 000000000..1e9f893ad --- /dev/null +++ b/PartPreviewWindow/GCodeDetails/GCodeDetailsView.cs @@ -0,0 +1,120 @@ +/* +Copyright (c) 2017, 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.Collections.Generic; +using System.Collections.ObjectModel; +using MatterHackers.Agg; +using MatterHackers.Agg.UI; +using MatterHackers.Localizations; +using MatterHackers.MatterControl.SlicerConfiguration; +using MatterHackers.MeshVisualizer; +using MatterHackers.RenderOpenGl; + +namespace MatterHackers.MatterControl.PartPreviewWindow +{ + public class GCodeDetailsView : FlowLayoutWidget + { + private TextWidget massTextWidget; + private TextWidget costTextWidget; + + private EventHandler unregisterEvents; + + public GCodeDetailsView(GCodeDetails gcodeDetails, int dataPointSize, int headingPointSize) + : base(FlowDirection.TopToBottom) + { + var margin = new BorderDouble(0, 9, 0, 3); + + TextWidget AddSetting(string title, string value, GuiWidget parentWidget) + { + parentWidget.AddChild( + new TextWidget(title + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: headingPointSize) + { + HAnchor = HAnchor.Left + }); + + var textWidget = new TextWidget(value, textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: dataPointSize) + { + HAnchor = HAnchor.Left, + Margin = margin + }; + + parentWidget.AddChild(textWidget); + + return textWidget; + } + + // put in the print time + AddSetting("Print Time".Localize(), gcodeDetails.EstimatedPrintTime, this); + + // show the filament used + AddSetting("Filament Length".Localize(), gcodeDetails.FilamentUsed, this); + + AddSetting("Filament Volume".Localize(), gcodeDetails.FilamentVolume, this); + + massTextWidget = AddSetting("Estimated Mass".Localize(), gcodeDetails.EstimatedMass, this); + + // Cost info is only displayed when available - conditionalCostPanel is invisible when cost <= 0 + var conditionalCostPanel = new FlowLayoutWidget(FlowDirection.TopToBottom) + { + HAnchor = HAnchor.Stretch, + VAnchor = VAnchor.Fit, + Visible = gcodeDetails.TotalCost > 0 + }; + this.AddChild(conditionalCostPanel); + + costTextWidget = AddSetting("Estimated Cost".Localize(), gcodeDetails.EstimatedCost, conditionalCostPanel); + + ActiveSliceSettings.SettingChanged.RegisterEvent((s, e) => + { + if (e is StringEventArgs stringEvent) + { + if (stringEvent.Data == SettingsKey.filament_cost + || stringEvent.Data == SettingsKey.filament_diameter + || stringEvent.Data == SettingsKey.filament_density) + { + massTextWidget.Text = gcodeDetails.EstimatedMass; + conditionalCostPanel.Visible = gcodeDetails.TotalCost > 0; + + if (gcodeDetails.TotalCost > 0) + { + costTextWidget.Text = gcodeDetails.EstimatedCost; + } + } + } + }, ref unregisterEvents); + } + + public override void OnClosed(ClosedEventArgs e) + { + unregisterEvents?.Invoke(this, null); + base.OnClosed(e); + } + } +} diff --git a/PartPreviewWindow/GCodeDetails/GCodeLayerDetailsView.cs b/PartPreviewWindow/GCodeDetails/GCodeLayerDetailsView.cs new file mode 100644 index 000000000..a84534ac9 --- /dev/null +++ b/PartPreviewWindow/GCodeDetails/GCodeLayerDetailsView.cs @@ -0,0 +1,107 @@ +/* +Copyright (c) 2017, 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.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using MatterHackers.Agg; +using MatterHackers.Agg.Platform; +using MatterHackers.Agg.UI; +using MatterHackers.Localizations; +using MatterHackers.MatterControl.ConfigurationPage; +using MatterHackers.MatterControl.CustomWidgets; +using MatterHackers.MatterControl.SlicerConfiguration; +using MatterHackers.MeshVisualizer; +using MatterHackers.RenderOpenGl; + +namespace MatterHackers.MatterControl.PartPreviewWindow +{ + public class GCodeLayerDetailsView : FlowLayoutWidget + { + private TextWidget massTextWidget; + private TextWidget costTextWidget; + private BedConfig sceneContext; + + private EventHandler unregisterEvents; + + public GCodeLayerDetailsView(GCodeDetails gcodeDetails, BedConfig sceneContext, int dataPointSize, int headingPointSize) + : base(FlowDirection.TopToBottom) + { + this.sceneContext = sceneContext; + var margin = new BorderDouble(0, 9, 0, 3); + + // local function to add setting + TextWidget AddSetting(string title, string value, GuiWidget parentWidget) + { + parentWidget.AddChild( + new TextWidget(title + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: headingPointSize) + { + HAnchor = HAnchor.Left + }); + + var textWidget = new TextWidget(value, textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: dataPointSize) + { + HAnchor = HAnchor.Left, + Margin = margin, + AutoExpandBoundsToText = true + }; + + parentWidget.AddChild(textWidget); + + return textWidget; + } + + GuiWidget layerTime = AddSetting("Time".Localize(), "", this); + GuiWidget layerHeight = AddSetting("Height".Localize(), "", this); + GuiWidget layerWidth = AddSetting("Z Offset".Localize(), "", this); + GuiWidget layerFanSpeeds = AddSetting("Fan Speed".Localize(), "", this); + + void UpdateLayerDisplay(object sender, EventArgs e) + { + layerTime.Text = gcodeDetails.LayerTime(sceneContext.ActiveLayerIndex); + layerHeight.Text = $"{gcodeDetails.GetLayerHeight(sceneContext.ActiveLayerIndex):0.###}"; + layerWidth.Text = $"{gcodeDetails.GetLayerZOffset(sceneContext.ActiveLayerIndex):0.###}"; + var fanSpeed = gcodeDetails.GetLayerFanSpeeds(sceneContext.ActiveLayerIndex); + layerFanSpeeds.Text = string.IsNullOrWhiteSpace(fanSpeed) ? "Unchanged" : fanSpeed; + } + + sceneContext.ActiveLayerChanged += UpdateLayerDisplay; + // and do the initial setting + UpdateLayerDisplay(this, null); + } + + public override void OnClosed(ClosedEventArgs e) + { + unregisterEvents?.Invoke(this, null); + base.OnClosed(e); + } + } +} diff --git a/PartPreviewWindow/GCodeDetailsView.cs b/PartPreviewWindow/GCodeDetails/GCodeOptionsPanel.cs similarity index 73% rename from PartPreviewWindow/GCodeDetailsView.cs rename to PartPreviewWindow/GCodeDetails/GCodeOptionsPanel.cs index 0858a0763..1891aee7f 100644 --- a/PartPreviewWindow/GCodeDetailsView.cs +++ b/PartPreviewWindow/GCodeDetails/GCodeOptionsPanel.cs @@ -27,8 +27,6 @@ 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.Collections.ObjectModel; using System.ComponentModel; using System.Linq; @@ -39,42 +37,9 @@ using MatterHackers.Localizations; using MatterHackers.MatterControl.ConfigurationPage; using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.MatterControl.SlicerConfiguration; -using MatterHackers.MeshVisualizer; -using MatterHackers.RenderOpenGl; namespace MatterHackers.MatterControl.PartPreviewWindow { - public interface IToggleOption - { - string Title { get; } - Func IsChecked { get; } - Action SetValue { get; } - } - - public class BoolOption : IToggleOption - { - public string Title { get; } - - public Func IsChecked { get; } - - public Func IsVisible { get; } - - public Action SetValue { get; } - - public BoolOption(string title, Func isChecked, Action setValue) - : this(title, isChecked, setValue, () => true) - { - } - - public BoolOption(string title, Func isChecked, Action setValue, Func isVisible) - { - this.Title = title; - this.IsChecked = isChecked; - this.SetValue = setValue; - this.IsVisible = isVisible; - } - } - public class GCodeOptionsPanel : FlowLayoutWidget { private RadioIconButton speedsButton; @@ -324,83 +289,4 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } } } - - public class GCodeDetailsView : FlowLayoutWidget - { - private TextWidget massTextWidget; - private TextWidget costTextWidget; - - private EventHandler unregisterEvents; - - public GCodeDetailsView(GCodeDetails gcodeDetails, int dataPointSize, int headingPointSize) - : base(FlowDirection.TopToBottom) - { - var margin = new BorderDouble(0, 9, 0, 3); - - TextWidget AddSetting(string title, string value, GuiWidget parentWidget) - { - parentWidget.AddChild( - new TextWidget(title + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: headingPointSize) - { - HAnchor = HAnchor.Left - }); - - var textWidget = new TextWidget(value, textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: dataPointSize) - { - HAnchor = HAnchor.Left, - Margin = margin - }; - - parentWidget.AddChild(textWidget); - - return textWidget; - } - - // put in the print time - AddSetting("Print Time".Localize(), gcodeDetails.EstimatedPrintTime, this); - - // show the filament used - AddSetting("Filament Length".Localize(), gcodeDetails.FilamentUsed, this); - - AddSetting("Filament Volume".Localize(), gcodeDetails.FilamentVolume, this); - - massTextWidget = AddSetting("Estimated Mass".Localize(), gcodeDetails.EstimatedMass, this); - - // Cost info is only displayed when available - conditionalCostPanel is invisible when cost <= 0 - var conditionalCostPanel = new FlowLayoutWidget(FlowDirection.TopToBottom) - { - HAnchor = HAnchor.Stretch, - VAnchor = VAnchor.Fit, - Visible = gcodeDetails.TotalCost > 0 - }; - this.AddChild(conditionalCostPanel); - - costTextWidget = AddSetting("Estimated Cost".Localize(), gcodeDetails.EstimatedCost, conditionalCostPanel); - - ActiveSliceSettings.SettingChanged.RegisterEvent((s, e) => - { - if (e is StringEventArgs stringEvent) - { - if (stringEvent.Data == SettingsKey.filament_cost - || stringEvent.Data == SettingsKey.filament_diameter - || stringEvent.Data == SettingsKey.filament_density) - { - massTextWidget.Text = gcodeDetails.EstimatedMass; - conditionalCostPanel.Visible = gcodeDetails.TotalCost > 0; - - if (gcodeDetails.TotalCost > 0) - { - costTextWidget.Text = gcodeDetails.EstimatedCost; - } - } - } - }, ref unregisterEvents); - } - - public override void OnClosed(ClosedEventArgs e) - { - unregisterEvents?.Invoke(this, null); - base.OnClosed(e); - } - } } diff --git a/PartPreviewWindow/GCodeDetails/IToggleOption.cs b/PartPreviewWindow/GCodeDetails/IToggleOption.cs new file mode 100644 index 000000000..1f794d5c9 --- /dev/null +++ b/PartPreviewWindow/GCodeDetails/IToggleOption.cs @@ -0,0 +1,40 @@ +/* +Copyright (c) 2017, 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.PartPreviewWindow +{ + public interface IToggleOption + { + string Title { get; } + Func IsChecked { get; } + Action SetValue { get; } + } +} diff --git a/Submodules/MatterSlice b/Submodules/MatterSlice index 4361510b6..1cec8e732 160000 --- a/Submodules/MatterSlice +++ b/Submodules/MatterSlice @@ -1 +1 @@ -Subproject commit 4361510b6188eea9d2b45f99fcab72c542a82dd9 +Subproject commit 1cec8e732bb95f09fdad483470f8afa84de670e8 diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index a7bdd9279..1ec939790 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit a7bdd9279952b7bf880bffa25c796c0c8af79030 +Subproject commit 1ec9397907ccc1a191421c10278ceec0d99b7687