diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-05-11 21:10:36 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-05-11 21:10:36 +0300 |
commit | 3cd46728f1ca599d1f2211d9ff07273135d670af (patch) | |
tree | 0f322d5ae72f35be4a0b793d0f82c7825a2ceb4d /UVtools.Core | |
parent | dc0e90a61311b2d78104e46ac34c8faf382dcbd3 (diff) |
v2.11.1v2.11.1
- **Shortcuts:**
- (Add) (Ctrl + Shift + R) to turn on and cycle the Rotate modes
- (Add) (Ctrl + Shift + F) to turn on and cycle the Flip modes
- (Add) (Ctrl + Shift + B) to select the build volume as ROI
- **GUI:**
- (Add) Allow to drag and drop '.uvtop' files into UVtools to sequential show and load operations from files
- (Change) Rotate icon on layer preview
- (Upgrade) AvaloniaUI from 0.10.3 to 0.10.4
- **Tools:**
- (Add) 'Reset to defaults' button on every dialog
- (Improvement) Window size and position handling
- (Improvement) Constrain profile box width to not stretch the window
- (Improvement) ROI section design
- **Dynamic lift:**
- (Add) View buttons to show the largest/smallest layers
- (Add) Light-off mode: Set the light-off with an extra delay
- (Add) Light-off mode: Set the light-off without an extra delay
- (Add) Light-off mode: Set the light-off to zero
- (Improvement) Disable bottom and/or normal layer fields when the selected range is outside
- (Add) Settings - Automations: Light-off delay set modes
- (Fix) Exposure time finder: Add staircase, bullseye and counter triangles to feature count at thumbnail
Diffstat (limited to 'UVtools.Core')
22 files changed, 338 insertions, 118 deletions
diff --git a/UVtools.Core/Enumerations.cs b/UVtools.Core/Enumerations.cs index 45f7ad6..13f3f7a 100644 --- a/UVtools.Core/Enumerations.cs +++ b/UVtools.Core/Enumerations.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Text; namespace UVtools.Core @@ -31,5 +32,20 @@ namespace UVtools.Core BottomLeft, BottomCenter, BottomRight, None } + + public enum LightOffDelaySetMode : byte + { + [Description("Set the light-off with an extra delay")] + UpdateWithExtraDelay, + + [Description("Set the light-off without an extra delay")] + UpdateWithoutExtraDelay, + + [Description("Set the light-off to zero")] + SetToZero, + + [Description("Disabled")] + NoAction + } } } diff --git a/UVtools.Core/Extensions/IEnumerableExtensions.cs b/UVtools.Core/Extensions/IEnumerableExtensions.cs deleted file mode 100644 index 8fe6096..0000000 --- a/UVtools.Core/Extensions/IEnumerableExtensions.cs +++ /dev/null @@ -1,29 +0,0 @@ -/* - * GNU AFFERO GENERAL PUBLIC LICENSE - * Version 3, 19 November 2007 - * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> - * Everyone is permitted to copy and distribute verbatim copies - * of this license document, but changing it is not allowed. - */ - -using System; -using System.Collections.Generic; - -namespace UVtools.Core.Extensions -{ - public static class IEnumerableExtensions - { - public static IEnumerable<TSource> DistinctBy<TSource, TKey> - (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) - { - HashSet<TKey> seenKeys = new(); - foreach (var element in source) - { - if (seenKeys.Add(keySelector(element))) - { - yield return element; - } - } - } - } -} diff --git a/UVtools.Core/Extensions/TypeExtensions.cs b/UVtools.Core/Extensions/TypeExtensions.cs index d46e2cf..bc00201 100644 --- a/UVtools.Core/Extensions/TypeExtensions.cs +++ b/UVtools.Core/Extensions/TypeExtensions.cs @@ -16,9 +16,9 @@ namespace UVtools.Core.Extensions /// Creates a new instance of this type /// </summary> /// <param name="type"></param> - public static object CreateInstance(this Type type) + public static object CreateInstance(this Type type, params object[]? paramArray) { - return Activator.CreateInstance(type); + return Activator.CreateInstance(type, paramArray); } /// <summary> @@ -27,9 +27,9 @@ namespace UVtools.Core.Extensions /// <typeparam name="T">Target type</typeparam> /// <param name="type"></param> /// <returns>New instance of <see cref="T"/></returns> - public static T CreateInstance<T>(this Type type) + public static T CreateInstance<T>(this Type type, params object[]? paramArray) { - return (T)Activator.CreateInstance(type); + return (T)Activator.CreateInstance(type, paramArray); } public static byte ToByte(this bool value) => (byte)(value ? 1 : 0); diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs index a8be672..8b4e801 100644 --- a/UVtools.Core/FileFormats/FileFormat.cs +++ b/UVtools.Core/FileFormats/FileFormat.cs @@ -1957,6 +1957,44 @@ namespace UVtools.Core.FileFormats return changed; } + public float CalculateBottomLightOffDelay(float extraTime = 0) => CalculateLightOffDelay(true, extraTime); + + public bool SetBottomLightOffDelay(float extraTime = 0) => SetLightOffDelay(true, extraTime); + + public float CalculateNormalLightOffDelay(float extraTime = 0) => CalculateLightOffDelay(false, extraTime); + + public bool SetNormalLightOffDelay(float extraTime = 0) => SetLightOffDelay(false, extraTime); + + public float CalculateLightOffDelay(bool isBottomLayer, float extraTime = 0) + { + return isBottomLayer + ? OperationCalculator.LightOffDelayC.CalculateSeconds(BottomLiftHeight, BottomLiftSpeed, RetractSpeed, extraTime) + : OperationCalculator.LightOffDelayC.CalculateSeconds(LiftHeight, LiftSpeed, RetractSpeed, extraTime); + } + + public bool SetLightOffDelay(bool isBottomLayer, float extraTime = 0) + { + float lightOff = CalculateLightOffDelay(isBottomLayer, extraTime); + if (isBottomLayer) + { + if (BottomLightOffDelay != lightOff) + { + BottomLightOffDelay = lightOff; + return true; + } + + return false; + } + + if (LightOffDelay != lightOff) + { + LightOffDelay = lightOff; + return true; + } + + return false; + } + /// <summary> /// Rebuilds GCode based on current settings /// </summary> diff --git a/UVtools.Core/Layer/Layer.cs b/UVtools.Core/Layer/Layer.cs index 20fa46c..f9f9695 100644 --- a/UVtools.Core/Layer/Layer.cs +++ b/UVtools.Core/Layer/Layer.cs @@ -506,7 +506,7 @@ namespace UVtools.Core return OperationCalculator.LightOffDelayC.CalculateSeconds(_liftHeight, _liftSpeed, _retractSpeed, extraTime); } - public void UpdateLightOffDelay(float extraTime = 0) + public void SetLightOffDelay(float extraTime = 0) { LightOffDelay = CalculateLightOffDelay(extraTime); } diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs index ef9f907..df3a950 100644 --- a/UVtools.Core/Layer/LayerManager.cs +++ b/UVtools.Core/Layer/LayerManager.cs @@ -19,6 +19,7 @@ using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; using Emgu.CV.Util; +using MoreLinq.Extensions; using UVtools.Core.Extensions; using UVtools.Core.FileFormats; using UVtools.Core.Objects; @@ -91,6 +92,11 @@ namespace UVtools.Core } /// <summary> + /// Gets the last layer index + /// </summary> + public uint LastLayerIndex => LayerCount - 1; + + /// <summary> /// Gets the first layer /// </summary> public Layer FirstLayer => _layers?[0]; @@ -101,9 +107,35 @@ namespace UVtools.Core public Layer LastLayer => _layers?[^1]; /// <summary> - /// Gets the last layer index + /// Gets the smallest bottom layer using the pixel count /// </summary> - public uint LastLayerIndex => LayerCount - 1; + public Layer SmallestBottomLayer => _layers?.Where(layer => layer.IsBottomLayer && !layer.IsEmpty).MinBy(layer => layer.NonZeroPixelCount).FirstOrDefault(); + + /// <summary> + /// Gets the largest bottom layer using the pixel count + /// </summary> + public Layer LargestBottomLayer => _layers?.Where(layer => layer.IsBottomLayer && !layer.IsEmpty).MaxBy(layer => layer.NonZeroPixelCount).FirstOrDefault(); + + /// <summary> + /// Gets the smallest normal layer using the pixel count + /// </summary> + public Layer SmallestNormalLayer => _layers?.Where(layer => layer.IsNormalLayer && !layer.IsEmpty).MinBy(layer => layer.NonZeroPixelCount).FirstOrDefault(); + + /// <summary> + /// Gets the largest layer using the pixel count + /// </summary> + public Layer LargestNormalLayer => _layers?.Where(layer => layer.IsNormalLayer && !layer.IsEmpty).MaxBy(layer => layer.NonZeroPixelCount).FirstOrDefault(); + + /// <summary> + /// Gets the smallest normal layer using the pixel count + /// </summary> + public Layer SmallestLayer => _layers?.Where(layer => !layer.IsEmpty).MinBy(layer => layer.NonZeroPixelCount).FirstOrDefault(); + + /// <summary> + /// Gets the largest layer using the pixel count + /// </summary> + public Layer LargestLayer => _layers?.MaxBy(layer => layer.NonZeroPixelCount).FirstOrDefault(); + /// <summary> /// Gets the bounding rectangle of the object @@ -152,7 +184,7 @@ namespace UVtools.Core public void Add(Layer layer) { - Layers = _layers.Append(layer).ToArray(); + Layers = Enumerable.Append(_layers, layer).ToArray(); } public void Add(IEnumerable<Layer> layers) @@ -600,6 +632,16 @@ namespace UVtools.Core return _layers[index]; } + public Layer GetSmallestLayerBetween(uint layerStartIndex, uint layerEndIndex) + { + return _layers?.Where((layer, index) => !layer.IsEmpty && index >= layerStartIndex && index <= layerEndIndex).MinBy(layer => layer.NonZeroPixelCount).FirstOrDefault(); + } + + public Layer GetLargestLayerBetween(uint layerStartIndex, uint layerEndIndex) + { + return _layers?.Where((layer, index) => !layer.IsEmpty && index >= layerStartIndex && index <= layerEndIndex).MaxBy(layer => layer.NonZeroPixelCount).FirstOrDefault(); + } + public static void MutateGetVarsIterationChamfer(uint startLayerIndex, uint endLayerIndex, int iterationsStart, int iterationsEnd, ref bool isFade, out float iterationSteps, out int maxIteration) { iterationSteps = 0; diff --git a/UVtools.Core/Managers/ClipboardManager.cs b/UVtools.Core/Managers/ClipboardManager.cs index e26dda3..2fbd6ab 100644 --- a/UVtools.Core/Managers/ClipboardManager.cs +++ b/UVtools.Core/Managers/ClipboardManager.cs @@ -13,11 +13,14 @@ using System.Diagnostics; using System.Linq; using UVtools.Core.FileFormats; using UVtools.Core.Objects; +using UVtools.Core.Operations; namespace UVtools.Core.Managers { public sealed class ClipboardItem : List<Layer> { + private Operation _operation; + #region Properties /// <summary> @@ -34,8 +37,16 @@ namespace UVtools.Core.Managers public bool IsFullBackup { get; set; } - - public Operations.Operation Operation { get; set; } + + public Operations.Operation Operation + { + get => _operation; + set + { + _operation = value; + _operation.ImportedFrom = Operation.OperationImportFrom.Undo; + } + } #endregion diff --git a/UVtools.Core/Managers/OperationSessionManager.cs b/UVtools.Core/Managers/OperationSessionManager.cs index f62093d..02b18bc 100644 --- a/UVtools.Core/Managers/OperationSessionManager.cs +++ b/UVtools.Core/Managers/OperationSessionManager.cs @@ -72,7 +72,10 @@ namespace UVtools.Core.Managers { if (item is null) return; _operations.RemoveAll(operation => operation.GetType() == item.GetType()); - _operations.Add(item.Clone()); + var operation = item.Clone(); + operation.ClearROIandMasks(); + operation.ImportedFrom = Operation.OperationImportFrom.Session; + _operations.Add(operation); } public void Clear() @@ -108,7 +111,9 @@ namespace UVtools.Core.Managers { if (item is null) return; _operations.RemoveAll(operation => operation.GetType() == item.GetType()); - _operations.Insert(index, item.Clone()); + var operation = item.Clone(); + operation.ImportedFrom = Operation.OperationImportFrom.Session; + _operations.Insert(index, operation); } public void RemoveAt(int index) diff --git a/UVtools.Core/Operations/Operation.cs b/UVtools.Core/Operations/Operation.cs index 56e2d12..166446d 100644 --- a/UVtools.Core/Operations/Operation.cs +++ b/UVtools.Core/Operations/Operation.cs @@ -8,12 +8,12 @@ using System; using System.Drawing; +using System.IO; using System.Xml.Serialization; using Emgu.CV; using Emgu.CV.Util; using UVtools.Core.Extensions; using UVtools.Core.FileFormats; -using UVtools.Core.Managers; using UVtools.Core.Objects; namespace UVtools.Core.Operations @@ -21,7 +21,19 @@ namespace UVtools.Core.Operations [Serializable] public abstract class Operation : BindableBase, IDisposable { + #region Enums + + public enum OperationImportFrom : byte + { + None, + Profile, + Session, + Undo, + } + #endregion #region Members + private FileFormat _slicerFile; + private OperationImportFrom _importedFrom = OperationImportFrom.None; private Rectangle _roi = Rectangle.Empty; private Point[][] _maskPoints; private uint _layerIndexEnd; @@ -29,11 +41,21 @@ namespace UVtools.Core.Operations private string _profileName; private bool _profileIsDefault; private Enumerations.LayerRangeSelection _layerRangeSelection = Enumerations.LayerRangeSelection.All; - private FileFormat _slicerFile; public const byte ClassNameLength = 9; #endregion #region Properties + + /// <summary> + /// Gets or sets from where this option got loaded/imported + /// </summary> + [XmlIgnore] + public OperationImportFrom ImportedFrom + { + get => _importedFrom; + set => RaiseAndSetIfChanged(ref _importedFrom, value); + } + [XmlIgnore] public FileFormat SlicerFile { @@ -463,6 +485,13 @@ namespace UVtools.Core.Operations operation.MaskPoints = MaskPoints; } + public void Serialize(string path) + { + XmlSerializer serializer = new(GetType()); + using StreamWriter writer = new(path); + serializer.Serialize(writer, this); + } + public virtual Operation Clone() { var operation = MemberwiseClone() as Operation; @@ -480,5 +509,20 @@ namespace UVtools.Core.Operations public virtual void Dispose() { } #endregion + + #region Static Methods + + public static Operation Deserialize(string path, Type type) + { + XmlSerializer serializer = new(type); + using var stream = File.OpenRead(path); + var operation = (Operation)serializer.Deserialize(stream); + operation.ImportedFrom = OperationImportFrom.Session; + return operation; + } + + public static Operation Deserialize(string path, Operation operation) => Deserialize(path, operation.GetType()); + + #endregion } } diff --git a/UVtools.Core/Operations/OperationCalculator.cs b/UVtools.Core/Operations/OperationCalculator.cs index e683af4..9e48a09 100644 --- a/UVtools.Core/Operations/OperationCalculator.cs +++ b/UVtools.Core/Operations/OperationCalculator.cs @@ -43,14 +43,18 @@ namespace UVtools.Core.Operations public OperationCalculator() { } public OperationCalculator(FileFormat slicerFile) : base(slicerFile) + { } + + public override void InitWithSlicerFile() { - CalcMillimetersToPixels = new MillimetersToPixels(slicerFile.Resolution, slicerFile.Display); + base.InitWithSlicerFile(); + CalcMillimetersToPixels = new MillimetersToPixels(SlicerFile.Resolution, SlicerFile.Display); CalcLightOffDelay = new LightOffDelayC( - (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); + (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); } #endregion diff --git a/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs b/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs index e9c2a03..eaa3c5f 100644 --- a/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs +++ b/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs @@ -359,12 +359,16 @@ namespace UVtools.Core.Operations public OperationCalibrateElephantFoot() { } public OperationCalibrateElephantFoot(FileFormat slicerFile) : base(slicerFile) + { } + + public override void InitWithSlicerFile() { - _layerHeight = (decimal)slicerFile.LayerHeight; + base.InitWithSlicerFile(); + _layerHeight = (decimal)SlicerFile.LayerHeight; //_bottomLayers = slicerFile.BottomLayerCount; - _bottomExposure = (decimal)slicerFile.BottomExposureTime; - _normalExposure = (decimal)slicerFile.ExposureTime; - _mirrorOutput = slicerFile.MirrorDisplay; + _bottomExposure = (decimal)SlicerFile.BottomExposureTime; + _normalExposure = (decimal)SlicerFile.ExposureTime; + _mirrorOutput = SlicerFile.MirrorDisplay; } #endregion diff --git a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs index 799b74d..8f79702 100644 --- a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs +++ b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs @@ -18,6 +18,7 @@ using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; using Emgu.CV.Util; +using MoreLinq; using UVtools.Core.Extensions; using UVtools.Core.FileFormats; using UVtools.Core.Objects; @@ -44,6 +45,7 @@ namespace UVtools.Core.Operations } } #endregion + #region Constants const byte TextMarkingSpacing = 60; @@ -954,17 +956,17 @@ namespace UVtools.Core.Operations public OperationCalibrateExposureFinder() { } public OperationCalibrateExposureFinder(FileFormat slicerFile) : base(slicerFile) - { - _layerHeight = (decimal)slicerFile.LayerHeight; - _bottomLayers = slicerFile.BottomLayerCount; - _bottomExposure = (decimal)slicerFile.BottomExposureTime; - _normalExposure = (decimal)slicerFile.ExposureTime; - _mirrorOutput = slicerFile.MirrorDisplay; - } + { } public override void InitWithSlicerFile() { base.InitWithSlicerFile(); + _layerHeight = (decimal)SlicerFile.LayerHeight; + _bottomLayers = SlicerFile.BottomLayerCount; + _bottomExposure = (decimal)SlicerFile.BottomExposureTime; + _normalExposure = (decimal)SlicerFile.ExposureTime; + _mirrorOutput = SlicerFile.MirrorDisplay; + if (SlicerFile.DisplayWidth > 0) DisplayWidth = (decimal)SlicerFile.DisplayWidth; if (SlicerFile.DisplayHeight > 0) @@ -1510,6 +1512,13 @@ namespace UVtools.Core.Operations CvInvoke.FillPoly(layers[1], vec, EmguExtensions.WhiteByte, _enableAntiAliasing ? LineType.AntiAlias : LineType.EightConnected); } + + /*byte size = 60; + var matRoi = new Mat(layers[1], new Rectangle( + new Point(xPos + triangleWidth - size / 2, yHalfPos - size / 2), + new Size(size, size))); + + CvInvoke.BitwiseNot(matRoi, matRoi);*/ if (_counterTrianglesFence) @@ -1586,7 +1595,7 @@ namespace UVtools.Core.Operations } else { - CvInvoke.PutText(thumbnail, $"Features: {Holes.Length + Bars.Length}", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness); + CvInvoke.PutText(thumbnail, $"Features: {(_staircaseThickness > 0 ? 1 : 0) + Holes.Length + Bars.Length + BullsEyes.Length + (_counterTrianglesEnabled ? 1 : 0)}", new Point(xSpacing, ySpacing * 4), fontFace, fontScale, EmguExtensions.White3Byte, fontThickness); } diff --git a/UVtools.Core/Operations/OperationCalibrateGrayscale.cs b/UVtools.Core/Operations/OperationCalibrateGrayscale.cs index ec4e624..caadd8e 100644 --- a/UVtools.Core/Operations/OperationCalibrateGrayscale.cs +++ b/UVtools.Core/Operations/OperationCalibrateGrayscale.cs @@ -8,7 +8,6 @@ using System; using System.Drawing; -using System.Globalization; using System.Text; using System.Threading.Tasks; using Emgu.CV; @@ -17,7 +16,6 @@ using Emgu.CV.Structure; using Emgu.CV.Util; using UVtools.Core.Extensions; using UVtools.Core.FileFormats; -using UVtools.Core.Objects; namespace UVtools.Core.Operations { @@ -105,13 +103,18 @@ namespace UVtools.Core.Operations public OperationCalibrateGrayscale() { } public OperationCalibrateGrayscale(FileFormat slicerFile) : base(slicerFile) + { } + + public override void InitWithSlicerFile() { - _layerHeight = (decimal)slicerFile.LayerHeight; - _bottomLayers = slicerFile.BottomLayerCount; - _bottomExposure = (decimal)slicerFile.BottomExposureTime; - _normalExposure = (decimal)slicerFile.ExposureTime; - _mirrorOutput = slicerFile.MirrorDisplay; + base.InitWithSlicerFile(); + _layerHeight = (decimal)SlicerFile.LayerHeight; + _bottomLayers = SlicerFile.BottomLayerCount; + _bottomExposure = (decimal)SlicerFile.BottomExposureTime; + _normalExposure = (decimal)SlicerFile.ExposureTime; + _mirrorOutput = SlicerFile.MirrorDisplay; } + #endregion #region Properties diff --git a/UVtools.Core/Operations/OperationCalibrateStressTower.cs b/UVtools.Core/Operations/OperationCalibrateStressTower.cs index 4d9bcb8..1a2784c 100644 --- a/UVtools.Core/Operations/OperationCalibrateStressTower.cs +++ b/UVtools.Core/Operations/OperationCalibrateStressTower.cs @@ -102,17 +102,17 @@ namespace UVtools.Core.Operations public OperationCalibrateStressTower() { } public OperationCalibrateStressTower(FileFormat slicerFile) : base(slicerFile) - { - _layerHeight = (decimal)slicerFile.LayerHeight; - _bottomLayers = slicerFile.BottomLayerCount; - _bottomExposure = (decimal)slicerFile.BottomExposureTime; - _normalExposure = (decimal)slicerFile.ExposureTime; - _mirrorOutput = slicerFile.MirrorDisplay; - } + { } public override void InitWithSlicerFile() { base.InitWithSlicerFile(); + _layerHeight = (decimal)SlicerFile.LayerHeight; + _bottomLayers = SlicerFile.BottomLayerCount; + _bottomExposure = (decimal)SlicerFile.BottomExposureTime; + _normalExposure = (decimal)SlicerFile.ExposureTime; + _mirrorOutput = SlicerFile.MirrorDisplay; + if (SlicerFile.DisplayWidth > 0) DisplayWidth = (decimal)SlicerFile.DisplayWidth; if (SlicerFile.DisplayHeight > 0) diff --git a/UVtools.Core/Operations/OperationCalibrateTolerance.cs b/UVtools.Core/Operations/OperationCalibrateTolerance.cs index 2cc4d3a..6681186 100644 --- a/UVtools.Core/Operations/OperationCalibrateTolerance.cs +++ b/UVtools.Core/Operations/OperationCalibrateTolerance.cs @@ -422,17 +422,17 @@ namespace UVtools.Core.Operations public OperationCalibrateTolerance() { } public OperationCalibrateTolerance(FileFormat slicerFile) : base(slicerFile) - { - _layerHeight = (decimal)slicerFile.LayerHeight; - _bottomLayers = slicerFile.BottomLayerCount; - _bottomExposure = (decimal)slicerFile.BottomExposureTime; - _normalExposure = (decimal)slicerFile.ExposureTime; - _mirrorOutput = slicerFile.MirrorDisplay; - } + { } public override void InitWithSlicerFile() { base.InitWithSlicerFile(); + _layerHeight = (decimal)SlicerFile.LayerHeight; + _bottomLayers = SlicerFile.BottomLayerCount; + _bottomExposure = (decimal)SlicerFile.BottomExposureTime; + _normalExposure = (decimal)SlicerFile.ExposureTime; + _mirrorOutput = SlicerFile.MirrorDisplay; + if (SlicerFile.DisplayWidth > 0) DisplayWidth = (decimal)SlicerFile.DisplayWidth; if (SlicerFile.DisplayHeight > 0) diff --git a/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs b/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs index 13f30e1..444178d 100644 --- a/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs +++ b/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs @@ -447,17 +447,17 @@ namespace UVtools.Core.Operations public OperationCalibrateXYZAccuracy() { } public OperationCalibrateXYZAccuracy(FileFormat slicerFile) : base(slicerFile) - { - _layerHeight = (decimal)slicerFile.LayerHeight; - _bottomLayers = slicerFile.BottomLayerCount; - _bottomExposure = (decimal)slicerFile.BottomExposureTime; - _normalExposure = (decimal)slicerFile.ExposureTime; - _mirrorOutput = slicerFile.MirrorDisplay; - } + { } public override void InitWithSlicerFile() { base.InitWithSlicerFile(); + _layerHeight = (decimal)SlicerFile.LayerHeight; + _bottomLayers = SlicerFile.BottomLayerCount; + _bottomExposure = (decimal)SlicerFile.BottomExposureTime; + _normalExposure = (decimal)SlicerFile.ExposureTime; + _mirrorOutput = SlicerFile.MirrorDisplay; + if (SlicerFile.DisplayWidth > 0) DisplayWidth = (decimal)SlicerFile.DisplayWidth; if (SlicerFile.DisplayHeight > 0) diff --git a/UVtools.Core/Operations/OperationChangeResolution.cs b/UVtools.Core/Operations/OperationChangeResolution.cs index 334833b..4982cd4 100644 --- a/UVtools.Core/Operations/OperationChangeResolution.cs +++ b/UVtools.Core/Operations/OperationChangeResolution.cs @@ -122,7 +122,11 @@ namespace UVtools.Core.Operations public OperationChangeResolution() { } public OperationChangeResolution(FileFormat slicerFile) : base(slicerFile) + { } + + public override void InitWithSlicerFile() { + base.InitWithSlicerFile(); NewResolutionX = SlicerFile.ResolutionX; NewResolutionY = SlicerFile.ResolutionY; } diff --git a/UVtools.Core/Operations/OperationDynamicLifts.cs b/UVtools.Core/Operations/OperationDynamicLifts.cs index 03c7412..7444f0f 100644 --- a/UVtools.Core/Operations/OperationDynamicLifts.cs +++ b/UVtools.Core/Operations/OperationDynamicLifts.cs @@ -7,8 +7,10 @@ */ using System; +using System.ComponentModel; using System.Linq; using System.Text; +using MoreLinq.Extensions; using UVtools.Core.Extensions; using UVtools.Core.FileFormats; @@ -17,6 +19,21 @@ namespace UVtools.Core.Operations [Serializable] public sealed class OperationDynamicLifts : Operation { + #region Enums + public enum DynamicLiftsLightOffDelaySetMode : byte + { + [Description("Set the light-off with an extra delay")] + UpdateWithExtraDelay, + + [Description("Set the light-off without an extra delay")] + UpdateWithoutExtraDelay, + + [Description("Set the light-off to zero")] + SetToZero, + } + #endregion + + #region Members private float _minBottomLiftHeight; private float _maxBottomLiftHeight; private float _minLiftHeight; @@ -25,11 +42,10 @@ namespace UVtools.Core.Operations private float _maxBottomLiftSpeed; private float _minLiftSpeed; private float _maxLiftSpeed; - private bool _updateLightOffDelay = true; + private float _lightOffDelayBottomExtraTime = 3; private float _lightOffDelayExtraTime = 2.5f; - - #region Members + private DynamicLiftsLightOffDelaySetMode _lightOffDelaySetMode = DynamicLiftsLightOffDelaySetMode.UpdateWithExtraDelay; #endregion @@ -91,16 +107,29 @@ namespace UVtools.Core.Operations $" [Bottom speed: {_minBottomLiftSpeed}/{_maxBottomLiftSpeed}mm/min]" + $" [Height: {_minLiftHeight}/{_maxLiftHeight}mm]" + $" [Speed: {_minLiftSpeed}/{_maxLiftSpeed}mm/min]" + - $" [Light-off: {_updateLightOffDelay} {_lightOffDelayBottomExtraTime}/{_lightOffDelayExtraTime}s]" + + $" [Light-off: {_lightOffDelaySetMode} {_lightOffDelayBottomExtraTime}/{_lightOffDelayExtraTime}s]" + LayerRangeString; if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}"; return result; } + protected override void OnPropertyChanged(PropertyChangedEventArgs e) + { + base.OnPropertyChanged(e); + if (e.PropertyName is nameof(LayerRangeCount)) + { + RaisePropertyChanged(nameof(IsBottomLayersEnabled)); + RaisePropertyChanged(nameof(IsNormalLayersEnabled)); + } + } + #endregion #region Properties + public bool IsBottomLayersEnabled => LayerIndexStart < SlicerFile.BottomLayerCount; + public bool IsNormalLayersEnabled => LayerIndexEnd >= SlicerFile.BottomLayerCount; + public float MinBottomLiftHeight { get => _minBottomLiftHeight; @@ -149,10 +178,10 @@ namespace UVtools.Core.Operations set => RaiseAndSetIfChanged(ref _maxLiftSpeed, (float)Math.Round(value, 2)); } - public bool UpdateLightOffDelay + public DynamicLiftsLightOffDelaySetMode LightOffDelaySetMode { - get => _updateLightOffDelay; - set => RaiseAndSetIfChanged(ref _updateLightOffDelay, value); + get => _lightOffDelaySetMode; + set => RaiseAndSetIfChanged(ref _lightOffDelaySetMode, value); } public float LightOffDelayBottomExtraTime @@ -198,11 +227,6 @@ namespace UVtools.Core.Operations where layer.Index <= LayerIndexEnd select layer.NonZeroPixelCount).Max(); - public Layer MinBottomLayer => SlicerFile.Where(layer => layer.IsBottomLayer && !layer.IsEmpty).OrderBy(layer => layer.NonZeroPixelCount).First(); - public Layer MaxBottomLayer => SlicerFile.Where(layer => layer.IsBottomLayer).OrderByDescending(layer => layer.NonZeroPixelCount).First(); - public Layer MinLayer => SlicerFile.Where(layer => layer.IsNormalLayer && !layer.IsEmpty).OrderBy(layer => layer.NonZeroPixelCount).First(); - public Layer MaxLayer => SlicerFile.Where(layer => layer.IsNormalLayer).OrderByDescending(layer => layer.NonZeroPixelCount).First(); - #endregion #region Constructor @@ -294,10 +318,21 @@ namespace UVtools.Core.Operations layer.LiftHeight = (float) Math.Round(liftHeight, 2); layer.LiftSpeed = (float) Math.Round(liftSpeed, 2); - if (_updateLightOffDelay) + switch (_lightOffDelaySetMode) { - layer.UpdateLightOffDelay(layer.IsBottomLayer ? _lightOffDelayBottomExtraTime : _lightOffDelayExtraTime); + case DynamicLiftsLightOffDelaySetMode.UpdateWithExtraDelay: + layer.SetLightOffDelay(layer.IsBottomLayer ? _lightOffDelayBottomExtraTime : _lightOffDelayExtraTime); + break; + case DynamicLiftsLightOffDelaySetMode.UpdateWithoutExtraDelay: + layer.SetLightOffDelay(); + break; + case DynamicLiftsLightOffDelaySetMode.SetToZero: + layer.LightOffDelay = 0; + break; + default: + throw new NotImplementedException(); } + progress++; } @@ -307,6 +342,15 @@ namespace UVtools.Core.Operations return !progress.Token.IsCancellationRequested; } + public Layer GetSmallestLayer(bool isBottom) + { + return SlicerFile.Where((layer, index) => !layer.IsEmpty && layer.IsBottomLayer == isBottom && index >= LayerIndexStart && index <= LayerIndexEnd).MinBy(layer => layer.NonZeroPixelCount).FirstOrDefault(); + } + + public Layer GetLargestLayer(bool isBottom) + { + return SlicerFile.Where((layer, index) => !layer.IsEmpty && layer.IsBottomLayer == isBottom && index >= LayerIndexStart && index <= LayerIndexEnd).MaxBy(layer => layer.NonZeroPixelCount).FirstOrDefault(); + } #endregion @@ -314,7 +358,7 @@ namespace UVtools.Core.Operations private bool Equals(OperationDynamicLifts other) { - return _minBottomLiftHeight.Equals(other._minBottomLiftHeight) && _maxBottomLiftHeight.Equals(other._maxBottomLiftHeight) && _minLiftHeight.Equals(other._minLiftHeight) && _maxLiftHeight.Equals(other._maxLiftHeight) && _minBottomLiftSpeed.Equals(other._minBottomLiftSpeed) && _maxBottomLiftSpeed.Equals(other._maxBottomLiftSpeed) && _minLiftSpeed.Equals(other._minLiftSpeed) && _maxLiftSpeed.Equals(other._maxLiftSpeed) && _updateLightOffDelay == other._updateLightOffDelay && _lightOffDelayBottomExtraTime.Equals(other._lightOffDelayBottomExtraTime) && _lightOffDelayExtraTime.Equals(other._lightOffDelayExtraTime); + return _minBottomLiftHeight.Equals(other._minBottomLiftHeight) && _maxBottomLiftHeight.Equals(other._maxBottomLiftHeight) && _minLiftHeight.Equals(other._minLiftHeight) && _maxLiftHeight.Equals(other._maxLiftHeight) && _minBottomLiftSpeed.Equals(other._minBottomLiftSpeed) && _maxBottomLiftSpeed.Equals(other._maxBottomLiftSpeed) && _minLiftSpeed.Equals(other._minLiftSpeed) && _maxLiftSpeed.Equals(other._maxLiftSpeed) && _lightOffDelayBottomExtraTime.Equals(other._lightOffDelayBottomExtraTime) && _lightOffDelayExtraTime.Equals(other._lightOffDelayExtraTime) && _lightOffDelaySetMode == other._lightOffDelaySetMode; } public override bool Equals(object obj) @@ -333,9 +377,9 @@ namespace UVtools.Core.Operations hashCode.Add(_maxBottomLiftSpeed); hashCode.Add(_minLiftSpeed); hashCode.Add(_maxLiftSpeed); - hashCode.Add(_updateLightOffDelay); hashCode.Add(_lightOffDelayBottomExtraTime); hashCode.Add(_lightOffDelayExtraTime); + hashCode.Add((int) _lightOffDelaySetMode); return hashCode.ToHashCode(); } diff --git a/UVtools.Core/Operations/OperationLayerReHeight.cs b/UVtools.Core/Operations/OperationLayerReHeight.cs index 8a9d338..1aee091 100644 --- a/UVtools.Core/Operations/OperationLayerReHeight.cs +++ b/UVtools.Core/Operations/OperationLayerReHeight.cs @@ -83,7 +83,7 @@ namespace UVtools.Core.Operations #region Properties - public OperationLayerReHeightItem[] Presets { get; } + public OperationLayerReHeightItem[] Presets { get; set; } public OperationLayerReHeightItem SelectedItem { @@ -136,8 +136,12 @@ namespace UVtools.Core.Operations public OperationLayerReHeight() { } public OperationLayerReHeight(FileFormat slicerFile) : base(slicerFile) + { } + + public override void InitWithSlicerFile() { - Presets = GetItems(slicerFile.LayerCount, (decimal) slicerFile.LayerHeight); + base.InitWithSlicerFile(); + Presets = GetItems(SlicerFile.LayerCount, (decimal)SlicerFile.LayerHeight); if (Presets is not null && Presets.Length > 0) { _selectedItem = Presets[0]; diff --git a/UVtools.Core/Operations/OperationMove.cs b/UVtools.Core/Operations/OperationMove.cs index 5c84b1e..bac56b6 100644 --- a/UVtools.Core/Operations/OperationMove.cs +++ b/UVtools.Core/Operations/OperationMove.cs @@ -177,11 +177,11 @@ namespace UVtools.Core.Operations public OperationMove() { } - public OperationMove(FileFormat slicerFile, Enumerations.Anchor anchor = Enumerations.Anchor.MiddleCenter) : base(slicerFile) + public OperationMove(FileFormat slicerFile) : this(slicerFile, Enumerations.Anchor.MiddleCenter) + { } + + public OperationMove(FileFormat slicerFile, Enumerations.Anchor anchor) : base(slicerFile) { - ROI = slicerFile.LayerManager.BoundingRectangle; - _imageWidth = slicerFile.ResolutionX; - _imageHeight = slicerFile.ResolutionY; _anchor = anchor; } @@ -190,6 +190,14 @@ namespace UVtools.Core.Operations if(!srcRoi.IsEmpty) ROI = srcRoi; } + public override void InitWithSlicerFile() + { + base.InitWithSlicerFile(); + ROI = SlicerFile.BoundingRectangle; + _imageWidth = SlicerFile.ResolutionX; + _imageHeight = SlicerFile.ResolutionY; + } + /*public OperationMove(FileFormat slicerFile, Rectangle srcRoi, Mat mat, Enumerations.Anchor anchor = Enumerations.Anchor.MiddleCenter) : this(slicerFile, srcRoi, anchor) { ImageWidth = (uint) mat.Width; diff --git a/UVtools.Core/Operations/OperationPattern.cs b/UVtools.Core/Operations/OperationPattern.cs index 15ac44d..b5a0bc8 100644 --- a/UVtools.Core/Operations/OperationPattern.cs +++ b/UVtools.Core/Operations/OperationPattern.cs @@ -75,8 +75,8 @@ namespace UVtools.Core.Operations set => RaiseAndSetIfChanged(ref _anchor, value); } - public uint ImageWidth { get; } - public uint ImageHeight { get; } + public uint ImageWidth { get; private set; } + public uint ImageHeight { get; private set; } public ushort Cols { @@ -190,12 +190,24 @@ namespace UVtools.Core.Operations public OperationPattern() { } - public OperationPattern(FileFormat slicerFile, Rectangle srcRoi = default) : base(slicerFile) + public OperationPattern(FileFormat slicerFile) : base(slicerFile) { - ImageWidth = slicerFile.ResolutionX; - ImageHeight = slicerFile.ResolutionY; + SetRoi(SlicerFile.BoundingRectangle); + } + + public OperationPattern(FileFormat slicerFile, Rectangle srcRoi) : base(slicerFile) + { + SetRoi(srcRoi.IsEmpty ? SlicerFile.BoundingRectangle : srcRoi); + } + + public override void InitWithSlicerFile() + { + base.InitWithSlicerFile(); + + ImageWidth = SlicerFile.ResolutionX; + ImageHeight = SlicerFile.ResolutionY; - SetRoi(srcRoi.IsEmpty ? slicerFile.BoundingRectangle : srcRoi); + SetRoi(SlicerFile.BoundingRectangle); Fill(); } diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index f9e1554..b0630af 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>2.11.0</Version> + <Version>2.11.1</Version> <Copyright>Copyright © 2020 PTRTECH</Copyright> <PackageIcon>UVtools.png</PackageIcon> <Platforms>AnyCPU;x64</Platforms> @@ -50,6 +50,7 @@ <PackageReference Include="BinarySerializer" Version="8.6.0" /> <PackageReference Include="Emgu.CV" Version="4.5.1.4349" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="3.10.0-2.final" /> + <PackageReference Include="morelinq" Version="3.3.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Portable.BouncyCastle" Version="1.8.10" /> <PackageReference Include="System.Memory" Version="4.5.4" /> |