diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2022-10-30 02:52:49 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2022-10-30 02:52:49 +0300 |
commit | 6dc26f74342411760a5905860ef863ece03a3239 (patch) | |
tree | 5e706336595126cccc175c7af4c182df9ce4f6a0 /UVtools.Core | |
parent | 38201dfb83e46ee269cd940c5684dd4e97bc61fe (diff) |
v3.8.0v3.8.0
- **File formats:**
- (Add) Property: DisplayTotalOnTime
- (Add) Property: DisplayTotalOffTime
- (Add) SL1File Property: high_viscosity_tilt_time
- **Tools**
- **I printed this file**
- (Add) Display on time for the print information
- (Improvement) Labels on numeric box
- (Improvement) Show print time label formatted as hh:mm:ss
- **PCB Exposure:**
- (Improvement) Increase "Exposure time" maximum from 200s to 1000s (#592)
- (Fix) Set `BottomLightHeight` to 0
- (Fix) Set `TransitionLayerCount` to 0
- **Issues:**
- (Improvement) Overhang detection by using a dynamic cross kernel
- (Improvement) Bring back the discard logic of "false-positive" islands based on overhang detection but improve the threshold of the detection to be safer (#591, #591)
- **PrusaSlicer:**
- (Change) Elegoo Mars 2 to use file version 4
- (Change) Elegoo Mars 2 Pro to use file version 4
- (Add) Status bar: On and Off time (hh:mm:ss) as tooltip in the Print time label
- (Improvement) When any of libcvextern dependencies are missing, it try to show the missing libraries in the error message (Linux only)
- (Improvement) Auto-upgrade procedure for non-Windows systems
- (Improvement) macOS arm64 (M1/M2) can now run natively if installed via the auto installer script
- (Fix) Error on Mat cache manager when file have only one layer
- (Fix) Suggestion "Transition layer count" shows as never applied when using with file formats that use in-firmware transition layers
- (Upgrade) openCV from 4.5.4 to 4.6.0
- Custom library is now built to strip unused dependencies and reduce library size
- (Remove) arch and rhel packages in favor of a generic linux
Diffstat (limited to 'UVtools.Core')
-rw-r--r-- | UVtools.Core/Extensions/RectangleExtensions.cs | 9 | ||||
-rw-r--r-- | UVtools.Core/FileFormats/FileFormat.cs | 50 | ||||
-rw-r--r-- | UVtools.Core/FileFormats/SL1File.cs | 3 | ||||
-rw-r--r-- | UVtools.Core/Managers/IssueManager.cs | 49 | ||||
-rw-r--r-- | UVtools.Core/Managers/KernelCacheManager.cs | 5 | ||||
-rw-r--r-- | UVtools.Core/Managers/MatCacheManager.cs | 2 | ||||
-rw-r--r-- | UVtools.Core/Objects/KernelConfiguration.cs | 14 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationCalculator.cs | 3 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationIPrintedThisFile.cs | 16 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationPCBExposure.cs | 8 | ||||
-rw-r--r-- | UVtools.Core/Printer/Machine.cs | 32 | ||||
-rw-r--r-- | UVtools.Core/Suggestions/SuggestionTransitionLayerCount.cs | 21 | ||||
-rw-r--r-- | UVtools.Core/UVtools.Core.csproj | 8 |
13 files changed, 172 insertions, 48 deletions
diff --git a/UVtools.Core/Extensions/RectangleExtensions.cs b/UVtools.Core/Extensions/RectangleExtensions.cs index 7678488..05fbb41 100644 --- a/UVtools.Core/Extensions/RectangleExtensions.cs +++ b/UVtools.Core/Extensions/RectangleExtensions.cs @@ -16,4 +16,13 @@ public static class RectangleExtensions return new Point(src.Left + src.Width / 2, src.Top + src.Height / 2); } + public static Rectangle OffsetBy(this Rectangle src, int x, int y) + { + var rect = src; + rect.Offset(x, y); + return rect; + } + + public static Rectangle OffsetBy(this Rectangle src, Point position) => src.OffsetBy(position.X, position.Y); + }
\ No newline at end of file diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs index a252117..136fe24 100644 --- a/UVtools.Core/FileFormats/FileFormat.cs +++ b/UVtools.Core/FileFormats/FileFormat.cs @@ -2746,6 +2746,10 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor if(!RaiseAndSetIfChanged(ref _printTime, value)) return; RaisePropertyChanged(nameof(PrintTimeHours)); RaisePropertyChanged(nameof(PrintTimeString)); + RaisePropertyChanged(nameof(DisplayTotalOnTime)); + RaisePropertyChanged(nameof(DisplayTotalOnTimeString)); + RaisePropertyChanged(nameof(DisplayTotalOffTime)); + RaisePropertyChanged(nameof(DisplayTotalOffTimeString)); } } @@ -2843,7 +2847,45 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor get { var printTime = PrintTime; - return TimeSpan.FromSeconds(printTime >= float.PositiveInfinity ? 0 : printTime).ToString("hh\\hmm\\m"); + return TimeSpan.FromSeconds(float.IsPositiveInfinity(printTime) || float.IsNaN(printTime) ? 0 : printTime).ToString("hh\\hmm\\m"); + } + } + + /// <summary> + /// Gets the total time in seconds the display will remain on exposing the layers during the print + /// </summary> + public float DisplayTotalOnTime => (float)Math.Round(this.Sum(layer => layer.ExposureTime), 2); + + /// <summary> + /// Gets the total time formatted in hours, minutes and seconds the display will remain on exposing the layers during the print + /// </summary> + public string DisplayTotalOnTimeString => TimeSpan.FromSeconds(DisplayTotalOnTime).ToString("hh\\hmm\\mss\\s"); + + /// <summary> + /// Gets the total time in seconds the display will remain off during the print. + /// This is the difference between <see cref="PrintTime"/> and <see cref="DisplayTotalOnTime"/> + /// </summary> + public float DisplayTotalOffTime + { + get + { + var printTime = PrintTime; + if (float.IsPositiveInfinity(printTime) || float.IsNaN(printTime)) return float.NaN; + var value = (float) Math.Round(PrintTime - DisplayTotalOnTime, 2); + return value <= 0 ? float.NaN : value; + } + } + + /// <summary> + /// Gets the total time formatted in hours, minutes and seconds the display will remain off during the print. + /// This is the difference between <see cref="PrintTime"/> and <see cref="DisplayTotalOnTime"/> + /// </summary> + public string DisplayTotalOffTimeString + { + get + { + var time = DisplayTotalOffTime; + return TimeSpan.FromSeconds(float.IsPositiveInfinity(time) || float.IsNaN(time) ? 0 : time).ToString("hh\\hmm\\mss\\s"); } } @@ -3916,6 +3958,12 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor } /// <summary> + /// Gets the transition step time from <see cref="BottomExposureTime"/> and <see cref="ExposureTime"/>, value is returned as positive from normal perspective and logic (Longer - shorter) + /// </summary> + /// <returns>Seconds</returns> + public float GetTransitionStepTime() => GetTransitionStepTime(TransitionLayerCount); + + /// <summary> /// Gets the transition layer count based on long and short exposure time /// </summary> /// <param name="longExposureTime">The long exposure time</param> diff --git a/UVtools.Core/FileFormats/SL1File.cs b/UVtools.Core/FileFormats/SL1File.cs index 417e71d..21af6a3 100644 --- a/UVtools.Core/FileFormats/SL1File.cs +++ b/UVtools.Core/FileFormats/SL1File.cs @@ -100,6 +100,7 @@ public class SL1File : FileFormat public float FastTiltTime { get; set; } = 5; public float SlowTiltTime { get; set; } = 8; + public float HighViscosityTiltTime { get; set; } = 10; public float AreaFill { get; set; } = 50; #endregion @@ -312,7 +313,7 @@ public class SL1File : FileFormat public string PrinterModel { get; set; } = "SL1"; public string PrinterProfile { get; set; } = About.Software; public string PrinterVariant { get; set; } = "default"; - public string PrusaSlicerVersion { get; set; } = "PrusaSlicer-2.3.3+win64-202107161027"; + public string PrusaSlicerVersion { get; set; } = "PrusaSlicer-2.5.0+win64-202209060714"; public float UsedMaterial { get; set; } public override string ToString() diff --git a/UVtools.Core/Managers/IssueManager.cs b/UVtools.Core/Managers/IssueManager.cs index 2a3f333..80d02d0 100644 --- a/UVtools.Core/Managers/IssueManager.cs +++ b/UVtools.Core/Managers/IssueManager.cs @@ -192,6 +192,9 @@ public sealed class IssueManager : RangeObservableCollection<MainIssue> var firstLayer = SlicerFile.FirstLayer; + int overhangsIterations = overhangConfig.ErodeIterations; + using var overhangsKernel = EmguExtensions.GetDynamicKernel(ref overhangsIterations, ElementShape.Cross); + // Detect contours Parallel.For(0, SlicerFile.LayerCount, CoreSettings.ParallelOptions, layerIndexInt => { @@ -330,7 +333,8 @@ public sealed class IssueManager : RangeObservableCollection<MainIssue> // Overhangs - var overhangCount = 0; + //var overhangCount = 0; + var overhangs = new List<MainIssue>(); //if (!islandConfig.Enabled && overhangConfig.Enabled || // (islandConfig.Enabled && overhangConfig.Enabled && overhangConfig.IndependentFromIslands)) if (overhangConfig.Enabled) @@ -354,8 +358,8 @@ public sealed class IssueManager : RangeObservableCollection<MainIssue> CvInvoke.Subtract(image.RoiMat, previousImage.RoiMat, overhangImage); CvInvoke.Threshold(overhangImage, overhangImage, 127, 255, ThresholdType.Binary); - CvInvoke.Erode(overhangImage, overhangImage, EmguExtensions.Kernel3x3Rectangle, - EmguExtensions.AnchorCenter, overhangConfig.ErodeIterations, BorderType.Default, default); + CvInvoke.Erode(overhangImage, overhangImage, overhangsKernel, + EmguExtensions.AnchorCenter, overhangsIterations, BorderType.Default, default); //CvInvoke.MorphologyEx(subtractedImage, subtractedImage, MorphOp.Open, EmguExtensions.Kernel3x3Rectangle, // EmguExtensions.AnchorCenter, 2, BorderType.Reflect101, default); @@ -366,12 +370,13 @@ public sealed class IssueManager : RangeObservableCollection<MainIssue> foreach (var contourGroup in contoursInGroups) { if (contourGroup[0].Size < 3) continue; // Single contour, single line, ignore - overhangCount++; var area = EmguContours.GetContourArea(contourGroup); if (area >= overhangConfig.RequiredPixelsToConsider) { var rect = CvInvoke.BoundingRectangle(contourGroup[0]); - AddIssue(new MainIssue(MainIssue.IssueType.Overhang, new IssueOfContours(layer, contourGroup.ToArrayOfArray(), rect, area))); + var overhangIssue = new MainIssue(MainIssue.IssueType.Overhang, new IssueOfContours(layer, contourGroup.ToArrayOfArray(), rect, area)); + overhangs.Add(overhangIssue); + AddIssue(overhangIssue); } } } @@ -481,16 +486,20 @@ public sealed class IssueManager : RangeObservableCollection<MainIssue> pixelsSupportingIsland >= Math.Max(1, points.Count / 2)) isIsland = false; // Not a island, but maybe weak bounding...*/ - IssueOfPoints? island = null; - if (pixelsSupportingIsland < requiredSupportingPixels) - { - island = new IssueOfPoints(layer, points.ToArray(), new Rectangle(rect.Location.OffsetBy(image.RoiLocation), rect.Size)); - } + if (pixelsSupportingIsland >= requiredSupportingPixels) continue; + + var islandBoundingRectangle = rect.OffsetBy(image.RoiLocation); // Check for overhangs in islands - if (island is not null && islandConfig.EnhancedDetection && pixelsSupportingIsland >= 10 && - (!overhangConfig.Enabled || (overhangConfig.Enabled && overhangCount > 0))) + if (islandConfig.EnhancedDetection && pixelsSupportingIsland >= 10 && pixelsSupportingIsland >= requiredSupportingPixels / 4) + // && (!overhangConfig.Enabled || (overhangConfig.Enabled && overhangCount > 0)) { + if (overhangConfig.Enabled && // No overhangs nor intersecting = discard island + overhangs.TrueForAll(overhang => !overhang.BoundingRectangle.IntersectsWith(islandBoundingRectangle))) + { + continue; + } + using var islandRoi = image.RoiMat.Roi(rect); using var previousIslandRoi = previousImage.RoiMat.Roi(rect); @@ -501,8 +510,8 @@ public sealed class IssueManager : RangeObservableCollection<MainIssue> CvInvoke.Subtract(islandRoi, previousIslandRoi, islandOverhangMat); CvInvoke.Threshold(islandOverhangMat, islandOverhangMat, 127, 255, ThresholdType.Binary); - CvInvoke.Erode(islandOverhangMat, islandOverhangMat, EmguExtensions.Kernel3x3Rectangle, - EmguExtensions.AnchorCenter, overhangConfig.ErodeIterations, BorderType.Default, default); + CvInvoke.Erode(islandOverhangMat, islandOverhangMat, overhangsKernel, + EmguExtensions.AnchorCenter, overhangsIterations, BorderType.Default, default); } using var subtractedImage = islandOverhangMat.Roi(rect); @@ -517,22 +526,20 @@ public sealed class IssueManager : RangeObservableCollection<MainIssue> { int labelX = rect.X + x; int labelY = rect.Y + y; - if (labelSpan[labelY, labelX] != i || subtractedSpan.DangerousGetReferenceAt(y, x) == 0) - continue; + if (labelSpan[labelY, labelX] != i || subtractedSpan.DangerousGetReferenceAt(y, x) == 0) continue; overhangPixels++; } - if(!ReferenceEquals(overhangImage, islandOverhangMat)) islandOverhangMat.Dispose(); + if (!ReferenceEquals(overhangImage, islandOverhangMat)) islandOverhangMat.Dispose(); if (overhangPixels < overhangConfig.RequiredPixelsToConsider) // No overhang = no island { - island = null; + continue; } - } - - if (island is not null) AddIssue(new MainIssue(MainIssue.IssueType.Island, island)); + + AddIssue(new MainIssue(MainIssue.IssueType.Island, new IssueOfPoints(layer, points, islandBoundingRectangle))); } } } diff --git a/UVtools.Core/Managers/KernelCacheManager.cs b/UVtools.Core/Managers/KernelCacheManager.cs index 909eafd..340c45c 100644 --- a/UVtools.Core/Managers/KernelCacheManager.cs +++ b/UVtools.Core/Managers/KernelCacheManager.cs @@ -9,6 +9,7 @@ using Emgu.CV; using System; using System.Collections.Concurrent; +using Emgu.CV.CvEnum; using UVtools.Core.Extensions; namespace UVtools.Core.Managers; @@ -19,6 +20,8 @@ public class KernelCacheManager : IDisposable public bool UseDynamicKernel { get; set; } + public ElementShape DynamicKernelShape { get; set; } = ElementShape.Ellipse; + private readonly Mat _defaultKernel; public KernelCacheManager(bool useDynamicKernel = false, Mat? defaultKernel = null) @@ -30,7 +33,7 @@ public class KernelCacheManager : IDisposable public Mat Get(ref int iterations) { if (!UseDynamicKernel) return _defaultKernel; - var mat = _kernelCache.GetOrAdd(iterations, i => EmguExtensions.GetDynamicKernel(ref i)); + var mat = _kernelCache.GetOrAdd(iterations, i => EmguExtensions.GetDynamicKernel(ref i, DynamicKernelShape)); iterations = 1; return mat; } diff --git a/UVtools.Core/Managers/MatCacheManager.cs b/UVtools.Core/Managers/MatCacheManager.cs index 9ffef33..79a36de 100644 --- a/UVtools.Core/Managers/MatCacheManager.cs +++ b/UVtools.Core/Managers/MatCacheManager.cs @@ -105,7 +105,7 @@ public class MatCacheManager : IDisposable public MatCacheManager(FileFormat slicerFile, uint layerIndexStart, uint layerIndexEnd, ushort cacheCount = 0, byte elementsPerCache = 1) { if (cacheCount == 0) cacheCount = (ushort)(Environment.ProcessorCount * 5); - if (layerIndexEnd == 0) layerIndexEnd = slicerFile.LayerCount; + if (layerIndexEnd == 0) layerIndexEnd = slicerFile.LayerCount > 0 ? slicerFile.LayerCount - 1 : 0; SlicerFile = slicerFile; LayerIndexStart = layerIndexStart; LayerIndexEnd = layerIndexEnd; diff --git a/UVtools.Core/Objects/KernelConfiguration.cs b/UVtools.Core/Objects/KernelConfiguration.cs index dac6fce..9c967bb 100644 --- a/UVtools.Core/Objects/KernelConfiguration.cs +++ b/UVtools.Core/Objects/KernelConfiguration.cs @@ -32,6 +32,8 @@ public sealed class KernelConfiguration : BindableBase, IDisposable private int _anchorY = -1; private Mat? _kernelMat; private readonly object _mutex = new(); + private ElementShape _dynamicKernelShape = ElementShape.Ellipse; + #endregion #region Properties @@ -45,6 +47,16 @@ public sealed class KernelConfiguration : BindableBase, IDisposable } } + public ElementShape DynamicKernelShape + { + get => _dynamicKernelShape; + set + { + if (!RaiseAndSetIfChanged(ref _dynamicKernelShape, value)) return; + _kernelCache.DynamicKernelShape = value; + } + } + public int AnchorX { get => _anchorX; @@ -227,7 +239,7 @@ public sealed class KernelConfiguration : BindableBase, IDisposable public Mat? GetKernel(ref int iterations) { - if (!UseDynamicKernel) return KernelMat; + if (!_useDynamicKernel) return KernelMat; return _kernelCache.Get(ref iterations); } diff --git a/UVtools.Core/Operations/OperationCalculator.cs b/UVtools.Core/Operations/OperationCalculator.cs index ec529cc..1be34b5 100644 --- a/UVtools.Core/Operations/OperationCalculator.cs +++ b/UVtools.Core/Operations/OperationCalculator.cs @@ -60,8 +60,7 @@ public class OperationCalculator : Operation (decimal)SlicerFile.LiftHeight, (decimal)SlicerFile.BottomLiftHeight, (decimal)SlicerFile.LiftSpeed, (decimal)SlicerFile.BottomLiftSpeed, (decimal)SlicerFile.RetractSpeed, (decimal)SlicerFile.RetractSpeed); - CalcOptimalModelTilt = new OptimalModelTilt(SlicerFile.Resolution, SlicerFile.Display, - (decimal)SlicerFile.LayerHeight); + CalcOptimalModelTilt = new OptimalModelTilt(SlicerFile.Resolution, SlicerFile.Display, (decimal)SlicerFile.LayerHeight); } #endregion diff --git a/UVtools.Core/Operations/OperationIPrintedThisFile.cs b/UVtools.Core/Operations/OperationIPrintedThisFile.cs index 8dbdf3d..f29cb1c 100644 --- a/UVtools.Core/Operations/OperationIPrintedThisFile.cs +++ b/UVtools.Core/Operations/OperationIPrintedThisFile.cs @@ -39,7 +39,7 @@ public class OperationIPrintedThisFile : Operation public override string Description => "Select a material and consume resin from stock and print time."; public override string ConfirmationText => - $"consume {FinalVolume}ml and {FinalPrintTimeHours:F4}h on:\n{_materialItem} ?"; + $"consume {FinalVolume}ml and {FinalPrintTimeString:F4}h on:\n{_materialItem} ?"; public override string ProgressTitle => $"Consuming"; @@ -68,7 +68,7 @@ public class OperationIPrintedThisFile : Operation public override string ToString() { - var result = $"{FinalVolume}ml {FinalPrintTimeHours:F4}h on {_materialItem?.Name}"; + var result = $"{FinalVolume}ml {FinalPrintTimeString:F4}h on {_materialItem?.Name}"; if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}"; return result; } @@ -87,7 +87,7 @@ public class OperationIPrintedThisFile : Operation get => _volume; set { - if(!RaiseAndSetIfChanged(ref _volume, value)) return; + if(!RaiseAndSetIfChanged(ref _volume, Math.Max(0, value))) return; RaisePropertyChanged(nameof(FinalVolume)); } } @@ -99,16 +99,16 @@ public class OperationIPrintedThisFile : Operation get => _printTime; set { - if(!RaiseAndSetIfChanged(ref _printTime, value)) return; - RaisePropertyChanged(nameof(PrintTimeHours)); + if(!RaiseAndSetIfChanged(ref _printTime, Math.Max(0, value))) return; + RaisePropertyChanged(nameof(PrintTimeString)); RaisePropertyChanged(nameof(FinalPrintTime)); - RaisePropertyChanged(nameof(FinalPrintTimeHours)); + RaisePropertyChanged(nameof(FinalPrintTimeString)); } } - public float PrintTimeHours => _printTime / 60 / 60; + public string PrintTimeString => TimeSpan.FromSeconds(_printTime).ToString("hh\\hmm\\mss\\s"); public float FinalPrintTime => _printTime * (float)_multiplier; - public float FinalPrintTimeHours => FinalPrintTime / 60 / 60; + public string FinalPrintTimeString => TimeSpan.FromSeconds(FinalPrintTime).ToString("hh\\hmm\\mss\\s"); /// <summary> /// Number of times this file has been printed diff --git a/UVtools.Core/Operations/OperationPCBExposure.cs b/UVtools.Core/Operations/OperationPCBExposure.cs index 3b50b45..017a1aa 100644 --- a/UVtools.Core/Operations/OperationPCBExposure.cs +++ b/UVtools.Core/Operations/OperationPCBExposure.cs @@ -145,7 +145,7 @@ public class OperationPCBExposure : Operation public decimal ExposureTime { get => _exposureTime; - set => RaiseAndSetIfChanged(ref _exposureTime, Math.Round(value, 2)); + set => RaiseAndSetIfChanged(ref _exposureTime, Math.Round(Math.Max(0, value), 2)); } public GerberMidpointRounding SizeMidpointRounding @@ -291,10 +291,16 @@ public class OperationPCBExposure : Operation SlicerFile.SuppressRebuildPropertiesWork(() => { SlicerFile.LayerHeight = (float) _layerHeight; + SlicerFile.TransitionLayerCount = 0; SlicerFile.BottomLayerCount = 1; SlicerFile.BottomExposureTime = (float) _exposureTime; SlicerFile.ExposureTime = (float)_exposureTime; + SlicerFile.BottomLiftHeightTotal = 0; SlicerFile.LiftHeightTotal = 0; + /*SlicerFile.BottomLiftSpeed = 300; + SlicerFile.BottomLiftSpeed2 = 300; + SlicerFile.LiftSpeed = 300; + SlicerFile.LiftSpeed2 = 300;*/ SlicerFile.SetNoDelays(); SlicerFile.Layers = layers.ToArray(); diff --git a/UVtools.Core/Printer/Machine.cs b/UVtools.Core/Printer/Machine.cs index 53a9b65..24d6a50 100644 --- a/UVtools.Core/Printer/Machine.cs +++ b/UVtools.Core/Printer/Machine.cs @@ -12,13 +12,20 @@ using System.Drawing; using System.IO; using System.Text; using UVtools.Core.Extensions; +using UVtools.Core.Objects; namespace UVtools.Core.Printer { - public class Machine + public class Machine : BindableBase { + #region Members + private float _totalPrintTime; + private float _totalDisplayOnTime; + #endregion + #region Properties - public PrinterBrand Brand { get; set; } + + public PrinterBrand Brand { get; set; } = PrinterBrand.Generic; public string Name { get; set; } = FileFormats.FileFormat.DefaultMachineName; public string Model { get; set; } = FileFormats.FileFormat.DefaultMachineName; @@ -35,6 +42,27 @@ namespace UVtools.Core.Printer public FlipDirection DisplayMirror { get; set; } public object? Tag { get; set; } + + public float TotalPrintTime + { + get => _totalPrintTime; + set => RaiseAndSetIfChanged(ref _totalPrintTime, (float)Math.Max(0f, Math.Round(value, 2))); + } + + public string TotalPrintTimeString => TimeSpan.FromSeconds(_totalPrintTime).ToString("hh\\hmm\\mss\\s"); + + public float TotalDisplayOnTime + { + get => _totalDisplayOnTime; + set => RaiseAndSetIfChanged(ref _totalDisplayOnTime, (float)Math.Max(0f, Math.Round(value, 2))); + } + + public string DisplayTotalOnTimeString => TimeSpan.FromSeconds(_totalDisplayOnTime).ToString("hh\\hmm\\mss\\s"); + + public float TotalDisplayOffTime => TotalPrintTime - TotalDisplayOnTime; + + public string DisplayTotalOffTimeString => TimeSpan.FromSeconds(TotalDisplayOffTime).ToString("hh\\hmm\\mss\\s"); + #endregion #region Constructor diff --git a/UVtools.Core/Suggestions/SuggestionTransitionLayerCount.cs b/UVtools.Core/Suggestions/SuggestionTransitionLayerCount.cs index 7cc84b5..433daf0 100644 --- a/UVtools.Core/Suggestions/SuggestionTransitionLayerCount.cs +++ b/UVtools.Core/Suggestions/SuggestionTransitionLayerCount.cs @@ -8,6 +8,7 @@ using System; using System.Text; +using UVtools.Core.FileFormats; using UVtools.Core.Operations; namespace UVtools.Core.Suggestions; @@ -47,7 +48,9 @@ public sealed class SuggestionTransitionLayerCount : Suggestion || SlicerFile.BottomLayerCount + _minimumTransitionLayerCount > SlicerFile.LayerCount || SlicerFile.MaximumPossibleTransitionLayerCount < _minimumTransitionLayerCount) return true; - var actualTransitionLayerCount = SlicerFile.ParseTransitionLayerCountFromLayers(); + var actualTransitionLayerCount = SlicerFile.TransitionLayerType == FileFormat.TransitionLayerTypes.Firmware + ? SlicerFile.TransitionLayerCount + : SlicerFile.ParseTransitionLayerCountFromLayers(); var suggestedTransitionLayerCount = TransitionLayerCount; if (actualTransitionLayerCount == suggestedTransitionLayerCount) return true; @@ -72,8 +75,12 @@ public sealed class SuggestionTransitionLayerCount : Suggestion { get { - var actualTransitionDecrementTime = SlicerFile.ParseTransitionStepTimeFromLayers(); - var actualTransitionLayerCount = SlicerFile.ParseTransitionLayerCountFromLayers(); + var actualTransitionDecrementTime = SlicerFile.TransitionLayerType == FileFormat.TransitionLayerTypes.Firmware + ? SlicerFile.GetTransitionStepTime() + : SlicerFile.ParseTransitionStepTimeFromLayers(); + var actualTransitionLayerCount = SlicerFile.TransitionLayerType == FileFormat.TransitionLayerTypes.Firmware + ? SlicerFile.TransitionLayerCount + : SlicerFile.ParseTransitionLayerCountFromLayers(); var suggestedTransitionLayerCount = TransitionLayerCount; var suggestedTransitionDecrementTime = SlicerFile.GetTransitionStepTime(suggestedTransitionLayerCount); @@ -93,8 +100,12 @@ public sealed class SuggestionTransitionLayerCount : Suggestion { get { - var actualTransitionDecrementTime = SlicerFile.ParseTransitionStepTimeFromLayers(); - var actualTransitionLayerCount = SlicerFile.ParseTransitionLayerCountFromLayers(); + var actualTransitionDecrementTime = SlicerFile.TransitionLayerType == FileFormat.TransitionLayerTypes.Firmware + ? SlicerFile.GetTransitionStepTime() + : SlicerFile.ParseTransitionStepTimeFromLayers(); + var actualTransitionLayerCount = SlicerFile.TransitionLayerType == FileFormat.TransitionLayerTypes.Firmware + ? SlicerFile.TransitionLayerCount + : SlicerFile.ParseTransitionLayerCountFromLayers(); var suggestedTransitionLayerCount = TransitionLayerCount; var suggestedTransitionDecrementTime = SlicerFile.GetTransitionStepTime(suggestedTransitionLayerCount); diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 0cd165f..350bf5a 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,7 +10,7 @@ <RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl> <PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl> <Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description> - <Version>3.7.2</Version> + <Version>3.8.0</Version> <Copyright>Copyright © 2020 PTRTECH</Copyright> <PackageIcon>UVtools.png</PackageIcon> <Platforms>AnyCPU;x64</Platforms> @@ -70,9 +70,9 @@ <PackageReference Include="AnimatedGif" Version="1.0.5" /> <PackageReference Include="BinarySerializer" Version="8.6.2.2" /> <PackageReference Include="CommunityToolkit.HighPerformance" Version="8.0.0" /> - <PackageReference Include="Emgu.CV" Version="4.5.5.4823" /> - <PackageReference Include="Emgu.CV.runtime.ubuntu.20.04-x64" Version="4.5.4.4788" /> - <PackageReference Include="Emgu.CV.runtime.windows" Version="4.5.4.4788" /> + <PackageReference Include="Emgu.CV" Version="4.6.0.5131" /> + <PackageReference Include="Emgu.CV.runtime.ubuntu-x64" Version="4.6.0.5131" /> + <PackageReference Include="Emgu.CV.runtime.windows" Version="4.6.0.5131" /> <PackageReference Include="K4os.Compression.LZ4" Version="1.2.16" /> <PackageReference Include="KdTree" Version="1.4.1" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.3.1" /> |