diff --git a/CHANGELOG.md b/CHANGELOG.md
index c097926..6bdf59b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
# Changelog
+## /09/2020 - v0.8.2.3
+
+
## 16/09/2020 - v0.8.2.2
* (Add) Support for PHZ zip files when renamed to .zip
diff --git a/CreateRelease.ps1 b/CreateRelease.ps1
index 03f5a5a..45dc54b 100644
--- a/CreateRelease.ps1
+++ b/CreateRelease.ps1
@@ -1,7 +1,7 @@
cd $PSScriptRoot
$version = (Get-Command UVtools.GUI\bin\Release\UVtools.Core.dll).FileVersionInfo.FileVersion
-Remove-Item "$PSScriptRoot\UVtools.GUI\bin\Release\Logs" -Recurse
+Remove-Item "$PSScriptRoot\UVtools.GUI\bin\Release\Logs" -Recurse -ErrorAction Ignore
Add-Type -A System.IO.Compression.FileSystem
[IO.Compression.ZipFile]::CreateFromDirectory("$PSScriptRoot\UVtools.GUI\bin\Release", "$PSScriptRoot\UVtools.GUI\bin\UVtools_v$version.zip")
diff --git a/UVtools.Core/FileFormats/UVJFile.cs b/UVtools.Core/FileFormats/UVJFile.cs
index 4b56d0c..79d232b 100644
--- a/UVtools.Core/FileFormats/UVJFile.cs
+++ b/UVtools.Core/FileFormats/UVJFile.cs
@@ -350,6 +350,8 @@ namespace UVtools.Core.FileFormats
public override void Decode(string fileFullPath, OperationProgress progress = null)
{
base.Decode(fileFullPath, progress);
+ if(progress is null) progress = new OperationProgress();
+ progress.Reset(OperationProgress.StatusGatherLayers, LayerCount);
FileFullPath = fileFullPath;
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
diff --git a/UVtools.Core/Objects/BindableBase.cs b/UVtools.Core/Objects/BindableBase.cs
index 5f9447b..946b5ca 100644
--- a/UVtools.Core/Objects/BindableBase.cs
+++ b/UVtools.Core/Objects/BindableBase.cs
@@ -49,6 +49,12 @@ namespace UVtools.Core.Objects
return true;
}
+ protected bool SetProperty([CallerMemberName] string propertyName = null)
+ {
+ OnPropertyChanged(propertyName);
+ return true;
+ }
+
///
/// Notifies listeners that a property value has changed.
///
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index f39e99f..9d1d0f1 100644
--- a/UVtools.Core/UVtools.Core.csproj
+++ b/UVtools.Core/UVtools.Core.csproj
@@ -10,12 +10,12 @@
https://github.com/sn4k3/UVtools
https://github.com/sn4k3/UVtools
MSLA/DLP, file analysis, repair, conversion and manipulation
- 0.8.2.2
+ 0.8.2.3
Copyright © 2020 PTRTECH
UVtools.png
AnyCPU;x64
- 0.8.2.2
- 0.8.2.2
+ 0.8.2.3
+ 0.8.2.3
diff --git a/UVtools.GUI/Properties/AssemblyInfo.cs b/UVtools.GUI/Properties/AssemblyInfo.cs
index 442aef9..e011fe6 100644
--- a/UVtools.GUI/Properties/AssemblyInfo.cs
+++ b/UVtools.GUI/Properties/AssemblyInfo.cs
@@ -35,5 +35,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.8.2.2")]
-[assembly: AssemblyFileVersion("0.8.2.2")]
+[assembly: AssemblyVersion("0.8.2.3")]
+[assembly: AssemblyFileVersion("0.8.2.3")]
diff --git a/UVtools.WPF/App.axaml.cs b/UVtools.WPF/App.axaml.cs
index d4730d7..85895f8 100644
--- a/UVtools.WPF/App.axaml.cs
+++ b/UVtools.WPF/App.axaml.cs
@@ -1,11 +1,15 @@
-using System.Diagnostics;
+/*
+ * GNU AFFERO GENERAL PUBLIC LICENSE
+ * Version 3, 19 November 2007
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ * Everyone is permitted to copy and distribute verbatim copies
+ * of this license document, but changing it is not allowed.
+ */
+
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.ThemeManager;
-using MessageBox.Avalonia.DTO;
-using MessageBox.Avalonia.Enums;
-using MessageBox.Avalonia.Models;
using UVtools.Core.FileFormats;
namespace UVtools.WPF
@@ -25,16 +29,16 @@ namespace UVtools.WPF
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
- Selector = ThemeSelector.Create("Themes");
- Selector.LoadSelectedTheme("UVtools.theme");
+ UserSettings.Load();
+
+ Selector = ThemeSelector.Create("Assets/Themes");
+ Selector.LoadSelectedTheme("Assets/selected.theme");
desktop.MainWindow = new MainWindow
{
//DataContext = Selector
};
desktop.Exit += (sender, e)
- => Selector.SaveSelectedTheme("UVtools.theme");
-
- Debug.WriteLine(Selector.Themes[1].Name);
+ => Selector.SaveSelectedTheme("Assets/selected.theme");
}
base.OnFrameworkInitializationCompleted();
diff --git a/UVtools.WPF/Assets/Icons/UVtools.ico b/UVtools.WPF/Assets/Icons/UVtools.ico
new file mode 100644
index 0000000..2a642ec
Binary files /dev/null and b/UVtools.WPF/Assets/Icons/UVtools.ico differ
diff --git a/UVtools.WPF/Themes/UVtools.themes b/UVtools.WPF/Assets/Themes/UVtools.themes
similarity index 100%
rename from UVtools.WPF/Themes/UVtools.themes
rename to UVtools.WPF/Assets/Themes/UVtools.themes
diff --git a/UVtools.WPF/Themes/UVtoolsDark.xaml b/UVtools.WPF/Assets/Themes/UVtoolsDark.xaml
similarity index 100%
rename from UVtools.WPF/Themes/UVtoolsDark.xaml
rename to UVtools.WPF/Assets/Themes/UVtoolsDark.xaml
diff --git a/UVtools.WPF/Themes/UVtoolsLight.xaml b/UVtools.WPF/Assets/Themes/UVtoolsLight.xaml
similarity index 100%
rename from UVtools.WPF/Themes/UVtoolsLight.xaml
rename to UVtools.WPF/Assets/Themes/UVtoolsLight.xaml
diff --git a/UVtools.WPF/Extensions/BitmapExtension.cs b/UVtools.WPF/Extensions/BitmapExtension.cs
index deee547..d82b89c 100644
--- a/UVtools.WPF/Extensions/BitmapExtension.cs
+++ b/UVtools.WPF/Extensions/BitmapExtension.cs
@@ -1,4 +1,11 @@
-using System;
+/*
+ * GNU AFFERO GENERAL PUBLIC LICENSE
+ * Version 3, 19 November 2007
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ * Everyone is permitted to copy and distribute verbatim copies
+ * of this license document, but changing it is not allowed.
+ */
+using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Avalonia;
@@ -16,6 +23,55 @@ namespace UVtools.WPF.Extensions
///
public static class BitmapExtension
{
+ public static int GetStep(this WriteableBitmap bitmap)
+ => (int)(bitmap.Size.Width * 4);
+
+ ///
+ /// Gets the total length of this
+ ///
+ ///
+ /// The total length of this
+ public static int GetLength(this WriteableBitmap bitmap)
+ => (int) (bitmap.Size.Width * 4 * bitmap.Size.Height);
+
+ public static int GetPixelPos(this WriteableBitmap bitmap, int x, int y)
+ => (int)(bitmap.Size.Width * 4 * y + x);
+
+ ///
+ /// Gets a single pixel span to manipulate or read pixels
+ ///
+ /// Pixel type
+ /// Input
+ /// A containing all pixels in data memory
+ public static unsafe Span GetPixelSpan(this WriteableBitmap bitmap)
+ {
+ using var l = bitmap.Lock();
+ return new Span(l.Address.ToPointer(), bitmap.GetLength());
+ }
+
+
+ public static unsafe Span GetPixelSpan(this WriteableBitmap bitmap, int length, int offset = 0)
+ {
+ using var l = bitmap.Lock();
+ return new Span(IntPtr.Add(l.Address, offset).ToPointer(), length);
+ }
+
+ public static Span GetSinglePixelSpan(this WriteableBitmap bitmap, int x, int y, int length = 3)
+ {
+ using var l = bitmap.Lock();
+ return bitmap.GetPixelSpan(length, bitmap.GetPixelPos(x, y));
+ }
+
+ public static Span GetSinglePixelPosSpan(this WriteableBitmap bitmap, int pos, int length = 3)
+ => bitmap.GetPixelSpan(length, pos);
+
+
+ public static unsafe Span GetPixelRowSpan(this WriteableBitmap bitmap, int y, int length = 0, int offset = 0)
+ {
+ using var l = bitmap.Lock();
+ return new Span(IntPtr.Add(l.Address, (int) (bitmap.Size.Width * 4 * y + offset)).ToPointer(), (int) (length == 0 ? bitmap.Size.Width * 4 : length));
+ }
+
public static SKBitmap ToSkBitmap(this Mat mat)
{
SKBitmap bitmap;
@@ -52,65 +108,77 @@ namespace UVtools.WPF.Extensions
return SKImage.FromBitmap(bitmap);
}
- public static Bitmap ToBitmap(this Mat mat)
+ public static WriteableBitmap ToBitmap(this Mat mat)
{
- if (mat.NumberOfChannels == 1)
- {
- var writeableBitmap = new WriteableBitmap(new PixelSize(mat.Width, mat.Height), new Vector(72, 72),
- PixelFormat.Rgba8888, AlphaFormat.Unpremul);
- var span = mat.GetPixelSpan();
- var bytes = new[] {0, 0, 0, 255};
- using (var lockBuffer = writeableBitmap.Lock())
- {
- for (var i = 1; i < span.Length; i++)
- {
- bytes[0] = bytes[1] = bytes[2] = span[i];
- Marshal.Copy(bytes, 0,
- new IntPtr(lockBuffer.Address.ToInt64() + i * 4), bytes.Length);
- }
- }
+ var dataCount = mat.Width * mat.Height;
- return writeableBitmap;
+ var writableBitmap = new WriteableBitmap(new PixelSize(mat.Width, mat.Height), new Vector(96, 96),
+ PixelFormat.Bgra8888, AlphaFormat.Unpremul);
+ using var lockBuffer = writableBitmap.Lock();
+
+ unsafe
+ {
+ var targetPixels = (uint*) (void*) lockBuffer.Address;
+ switch (mat.NumberOfChannels)
+ {
+ //Stopwatch sw = Stopwatch.StartNew();
+ // Method 1 (Span copy)
+ case 1:
+ var srcPixels1 = (byte*) (void*) mat.DataPointer;
+ for (var i = 0; i < dataCount; i++)
+ {
+ var color = srcPixels1[i];
+ targetPixels[i] = (uint) (color | color << 8 | color << 16 | 0xff << 24);
+ }
+
+ break;
+ case 3:
+ var srcPixels2 = (byte*) (void*) mat.DataPointer;
+ uint pixel = 0;
+ for (uint i = 0; i < dataCount; i++)
+ {
+ targetPixels[i] = (uint)(srcPixels2[pixel++] | srcPixels2[pixel++] << 8 | srcPixels2[pixel++] << 16 | 0xff << 24);
+ }
+
+ break;
+ case 4:
+ var srcPixels4 = (uint*) (void*) mat.DataPointer;
+ for (uint i = 0; i < dataCount; i++)
+ {
+ targetPixels[i] = srcPixels4[i];
+ }
+
+ break;
+ }
}
- return null;
- }
- /*PixelFormat targetPixelFormat = PixelFormat.Bgra8888;
-
- switch (mat.NumberOfChannels)
- {
- case 3:
- targetPixelFormat = PixelFormat.Rgb565;
- break;
- case 4:
- targetPixelFormat = PixelFormat.Bgra8888;
- break;
- default:
- throw new Exception("Unknown color type");
- }
+ return writableBitmap;
+ /*Debug.WriteLine($"Method 1 (Span copy): {sw.ElapsedMilliseconds}ms");
+
+ // Method 2 (OpenCV Convertion + Copy Marshal)
+ sw.Restart();
+ CvInvoke.CvtColor(mat, target, ColorConversion.Bgr2Bgra);
+ var buffer = target.GetBytes();
+ Marshal.Copy(buffer, 0, lockBuffer.Address, buffer.Length);
+ Debug.WriteLine($"Method 2 (OpenCV Convertion + Copy Marshal): {sw.ElapsedMilliseconds}ms");
-
- var writeableBitmap = new WriteableBitmap(new PixelSize(mat.Width, mat.Height), new Vector(72, 72), targetPixelFormat, AlphaFormat.Unpremul);
- using var lockBuffer = writeableBitmap.Lock();
- var buffer = mat.GetBytes();
- for (var y = 0; y < mat.Height; y++)
- {
- Marshal.Copy(buffer, y * lockBuffer.RowBytes, new IntPtr(lockBuffer.Address.ToInt64() + y * lockBuffer.RowBytes), lockBuffer.RowBytes);
+
+ //sw.Restart();
+ CvInvoke.CvtColor(mat, target, ColorConversion.Bgr2Bgra);
+ unsafe
+ {
+ var srcAddress = (uint*)(void*)target.DataPointer;
+ var targetAddress = (uint*)(void*)lockBuffer.Address;
+ *targetAddress = *srcAddress;
+ }
+ //Debug.WriteLine($"Method 3 (OpenCV Convertion + Set Address): {sw.ElapsedMilliseconds}ms");
+
+ return writableBitmap;
+ */
+ /* for (var y = 0; y < mat.Height; y++)
+ {
+ Marshal.Copy(buffer, y * lockBuffer.RowBytes, new IntPtr(lockBuffer.Address.ToInt64() + y * lockBuffer.RowBytes), lockBuffer.RowBytes);
+ }*/
}
- //Marshal.Copy(buffer, 0, lockBuffer.Address, buffer.Length);
-
- SKBitmap bitmap = new SKBitmap(new SKImageInfo(mat.Width, mat.Height, SKColorType.Gray8));
- bitmap.SetPixels(mat.DataPointer);
- Debug.WriteLine(bitmap.Info.ColorType);
-
- bitmap = SKBitmap.Decode(buffer.AsSpan(), new SKImageInfo
- {
- Width = mat.Width,
- Height = mat.Height,
- ColorType = SKColorType.Gray8,
- });*/
-
- /*return writeableBitmap;
- }*/
}
}
\ No newline at end of file
diff --git a/UVtools.WPF/Extensions/MatrixHelper.cs b/UVtools.WPF/Extensions/MatrixHelper.cs
deleted file mode 100644
index f8b1e78..0000000
--- a/UVtools.WPF/Extensions/MatrixHelper.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-using System;
-using Avalonia;
-
-namespace UVtools.WPF.Extensions
-{
- ///
- /// Avalonia Matrix helper methods.
- ///
- public static class MatrixHelper
- {
- ///
- /// Creates a translation matrix using the specified offsets.
- ///
- /// X-coordinate offset.
- /// Y-coordinate offset.
- /// The created translation matrix.
- public static Matrix Translate(double offsetX, double offsetY)
- {
- return new Matrix(1.0, 0.0, 0.0, 1.0, offsetX, offsetY);
- }
-
- ///
- /// Prepends a translation around the center of provided matrix.
- ///
- /// The matrix to prepend translation.
- /// X-coordinate offset.
- /// Y-coordinate offset.
- /// The created translation matrix.
- public static Matrix TranslatePrepend(Matrix matrix, double offsetX, double offsetY)
- {
- return Translate(offsetX, offsetY) * matrix;
- }
-
- ///
- /// Creates a matrix that scales along the x-axis and y-axis.
- ///
- /// Scaling factor that is applied along the x-axis.
- /// Scaling factor that is applied along the y-axis.
- /// The created scaling matrix.
- public static Matrix Scale(double scaleX, double scaleY)
- {
- return new Matrix(scaleX, 0, 0, scaleY, 0.0, 0.0);
- }
-
- ///
- /// Creates a matrix that is scaling from a specified center.
- ///
- /// Scaling factor that is applied along the x-axis.
- /// Scaling factor that is applied along the y-axis.
- /// The center X-coordinate of the scaling.
- /// The center Y-coordinate of the scaling.
- /// The created scaling matrix.
- public static Matrix ScaleAt(double scaleX, double scaleY, double centerX, double centerY)
- {
- return new Matrix(scaleX, 0, 0, scaleY, centerX - (scaleX * centerX), centerY - (scaleY * centerY));
- }
-
- ///
- /// Prepends a scale around the center of provided matrix.
- ///
- /// The matrix to prepend scale.
- /// Scaling factor that is applied along the x-axis.
- /// Scaling factor that is applied along the y-axis.
- /// The center X-coordinate of the scaling.
- /// The center Y-coordinate of the scaling.
- /// The created scaling matrix.
- public static Matrix ScaleAtPrepend(Matrix matrix, double scaleX, double scaleY, double centerX, double centerY)
- {
- return ScaleAt(scaleX, scaleY, centerX, centerY) * matrix;
- }
-
- ///
- /// Creates a skew matrix.
- ///
- /// Angle of skew along the X-axis in radians.
- /// Angle of skew along the Y-axis in radians.
- /// When the method completes, contains the created skew matrix.
- public static Matrix Skew(float angleX, float angleY)
- {
- return new Matrix(1.0, Math.Tan(angleX), Math.Tan(angleY), 1.0, 0.0, 0.0);
- }
-
- ///
- /// Creates a matrix that rotates.
- ///
- /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis.
- /// The created rotation matrix.
- public static Matrix Rotation(double radians)
- {
- double cos = Math.Cos(radians);
- double sin = Math.Sin(radians);
- return new Matrix(cos, sin, -sin, cos, 0, 0);
- }
-
- ///
- /// Creates a matrix that rotates about a specified center.
- ///
- /// Angle of rotation in radians.
- /// The center X-coordinate of the rotation.
- /// The center Y-coordinate of the rotation.
- /// The created rotation matrix.
- public static Matrix Rotation(double angle, double centerX, double centerY)
- {
- return Translate(-centerX, -centerY) * Rotation(angle) * Translate(centerX, centerY);
- }
-
- ///
- /// Creates a matrix that rotates about a specified center.
- ///
- /// Angle of rotation in radians.
- /// The center of the rotation.
- /// The created rotation matrix.
- public static Matrix Rotation(double angle, Vector center)
- {
- return Translate(-center.X, -center.Y) * Rotation(angle) * Translate(center.X, center.Y);
- }
-
- ///
- /// Transforms a point by this matrix.
- ///
- /// The matrix to use as a transformation matrix.
- /// >The original point to apply the transformation.
- /// The result of the transformation for the input point.
- public static Point TransformPoint(Matrix matrix, Point point)
- {
- return new Point(
- (point.X * matrix.M11) + (point.Y * matrix.M21) + matrix.M31,
- (point.X * matrix.M12) + (point.Y * matrix.M22) + matrix.M32);
- }
- }
-}
diff --git a/UVtools.WPF/Extensions/PrimitivesExtensions.cs b/UVtools.WPF/Extensions/PrimitivesExtensions.cs
index d4ff66c..7c99cf4 100644
--- a/UVtools.WPF/Extensions/PrimitivesExtensions.cs
+++ b/UVtools.WPF/Extensions/PrimitivesExtensions.cs
@@ -1,4 +1,12 @@
-using Avalonia;
+/*
+ * GNU AFFERO GENERAL PUBLIC LICENSE
+ * Version 3, 19 November 2007
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ * Everyone is permitted to copy and distribute verbatim copies
+ * of this license document, but changing it is not allowed.
+ */
+
+using Avalonia;
namespace UVtools.WPF.Extensions
{
diff --git a/UVtools.WPF/Extensions/WindowExtensions.cs b/UVtools.WPF/Extensions/WindowExtensions.cs
index 191ae84..84d5ad3 100644
--- a/UVtools.WPF/Extensions/WindowExtensions.cs
+++ b/UVtools.WPF/Extensions/WindowExtensions.cs
@@ -1,11 +1,14 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
+/*
+ * GNU AFFERO GENERAL PUBLIC LICENSE
+ * Version 3, 19 November 2007
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ * Everyone is permitted to copy and distribute verbatim copies
+ * of this license document, but changing it is not allowed.
+ */
using System.Threading.Tasks;
using Avalonia.Controls;
using MessageBox.Avalonia.DTO;
using MessageBox.Avalonia.Enums;
-using MessageBox.Avalonia.Models;
namespace UVtools.WPF.Extensions
{
diff --git a/UVtools.WPF/MainWindow.axaml b/UVtools.WPF/MainWindow.axaml
index 6a55a48..a89a854 100644
--- a/UVtools.WPF/MainWindow.axaml
+++ b/UVtools.WPF/MainWindow.axaml
@@ -7,9 +7,11 @@
xmlns:idc="clr-namespace:Dock.Avalonia.Controls;assembly=Dock.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="UVtools.WPF.MainWindow"
- Title="UVtools">
+ Title="UVtools"
+ Icon="/Assets/Icons/UVtools.ico"
+ >
-
+
+
+ true
+
+
+ true
@@ -13,6 +27,7 @@
+
@@ -20,6 +35,9 @@
+
+
+
MSBuild:Compile
@@ -27,14 +45,18 @@
MSBuild:Compile
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
+
+ True
+
+
diff --git a/UVtools.WPF/UserSettings.cs b/UVtools.WPF/UserSettings.cs
new file mode 100644
index 0000000..e0e5f6d
--- /dev/null
+++ b/UVtools.WPF/UserSettings.cs
@@ -0,0 +1,231 @@
+/*
+ * GNU AFFERO GENERAL PUBLIC LICENSE
+ * Version 3, 19 November 2007
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ * Everyone is permitted to copy and distribute verbatim copies
+ * of this license document, but changing it is not allowed.
+ */
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Xml.Serialization;
+using Avalonia.Media;
+
+namespace UVtools.WPF
+{
+ [Serializable]
+ public sealed class UserSettings
+ {
+ #region Sub classes
+ [Serializable]
+ public sealed class GeneralUserSettings
+ {
+ public bool StartMaximized { get; set; } = true;
+ public bool CheckForUpdatesOnStartup { get; set; } = true;
+ public byte DefaultOpenFileExtensionIndex { get; set; }
+ public string DefaultDirectoryOpenFile { get; set; }
+ public string DefaultDirectorySaveFile { get; set; }
+ public string DefaultDirectoryExtractFile { get; set; }
+ public string DefaultDirectoryConvertFile { get; set; }
+ public bool PromptOverwriteFileSave { get; set; } = true;
+ public string FileSaveNamePrefix { get; set; }
+ public string FileSaveNameSuffix { get; set; } = "_copy";
+ }
+
+ [Serializable]
+ public sealed class LayerPreviewUserSettings
+ {
+ public Color TooltipOverlayBackgroundColor { get; set; } = new Color(210, 255, 255, 192);
+
+ public bool TooltipOverlay { get; set; } = true;
+
+ public Color VolumeBoundsOutlineColor { get; set; } = new Color(210, 0, 255, 0);
+ public byte VolumeBoundsOutlineThickness { get; set; } = 3;
+ public bool VolumeBoundsOutline { get; set; } = true;
+
+ public Color LayerBoundsOutlineColor { get; set; } = new Color(210, 0, 255, 0);
+ public byte LayerBoundsOutlineThickness { get; set; } = 3;
+ public bool LayerBoundsOutline { get; set; } = true;
+
+ public Color HollowOutlineColor { get; set; } = new Color(210, 255, 165, 0);
+ public byte HollowOutlineLineThickness { get; set; } = 3;
+ public bool HollowOutline { get; set; } = true;
+
+ public Color PreviousLayerDifferenceColor { get; set; } = new Color(255, 255, 0, 255);
+ public Color NextLayerDifferenceColor { get; set; } = new Color(255, 0, 255, 255);
+ public Color BothLayerDifferenceColor { get; set; } = new Color(255, 255, 0, 0);
+ public bool ShowLayerDifference { get; set; } = true;
+
+ public Color IslandColor { get; set; } = new Color(255, 255,215, 0);
+ public Color IslandHighlightColor { get; set; } = new Color(255, 255,255, 0);
+ public Color ResinTrapColor { get; set; } = new Color(255, 244, 164, 96);
+ public Color ResinTrapHighlightColor { get; set; } = new Color(255, 255, 165, 0);
+ public Color TouchingBoundsColor { get; set; } = new Color(255, 255, 0, 0);
+ public Color CrosshairColor { get; set; } = new Color(255, 255, 0, 0);
+
+ public bool ZoomToFitPrintVolumeBounds { get; set; } = true;
+ public byte ZoomLockLevelIndex { get; set; } = 7;
+ public bool ZoomIssues { get; set; } = true;
+
+ public bool CrosshairShowOnlyOnSelectedIssues { get; set; } = false;
+ public byte CrosshairFadeLevelIndex { get; set; } = 5;
+ public uint CrosshairLength { get; set; } = 20;
+ public byte CrosshairMargin { get; set; } = 5;
+
+ public bool AutoRotateLayerBestView { get; set; } = true;
+ public bool LayerZoomToFitOnLoad { get; set; } = true;
+
+ }
+
+ [Serializable]
+ public sealed class IssuesUserSettings
+ {
+ public bool ComputeIssuesOnLoad { get; set; } = false;
+ public bool ComputeIssuesOnClickTab { get; set; } = true;
+ public bool ComputeIslands { get; set; } = true;
+ public bool ComputeResinTraps { get; set; } = true;
+ public bool ComputeTouchingBounds { get; set; } = true;
+ public bool ComputeEmptyLayers { get; set; } = true;
+
+ public bool IslandAllowDiagonalBonds { get; set; } = false;
+ public byte IslandBinaryThreshold { get; set; } = 0;
+ public byte IslandRequiredAreaToProcessCheck { get; set; } = 1;
+ public byte IslandRequiredPixelsToSupport { get; set; } = 10;
+ public byte IslandRequiredPixelBrightnessToSupport { get; set; } = 150;
+
+
+ public byte ResinTrapBinaryThreshold { get; set; } = 127;
+ public byte ResinTrapRequiredAreaToProcessCheck { get; set; } = 17;
+ public byte ResinTrapRequiredBlackPixelsToDrain { get; set; } = 10;
+ public byte ResinTrapMaximumPixelBrightnessToDrain { get; set; } = 30;
+
+ }
+
+ [Serializable]
+ public sealed class PixelEditorUserSettings
+ {
+ public Color AddPixelColor { get; set; } = new Color(255, 144, 238, 144);
+ public Color AddPixelHighlightColor { get; set; } = new Color(255, 0, 255, 0);
+
+ public Color RemovePixelColor { get; set; } = new Color(255, 219, 112, 147);
+ public Color RemovePixelHighlightColor { get; set; } = new Color(255, 139, 0, 0);
+
+ public Color SupportsColor { get; set; } = new Color(255, 0, 255, 255);
+ public Color SupportsHighlightColor { get; set; } = new Color(255, 0, 139, 139);
+
+ public Color DrainHolesColor { get; set; } = new Color(255, 142, 69, 133);
+ public Color DrainHolesHighlightColor { get; set; } = new Color(255, 159, 0, 197);
+
+ public bool PartialUpdateIslandsOnEditing { get; set; } = true;
+ public bool CloseEditorOnApply { get; set; } = false;
+ }
+
+ [Serializable]
+ public sealed class LayerRepairUserSettings
+ {
+
+ public byte ClosingIterations { get; set; } = 2;
+ public byte OpeningIterations { get; set; } = 0;
+ public byte RemoveIslandsBelowEqualPixels { get; set; } = 10;
+
+ public bool RepairIslands { get; set; } = true;
+ public bool RepairResinTraps { get; set; } = true;
+ public bool RemoveEmptyLayers { get; set; } = true;
+ }
+
+ #endregion
+
+ #region Singleton
+ ///
+ /// Default filepath for store
+ ///
+ private const string FilePath = "Assets/usersettings.xml";
+
+
+ private static UserSettings _instance;
+ ///
+ /// Instance of (singleton)
+ ///
+ public static UserSettings Instance => _instance ??= new UserSettings();
+ #endregion
+
+ #region Properties
+
+ public GeneralUserSettings General { get; set; } = new GeneralUserSettings();
+ public LayerPreviewUserSettings LayerPreview { get; set; } = new LayerPreviewUserSettings();
+ public IssuesUserSettings Issues { get; set; } = new IssuesUserSettings();
+ public PixelEditorUserSettings PixelEditor { get; set; } = new PixelEditorUserSettings();
+ public LayerRepairUserSettings LayerRepair { get; set; } = new LayerRepairUserSettings();
+
+ ///
+ /// Gets or sets the number of times this file has been saved
+ ///
+ public uint SavesCount { get; set; }
+
+ ///
+ /// Gets or sets the last time this file has been modified
+ ///
+ public DateTime ModifiedDateTime { get; set; }
+ #endregion
+
+ #region Constructor
+ private UserSettings()
+ { }
+ #endregion
+
+ #region Static Methods
+ ///
+ /// Reset settings to defaults
+ ///
+ /// True to save settings on file, otherwise false
+ public static void Reset(bool save = false)
+ {
+ _instance = new UserSettings();
+ if(save) Save();
+ }
+
+ ///
+ /// Load settings from file
+ ///
+ public static void Load()
+ {
+ if (!File.Exists(FilePath))
+ {
+ return;
+ }
+
+ var serializer = new XmlSerializer(typeof(UserSettings));
+ using StreamReader myXmlReader = new StreamReader(FilePath);
+ try
+ {
+ _instance = (UserSettings)serializer.Deserialize(myXmlReader);
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine(e.Message);
+ }
+ }
+
+
+ ///
+ /// Save settings to file
+ ///
+ public static void Save()
+ {
+ Instance.SavesCount++;
+ _instance.ModifiedDateTime = DateTime.Now;
+ var serializer = new XmlSerializer(_instance.GetType());
+ using StreamWriter myXmlWriter = new StreamWriter(FilePath);
+ try
+ {
+ serializer.Serialize(myXmlWriter, _instance);
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine(e.Message);
+ }
+ }
+ #endregion
+ }
+}
diff --git a/UVtools.WPF/ViewModels/MainWindowViewModel.cs b/UVtools.WPF/ViewModels/MainWindowViewModel.cs
index c69bf7f..2583d5f 100644
--- a/UVtools.WPF/ViewModels/MainWindowViewModel.cs
+++ b/UVtools.WPF/ViewModels/MainWindowViewModel.cs
@@ -1,4 +1,5 @@
using System.Diagnostics;
+using System.Reflection;
using Avalonia.Controls;
using JetBrains.Annotations;
using MessageBox.Avalonia.DTO;
@@ -6,13 +7,26 @@ using MessageBox.Avalonia.Enums;
using MessageBox.Avalonia.Models;
using UVtools.Core.Objects;
using UVtools.WPF.Extensions;
+using UVtools.WPF.Windows;
namespace UVtools.WPF.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private MainWindow Parent;
- public bool IsFileLoaded => !ReferenceEquals(App.SlicerFile, null);
+
+ private bool _isGUIEnabled = true;
+ public bool IsGUIEnabled
+ {
+ get => _isGUIEnabled;
+ set => SetProperty(ref _isGUIEnabled, value);
+ }
+
+ public bool IsFileLoaded
+ {
+ get => !ReferenceEquals(App.SlicerFile, null);
+ set => SetProperty();
+ }
public MainWindowViewModel(MainWindow parent)
{
@@ -28,5 +42,12 @@ namespace UVtools.WPF.ViewModels
var files = await dialog.ShowAsync(Parent);
Parent.ProcessFiles(files);
}
+
+ public async void MenuFileSettingsClicked()
+ {
+ SettingsWindow settingsWindow = new SettingsWindow();
+ settingsWindow.Title += $" [v{Assembly.GetEntryAssembly().GetName().Version}]";
+ await settingsWindow.ShowDialog(Parent);
+ }
}
}
diff --git a/UVtools.WPF/Windows/ProgressWindow.axaml b/UVtools.WPF/Windows/ProgressWindow.axaml
new file mode 100644
index 0000000..fbcc4a2
--- /dev/null
+++ b/UVtools.WPF/Windows/ProgressWindow.axaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/UVtools.WPF/Windows/ProgressWindow.axaml.cs b/UVtools.WPF/Windows/ProgressWindow.axaml.cs
new file mode 100644
index 0000000..b9744e6
--- /dev/null
+++ b/UVtools.WPF/Windows/ProgressWindow.axaml.cs
@@ -0,0 +1,26 @@
+/*
+ * GNU AFFERO GENERAL PUBLIC LICENSE
+ * Version 3, 19 November 2007
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ * Everyone is permitted to copy and distribute verbatim copies
+ * of this license document, but changing it is not allowed.
+ */
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace UVtools.WPF.Windows
+{
+ public class ProgressWindow : Window
+ {
+ public ProgressWindow()
+ {
+ InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+
+ }
+ }
+}
diff --git a/UVtools.WPF/Windows/SettingsWindow.axaml b/UVtools.WPF/Windows/SettingsWindow.axaml
new file mode 100644
index 0000000..6ff2278
--- /dev/null
+++ b/UVtools.WPF/Windows/SettingsWindow.axaml
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/UVtools.WPF/Windows/SettingsWindow.axaml.cs b/UVtools.WPF/Windows/SettingsWindow.axaml.cs
new file mode 100644
index 0000000..dee093d
--- /dev/null
+++ b/UVtools.WPF/Windows/SettingsWindow.axaml.cs
@@ -0,0 +1,19 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace UVtools.WPF.Windows
+{
+ public class SettingsWindow : Window
+ {
+ public SettingsWindow()
+ {
+ InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+ }
+}