diff --git a/CHANGELOG.md b/CHANGELOG.md index e860122..600081d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 02/04/2022 - v3.2.1 + +- **AnyCubic file format:** + - (Fix) Lift height and speed are not being correctly set on old version, keeping a constant value (#441) + - (Fix) Retract speed getter was not return value from TSMC if using version 516 +- **Tool - Infill:** + - (Add) Waves infill type + - (Add) Concentric infill type + - (Add) Gyroid infill type (#443) + - (Change) Increase the default spacing from 200px to 300px + - (Improvement) Fastter infill processing by use the model bounds +- (Add) `FormatSpeedUnit` property to file formats to get the speed unit which the file use internally +- (Fix) UI: ROI rectangle can overlap scroll bars while selecting + ## 26/03/2022 - v3.2.0 - **Core:** diff --git a/UVtools.AvaloniaControls/AdvancedImageBox.axaml.cs b/UVtools.AvaloniaControls/AdvancedImageBox.axaml.cs index 71d8ed8..e2133df 100644 --- a/UVtools.AvaloniaControls/AdvancedImageBox.axaml.cs +++ b/UVtools.AvaloniaControls/AdvancedImageBox.axaml.cs @@ -10,6 +10,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics; using System.Drawing; using System.Runtime.CompilerServices; using Avalonia; @@ -1074,7 +1075,10 @@ public class AdvancedImageBox : UserControl HorizontalScrollBar.Scroll += ScrollBarOnScroll; VerticalScrollBar.Scroll += ScrollBarOnScroll; - ViewPort.PointerWheelChanged += FillContainerOnPointerWheelChanged; + ViewPort.PointerPressed += ViewPortOnPointerPressed; + ViewPort.PointerLeave += ViewPortOnPointerLeave; + ViewPort.PointerMoved += ViewPortOnPointerMoved; + ViewPort.PointerWheelChanged += ViewPortOnPointerWheelChanged; } private void InitializeComponent() @@ -1088,7 +1092,6 @@ public class AdvancedImageBox : UserControl { if (!_canRender) return; if (renderOnlyCursorTracker && _trackerImage is null) return; - InvalidateVisual(); } @@ -1096,7 +1099,8 @@ public class AdvancedImageBox : UserControl { //Debug.WriteLine($"Render: {DateTime.Now.Ticks}"); base.Render(context); - + + var viewPortSize = ViewPortSize; // Draw Grid var gridCellSize = GridCellSize; if (ShowGrid & gridCellSize > 0 && (!IsHorizontalBarVisible || !IsVerticalBarVisible)) @@ -1105,11 +1109,11 @@ public class AdvancedImageBox : UserControl var gridColor = GridColor; var altColor = GridColorAlternate; var currentColor = gridColor; - for (int y = 0; y < ViewPortSize.Height; y += gridCellSize) + for (int y = 0; y < viewPortSize.Height; y += gridCellSize) { var firstRowColor = currentColor; - for (int x = 0; x < ViewPortSize.Width; x += gridCellSize) + for (int x = 0; x < viewPortSize.Width; x += gridCellSize) { context.FillRectangle(currentColor, new Rect(x, y, gridCellSize, gridCellSize)); currentColor = ReferenceEquals(currentColor, gridColor) ? altColor : gridColor; @@ -1127,15 +1131,17 @@ public class AdvancedImageBox : UserControl var image = Image; if (image is null) return; + var imageViewPort = GetImageViewPort(); + + // Draw iamge context.DrawImage(image, GetSourceImageRegion(), - GetImageViewPort() + imageViewPort ); var zoomFactor = ZoomFactor; - - + if (HaveTrackerImage && _pointerPosition.X >= 0 && _pointerPosition.Y >= 0) { var destSize = TrackerImageAutoZoom @@ -1155,22 +1161,21 @@ public class AdvancedImageBox : UserControl // Draw pixel grid if (zoomFactor > PixelGridZoomThreshold && SizeMode == SizeModes.Normal) { - var viewport = GetImageViewPort(); var offsetX = Offset.X % zoomFactor; var offsetY = Offset.Y % zoomFactor; Pen pen = new(PixelGridColor); - for (double x = viewport.X + zoomFactor - offsetX; x < viewport.Right; x += zoomFactor) + for (double x = imageViewPort.X + zoomFactor - offsetX; x < imageViewPort.Right; x += zoomFactor) { - context.DrawLine(pen, new Point(x, viewport.X), new Point(x, viewport.Bottom)); + context.DrawLine(pen, new Point(x, imageViewPort.X), new Point(x, imageViewPort.Bottom)); } - for (double y = viewport.Y + zoomFactor - offsetY; y < viewport.Bottom; y += zoomFactor) + for (double y = imageViewPort.Y + zoomFactor - offsetY; y < imageViewPort.Bottom; y += zoomFactor) { - context.DrawLine(pen, new Point(viewport.Y, y), new Point(viewport.Right, y)); + context.DrawLine(pen, new Point(imageViewPort.Y, y), new Point(imageViewPort.Right, y)); } - context.DrawRectangle(pen, viewport); + context.DrawRectangle(pen, imageViewPort); } if (!SelectionRegion.IsEmpty) @@ -1178,7 +1183,7 @@ public class AdvancedImageBox : UserControl var rect = GetOffsetRectangle(SelectionRegion); var selectionColor = SelectionColor; context.FillRectangle(selectionColor, rect); - Color color = Color.FromArgb(255, selectionColor.Color.R, selectionColor.Color.G, selectionColor.Color.B); + var color = Color.FromArgb(255, selectionColor.Color.R, selectionColor.Color.G, selectionColor.Color.B); context.DrawRectangle(new Pen(color.ToUint32()), rect); } } @@ -1248,7 +1253,7 @@ public class AdvancedImageBox : UserControl base.OnScrollChanged(e); }*/ - private void FillContainerOnPointerWheelChanged(object? sender, PointerWheelEventArgs e) + private void ViewPortOnPointerWheelChanged(object? sender, PointerWheelEventArgs e) { e.Handled = true; if (Image is null) return; @@ -1265,9 +1270,8 @@ public class AdvancedImageBox : UserControl } } - protected override void OnPointerPressed(PointerPressedEventArgs e) + private void ViewPortOnPointerPressed(object? sender, PointerPressedEventArgs e) { - base.OnPointerPressed(e); if (e.Handled || _isPanning || _isSelecting @@ -1307,6 +1311,49 @@ public class AdvancedImageBox : UserControl _startMousePosition = location; } + /*protected override void OnPointerPressed(PointerPressedEventArgs e) + { + base.OnPointerPressed(e); + + if (e.Handled + || _isPanning + || _isSelecting + || Image is null) return; + + var pointer = e.GetCurrentPoint(this); + + if (SelectionMode != SelectionModes.None) + { + if (!( + pointer.Properties.IsLeftButtonPressed && (SelectWithMouseButtons & MouseButtons.LeftButton) != 0 || + pointer.Properties.IsMiddleButtonPressed && (SelectWithMouseButtons & MouseButtons.MiddleButton) != 0 || + pointer.Properties.IsRightButtonPressed && (SelectWithMouseButtons & MouseButtons.RightButton) != 0 + ) + ) return; + IsSelecting = true; + } + else + { + if (!( + pointer.Properties.IsLeftButtonPressed && (PanWithMouseButtons & MouseButtons.LeftButton) != 0 || + pointer.Properties.IsMiddleButtonPressed && (PanWithMouseButtons & MouseButtons.MiddleButton) != 0 || + pointer.Properties.IsRightButtonPressed && (PanWithMouseButtons & MouseButtons.RightButton) != 0 + ) + || !AutoPan + || SizeMode != SizeModes.Normal + + ) return; + + IsPanning = true; + } + + var location = pointer.Position; + + if (location.X > ViewPortSize.Width) return; + if (location.Y > ViewPortSize.Height) return; + _startMousePosition = location; + }*/ + protected override void OnPointerReleased(PointerReleasedEventArgs e) { base.OnPointerReleased(e); @@ -1316,20 +1363,111 @@ public class AdvancedImageBox : UserControl IsSelecting = false; } - protected override void OnPointerLeave(PointerEventArgs e) + private void ViewPortOnPointerLeave(object? sender, PointerEventArgs e) { - base.OnPointerLeave(e); PointerPosition = new Point(-1, -1); TriggerRender(true); e.Handled = true; } - protected override void OnPointerMoved(PointerEventArgs e) + /*protected override void OnPointerLeave(PointerEventArgs e) + { + base.OnPointerLeave(e); + PointerPosition = new Point(-1, -1); + TriggerRender(true); + e.Handled = true; + }*/ + + private void ViewPortOnPointerMoved(object? sender, PointerEventArgs e) { - base.OnPointerMoved(e); if (e.Handled) return; - var pointer = e.GetCurrentPoint(this); + var pointer = e.GetCurrentPoint(ViewPort); + PointerPosition = pointer.Position; + + if (!_isPanning && !_isSelecting) + { + TriggerRender(true); + return; + } + + if (_isPanning) + { + double x; + double y; + + if (!InvertMousePan) + { + x = _startScrollPosition.X + (_startMousePosition.X - _pointerPosition.X); + y = _startScrollPosition.Y + (_startMousePosition.Y - _pointerPosition.Y); + } + else + { + x = (_startScrollPosition.X - (_startMousePosition.X - _pointerPosition.X)); + y = (_startScrollPosition.Y - (_startMousePosition.Y - _pointerPosition.Y)); + } + + Offset = new Vector(x, y); + } + else if (_isSelecting) + { + var viewPortPoint = new Point( + Math.Min(_pointerPosition.X, ViewPort.Bounds.Right), + Math.Min(_pointerPosition.Y, ViewPort.Bounds.Bottom)); + + double x; + double y; + double w; + double h; + + var imageOffset = GetImageViewPort().Position; + + if (viewPortPoint.X < _startMousePosition.X) + { + x = viewPortPoint.X; + w = _startMousePosition.X - viewPortPoint.X; + } + else + { + x = _startMousePosition.X; + w = viewPortPoint.X - _startMousePosition.X; + } + + if (viewPortPoint.Y < _startMousePosition.Y) + { + y = viewPortPoint.Y; + h = _startMousePosition.Y - viewPortPoint.Y; + } + else + { + y = _startMousePosition.Y; + h = viewPortPoint.Y - _startMousePosition.Y; + } + + x -= imageOffset.X - Offset.X; + y -= imageOffset.Y - Offset.Y; + + var zoomFactor = ZoomFactor; + x /= zoomFactor; + y /= zoomFactor; + w /= zoomFactor; + h /= zoomFactor; + + if (w > 0 && h > 0) + { + SelectionRegion = FitRectangle(new Rect(x, y, w, h)); + } + } + + e.Handled = true; + } + + /*protected override void OnPointerMoved(PointerEventArgs e) + { + base.OnPointerMoved(e); + if (e.Handled || !ViewPort.IsPointerOver) return; + + var pointer = e.GetCurrentPoint(ViewPort); PointerPosition = pointer.Position; if (!_isPanning && !_isSelecting) @@ -1396,14 +1534,15 @@ public class AdvancedImageBox : UserControl w /= zoomFactor; h /= zoomFactor; - if (w != 0 && h != 0) + if (w > 0 && h > 0) { + SelectionRegion = FitRectangle(new Rect(x, y, w, h)); } } e.Handled = true; - } + }*/ #endregion #region Zoom and Size modes @@ -1729,7 +1868,7 @@ public class AdvancedImageBox : UserControl var scaled = GetScaledRectangle(source); var offsetX = viewport.Left - Offset.X; var offsetY = viewport.Top - Offset.Y; - + return new(new Point(scaled.Left + offsetX, scaled.Top + offsetY), scaled.Size); } @@ -2151,7 +2290,8 @@ public class AdvancedImageBox : UserControl /// public Rect GetImageViewPort() { - if (!IsImageLoaded || (ViewPortSize.Width == 0 && ViewPortSize.Height == 0)) return Rect.Empty; + var viewPortSize = ViewPortSize; + if (!IsImageLoaded || (viewPortSize.Width == 0 && viewPortSize.Height == 0)) return Rect.Empty; double xOffset = 0; double yOffset = 0; @@ -2163,28 +2303,28 @@ public class AdvancedImageBox : UserControl case SizeModes.Normal: if (AutoCenter) { - xOffset = (!IsHorizontalBarVisible ? (ViewPortSize.Width - ScaledImageWidth) / 2 : 0); - yOffset = (!IsVerticalBarVisible ? (ViewPortSize.Height - ScaledImageHeight) / 2 : 0); + xOffset = (!IsHorizontalBarVisible ? (viewPortSize.Width - ScaledImageWidth) / 2 : 0); + yOffset = (!IsVerticalBarVisible ? (viewPortSize.Height - ScaledImageHeight) / 2 : 0); } - width = Math.Min(ScaledImageWidth - Math.Abs(Offset.X), ViewPortSize.Width); - height = Math.Min(ScaledImageHeight - Math.Abs(Offset.Y), ViewPortSize.Height); + width = Math.Min(ScaledImageWidth - Math.Abs(Offset.X), viewPortSize.Width); + height = Math.Min(ScaledImageHeight - Math.Abs(Offset.Y), viewPortSize.Height); break; case SizeModes.Stretch: - width = ViewPortSize.Width; - height = ViewPortSize.Height; + width = viewPortSize.Width; + height = viewPortSize.Height; break; case SizeModes.Fit: var image = Image; - double scaleFactor = Math.Min(ViewPortSize.Width / image!.Size.Width, ViewPortSize.Height / image.Size.Height); + double scaleFactor = Math.Min(viewPortSize.Width / image!.Size.Width, viewPortSize.Height / image.Size.Height); width = Math.Floor(image.Size.Width * scaleFactor); height = Math.Floor(image.Size.Height * scaleFactor); if (AutoCenter) { - xOffset = (ViewPortSize.Width - width) / 2; - yOffset = (ViewPortSize.Height - height) / 2; + xOffset = (viewPortSize.Width - width) / 2; + yOffset = (viewPortSize.Height - height) / 2; } break; diff --git a/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj b/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj index 5a23b57..676fb95 100644 --- a/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj +++ b/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj @@ -14,7 +14,7 @@ true AvaloniaUI Controls - AdvancedImageBox: Pan, zoom, cursor, pixel grid and selections image box - 2.0.0 + 2.0.1 enable https://github.com/sn4k3/UVtools README.md diff --git a/UVtools.Core/Extensions/EmguExtensions.cs b/UVtools.Core/Extensions/EmguExtensions.cs index aae8bd6..243b669 100644 --- a/UVtools.Core/Extensions/EmguExtensions.cs +++ b/UVtools.Core/Extensions/EmguExtensions.cs @@ -174,24 +174,18 @@ public static class EmguExtensions /// /// public static unsafe byte* GetBytePointer(this Mat mat) - { - return (byte*)mat.DataPointer.ToPointer(); - } + => (byte*)mat.DataPointer.ToPointer(); /// /// Gets the whole data span to manipulate or read pixels /// /// /// - public static unsafe Span GetDataByteSpan(this Mat mat) - { - return new(mat.DataPointer.ToPointer(), mat.GetLength()); - } + public static unsafe Span GetDataByteSpan(this Mat mat) + => new(mat.DataPointer.ToPointer(), mat.GetLength()); - public static unsafe Span GetDataByteSpan(this Mat mat, int length, int offset = 0) - { - return new(IntPtr.Add(mat.DataPointer, offset).ToPointer(), length <= 0 ? mat.GetLength() : length); - } + public static unsafe Span GetDataByteSpan(this Mat mat, int length, int offset = 0) + => new(IntPtr.Add(mat.DataPointer, offset).ToPointer(), length <= 0 ? mat.GetLength() : length); /// /// Gets the data span to manipulate or read pixels given a length and offset @@ -201,10 +195,8 @@ public static class EmguExtensions /// /// /// - public static unsafe Span GetDataSpan(this Mat mat, int length = 0, int offset = 0) - { - return new(IntPtr.Add(mat.DataPointer, offset).ToPointer(), length <= 0 ? mat.GetLength() : length); - } + public static unsafe Span GetDataSpan(this Mat mat, int length = 0, int offset = 0) + => new(IntPtr.Add(mat.DataPointer, offset).ToPointer(), length <= 0 ? mat.GetLength() : length); /// /// Gets a single pixel span to manipulate or read pixels @@ -214,10 +206,8 @@ public static class EmguExtensions /// /// /// - public static Span GetPixelSpan(this Mat mat, int x, int y) - { - return mat.GetDataSpan(mat.NumberOfChannels, mat.GetPixelPos(x, y)); - } + public static Span GetPixelSpan(this Mat mat, int x, int y) + => mat.GetDataSpan(mat.NumberOfChannels, mat.GetPixelPos(x, y)); /// /// Gets a single pixel span to manipulate or read pixels @@ -226,10 +216,8 @@ public static class EmguExtensions /// /// /// - public static Span GetPixelSpan(this Mat mat, int pos) - { - return mat.GetDataSpan(mat.NumberOfChannels, pos); - } + public static Span GetPixelSpan(this Mat mat, int pos) + => mat.GetDataSpan(mat.NumberOfChannels, pos); /// /// Gets a row span to manipulate or read pixels @@ -240,10 +228,8 @@ public static class EmguExtensions /// /// /// - public static unsafe Span GetRowSpan(this Mat mat, int y, int length = 0, int offset = 0) - { - return new(IntPtr.Add(mat.DataPointer, y * mat.GetRealStep() + offset).ToPointer(), length <= 0 ? mat.GetRealStep() : length); - } + public static unsafe Span GetRowSpan(this Mat mat, int y, int length = 0, int offset = 0) + => new(IntPtr.Add(mat.DataPointer, y * mat.GetRealStep() + offset).ToPointer(), length <= 0 ? mat.GetRealStep() : length); /// /// Gets a col span to manipulate or read pixels @@ -325,7 +311,7 @@ public static class EmguExtensions } /// - /// Gets the total length of this + /// Gets the total length of this /// /// /// The total length of this @@ -471,6 +457,23 @@ public static class EmguExtensions return src.CreateMask(vec); } + public static Mat TrimByBounds(this Mat src) + { + var rect = CvInvoke.BoundingRectangle(src); + if (rect.Size == Size.Empty) return src.New(); + if (src.Size == rect.Size) return src.Clone(); + using var roi = src.Roi(rect); + return roi.Clone(); + } + + public static void TrimByBounds(this Mat src, Mat dst) + { + var mat = src.TrimByBounds(); + CvInvoke.Swap(mat, dst); + src.Dispose(); + } + + #endregion #region Copy methods diff --git a/UVtools.Core/FileFormats/CXDLPFile.cs b/UVtools.Core/FileFormats/CXDLPFile.cs index a90faf2..eea39a5 100644 --- a/UVtools.Core/FileFormats/CXDLPFile.cs +++ b/UVtools.Core/FileFormats/CXDLPFile.cs @@ -407,6 +407,8 @@ public class CXDLPFile : FileFormat new(typeof(CXDLPFile), "cxdlp", "Creality CXDLP"), }; + public override SpeedUnit FormatSpeedUnit => SpeedUnit.MillimetersPerSecond; + public override PrintParameterModifier[]? PrintParameterModifiers { get; } = { PrintParameterModifier.BottomLayerCount, @@ -577,8 +579,8 @@ public class CXDLPFile : FileFormat public override float BottomLiftSpeed { - get => SpeedConverter.Convert(SlicerInfoSettings.BottomLiftSpeed, SpeedUnit.MillimetersPerSecond, DefaultSpeedUnit); - set => base.BottomLiftSpeed = SlicerInfoSettings.BottomLiftSpeed = SlicerInfoSettings.BottomLiftSpeed = (ushort)SpeedConverter.Convert(value, DefaultSpeedUnit, SpeedUnit.MillimetersPerSecond); + get => SpeedConverter.Convert(SlicerInfoSettings.BottomLiftSpeed, FormatSpeedUnit, CoreSpeedUnit); + set => base.BottomLiftSpeed = SlicerInfoSettings.BottomLiftSpeed = SlicerInfoSettings.BottomLiftSpeed = (ushort)SpeedConverter.Convert(value, CoreSpeedUnit, FormatSpeedUnit); } public override float LiftHeight @@ -589,16 +591,16 @@ public class CXDLPFile : FileFormat public override float LiftSpeed { - get => SpeedConverter.Convert(SlicerInfoSettings.LiftSpeed, SpeedUnit.MillimetersPerSecond, DefaultSpeedUnit); - set => base.LiftSpeed = SlicerInfoSettings.LiftSpeed = (ushort)SpeedConverter.Convert(value, DefaultSpeedUnit, SpeedUnit.MillimetersPerSecond); + get => SpeedConverter.Convert(SlicerInfoSettings.LiftSpeed, FormatSpeedUnit, CoreSpeedUnit); + set => base.LiftSpeed = SlicerInfoSettings.LiftSpeed = (ushort)SpeedConverter.Convert(value, CoreSpeedUnit, FormatSpeedUnit); } public override float BottomRetractSpeed => RetractSpeed; public override float RetractSpeed { - get => SpeedConverter.Convert(SlicerInfoSettings.RetractSpeed, SpeedUnit.MillimetersPerSecond, DefaultSpeedUnit); - set => base.RetractSpeed = SlicerInfoSettings.RetractSpeed = (ushort)SpeedConverter.Convert(value, DefaultSpeedUnit, SpeedUnit.MillimetersPerSecond); + get => SpeedConverter.Convert(SlicerInfoSettings.RetractSpeed, FormatSpeedUnit, CoreSpeedUnit); + set => base.RetractSpeed = SlicerInfoSettings.RetractSpeed = (ushort)SpeedConverter.Convert(value, CoreSpeedUnit, FormatSpeedUnit); } public override byte BottomLightPWM diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs index d651bdc..8f10c8e 100644 --- a/UVtools.Core/FileFormats/FileFormat.cs +++ b/UVtools.Core/FileFormats/FileFormat.cs @@ -44,7 +44,7 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable /// Gets the file format type /// @@ -1004,8 +1006,11 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable public abstract FileExtension[] FileExtensions { get; } - public FileDecodeType DecodeType { get; private set; } = FileDecodeType.Full; - + /// + /// The speed unit used by this file format in his internal data + /// + public virtual SpeedUnit FormatSpeedUnit => CoreSpeedUnit; + /// /// Gets the available /// diff --git a/UVtools.Core/FileFormats/JXSFile.cs b/UVtools.Core/FileFormats/JXSFile.cs index bc8758a..098042a 100644 --- a/UVtools.Core/FileFormats/JXSFile.cs +++ b/UVtools.Core/FileFormats/JXSFile.cs @@ -53,11 +53,11 @@ public class JXSFile : FileFormat [DisplayName("nJobName")] public string JobName { get; set; } = string.Empty; [DisplayName("NumBottomLayers")] public ushort BottomLayerCount { get; set; } = DefaultBottomLayerCount; [DisplayName("LiftDistance1")] public float LiftHeight1 { get; set; } = DefaultBottomLiftHeight; - [DisplayName("LiftFeedrate1")] public float LiftSpeed1 { get; set; } = SpeedConverter.Convert(DefaultLiftSpeed, SpeedUnit.MillimetersPerMinute, SpeedUnit.MillimetersPerSecond); + [DisplayName("LiftFeedrate1")] public float LiftSpeed1 { get; set; } = DefaultLiftSpeed; [DisplayName("LiftDistance2")] public float LiftHeight2 { get; set; } = DefaultLiftHeight2; - [DisplayName("LiftFeedrate2")] public float LiftSpeed2 { get; set; } = SpeedConverter.Convert(DefaultLiftSpeed2, SpeedUnit.MillimetersPerMinute, SpeedUnit.MillimetersPerSecond); - [DisplayName("BottomLiftFeedrate")] public float BottomLiftSpeed { get; set; } = SpeedConverter.Convert(DefaultBottomLiftSpeed, SpeedUnit.MillimetersPerMinute, SpeedUnit.MillimetersPerSecond); - [DisplayName("RetractFeedrate")] public float RetractSpeed { get; set; } = SpeedConverter.Convert(DefaultRetractSpeed, SpeedUnit.MillimetersPerMinute, SpeedUnit.MillimetersPerSecond); + [DisplayName("LiftFeedrate2")] public float LiftSpeed2 { get; set; } = DefaultLiftSpeed2; + [DisplayName("BottomLiftFeedrate")] public float BottomLiftSpeed { get; set; } = DefaultBottomLiftSpeed; + [DisplayName("RetractFeedrate")] public float RetractSpeed { get; set; } = DefaultRetractSpeed; [DisplayName("ZMoveTimeCompensation")] public uint WaitTimeBeforeCure { get; set; } = 1500; [DisplayName("ZMoveTimeCompensationBottom")] public uint BottomWaitTimeBeforeCure { get; set; } = 8000; public string OnLightCode { get; set; } = "M106 S255"; @@ -80,8 +80,8 @@ public class JXSFile : FileFormat #endregion #region Properties - public JXSConfig ConfigFile { get; set; } = new (); - public JXSControl ControlFile { get; set; } = new (); + public JXSConfig ConfigFile { get; set; } = new(); + public JXSControl ControlFile { get; set; } = new(); public override FileFormatType FileType => FileFormatType.Archive; diff --git a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs index 0e656ef..19b1d4d 100644 --- a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs +++ b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs @@ -15,6 +15,7 @@ using System.Drawing; using System.IO; using System.Linq; using System.Threading.Tasks; +using UVtools.Core.Converters; using UVtools.Core.Extensions; using UVtools.Core.Layers; using UVtools.Core.Operations; @@ -287,18 +288,18 @@ public class PhotonWorkshopFile : FileFormat /// /// 58 /// - [FieldOrder(7)] public float LiftHeight { get; set; } = 6; + [FieldOrder(7)] public float LiftHeight { get; set; } = DefaultLiftHeight; /// /// Gets the lift speed in mm/s /// 5C /// - [FieldOrder(8)] public float LiftSpeed { get; set; } = 3; // mm/s + [FieldOrder(8)] public float LiftSpeed { get; set; } = SpeedConverter.Convert(DefaultLiftSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond); // mm/s /// /// Gets the retract speed in mm/s /// 60 /// - [FieldOrder(9)] public float RetractSpeed { get; set; } = 3; // mm/s + [FieldOrder(9)] public float RetractSpeed { get; set; } = SpeedConverter.Convert(DefaultRetractSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond); // mm/s /// /// 64 @@ -557,7 +558,7 @@ public class PhotonWorkshopFile : FileFormat LayerHeight = layer.RelativePositionZ; ExposureTime = layer.ExposureTime; LiftHeight = layer.LiftHeight; - LiftSpeed = (float) Math.Round(layer.LiftSpeed / 60, 2); + LiftSpeed = SpeedConverter.Convert(layer.LiftSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond); NonZeroPixelCount = layer.NonZeroPixelCount; } @@ -566,7 +567,7 @@ public class PhotonWorkshopFile : FileFormat // Don't forget to compute LayerHeight outside here layer.ExposureTime = ExposureTime; layer.LiftHeight = LiftHeight; - layer.LiftSpeed = (float)Math.Round(LiftSpeed * 60, 2); + layer.LiftSpeed = SpeedConverter.Convert(LiftSpeed, SpeedUnit.MillimetersPerSecond, CoreSpeedUnit); } public Mat Decode(bool consumeData = true) @@ -942,18 +943,18 @@ public class PhotonWorkshopFile : FileFormat [FieldOrder(1)] public uint Unknown0 { get; set; } = 24; [FieldOrder(2)] public uint Unknown1 { get; set; } = 2; [FieldOrder(3)] public float BottomLiftHeight1 { get; set; } - [FieldOrder(4)] public float BottomLiftSpeed1 { get; set; } - [FieldOrder(5)] public float BottomRetractSpeed1 { get; set; } + [FieldOrder(4)] public float BottomLiftSpeed1 { get; set; } = SpeedConverter.Convert(DefaultBottomLiftSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond); + [FieldOrder(5)] public float BottomRetractSpeed1 { get; set; } = SpeedConverter.Convert(DefaultBottomRetractSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond); [FieldOrder(6)] public float BottomLiftHeight2 { get; set; } - [FieldOrder(7)] public float BottomLiftSpeed2 { get; set; } - [FieldOrder(8)] public float BottomRetractSpeed2 { get; set; } + [FieldOrder(7)] public float BottomLiftSpeed2 { get; set; } = SpeedConverter.Convert(DefaultBottomLiftSpeed2, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond); + [FieldOrder(8)] public float BottomRetractSpeed2 { get; set; } = SpeedConverter.Convert(DefaultBottomRetractSpeed2, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond); [FieldOrder(9)] public uint Unknown2 { get; set; } = 2; [FieldOrder(10)] public float LiftHeight1 { get; set; } - [FieldOrder(11)] public float LiftSpeed1 { get; set; } - [FieldOrder(12)] public float RetractSpeed1 { get; set; } + [FieldOrder(11)] public float LiftSpeed1 { get; set; } = SpeedConverter.Convert(DefaultLiftSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond); + [FieldOrder(12)] public float RetractSpeed1 { get; set; } = SpeedConverter.Convert(DefaultRetractSpeed, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond); [FieldOrder(13)] public float LiftHeight2 { get; set; } - [FieldOrder(14)] public float LiftSpeed2 { get; set; } - [FieldOrder(15)] public float RetractSpeed2 { get; set; } + [FieldOrder(14)] public float LiftSpeed2 { get; set; } = SpeedConverter.Convert(DefaultLiftSpeed2, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond); + [FieldOrder(15)] public float RetractSpeed2 { get; set; } = SpeedConverter.Convert(DefaultRetractSpeed2, CoreSpeedUnit, SpeedUnit.MillimetersPerSecond); public Extra() { @@ -1043,10 +1044,10 @@ public class PhotonWorkshopFile : FileFormat new(typeof(PhotonWorkshopFile), "pwms", "Photon Mono SE (PWMS)"), new(typeof(PhotonWorkshopFile), "pwma", "Photon Mono 4K (PWMA)"), new(typeof(PhotonWorkshopFile), "pmsq", "Photon Mono SQ (PMSQ)"), - - }; + public override SpeedUnit FormatSpeedUnit => SpeedUnit.MillimetersPerSecond; + public override PrintParameterModifier[]? PrintParameterModifiers { get @@ -1297,11 +1298,7 @@ public class PhotonWorkshopFile : FileFormat public override float BottomLiftHeight { - get - { - if (FileMarkSettings.Version >= VERSION_516) return ExtraSettings.BottomLiftHeight1; - return base.BottomLiftHeight; - } + get => FileMarkSettings.Version >= VERSION_516 ? ExtraSettings.BottomLiftHeight1 : base.BottomLiftHeight; set { value = (float)Math.Round(value, 2); @@ -1321,26 +1318,20 @@ public class PhotonWorkshopFile : FileFormat public override float BottomLiftSpeed { - get - { - if (FileMarkSettings.Version >= VERSION_516) return (float)Math.Round(ExtraSettings.BottomLiftSpeed1 * 60, 2); - return base.BottomLiftSpeed; - } + get => FileMarkSettings.Version >= VERSION_516 + ? SpeedConverter.Convert(ExtraSettings.BottomLiftSpeed1, FormatSpeedUnit, CoreSpeedUnit) + : base.BottomLiftSpeed; set { value = (float)Math.Round(value, 2); - ExtraSettings.BottomLiftSpeed1 = (float)Math.Round(value / 60, 2); + ExtraSettings.BottomLiftSpeed1 = SpeedConverter.Convert(value, CoreSpeedUnit, FormatSpeedUnit); base.BottomLiftSpeed = value; } } public override float LiftHeight { - get - { - if (FileMarkSettings.Version >= VERSION_516) return ExtraSettings.LiftHeight1; - return HeaderSettings.LiftHeight; - } + get => FileMarkSettings.Version >= VERSION_516 ? ExtraSettings.LiftHeight1 : HeaderSettings.LiftHeight; set { value = (float)Math.Round(value, 2); @@ -1354,21 +1345,17 @@ public class PhotonWorkshopFile : FileFormat layer.LiftHeight = base.LiftHeight; } } - else base.LiftHeight = value; + else base.LiftHeight = HeaderSettings.LiftHeight = value; } } public override float LiftSpeed { - get - { - if (FileMarkSettings.Version >= VERSION_516) return (float)Math.Round(ExtraSettings.LiftSpeed1 * 60, 2); - return (float)Math.Round(HeaderSettings.LiftSpeed * 60, 2); - } + get => SpeedConverter.Convert(FileMarkSettings.Version >= VERSION_516 ? ExtraSettings.LiftSpeed1 : HeaderSettings.LiftSpeed, FormatSpeedUnit, CoreSpeedUnit); set { value = (float)Math.Round(value, 2); - HeaderSettings.LiftSpeed = ExtraSettings.LiftSpeed1 = (float)Math.Round(value / 60, 2); + HeaderSettings.LiftSpeed = ExtraSettings.LiftSpeed1 = SpeedConverter.Convert(value, CoreSpeedUnit, FormatSpeedUnit); base.LiftSpeed = value; } } @@ -1388,12 +1375,12 @@ public class PhotonWorkshopFile : FileFormat public override float BottomLiftSpeed2 { - get => FileMarkSettings.Version >= VERSION_516 ? (float)Math.Round(ExtraSettings.BottomLiftSpeed2 * 60, 2) : 0; + get => FileMarkSettings.Version >= VERSION_516 ? SpeedConverter.Convert(ExtraSettings.BottomLiftSpeed2, FormatSpeedUnit, CoreSpeedUnit) : 0; set { if (FileMarkSettings.Version < VERSION_516) return; value = (float)Math.Round(value, 2); - ExtraSettings.BottomLiftSpeed2 = (float)Math.Round(value / 60, 2); + ExtraSettings.BottomLiftSpeed2 = SpeedConverter.Convert(value, CoreSpeedUnit, FormatSpeedUnit); base.BottomLiftSpeed2 = value; } } @@ -1413,67 +1400,59 @@ public class PhotonWorkshopFile : FileFormat public override float LiftSpeed2 { - get => FileMarkSettings.Version >= VERSION_516 ? (float)Math.Round(ExtraSettings.LiftSpeed2 * 60, 2) : 0; + get => FileMarkSettings.Version >= VERSION_516 ? SpeedConverter.Convert(ExtraSettings.LiftSpeed2, FormatSpeedUnit, CoreSpeedUnit) : 0; set { if (FileMarkSettings.Version < VERSION_516) return; - base.LiftSpeed2 = ExtraSettings.LiftSpeed2 = (float)Math.Round(value / 60, 2); + value = (float)Math.Round(value, 2); + ExtraSettings.LiftSpeed2 = SpeedConverter.Convert(value, CoreSpeedUnit, FormatSpeedUnit); + base.LiftSpeed2 = value; } } public override float BottomRetractSpeed { - get - { - if (FileMarkSettings.Version >= VERSION_516) return (float)Math.Round(ExtraSettings.BottomRetractSpeed1 * 60, 2); - return RetractSpeed; - } + get => FileMarkSettings.Version >= VERSION_516 ? SpeedConverter.Convert(ExtraSettings.BottomRetractSpeed1, FormatSpeedUnit, CoreSpeedUnit) : RetractSpeed; set { value = (float)Math.Round(value, 2); - if (FileMarkSettings.Version >= VERSION_516) - { - ExtraSettings.BottomRetractSpeed1 = (float)Math.Round(value / 60, 2); - } - else - { - RetractSpeed = value; - } + if (FileMarkSettings.Version < VERSION_516) return; + ExtraSettings.BottomRetractSpeed1 = SpeedConverter.Convert(value, CoreSpeedUnit, FormatSpeedUnit); } } public override float RetractSpeed { - get => (float)Math.Round(HeaderSettings.RetractSpeed * 60, 2); + get => SpeedConverter.Convert(FileMarkSettings.Version >= VERSION_516 ? ExtraSettings.RetractSpeed1 : HeaderSettings.RetractSpeed, FormatSpeedUnit, CoreSpeedUnit); set { value = (float)Math.Round(value, 2); - ExtraSettings.RetractSpeed1 = HeaderSettings.RetractSpeed = (float) Math.Round(value / 60, 2); + ExtraSettings.RetractSpeed1 = HeaderSettings.RetractSpeed = SpeedConverter.Convert(value, CoreSpeedUnit, FormatSpeedUnit); base.RetractSpeed = value; } } public override float BottomRetractSpeed2 { - get => FileMarkSettings.Version >= VERSION_516 ? (float)Math.Round(ExtraSettings.BottomRetractSpeed2 * 60, 2) : 0; + get => FileMarkSettings.Version >= VERSION_516 ? SpeedConverter.Convert(ExtraSettings.BottomRetractSpeed2, FormatSpeedUnit, CoreSpeedUnit) : 0; set { if (FileMarkSettings.Version < VERSION_516) return; value = (float)Math.Round(value, 2); - ExtraSettings.BottomRetractSpeed2 = (float)Math.Round(value / 60, 2); + ExtraSettings.BottomRetractSpeed2 = SpeedConverter.Convert(value, CoreSpeedUnit, FormatSpeedUnit); base.BottomRetractSpeed2 = value; } } public override float RetractSpeed2 { - get => FileMarkSettings.Version >= VERSION_516 ? (float)Math.Round(ExtraSettings.RetractSpeed2 * 60, 2) : 0; + get => FileMarkSettings.Version >= VERSION_516 ? SpeedConverter.Convert(ExtraSettings.RetractSpeed2, FormatSpeedUnit, CoreSpeedUnit) : 0; set { if (FileMarkSettings.Version < VERSION_516) return; value = (float)Math.Round(value, 2); - ExtraSettings.RetractSpeed2 = (float)Math.Round(value / 60, 2); + ExtraSettings.RetractSpeed2 = SpeedConverter.Convert(value, CoreSpeedUnit, FormatSpeedUnit); base.RetractSpeed2 = value; } } diff --git a/UVtools.Core/Operations/Operation.cs b/UVtools.Core/Operations/Operation.cs index c22cee7..a1c51ee 100644 --- a/UVtools.Core/Operations/Operation.cs +++ b/UVtools.Core/Operations/Operation.cs @@ -461,6 +461,13 @@ public abstract class Operation : BindableBase, IDisposable return HaveROI ? _roi.Size : fallbackSize; } + public Size GetRoiSizeOrVolumeSize() => GetRoiSizeOrVolumeSize(_originalBoundingRectangle.Size); + + public Size GetRoiSizeOrVolumeSize(Size fallbackSize) + { + return HaveROI ? _roi.Size : fallbackSize; + } + public Mat GetRoiOrDefault(Mat defaultMat) { diff --git a/UVtools.Core/Operations/OperationInfill.cs b/UVtools.Core/Operations/OperationInfill.cs index 5e2e5d6..9085ad3 100644 --- a/UVtools.Core/Operations/OperationInfill.cs +++ b/UVtools.Core/Operations/OperationInfill.cs @@ -10,8 +10,10 @@ using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; using System; +using System.Collections.Generic; using System.ComponentModel; using System.Drawing; +using System.Linq; using System.Threading.Tasks; using UVtools.Core.Extensions; using UVtools.Core.FileFormats; @@ -25,8 +27,8 @@ public sealed class OperationInfill : Operation private InfillAlgorithm _infillType = InfillAlgorithm.CubicCrossAlternating; private ushort _wallThickness = 64; private ushort _infillThickness = 45; - private ushort _infillSpacing = 200; - private ushort _infillBrightness = 255; + private ushort _infillSpacing = 300; + private byte _infillBrightness = 255; private bool _reinforceInfill; #endregion @@ -55,6 +57,12 @@ public sealed class OperationInfill : Operation [Description("Straight pillars (Weak)")] Pillars, + [Description("Concentric (Weak)")] + Concentric, + + [Description("Waves (Medium)")] + Waves, + [Description("Cubic cross: Fixed pilars with crossing sections (Optimal)")] CubicCross, @@ -65,7 +73,10 @@ public sealed class OperationInfill : Operation CubicStar, [Description("Honeycomb (Strong)")] - Honeycomb + Honeycomb, + + [Description("Gyroid (Strong)")] + Gyroid, } #endregion @@ -82,7 +93,7 @@ public sealed class OperationInfill : Operation set => RaiseAndSetIfChanged(ref _wallThickness, value); } - public ushort InfillBrightness + public byte InfillBrightness { get => _infillBrightness; set => RaiseAndSetIfChanged(ref _infillBrightness, value); @@ -149,7 +160,11 @@ public sealed class OperationInfill : Operation Mat? mask = null; if (_infillType == InfillAlgorithm.Honeycomb) { - mask = GetHoneycombMask(GetRoiSizeOrDefault()); + mask = GetHoneycombMask(GetRoiSizeOrVolumeSize()); + } + else if (_infillType == InfillAlgorithm.Concentric) + { + mask = GetConcentricMask(GetRoiSizeOrVolumeSize()); } Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex => @@ -176,7 +191,7 @@ public sealed class OperationInfill : Operation Mat? patternMask = null; using Mat erode = new (); using Mat diff = new (); - var target = GetRoiOrDefault(mat); + var target = GetRoiOrVolumeBounds(mat); using var mask = GetMask(mat); bool disposeTargetMask = true; @@ -203,10 +218,6 @@ public sealed class OperationInfill : Operation firstPattern = false; accumulator += _infillThickness; } - else - { - //accumulator += _infillSpacing; - } } if (firstPattern) @@ -319,7 +330,7 @@ public sealed class OperationInfill : Operation CvInvoke.Repeat(infillPattern, target.Rows / infillPattern.Rows + 1, target.Cols / infillPattern.Cols + 1, matPattern); - patternMask = new Mat(matPattern, new Rectangle(0, 0, target.Width, target.Height)); + patternMask = matPattern.Roi(target); disposeTargetMask = true; } else if (_infillType == InfillAlgorithm.Honeycomb) @@ -335,6 +346,124 @@ public sealed class OperationInfill : Operation disposeTargetMask = true; } } + else if (_infillType == InfillAlgorithm.Concentric) + { + if (arguments.Length >= 2) + { + patternMask = (Mat)arguments[1]; + disposeTargetMask = false; + } + else + { + patternMask = GetConcentricMask(target.Size); + disposeTargetMask = true; + } + } + else if (_infillType == InfillAlgorithm.Waves) + { + var sineHeight = 100; + var sineWidth = 100; + var radius = (ushort)(_infillThickness / 2); + + var points = new List(); + + bool isHorizontal = true; + float accumulator = 0; + for (int i = 0; i <= layerIndex; i++) + { + accumulator += SlicerFile[index].RelativePositionZ; + if (accumulator >= 2) + { + isHorizontal = !isHorizontal; + accumulator = 0; + } + } + + //using var infillPattern = EmguExtensions.InitMat(new Size(_infillSpacing, _infillSpacing)); + //using var matPattern = new Mat(); + using var infillPattern = mat.NewBlank(); + + int maxY = 0; + + if (isHorizontal) + { + for (int x = 0; x < mat.Width; x += radius) + { + int y = (int) (Math.Sin((double) x / sineWidth /*+ sineWidth * layerIndex*/) * sineHeight / 2.0 + + sineHeight / 2.0 + radius); + points.Add(new Point(x, y)); + maxY = Math.Max(maxY, y); + } + var infillPatternRoi = infillPattern.Roi(new Size(infillPattern.Width, maxY + radius + 2 + _infillSpacing)); + CvInvoke.Polylines(infillPatternRoi, points.ToArray(), false, infillColor, _infillThickness); + + CvInvoke.Repeat(infillPatternRoi, target.Rows / infillPatternRoi.Rows + 1, 1, infillPattern); + } + else + { + for (int y = 0; y < mat.Height; y += radius) + { + int x = (int)(Math.Sin((double)y / sineWidth /*+ sineWidth * layerIndex*/) * sineHeight / 2.0 + + sineHeight / 2.0 + radius); + points.Add(new Point(x, y)); + maxY = Math.Max(maxY, x); + } + var infillPatternRoi = infillPattern.Roi(new Size(maxY + radius + 2 + _infillSpacing, infillPattern.Height)); + CvInvoke.Polylines(infillPatternRoi, points.ToArray(), false, infillColor, _infillThickness); + CvInvoke.Repeat(infillPatternRoi, 1, target.Cols / infillPatternRoi.Cols + 1, infillPattern); + + } + points.Clear(); + + patternMask = infillPattern.Roi(target); + disposeTargetMask = true; + } + else if (_infillType == InfillAlgorithm.Gyroid) + { + patternMask = target.NewBlank(); + + var scaleRatio = 0.0012 / (_infillSpacing + _infillThickness / 2); + //var scaleX = 0.04 * _infillSpacing * Math.PI / target.Width; + //var scaleY = 0.04 * _infillSpacing * Math.PI / target.Height; + var scaleX = scaleRatio * mat.Width; + var scaleY = scaleRatio * mat.Height; + + //const double scaleZ = 2.0 * Math.PI; + //var dz = 2.0 * scaleZ / LayerRangeCount; // z step + //var zz = 0.05 * (SlicerFile[index].LayerHeight / 0.05f) * (layerIndex + 1); + float zz = 0; + for (var i = LayerIndexStart; i <= index; i++) + { + zz += SlicerFile[i].RelativePositionZ; + } + + for (int y = 0; y < patternMask.Height; y++) + { + var span = patternMask.GetRowSpan(y); + var yy = y * scaleY; // y position of pixel + for (int x = 0; x < patternMask.Width; x++) + { + var xx = x * scaleX; // x position of pixel + + var d = Math.Sin(xx) * Math.Cos(yy) // compute gyroid equation + + Math.Sin(yy) * Math.Cos(zz) + + Math.Sin(zz) * Math.Cos(xx); + //if (d > 1e-6) continue; // Far from surface + if (Math.Abs(d) - 0.006*_infillThickness > 0) continue; + //if (d - 0.05 > 1e-6) continue; + + span[x] = _infillBrightness; + } + } + + + //using var contours = patternMask.FindContours(); + //CvInvoke.DrawContours(patternMask, contours, -1, infillColor, _infillThickness); + + disposeTargetMask = true; + } + + //patternMask.Save("D:\\pattern.png"); CvInvoke.Erode(target, erode, kernel, anchor, WallThickness, BorderType.Reflect101, default); @@ -390,5 +519,58 @@ public sealed class OperationInfill : Operation return patternMask; } + public Mat GetConcentricMask(Size targetSize) + { + var patternMask = EmguExtensions.InitMat(targetSize); + + //var halfInfillSpacing = _infillSpacing / 2; + //var halfThickenss = _infillThickness / 2; + int multiplicator = 1; + byte position = 0; + + int x = patternMask.Width / 2; + int y = patternMask.Height / 2; + + Point[] directions = { + new(0, -_infillSpacing), // top + new(_infillSpacing, 0), // right + new(0, _infillSpacing), // bottom + new(-_infillSpacing, 0), // left + }; + + bool[] hitLimits = + { + false, + false, + false, + false + }; + + var points = new List {new(x, y)}; + + while (hitLimits.Any(hitLimit => !hitLimit)) + { + x += directions[position].X * multiplicator; + y += directions[position].Y * multiplicator; + if (x < 0 || y < 0 || x >= patternMask.Width || y >= patternMask.Height) hitLimits[position] = true; + points.Add(new Point(x, y)); + position++; + if (position == 2) + { + multiplicator++; + } + else if (position == 4) + { + multiplicator++; + position = 0; + } + } + + + CvInvoke.Polylines(patternMask, points.ToArray(), false, new MCvScalar(_infillBrightness), _infillThickness); + + return patternMask; + } + #endregion } \ No newline at end of file diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index f54b303..c9bc034 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -1,75 +1,85 @@ - - net6.0 - true - LICENSE - PTRTECH - Tiago Conceição - Git - https://github.com/sn4k3/UVtools - https://github.com/sn4k3/UVtools - MSLA/DLP, file analysis, calibration, repair, conversion and manipulation - 3.2.0 - Copyright © 2020 PTRTECH - UVtools.png - AnyCPU;x64 - false - - msla, dlp, resin, printer, slicer, 3d printing, image processing, layers - UVtools.ico - README.md - enable - + + net6.0 + true + LICENSE + PTRTECH + Tiago Conceição + Git + https://github.com/sn4k3/UVtools + https://github.com/sn4k3/UVtools + MSLA/DLP, file analysis, calibration, repair, conversion and manipulation + 3.2.1 + Copyright © 2020 PTRTECH + UVtools.png + AnyCPU;x64 + false + + msla, dlp, resin, printer, slicer, 3d printing, image processing, layers + UVtools.ico + README.md + enable + - - true - - + + true + + - - true - + + true + - - true - + + true + - - true - + + true + - - - + + + - - - True - - - - True - \ - - - True - - - + + + True + + + + True + \ + + + True + + + + + + + + + + + + + + + + + + + + + + + + + @(ReleaseNoteLines, '%0a') + + - - - - - - - - - - - - - - diff --git a/UVtools.InstallerMM/UVtools.InstallerMM.wxs b/UVtools.InstallerMM/UVtools.InstallerMM.wxs index bd403a9..cc40285 100644 --- a/UVtools.InstallerMM/UVtools.InstallerMM.wxs +++ b/UVtools.InstallerMM/UVtools.InstallerMM.wxs @@ -2,7 +2,7 @@ - + diff --git a/UVtools.WPF/MainWindow.axaml b/UVtools.WPF/MainWindow.axaml index 15c9a9c..95b010c 100644 --- a/UVtools.WPF/MainWindow.axaml +++ b/UVtools.WPF/MainWindow.axaml @@ -13,2106 +13,2104 @@ MinHeight="600" DragDrop.AllowDrop="True"> - - - - - + + + + + - + - + Items="{Binding MenuFileOpenRecentItems}" + i:MenuItem.Icon="fas fa-file-import"/> - + i:MenuItem.Icon="fas fa-file-import"/> - + - + - + - + - - - + - + - + - + - + + + - + - + - + - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + - - + + - - + + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +