Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sn4k3/UVtools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiago Conceição <Tiago_caza@hotmail.com>2022-04-06 20:17:48 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2022-04-06 20:17:48 +0300
commit331d37be7c8e3dfcbf08a4896fff1103b519d977 (patch)
tree8ad40f70b9e1943ea5c1fbf8a86f28e696e887a5
parent7538d49acafb7667efd3f38fd84e7c5f7de8f241 (diff)
v3.2.2 - Birthday release 🎁 (2 years old) 🥳v3.2.2
- **Settings:** - (Add) Remove source file after automatic conversion (#444) - (Add) Remove source file after manual conversion (#444) - (Add) **Average resin bottle cost:** The average cost per one resin bottle of 1000ml. Used to calculate the material cost when the file lacks that information. Use 0 to disable this feature and only show the cost if file have that information. If this value is changed, you need to reload the current file to update the cost. - (Change) Move "Expand and show tool descriptions by default" to From `General` to `Tools` tab (Setting will reset to default) - **File formats:** - (Add) Property `StartingMaterialMilliliters`: Gets the starting material milliliters when the file was loaded - (Add) Property `StartingMaterialCost`: Gets the starting material cost when the file was loaded - (Add) Property `MaterialMilliliterCost`: Gets the material cost per one milliliter - (Improvement) Update `MaterialCost` when `MaterialMilliliters` changes (#449) - **Raft relief:** - (Add) Linked lines: Remove the raft, keep supports and link them with lines - (Improvement) Change the supports detection parameters to be more effective and precise on detect the starting layer - (Fix) Brightness percentage not getting updated - (Fix) Remove anti-aliased edges from Tabs - (Improvement) Core: Minor clean-up - (Fix) Issue repair error when 'Auto repair layers and issues on file load' is enabled (#446) - (Fix) UI: Selecting a object with ROI when flip is verically, will cause 1px up-shift on the preview - (Fix) macOS permission error due loss of attributes on the build script, WSL have bug with mv, using ln&rm instead
-rw-r--r--CHANGELOG.md25
-rw-r--r--RELEASE_NOTES.md23
-rw-r--r--UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj2
-rw-r--r--UVtools.Cmd/UVtools.Cmd.csproj2
-rw-r--r--UVtools.Core/About.cs147
-rw-r--r--UVtools.Core/CoreSettings.cs8
-rw-r--r--UVtools.Core/EmguCV/EmguContours.cs68
-rw-r--r--UVtools.Core/Extensions/DateTimeExtensions.cs32
-rw-r--r--UVtools.Core/FileFormats/FileFormat.cs21
-rw-r--r--UVtools.Core/GCode/GCodeBuilder.cs2
-rw-r--r--UVtools.Core/Layers/Layer.cs36
-rw-r--r--UVtools.Core/Operations/OperationLayerExportImage.cs2
-rw-r--r--UVtools.Core/Operations/OperationRaftRelief.cs143
-rw-r--r--UVtools.Core/Operations/OperationRepairLayers.cs19
-rw-r--r--UVtools.Core/RELEASE_NOTES.md12
-rw-r--r--UVtools.Core/UVtools.Core.csproj8
-rw-r--r--UVtools.InstallerMM/UVtools.InstallerMM.wxs2
-rw-r--r--UVtools.WPF/App.axaml.cs47
-rw-r--r--UVtools.WPF/Assets/Styles/Styles.xaml8
-rw-r--r--UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml95
-rw-r--r--UVtools.WPF/ErrorLog.cs3
-rw-r--r--UVtools.WPF/MainWindow.LayerPreview.cs2
-rw-r--r--UVtools.WPF/MainWindow.axaml.cs14
-rw-r--r--UVtools.WPF/Structures/AppVersionChecker.cs6
-rw-r--r--UVtools.WPF/UVtools.WPF.csproj14
-rw-r--r--UVtools.WPF/UserSettings.cs32
-rw-r--r--UVtools.WPF/Windows/AboutWindow.axaml18
-rw-r--r--UVtools.WPF/Windows/AboutWindow.axaml.cs41
-rw-r--r--UVtools.WPF/Windows/BenchmarkWindow.axaml.cs8
-rw-r--r--UVtools.WPF/Windows/SettingsWindow.axaml39
-rw-r--r--UVtools.WPF/Windows/SettingsWindow.axaml.cs3
-rw-r--r--UVtools.WPF/Windows/ToolWindow.axaml2
-rw-r--r--build/createRelease.ps12
33 files changed, 674 insertions, 212 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 600081d..e9ffca0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,30 @@
# Changelog
+## 06/04/2022 - v3.2.2
+
+- **Settings:**
+ - (Add) Remove source file after automatic conversion (#444)
+ - (Add) Remove source file after manual conversion (#444)
+ - (Add) **Average resin bottle cost:** The average cost per one resin bottle of 1000ml.
+ Used to calculate the material cost when the file lacks that information.
+ Use 0 to disable this feature and only show the cost if file have that information.
+ If this value is changed, you need to reload the current file to update the cost.
+ - (Change) Move "Expand and show tool descriptions by default" to From `General` to `Tools` tab (Setting will reset to default)
+- **File formats:**
+ - (Add) Property `StartingMaterialMilliliters`: Gets the starting material milliliters when the file was loaded
+ - (Add) Property `StartingMaterialCost`: Gets the starting material cost when the file was loaded
+ - (Add) Property `MaterialMilliliterCost`: Gets the material cost per one milliliter
+ - (Improvement) Update `MaterialCost` when `MaterialMilliliters` changes (#449)
+- **Raft relief:**
+ - (Add) Linked lines: Remove the raft, keep supports and link them with lines
+ - (Improvement) Change the supports detection parameters to be more effective and precise on detect the starting layer
+ - (Fix) Brightness percentage not getting updated
+ - (Fix) Remove anti-aliased edges from Tabs
+- (Improvement) Core: Minor clean-up
+- (Fix) Issue repair error when 'Auto repair layers and issues on file load' is enabled (#446)
+- (Fix) UI: Selecting a object with ROI when flip is verically, will cause 1px up-shift on the preview
+- (Fix) macOS permission error due loss of attributes on the build script, WSL have bug with mv, using ln&rm instead
+
## 02/04/2022 - v3.2.1
- **AnyCubic file format:**
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
new file mode 100644
index 0000000..1ebb05c
--- /dev/null
+++ b/RELEASE_NOTES.md
@@ -0,0 +1,23 @@
+- **Settings:**
+ - (Add) Remove source file after automatic conversion (#444)
+ - (Add) Remove source file after manual conversion (#444)
+ - (Add) **Average resin bottle cost:** The average cost per one resin bottle of 1000ml.
+ Used to calculate the material cost when the file lacks that information.
+ Use 0 to disable this feature and only show the cost if file have that information.
+ If this value is changed, you need to reload the current file to update the cost.
+ - (Change) Move "Expand and show tool descriptions by default" to From `General` to `Tools` tab (Setting will reset to default)
+- **File formats:**
+ - (Add) Property `StartingMaterialMilliliters`: Gets the starting material milliliters when the file was loaded
+ - (Add) Property `StartingMaterialCost`: Gets the starting material cost when the file was loaded
+ - (Add) Property `MaterialMilliliterCost`: Gets the material cost per one milliliter
+ - (Improvement) Update `MaterialCost` when `MaterialMilliliters` changes (#449)
+- **Raft relief:**
+ - (Add) Linked lines: Remove the raft, keep supports and link them with lines
+ - (Improvement) Change the supports detection parameters to be more effective and precise on detect the starting layer
+ - (Fix) Brightness percentage not getting updated
+ - (Fix) Remove anti-aliased edges from Tabs
+- (Improvement) Core: Minor clean-up
+- (Fix) Issue repair error when 'Auto repair layers and issues on file load' is enabled (#446)
+- (Fix) UI: Selecting a object with ROI when flip is verically, will cause 1px up-shift on the preview
+- (Fix) macOS permission error due loss of attributes on the build script, WSL have bug with mv, using ln&rm instead
+
diff --git a/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj b/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj
index 676fb95..a3f8722 100644
--- a/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj
+++ b/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj
@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
- <Authors>Tiago Conceição</Authors>
+ <Authors>Tiago Conceição, sn4k3</Authors>
<Company>PTRTECH</Company>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
diff --git a/UVtools.Cmd/UVtools.Cmd.csproj b/UVtools.Cmd/UVtools.Cmd.csproj
index 9240a90..0f7493f 100644
--- a/UVtools.Cmd/UVtools.Cmd.csproj
+++ b/UVtools.Cmd/UVtools.Cmd.csproj
@@ -6,7 +6,7 @@
<AssemblyName>UVtoolsCmd</AssemblyName>
<ApplicationIcon>UVtools.ico</ApplicationIcon>
<Version>1.0.0</Version>
- <Authors>Tiago Conceição</Authors>
+ <Authors>Tiago Conceição, sn4k3</Authors>
<Company>PTRTECH</Company>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
diff --git a/UVtools.Core/About.cs b/UVtools.Core/About.cs
index db116bf..b41c27b 100644
--- a/UVtools.Core/About.cs
+++ b/UVtools.Core/About.cs
@@ -7,27 +7,162 @@
*/
using System;
+using System.IO;
+using System.Linq;
using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using UVtools.Core.Extensions;
+using UVtools.Core.FileFormats;
namespace UVtools.Core;
public static class About
{
public const string Software = "UVtools";
+ public static Version Version => CoreAssembly.GetName().Version!;
+ public static string VersionStr => Version.ToString(3);
+ public static string VersionArch => $"{VersionStr} {RuntimeInformation.ProcessArchitecture}";
public static string SoftwareWithVersion => $"{Software} v{VersionStr}";
+ public static string SoftwareWithVersionArch => $"{Software} v{VersionArch}";
public const string Author = "Tiago Conceição";
- public const string Company = "PTRTECH";
public const string License = "GNU Affero General Public License v3.0 (AGPL)";
public const string LicenseUrl = "https://github.com/sn4k3/UVtools/blob/master/LICENSE";
public const string Website = "https://github.com/sn4k3/UVtools";
public const string Donate = "https://paypal.me/SkillTournament";
public const string Sponsor = "https://github.com/sponsors/sn4k3";
- public const string DemoFile = "UVtools_demo_file.sl1";
+ #region Assembly properties
+ public static Assembly CoreAssembly => Assembly.GetExecutingAssembly();
- public static Version Version => CoreAssembly.GetName().Version!;
- public static string VersionStr => Version.ToString(3);
- public static string Arch => Environment.Is64BitOperatingSystem ? "64-bits" : "32-bits";
+ public static string AssemblyVersion => CoreAssembly.GetName().Version?.ToString()!;
+
+ public static string AssemblyName => Assembly.GetExecutingAssembly().GetName().Name!;
+
+ public static string AssemblyTitle
+ {
+ get
+ {
+ var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
+ if (attributes.Length > 0)
+ {
+ var titleAttribute = (AssemblyTitleAttribute)attributes[0];
+ if (titleAttribute.Title != string.Empty)
+ {
+ return titleAttribute.Title;
+ }
+ }
+ return Path.GetFileNameWithoutExtension(CoreAssembly.Location);
+ }
+ }
+
+ public static string AssemblyDescription
+ {
+ get
+ {
+ var attributes = CoreAssembly.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return string.Empty;
+ }
+
+ var description = ((AssemblyDescriptionAttribute)attributes[0]).Description + $"{Environment.NewLine}{Environment.NewLine}Available File Formats:";
+
+ return FileFormat.AvailableFormats.SelectMany(fileFormat => fileFormat.FileExtensions).Aggregate(description, (current, fileExtension) => current + $"{Environment.NewLine}- {fileExtension.Description} (.{fileExtension.Extension})");
+ }
+ }
+
+ public static string AssemblyProduct
+ {
+ get
+ {
+ var attributes = CoreAssembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);
+ return attributes.Length == 0 ? string.Empty : ((AssemblyProductAttribute)attributes[0]).Product;
+ }
+ }
+
+ public static string AssemblyCopyright
+ {
+ get
+ {
+ var attributes = CoreAssembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
+ return attributes.Length == 0 ? string.Empty : ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
+ }
+ }
+
+ public static string AssemblyCompany
+ {
+ get
+ {
+ var attributes = CoreAssembly.GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
+ return attributes.Length == 0 ? string.Empty : ((AssemblyCompanyAttribute)attributes[0]).Company;
+ }
+ }
+ #endregion
+
+ public static string SystemBits => Environment.Is64BitOperatingSystem ? "64-bits" : "32-bits";
+
+ /// <summary>
+ /// Gets UVtools born date and time
+ /// </summary>
+ public static DateTime Born => new(2020, 4, 6, 20, 33, 14);
+
+ /// <summary>
+ /// Gets UVtools years
+ /// </summary>
+ public static int YearsOld => Born.Age();
+
+ /// <summary>
+ /// Return full age in a readable string
+ /// </summary>
+ public static string AgeStr
+ {
+ get
+ {
+ var sb = new StringBuilder($"{YearsOld} years");
+ var born = Born;
+ var now = DateTime.Now;
+
+ var months = 12 + now.Month - born.Month + (now.Day >= born.Day ? 0 : -1);
+ if (months >= 12) months -= 12;
+ if (months > 0) sb.Append($", {months} month(s)");
+
+
+
+ var days = 31 + now.Day - born.Day;
+ if (days >= 31) days -= 31;
+ if (days > 0) sb.Append($", {days} day(s)");
+
+ var hours = 12 + now.Hour - born.Hour;
+ if (hours >= 12) hours -= 12;
+ if (hours > 0) sb.Append($", {hours} hour(s)");
+
+ var minutes = 60 + now.Minute - born.Minute;
+ if (minutes >= 60) minutes -= 60;
+ if (minutes > 0) sb.Append($", {minutes} minutes(s)");
+
+ var seconds = 60 + now.Second - born.Second;
+ if (seconds >= 60) seconds -= 60;
+ if (seconds > 0) sb.Append($", {seconds} seconds(s)");
+
+
+ return sb.ToString();
+ }
+ }
+
+ /// <summary>
+ /// Checks if today is UVtools birthday
+ /// </summary>
+ public static bool IsBirthday
+ {
+ get
+ {
+ var born = Born;
+ var now = DateTime.Now;
+ return born.Month == now.Month && born.Day == now.Day;
+ }
+ }
+
+ public const string DemoFile = "UVtools_demo_file.sl1";
- public static Assembly CoreAssembly => Assembly.GetExecutingAssembly();
} \ No newline at end of file
diff --git a/UVtools.Core/CoreSettings.cs b/UVtools.Core/CoreSettings.cs
index f048af2..10246be 100644
--- a/UVtools.Core/CoreSettings.cs
+++ b/UVtools.Core/CoreSettings.cs
@@ -71,7 +71,13 @@ public static class CoreSettings
/// <summary>
/// Gets or sets the default compression type for layers
/// </summary>
- public static Layer.LayerCompressionCodec DefaultLayerCompressionCodec { get; set; } = Layer.LayerCompressionCodec.Png;
+ public static LayerCompressionCodec DefaultLayerCompressionCodec { get; set; } = LayerCompressionCodec.Png;
+
+ /// <summary>
+ /// <para>The average resin 1000ml bottle cost, to use when bottle cost is not available.</para>
+ /// <para>Use 0 to disable.</para>
+ /// </summary>
+ public static float AverageResin1000MlBottleCost = 60f;
/// <summary>
/// Gets the default folder to save the settings
diff --git a/UVtools.Core/EmguCV/EmguContours.cs b/UVtools.Core/EmguCV/EmguContours.cs
index 958cfd8..d8c0639 100644
--- a/UVtools.Core/EmguCV/EmguContours.cs
+++ b/UVtools.Core/EmguCV/EmguContours.cs
@@ -6,10 +6,13 @@
* of this license document, but changing it is not allowed.
*/
+using System;
+using System.Collections;
using Emgu.CV;
using Emgu.CV.Util;
using System.Collections.Generic;
using System.Drawing;
+using System.Linq;
using System.Threading.Tasks;
using UVtools.Core.Extensions;
@@ -19,8 +22,71 @@ namespace UVtools.Core.EmguCV;
/// Utility methods for contour handling.
/// Use only with Tree type
/// </summary>
-public static class EmguContours
+public class EmguContours : IReadOnlyList<EmguContour>, IDisposable
{
+ private readonly EmguContour[] _contours;
+
+ public IEnumerator<EmguContour> GetEnumerator()
+ {
+ return ((IEnumerable<EmguContour>)_contours).GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _contours.GetEnumerator();
+ }
+
+ public int Count => _contours.Length;
+
+
+
+ public EmguContour this[int index] => _contours[index];
+
+ public EmguContours(VectorOfVectorOfPoint vectorOfPointsOfPoints)
+ {
+ _contours = new EmguContour[vectorOfPointsOfPoints.Size];
+ for (int i = 0; i < _contours.Length; i++)
+ {
+ _contours[i] = new EmguContour(vectorOfPointsOfPoints[i]);
+ }
+ }
+
+ public (int Index, EmguContour Contour, double Distance)[][] CalculateCentroidDistances(bool includeOwn = false, bool sortByDistance = true)
+ {
+ var items = new (int Index, EmguContour Contour, double Distance)[Count][];
+ for (int i = 0; i < Count; i++)
+ {
+ items[i] = new (int Index, EmguContour Contour, double Distance)[Count-1];
+ int count = 0;
+ for (int x = 0; x < Count; x++)
+ {
+ if (x == i)
+ {
+ if (includeOwn)
+ {
+ items[i][count] = new(x, this[x], 0);
+ }
+ continue;
+ }
+ items[i][count] = new (x, this[x], PointExtensions.FindLength(this[i].Centroid, this[x].Centroid));
+
+ count++;
+ }
+
+ if(sortByDistance) items[i] = items[i].OrderBy(tuple => tuple.Distance).ToArray();
+ }
+
+ return items;
+ }
+
+ public void Dispose()
+ {
+ foreach (var contour in _contours)
+ {
+ contour.Dispose();
+ }
+ }
+
/// <summary>
/// Gets contours inside a point
/// </summary>
diff --git a/UVtools.Core/Extensions/DateTimeExtensions.cs b/UVtools.Core/Extensions/DateTimeExtensions.cs
index ebb132e..9186d5d 100644
--- a/UVtools.Core/Extensions/DateTimeExtensions.cs
+++ b/UVtools.Core/Extensions/DateTimeExtensions.cs
@@ -47,4 +47,36 @@ public static class DateTimeExtensions
{
return DateTime.UnixEpoch.AddMinutes(minutes);
}
+
+ /// <summary>
+ /// Calculates the age in years of the current System.DateTime object today.
+ /// </summary>
+ /// <param name="birthDate">The date of birth</param>
+ /// <returns>Age in years today. 0 is returned for a future date of birth.</returns>
+ public static int Age(this DateTime birthDate)
+ {
+ return Age(birthDate, DateTime.Today);
+ }
+
+ /// <summary>
+ /// Calculates the age in years of the current System.DateTime object on a later date.
+ /// </summary>
+ /// <param name="birthDate">The date of birth</param>
+ /// <param name="laterDate">The date on which to calculate the age.</param>
+ /// <returns>Age in years on a later day. 0 is returned as minimum.</returns>
+ public static int Age(this DateTime birthDate, DateTime laterDate)
+ {
+ var age = laterDate.Year - birthDate.Year;
+
+ if (age > 0)
+ {
+ age -= Convert.ToInt32(laterDate.Date < birthDate.Date.AddYears(age));
+ }
+ else
+ {
+ age = 0;
+ }
+
+ return age;
+ }
} \ No newline at end of file
diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs
index 12ad9e4..6102aef 100644
--- a/UVtools.Core/FileFormats/FileFormat.cs
+++ b/UVtools.Core/FileFormats/FileFormat.cs
@@ -2725,7 +2725,7 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
}
/// <summary>
- /// Gets the starting material milliliters when the file loaded
+ /// Gets the starting material milliliters when the file was loaded
/// </summary>
public float StartingMaterialMilliliters { get; private set; }
@@ -2749,7 +2749,7 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
if (StartingMaterialMilliliters > 0 && StartingMaterialCost > 0)
{
- MaterialCost = _materialMilliliters * StartingMaterialCost / StartingMaterialMilliliters;
+ MaterialCost = GetMaterialCostPer(_materialMilliliters);
}
//RaisePropertyChanged(nameof(MaterialCost));
}
@@ -2768,7 +2768,7 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
}
/// <summary>
- /// Gets the starting material cost when the file loaded
+ /// Gets the starting material cost when the file was loaded
/// </summary>
public float StartingMaterialCost { get; private set; }
@@ -2782,6 +2782,13 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
}
/// <summary>
+ /// Gets the material cost per one milliliter
+ /// </summary>
+ public float MaterialMilliliterCost => StartingMaterialMilliliters > 0 ? StartingMaterialCost / StartingMaterialMilliliters : 0;
+
+ public float GetMaterialCostPer(float milliliters, byte roundDigits = 3) => (float)Math.Round(MaterialMilliliterCost * milliliters, roundDigits);
+
+ /// <summary>
/// Gets the material name
/// </summary>
public virtual string? MaterialName
@@ -3313,7 +3320,11 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
IsModified = false;
StartingMaterialMilliliters = MaterialMilliliters;
StartingMaterialCost = MaterialCost;
-
+ if (StartingMaterialCost <= 0)
+ {
+ StartingMaterialCost = StartingMaterialMilliliters * CoreSettings.AverageResin1000MlBottleCost / 1000f;
+ MaterialCost = StartingMaterialCost;
+ }
progress.ThrowIfCancellationRequested();
@@ -4629,7 +4640,7 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
/// </summary>
/// <param name="newCodec">The new method to change to</param>
/// <param name="progress"></param>
- public void ChangeLayersCompressionMethod(Layer.LayerCompressionCodec newCodec, OperationProgress? progress = null)
+ public void ChangeLayersCompressionMethod(LayerCompressionCodec newCodec, OperationProgress? progress = null)
{
progress ??= new OperationProgress($"Changing layers compression codec to {newCodec}");
progress.Reset("Layers", LayerCount);
diff --git a/UVtools.Core/GCode/GCodeBuilder.cs b/UVtools.Core/GCode/GCodeBuilder.cs
index 98b224f..1cacb93 100644
--- a/UVtools.Core/GCode/GCodeBuilder.cs
+++ b/UVtools.Core/GCode/GCodeBuilder.cs
@@ -309,7 +309,7 @@ public class GCodeBuilder : BindableBase
public void AppendUVtools()
{
- AppendComment($"Generated by {About.Software} v{About.VersionStr} {About.Arch} @ {DateTime.UtcNow}");
+ AppendComment($"Generated by {About.Software} v{About.VersionStr} {About.SystemBits} @ {DateTime.UtcNow}");
}
public void AppendStartGCode()
diff --git a/UVtools.Core/Layers/Layer.cs b/UVtools.Core/Layers/Layer.cs
index 2015ac7..4db7a9e 100644
--- a/UVtools.Core/Layers/Layer.cs
+++ b/UVtools.Core/Layers/Layer.cs
@@ -25,29 +25,29 @@ using UVtools.Core.Operations;
namespace UVtools.Core.Layers;
+#region Enums
+
+public enum LayerCompressionCodec : byte
+{
+ [Description("PNG: Compression=High Speed=Slow (Use with low RAM)")]
+ Png,
+ [Description("GZip: Compression=Medium Speed=Medium (Optimal)")]
+ GZip,
+ [Description("Deflate: Compression=Medium Speed=Medium (Optimal)")]
+ Deflate,
+ [Description("LZ4: Compression=Low Speed=Fast (Use with high RAM)")]
+ Lz4,
+ //[Description("None: Compression=None Speed=Fastest (Your soul belongs to RAM)")]
+ //None
+}
+
+#endregion
+
/// <summary>
/// Represent a Layer
/// </summary>
public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
{
- #region Enums
-
- public enum LayerCompressionCodec : byte
- {
- [Description("PNG: Compression=High Speed=Slow (Use with low RAM)")]
- Png,
- [Description("GZip: Compression=Medium Speed=Medium (Optimal)")]
- GZip,
- [Description("Deflate: Compression=Medium Speed=Medium (Optimal)")]
- Deflate,
- [Description("LZ4: Compression=Low Speed=Fast (Use with high RAM)")]
- Lz4,
- //[Description("None: Compression=None Speed=Fastest (Your soul belongs to RAM)")]
- //None
- }
-
- #endregion
-
#region Constants
public const byte HeightPrecision = 3;
public const decimal HeightPrecisionIncrement = 0.001M;
diff --git a/UVtools.Core/Operations/OperationLayerExportImage.cs b/UVtools.Core/Operations/OperationLayerExportImage.cs
index 918c66b..5fbc7ca 100644
--- a/UVtools.Core/Operations/OperationLayerExportImage.cs
+++ b/UVtools.Core/Operations/OperationLayerExportImage.cs
@@ -216,7 +216,7 @@ public sealed class OperationLayerExportImage : Operation
using TextWriter tw = new StreamWriter(fileFullPath);
tw.WriteLine("<!--");
- tw.WriteLine($"# Generated by {About.Software} v{About.VersionStr} {About.Arch} @ {DateTime.UtcNow} #");
+ tw.WriteLine($"# Generated by {About.Software} v{About.VersionStr} {About.SystemBits} @ {DateTime.UtcNow} #");
tw.WriteLine($"File: {SlicerFile.Filename}");
tw.WriteLine($"{SlicerFile[layerIndex].ToString().Replace(", ", "\n")}");
tw.WriteLine("-->");
diff --git a/UVtools.Core/Operations/OperationRaftRelief.cs b/UVtools.Core/Operations/OperationRaftRelief.cs
index 9725317..3b4ccef 100644
--- a/UVtools.Core/Operations/OperationRaftRelief.cs
+++ b/UVtools.Core/Operations/OperationRaftRelief.cs
@@ -30,6 +30,9 @@ public class OperationRaftRelief : Operation
[Description("Relief: Drill raft to relief pressure and remove some mass")]
Relief,
+ [Description("Linked lines: Remove the raft, keep supports and link them with lines")]
+ LinkedLines,
+
[Description("Dimming: Darkens the raft to cure it less")]
Dimming,
@@ -45,12 +48,15 @@ public class OperationRaftRelief : Operation
private RaftReliefTypes _reliefType = RaftReliefTypes.Relief;
private uint _maskLayerIndex;
private byte _ignoreFirstLayers;
- private byte _brightness;
+ private byte _lowBrightness;
private byte _dilateIterations = 15;// +/- 1.5mm radius
private byte _wallMargin = 40; // +/- 2mm
private byte _holeDiameter = 80; // +/- 4mm
private byte _holeSpacing = 40; // +/- 2mm
- private byte _tabBrightness = byte.MaxValue;
+ private byte _linkedLineThickness = 26;
+ private byte _linkedMinimumLinks = 4;
+ private bool _linkedExternalSupports = true;
+ private byte _highBrightness = byte.MaxValue;
private ushort _tabTriangleBase = 200;
private ushort _tabTriangleHeight = 250;
@@ -60,7 +66,7 @@ public class OperationRaftRelief : Operation
public override string IconClass => "fas fa-bowling-ball";
public override string Title => "Raft relief";
public override string Description =>
- "Relief raft by adding holes in between to reduce FEP suction, save resin and easier to remove the prints.";
+ "Relief raft with a strategy to remove mass, reduce FEP suction, spare resin and easier to remove the prints.";
public override string ConfirmationText =>
$"relief the raft";
@@ -70,8 +76,7 @@ public class OperationRaftRelief : Operation
public override string ProgressAction => "Relieved layers";
- public override LayerRangeSelection StartLayerRangeSelection =>
- LayerRangeSelection.None;
+ public override LayerRangeSelection StartLayerRangeSelection => LayerRangeSelection.None;
public override string? ValidateInternally()
{
@@ -80,7 +85,11 @@ public class OperationRaftRelief : Operation
{
if(_tabTriangleHeight == 0) sb.AppendLine("The tab height can't be 0");
if(_tabTriangleBase == 0) sb.AppendLine("The tab base can't be 0");
- if(_tabBrightness == 0) sb.AppendLine("The tab brightness can't be 0");
+ if(_highBrightness == 0) sb.AppendLine("The tab brightness can't be 0");
+ }
+ else if (_reliefType == RaftReliefTypes.LinkedLines)
+ {
+ if(_linkedLineThickness < 4) sb.AppendLine("The link thickness can't be less than 4");
}
return sb.ToString();
@@ -88,7 +97,7 @@ public class OperationRaftRelief : Operation
public override string ToString()
{
- var result = $"[{_reliefType}] [Mask layer: {_maskLayerIndex}] [Ignore: {_ignoreFirstLayers}] [B: {_brightness}] [Dilate: {_dilateIterations}] [Wall margin: {_wallMargin}] [Hole diameter: {_holeDiameter}] [Hole spacing: {_holeSpacing}]";
+ var result = $"[{_reliefType}] [Mask layer: {_maskLayerIndex}] [Ignore: {_ignoreFirstLayers}] [B: {_lowBrightness}] [Dilate: {_dilateIterations}] [Wall margin: {_wallMargin}] [Hole diameter: {_holeDiameter}] [Hole spacing: {_holeSpacing}]";
if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}";
return result;
}
@@ -110,6 +119,7 @@ public class OperationRaftRelief : Operation
{
if(!RaiseAndSetIfChanged(ref _reliefType, value)) return;
RaisePropertyChanged(nameof(IsRelief));
+ RaisePropertyChanged(nameof(IsLinkedLines));
RaisePropertyChanged(nameof(IsDimming));
RaisePropertyChanged(nameof(IsDecimate));
RaisePropertyChanged(nameof(IsTabs));
@@ -118,6 +128,7 @@ public class OperationRaftRelief : Operation
}
public bool IsRelief => _reliefType == RaftReliefTypes.Relief;
+ public bool IsLinkedLines => _reliefType == RaftReliefTypes.LinkedLines;
public bool IsDimming => _reliefType == RaftReliefTypes.Dimming;
public bool IsDecimate => _reliefType == RaftReliefTypes.Decimate;
public bool IsTabs => _reliefType == RaftReliefTypes.Tabs;
@@ -134,17 +145,27 @@ public class OperationRaftRelief : Operation
set => RaiseAndSetIfChanged(ref _ignoreFirstLayers, value);
}
- public byte Brightness
+ public byte LowBrightness
{
- get => _brightness;
+ get => _lowBrightness;
set
{
- if (!RaiseAndSetIfChanged(ref _brightness, value)) return;
+ if (!RaiseAndSetIfChanged(ref _lowBrightness, value)) return;
RaisePropertyChanged(nameof(BrightnessPercent));
}
}
- public decimal BrightnessPercent => Math.Round((_reliefType == RaftReliefTypes.Tabs ? _tabBrightness : _brightness) * 100 / 255M, 2);
+ public byte HighBrightness
+ {
+ get => _highBrightness;
+ set
+ {
+ if(!RaiseAndSetIfChanged(ref _highBrightness, Math.Max((byte) 1, value))) return;
+ RaisePropertyChanged(nameof(BrightnessPercent));
+ }
+ }
+
+ public decimal BrightnessPercent => Math.Round((_reliefType is RaftReliefTypes.LinkedLines or RaftReliefTypes.Tabs ? _highBrightness : _lowBrightness) * 100 / 255M, 2);
public byte DilateIterations
{
@@ -170,10 +191,22 @@ public class OperationRaftRelief : Operation
set => RaiseAndSetIfChanged(ref _holeSpacing, value);
}
- public byte TabBrightness
+ public byte LinkedLineThickness
{
- get => _tabBrightness;
- set => RaiseAndSetIfChanged(ref _tabBrightness, Math.Max((byte)1, value));
+ get => _linkedLineThickness;
+ set => RaiseAndSetIfChanged(ref _linkedLineThickness, Math.Max((byte)4, value));
+ }
+
+ public byte LinkedMinimumLinks
+ {
+ get => _linkedMinimumLinks;
+ set => RaiseAndSetIfChanged(ref _linkedMinimumLinks, value);
+ }
+
+ public bool LinkedExternalSupports
+ {
+ get => _linkedExternalSupports;
+ set => RaiseAndSetIfChanged(ref _linkedExternalSupports, value);
}
public ushort TabTriangleBase
@@ -198,7 +231,7 @@ public class OperationRaftRelief : Operation
protected bool Equals(OperationRaftRelief other)
{
- return _reliefType == other._reliefType && _maskLayerIndex == other._maskLayerIndex && _ignoreFirstLayers == other._ignoreFirstLayers && _brightness == other._brightness && _dilateIterations == other._dilateIterations && _wallMargin == other._wallMargin && _holeDiameter == other._holeDiameter && _holeSpacing == other._holeSpacing && _tabTriangleBase == other._tabTriangleBase && _tabTriangleHeight == other._tabTriangleHeight;
+ return _reliefType == other._reliefType && _maskLayerIndex == other._maskLayerIndex && _ignoreFirstLayers == other._ignoreFirstLayers && _lowBrightness == other._lowBrightness && _dilateIterations == other._dilateIterations && _wallMargin == other._wallMargin && _holeDiameter == other._holeDiameter && _holeSpacing == other._holeSpacing && _linkedLineThickness == other._linkedLineThickness && _linkedMinimumLinks == other._linkedMinimumLinks && _linkedExternalSupports == other._linkedExternalSupports && _highBrightness == other._highBrightness && _tabTriangleBase == other._tabTriangleBase && _tabTriangleHeight == other._tabTriangleHeight;
}
public override bool Equals(object? obj)
@@ -215,11 +248,15 @@ public class OperationRaftRelief : Operation
hashCode.Add((int) _reliefType);
hashCode.Add(_maskLayerIndex);
hashCode.Add(_ignoreFirstLayers);
- hashCode.Add(_brightness);
+ hashCode.Add(_lowBrightness);
hashCode.Add(_dilateIterations);
hashCode.Add(_wallMargin);
hashCode.Add(_holeDiameter);
hashCode.Add(_holeSpacing);
+ hashCode.Add(_linkedLineThickness);
+ hashCode.Add(_linkedMinimumLinks);
+ hashCode.Add(_linkedExternalSupports);
+ hashCode.Add(_highBrightness);
hashCode.Add(_tabTriangleBase);
hashCode.Add(_tabTriangleHeight);
return hashCode.ToHashCode();
@@ -248,7 +285,8 @@ public class OperationRaftRelief : Operation
{
progress.ThrowIfCancellationRequested();
supportsMat = GetRoiOrDefault(SlicerFile[firstSupportLayerIndex].LayerMat);
- var circles = CvInvoke.HoughCircles(supportsMat, HoughModes.Gradient, 1, 5, 80, 35, 5, 200);
+ //var circles = CvInvoke.HoughCircles(supportsMat, HoughModes.Gradient, 1, 5, 80, 35, 5, 255); // OLD
+ var circles = CvInvoke.HoughCircles(supportsMat, HoughModes.GradientAlt, 1.5, 25, 300, 0.80, 5, 255);
if (circles.Length >= minSupportsRequired) break;
supportsMat.Dispose();
@@ -263,20 +301,21 @@ public class OperationRaftRelief : Operation
if (supportsMat is null || /*firstSupportLayerIndex == 0 ||*/ _ignoreFirstLayers >= firstSupportLayerIndex) return false;
Mat? patternMat = null;
+ using var supportsMatOriginal = supportsMat.Clone();
- if (DilateIterations > 0)
+ if (_dilateIterations > 0)
{
CvInvoke.Dilate(supportsMat, supportsMat,
CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), new Point(-1, -1)),
- new Point(-1, -1), DilateIterations, BorderType.Reflect101, new MCvScalar());
+ new Point(-1, -1), _dilateIterations, BorderType.Reflect101, new MCvScalar());
}
- var color = new MCvScalar(255 - Brightness);
+ var color = new MCvScalar(255 - _lowBrightness);
switch (ReliefType)
{
case RaftReliefTypes.Relief:
- patternMat = EmguExtensions.InitMat(supportsMat.Size);
+ patternMat = supportsMat.NewBlank();
int shapeSize = HoleDiameter + HoleSpacing;
using (var shape = EmguExtensions.InitMat(new Size(shapeSize, shapeSize)))
{
@@ -296,6 +335,61 @@ public class OperationRaftRelief : Operation
}
break;
+ case RaftReliefTypes.LinkedLines:
+ {
+ using var contours = new EmguContours(supportsMatOriginal.FindContours());
+ using var supportsRedraw = _linkedExternalSupports ? supportsMatOriginal.Clone() : null;
+ using var supportsBrightnessCorrection = _highBrightness < byte.MaxValue ? supportsMat.Clone() : null;
+
+ var centroidDistance = contours.CalculateCentroidDistances(false, true);
+
+ var links = Math.Min(_linkedMinimumLinks, contours.Count-1);
+ var linkColor = new MCvScalar(_highBrightness);
+
+ //var listPoints = new List<Point>();
+
+ for (int i = 0; i < contours.Count; i++)
+ {
+ if(contours[i].Centroid.IsAnyNegative()) continue;
+ //listPoints.Add(contours[i].Centroid);
+
+ // Link all centroids to each other to calculate the external contour
+ if (_linkedExternalSupports)
+ {
+ for (int x = 0; x < contours.Count; x++)
+ {
+ if (x == i) continue;
+ if (contours[x].Centroid.IsAnyNegative()) continue;
+ CvInvoke.Line(supportsRedraw, contours[i].Centroid, contours[x].Centroid, linkColor, 4);
+ }
+ }
+
+ for (int link = 0; link < links; link++)
+ {
+ CvInvoke.Line(supportsMat, contours[i].Centroid, centroidDistance[i][link].Contour.Centroid, linkColor, _linkedLineThickness);
+ }
+ }
+
+
+ //CvInvoke.Polylines(supportsMat, listPoints.ToArray(), false, linkColor, _linkedLineThickness);
+ // Link external centroids
+ if (_linkedExternalSupports)
+ {
+ using var externalContours = supportsRedraw!.FindContours(RetrType.External);
+ CvInvoke.DrawContours(supportsMat, externalContours, -1, linkColor, _linkedLineThickness);
+ }
+
+ // Fix original supports brightness
+ if (_highBrightness < byte.MaxValue)
+ {
+ supportsBrightnessCorrection!.CopyTo(supportsMat, supportsBrightnessCorrection);
+ }
+
+ // Close minor holes, round imperfections, stronger joints
+ CvInvoke.MorphologyEx(supportsMat, supportsMat, MorphOp.Close, EmguExtensions.Kernel3x3Rectangle, new Point(-1, -1), 1, BorderType.Reflect101, default);
+
+ break;
+ }
case RaftReliefTypes.Dimming:
patternMat = EmguExtensions.InitMat(supportsMat.Size, color);
break;
@@ -324,6 +418,7 @@ public class OperationRaftRelief : Operation
}
break;
+ case RaftReliefTypes.LinkedLines:
case RaftReliefTypes.Decimate:
supportsMat.CopyTo(target);
break;
@@ -348,7 +443,7 @@ public class OperationRaftRelief : Operation
new Point(-1, 0), // Left
};
- var color = new MCvScalar(_tabBrightness);
+ var color = new MCvScalar(_highBrightness);
for (var i = 0; i < contours.Size; i++)
{
@@ -419,9 +514,9 @@ public class OperationRaftRelief : Operation
break;
}
- CvInvoke.Ellipse(mat, new Point(x, y), new Size(triangleBaseRadius, (int)(triangleBaseRadius / 1.5)), 90 * dir, 0, 180, EmguExtensions.WhiteColor, -1, LineType.AntiAlias);
+ CvInvoke.Ellipse(mat, new Point(x, y), new Size(triangleBaseRadius, (int)(triangleBaseRadius / 1.5)), 90 * dir, 0, 180, EmguExtensions.WhiteColor, -1);
using var vec = new VectorOfPoint(polygon);
- CvInvoke.FillPoly(mat, vec, color, LineType.AntiAlias);
+ CvInvoke.FillPoly(mat, vec, color);
}
}
diff --git a/UVtools.Core/Operations/OperationRepairLayers.cs b/UVtools.Core/Operations/OperationRepairLayers.cs
index f1b5bec..f839390 100644
--- a/UVtools.Core/Operations/OperationRepairLayers.cs
+++ b/UVtools.Core/Operations/OperationRepairLayers.cs
@@ -159,8 +159,7 @@ public class OperationRepairLayers : Operation
set => RaiseAndSetIfChanged(ref _noiseRemovalIterations, value);
}
- [XmlIgnore]
- public IslandDetectionConfiguration? IslandDetectionConfig { get; set; }
+ [XmlIgnore] public IslandDetectionConfiguration IslandDetectionConfig { get; set; } = new();
#endregion
@@ -205,8 +204,8 @@ public class OperationRepairLayers : Operation
var issues = SlicerFile.IssueManager.GetVisible().ToList();
// Remove islands
if (//Issues is not null
- IslandDetectionConfig is not null
- && _repairIslands
+ //IslandDetectionConfig is not null
+ _repairIslands
&& _removeIslandsBelowEqualPixelCount > 0
&& _removeIslandsRecursiveIterations != 1)
{
@@ -282,7 +281,7 @@ public class OperationRepairLayers : Operation
if (islandsToProcess.Count == 0)
{
- var islandConfig = IslandDetectionConfig?.Clone() ?? new IslandDetectionConfiguration();
+ var islandConfig = IslandDetectionConfig.Clone();
var overhangConfig = new OverhangDetectionConfiguration(false);
var touchingBoundsConfig = new TouchingBoundDetectionConfiguration(false);
var printHeightConfig = new PrintHeightDetectionConfiguration(false);
@@ -292,12 +291,12 @@ public class OperationRepairLayers : Operation
islandConfig.Enabled = true;
islandsToProcess = SlicerFile.IssueManager.DetectIssues(islandConfig, overhangConfig, resinTrapsConfig, touchingBoundsConfig, printHeightConfig, emptyLayersConfig, progress);
- islandsToProcess?.RemoveAll(mainIssue => SlicerFile.IssueManager.IgnoredIssues.Contains(mainIssue));
+ islandsToProcess.RemoveAll(mainIssue => SlicerFile.IssueManager.IgnoredIssues.Contains(mainIssue));
}
- var issuesGroup = IssueManager.GetIssuesBy(islandsToProcess!, MainIssue.IssueType.Island).GroupBy(issue => issue.LayerIndex);
+ var issuesGroup = IssueManager.GetIssuesBy(islandsToProcess, MainIssue.IssueType.Island).GroupBy(issue => issue.LayerIndex);
- progress.Reset("Attempt to attach islands below", (uint) islandsToProcess!.Count);
+ progress.Reset("Attempt to attach islands below", (uint) islandsToProcess.Count);
var sync = new object();
Parallel.ForEach(issuesGroup, CoreSettings.GetParallelOptions(progress), group =>
{
@@ -310,7 +309,7 @@ public class OperationRepairLayers : Operation
for (var layerIndex = startLayer+1; layerIndex >= lowestPossibleLayer; layerIndex--)
{
- Debug.WriteLine(layerIndex);
+ //Debug.WriteLine(layerIndex);
Monitor.Enter(SlicerFile[layerIndex].Mutex);
matCache.Add((uint) layerIndex, SlicerFile[layerIndex].LayerMat);
matCacheModified.Add((uint) layerIndex, false);
@@ -319,7 +318,7 @@ public class OperationRepairLayers : Operation
foreach (IssueOfPoints issue in group)
{
int foundAt = startLayer == 0 ? 0 : - 1;
- var requiredSupportingPixels = Math.Max(1, issue.PixelsCount * IslandDetectionConfig!.RequiredPixelsToSupportMultiplier);
+ var requiredSupportingPixels = Math.Max(1, issue.PixelsCount * IslandDetectionConfig.RequiredPixelsToSupportMultiplier);
for (var layerIndex = startLayer; layerIndex >= lowestPossibleLayer && foundAt < 0; layerIndex--)
{
diff --git a/UVtools.Core/RELEASE_NOTES.md b/UVtools.Core/RELEASE_NOTES.md
deleted file mode 100644
index 5efb19e..0000000
--- a/UVtools.Core/RELEASE_NOTES.md
+++ /dev/null
@@ -1,12 +0,0 @@
-- **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
-
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index 5321ef9..69928f1 100644
--- a/UVtools.Core/UVtools.Core.csproj
+++ b/UVtools.Core/UVtools.Core.csproj
@@ -5,12 +5,12 @@
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<Company>PTRTECH</Company>
- <Authors>Tiago Conceição</Authors>
+ <Authors>Tiago Conceição, sn4k3</Authors>
<RepositoryType>Git</RepositoryType>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
- <Version>3.2.1</Version>
+ <Version>3.2.2</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
@@ -50,7 +50,7 @@
</None>
<None Include="..\README.md">
<Pack>True</Pack>
- <PackagePath>\</PackagePath>
+ <PackagePath></PackagePath>
</None>
<None Include="..\UVtools.CAD\UVtools.png">
<Pack>True</Pack>
@@ -74,7 +74,7 @@
</ItemGroup>
<Target Name="PreparePackageReleaseNotesFromFile" BeforeTargets="GenerateNuspec">
- <ReadLinesFromFile File="RELEASE_NOTES.md">
+ <ReadLinesFromFile File="..\RELEASE_NOTES.md">
<Output TaskParameter="Lines" ItemName="ReleaseNoteLines" />
</ReadLinesFromFile>
<PropertyGroup>
diff --git a/UVtools.InstallerMM/UVtools.InstallerMM.wxs b/UVtools.InstallerMM/UVtools.InstallerMM.wxs
index cc40285..fb18481 100644
--- a/UVtools.InstallerMM/UVtools.InstallerMM.wxs
+++ b/UVtools.InstallerMM/UVtools.InstallerMM.wxs
@@ -2,7 +2,7 @@
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define ComponentRules="OneToOne"?>
<!-- SourceDir instructs IsWiX the location of the directory that contains files for this merge module -->
- <?define SourceDir="..\publish\UVtools_win-x64_v3.2.1"?>
+ <?define SourceDir="..\publish\UVtools_win-x64_v3.2.2"?>
<Module Id="UVtools" Language="1033" Version="1.0.0.0">
<Package Id="12aaa1cf-ff06-4a02-abd5-2ac01ac4f83b" Manufacturer="PTRTECH" InstallerVersion="200" Keywords="MSLA, DLP" Description="MSLA/DLP, file analysis, repair, conversion and manipulation" InstallScope="perMachine" Platform="x64" />
<Directory Id="TARGETDIR" Name="SourceDir">
diff --git a/UVtools.WPF/App.axaml.cs b/UVtools.WPF/App.axaml.cs
index 7003486..61f3b8b 100644
--- a/UVtools.WPF/App.axaml.cs
+++ b/UVtools.WPF/App.axaml.cs
@@ -330,10 +330,10 @@ public class App : Application
#endregion
- #region Assembly Attribute Accessors
+ #region Assembly properties
+ public static Assembly WpfAssembly => Assembly.GetExecutingAssembly();
- public static Version Version => Assembly.GetExecutingAssembly().GetName().Version!;
- public static string VersionStr => Version.ToString(3);
+ public static string AssemblyVersion => WpfAssembly.GetName().Version?.ToString()!;
public static string AssemblyName => Assembly.GetExecutingAssembly().GetName().Name!;
@@ -341,32 +341,30 @@ public class App : Application
{
get
{
- object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
+ var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
if (attributes.Length > 0)
{
- AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
- if (titleAttribute.Title != "")
+ var titleAttribute = (AssemblyTitleAttribute)attributes[0];
+ if (titleAttribute.Title != string.Empty)
{
return titleAttribute.Title;
}
}
- return Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location);
+ return Path.GetFileNameWithoutExtension(WpfAssembly.Location);
}
}
- public static string AssemblyVersion => Assembly.GetExecutingAssembly().GetName().Version?.ToString()!;
-
public static string AssemblyDescription
{
get
{
- object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
+ var attributes = WpfAssembly.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
if (attributes.Length == 0)
{
- return "";
+ return string.Empty;
}
- string description = ((AssemblyDescriptionAttribute)attributes[0]).Description + $"{Environment.NewLine}{Environment.NewLine}Available File Formats:";
+ var description = ((AssemblyDescriptionAttribute)attributes[0]).Description + $"{Environment.NewLine}{Environment.NewLine}Available File Formats:";
return FileFormat.AvailableFormats.SelectMany(fileFormat => fileFormat.FileExtensions).Aggregate(description, (current, fileExtension) => current + $"{Environment.NewLine}- {fileExtension.Description} (.{fileExtension.Extension})");
}
@@ -376,12 +374,8 @@ public class App : Application
{
get
{
- object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
- if (attributes.Length == 0)
- {
- return "";
- }
- return ((AssemblyProductAttribute)attributes[0]).Product;
+ var attributes = WpfAssembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);
+ return attributes.Length == 0 ? string.Empty : ((AssemblyProductAttribute)attributes[0]).Product;
}
}
@@ -389,12 +383,8 @@ public class App : Application
{
get
{
- object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
- if (attributes.Length == 0)
- {
- return "";
- }
- return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
+ var attributes = WpfAssembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
+ return attributes.Length == 0 ? string.Empty : ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
}
}
@@ -402,14 +392,9 @@ public class App : Application
{
get
{
- object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
- if (attributes.Length == 0)
- {
- return "";
- }
- return ((AssemblyCompanyAttribute)attributes[0]).Company;
+ var attributes = WpfAssembly.GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
+ return attributes.Length == 0 ? string.Empty : ((AssemblyCompanyAttribute)attributes[0]).Company;
}
}
-
#endregion
} \ No newline at end of file
diff --git a/UVtools.WPF/Assets/Styles/Styles.xaml b/UVtools.WPF/Assets/Styles/Styles.xaml
index bcfcfbd..05e5ccf 100644
--- a/UVtools.WPF/Assets/Styles/Styles.xaml
+++ b/UVtools.WPF/Assets/Styles/Styles.xaml
@@ -248,6 +248,14 @@
</Setter>
</Style>
+ <Style Selector="TextBox.ValueLabel_euro, NumericUpDown.ValueLabel_euro /template/ TextBox">
+ <Setter Property="InnerRightContent">
+ <Template>
+ <TextBox Classes="NumericUpDownValueLabel" Text="€" ToolTip.Tip="Euros" />
+ </Template>
+ </Setter>
+ </Style>
+
<!--
<Style Selector="NumericUpDown /template/ TextBox:not(.empty)">
<Setter Property="MinWidth" Value="0"/>
diff --git a/UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml b/UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml
index 71323e1..eb49faa 100644
--- a/UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml
+++ b/UVtools.WPF/Controls/Tools/ToolRaftReliefControl.axaml
@@ -8,13 +8,12 @@
<Grid
ColumnDefinitions="Auto,10,200,5,Auto"
- RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto"
- >
+ RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto">
<TextBlock Text="Relief type:" VerticalAlignment="Center"/>
- <ComboBox Grid.Row="0"
- Grid.Column="2"
- HorizontalAlignment="Stretch"
+ <ComboBox Grid.Row="0" Grid.Column="2" Grid.ColumnSpan="3"
+ Width="458"
+ HorizontalAlignment="Left"
Items="{Binding Operation.ReliefType, Converter={StaticResource EnumToCollectionConverter}, Mode=OneTime}"
SelectedItem="{Binding Operation.ReliefType, Converter={StaticResource FromValueDescriptionToEnumConverter}}"/>
@@ -31,6 +30,7 @@ you must manually input the layer index of the last raft where it ends and suppo
Classes="ValueLabel ValueLabel_layers"
Minimum="0"
Maximum="{Binding SlicerFile.LastLayerIndex}"
+ Increment="1"
Value="{Binding Operation.MaskLayerIndex}"/>
<StackPanel Grid.Row="2" Grid.Column="4"
Orientation="Horizontal" Spacing="5">
@@ -50,6 +50,7 @@ you must manually input the layer index of the last raft where it ends and suppo
Classes="ValueLabel ValueLabel_layers"
Minimum="0"
Maximum="255"
+ Increment="1"
Value="{Binding Operation.IgnoreFirstLayers}"/>
<TextBlock
Grid.Row="4" Grid.Column="4"
@@ -65,7 +66,8 @@ you must manually input the layer index of the last raft where it ends and suppo
Classes="ValueLabel ValueLabel_sun"
Minimum="0"
Maximum="255"
- Value="{Binding Operation.Brightness}">
+ Increment="1"
+ Value="{Binding Operation.LowBrightness}">
<NumericUpDown.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.Or}">
<Binding Path="Operation.IsRelief"/>
@@ -78,8 +80,15 @@ you must manually input the layer index of the last raft where it ends and suppo
Classes="ValueLabel ValueLabel_sun"
Minimum="0"
Maximum="255"
- IsVisible="{Binding Operation.IsTabs}"
- Value="{Binding Operation.TabBrightness}"/>
+ Increment="1"
+ Value="{Binding Operation.HighBrightness}">
+ <NumericUpDown.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.Or}">
+ <Binding Path="Operation.IsLinkedLines"/>
+ <Binding Path="Operation.IsTabs"/>
+ </MultiBinding>
+ </NumericUpDown.IsVisible>
+ </NumericUpDown>
<TextBlock Grid.Row="6" Grid.Column="4"
IsVisible="{Binding !Operation.IsDecimate}"
@@ -96,10 +105,16 @@ you must manually input the layer index of the last raft where it ends and suppo
</TextBlock>
<TextBlock Grid.Row="8" Grid.Column="0"
- IsVisible="{Binding Operation.IsDecimate}"
ToolTip.Tip="Raft will be replaced by the present supports and then dilated by this value to thicken the supports and increase the adhesion.
&#x0a;Use large numbers with tiny supports for best adhesion."
- Text="Dilate supports by:" VerticalAlignment="Center"/>
+ Text="Dilate supports by:" VerticalAlignment="Center">
+ <TextBlock.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.Or}">
+ <Binding Path="Operation.IsLinkedLines"/>
+ <Binding Path="Operation.IsDecimate"/>
+ </MultiBinding>
+ </TextBlock.IsVisible>
+ </TextBlock>
<TextBlock Grid.Row="8" Grid.Column="0"
IsVisible="{Binding Operation.IsTabs}"
@@ -109,6 +124,7 @@ you must manually input the layer index of the last raft where it ends and suppo
Classes="ValueLabel ValueLabel_px"
Minimum="0"
Maximum="255"
+ Increment="1"
IsVisible="{Binding !Operation.IsTabs}"
Value="{Binding Operation.DilateIterations}"/>
@@ -117,6 +133,7 @@ you must manually input the layer index of the last raft where it ends and suppo
Classes="ValueLabel ValueLabel_px"
Minimum="5"
Maximum="65535"
+ Increment="1"
IsVisible="{Binding Operation.IsTabs}"
Value="{Binding Operation.TabTriangleBase}"/>
@@ -132,14 +149,20 @@ you must manually input the layer index of the last raft where it ends and suppo
</TextBlock>
<TextBlock Grid.Row="10" Grid.Column="0"
+ IsVisible="{Binding Operation.IsLinkedLines}"
+ ToolTip.Tip="Each support will be linked to the nearby neighbours at least the defined times."
+ Text="Minimum links:" VerticalAlignment="Center"/>
+
+ <TextBlock Grid.Row="10" Grid.Column="0"
IsVisible="{Binding Operation.IsTabs}"
Text="Tab triangle height:" VerticalAlignment="Center"/>
<NumericUpDown Grid.Row="10" Grid.Column="2"
Classes="ValueLabel ValueLabel_px"
- Minimum="1"
- Maximum="255"
- Value="{Binding Operation.WallMargin}">
+ Minimum="1"
+ Maximum="255"
+ Increment="1"
+ Value="{Binding Operation.WallMargin}">
<NumericUpDown.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.Or}">
<Binding Path="Operation.IsRelief"/>
@@ -149,9 +172,25 @@ you must manually input the layer index of the last raft where it ends and suppo
</NumericUpDown>
<NumericUpDown Grid.Row="10" Grid.Column="2"
+ Classes="ValueLabel ValueLabel_times"
+ Minimum="0"
+ Maximum="255"
+ Increment="1"
+ IsVisible="{Binding Operation.IsLinkedLines}"
+ Value="{Binding Operation.LinkedMinimumLinks}"/>
+
+ <CheckBox Grid.Row="10" Grid.Column="4"
+ VerticalAlignment="Center"
+ Content="Links outer-most supports"
+ ToolTip.Tip="Links outer-most supports all together, creating a perimeter around inner supports."
+ IsVisible="{Binding Operation.IsLinkedLines}"
+ IsChecked="{Binding Operation.LinkedExternalSupports}"/>
+
+ <NumericUpDown Grid.Row="10" Grid.Column="2"
Classes="ValueLabel ValueLabel_px"
Minimum="5"
Maximum="65535"
+ Increment="1"
IsVisible="{Binding Operation.IsTabs}"
Value="{Binding Operation.TabTriangleHeight}"/>
@@ -161,12 +200,25 @@ you must manually input the layer index of the last raft where it ends and suppo
Text="Hole diameter:" VerticalAlignment="Center"
IsVisible="{Binding Operation.IsRelief}"/>
+ <TextBlock Grid.Row="12" Grid.Column="0"
+ Text="Line thickness:" VerticalAlignment="Center"
+ IsVisible="{Binding Operation.IsLinkedLines}"/>
+
<NumericUpDown Grid.Row="12" Grid.Column="2"
Classes="ValueLabel ValueLabel_px"
- Minimum="10"
- Maximum="255"
- Value="{Binding Operation.HoleDiameter}"
- IsVisible="{Binding Operation.IsRelief}"/>
+ Minimum="10"
+ Maximum="255"
+ Increment="1"
+ Value="{Binding Operation.HoleDiameter}"
+ IsVisible="{Binding Operation.IsRelief}"/>
+
+ <NumericUpDown Grid.Row="12" Grid.Column="2"
+ Classes="ValueLabel ValueLabel_px"
+ Minimum="4"
+ Maximum="255"
+ Increment="1"
+ IsVisible="{Binding Operation.IsLinkedLines}"
+ Value="{Binding Operation.LinkedLineThickness}"/>
<TextBlock
Grid.Row="14" Grid.Column="0"
@@ -175,10 +227,11 @@ you must manually input the layer index of the last raft where it ends and suppo
<NumericUpDown Grid.Row="14" Grid.Column="2"
Classes="ValueLabel ValueLabel_px"
- Minimum="10"
- Maximum="255"
- Value="{Binding Operation.HoleSpacing}"
- IsVisible="{Binding Operation.IsRelief}"/>
+ Minimum="10"
+ Maximum="255"
+ Increment="1"
+ Value="{Binding Operation.HoleSpacing}"
+ IsVisible="{Binding Operation.IsRelief}"/>
</Grid>
diff --git a/UVtools.WPF/ErrorLog.cs b/UVtools.WPF/ErrorLog.cs
index 17e1a4f..0955aed 100644
--- a/UVtools.WPF/ErrorLog.cs
+++ b/UVtools.WPF/ErrorLog.cs
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.IO;
+using UVtools.Core;
namespace UVtools.WPF;
@@ -15,7 +16,7 @@ public static class ErrorLog
try
{
File.AppendAllText(FullPath,
- $"[v{App.VersionStr}] ({errorType}) @ {DateTime.Now}: {text}{Environment.NewLine}");
+ $"[v{About.VersionStr}] ({errorType}) @ {DateTime.Now}: {text}{Environment.NewLine}");
}
catch (Exception exception)
{
diff --git a/UVtools.WPF/MainWindow.LayerPreview.cs b/UVtools.WPF/MainWindow.LayerPreview.cs
index c554a53..b8bb051 100644
--- a/UVtools.WPF/MainWindow.LayerPreview.cs
+++ b/UVtools.WPF/MainWindow.LayerPreview.cs
@@ -1540,7 +1540,7 @@ public partial class MainWindow
if (_showLayerImageFlippedVertically)
{
- rectangle.Location = new Point(rectangle.X, LayerCache.Image.Height - 1 - rectangle.Bottom);
+ rectangle.Location = new Point(rectangle.X, LayerCache.Image.Height - rectangle.Bottom);
}
}
diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs
index 3a53925..7165d44 100644
--- a/UVtools.WPF/MainWindow.axaml.cs
+++ b/UVtools.WPF/MainWindow.axaml.cs
@@ -885,6 +885,13 @@ public partial class MainWindow : WindowEx
return true;
}, TimeSpan.FromSeconds(1));
Program.ProgramStartupTime.Stop();
+
+ /*if (About.IsBirthday)
+ {
+ this.MessageBoxInfo($"Age: {About.AgeStr}\n" +
+ $"This message will only show today, see you in next year!\n" +
+ $"Thank you for using {About.Software}.", $"Today it's the {About.Software} birthday!").ConfigureAwait(false);
+ }*/
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -1260,7 +1267,7 @@ public partial class MainWindow : WindowEx
{
var result =
await this.MessageBoxWithHeaderQuestion(
- $"Do you like to auto-update {About.Software} v{App.VersionStr} to v{VersionChecker.Version}?",
+ $"Do you like to auto-update {About.Software} v{About.VersionStr} to v{VersionChecker.Version}?",
"Yes: Auto update \n" +
"No: Manual update \n" +
"Cancel: No action \n\n" +
@@ -1322,7 +1329,7 @@ public partial class MainWindow : WindowEx
title += $"File: {SlicerFile.Filename} ({Math.Round(LastStopWatch.ElapsedMilliseconds / 1000m, 2)}s) ";
}
- title += $"Version: {App.VersionStr} RAM: {SizeExtensions.SizeSuffix(Environment.WorkingSet)}";
+ title += $"Version: {About.VersionStr} RAM: {SizeExtensions.SizeSuffix(Environment.WorkingSet)}";
if (IsFileLoaded)
{
@@ -1755,8 +1762,7 @@ public partial class MainWindow : WindowEx
if (SlicerFile.IssueManager.Count > 0)
{
SelectedTabItem = TabIssues;
- if (Settings.Issues.AutoRepairIssuesOnLoad)
- await RunOperation(ToolRepairLayersControl.GetOperationRepairLayers());
+ if (Settings.Issues.AutoRepairIssuesOnLoad) await RunOperation(ToolRepairLayersControl.GetOperationRepairLayers());
}
}
else
diff --git a/UVtools.WPF/Structures/AppVersionChecker.cs b/UVtools.WPF/Structures/AppVersionChecker.cs
index b569571..d12d733 100644
--- a/UVtools.WPF/Structures/AppVersionChecker.cs
+++ b/UVtools.WPF/Structures/AppVersionChecker.cs
@@ -146,11 +146,11 @@ public class AppVersionChecker : BindableBase
string tag_name = json["tag_name"]?.ToString();
if (string.IsNullOrEmpty(tag_name)) return false;
tag_name = tag_name.Trim(' ', 'v', 'V');
- Debug.WriteLine($"Version checker: v{App.VersionStr} <=> v{tag_name}");
+ Debug.WriteLine($"Version checker: v{About.VersionStr} <=> v{tag_name}");
Version checkVersion = new(tag_name);
Changelog = json["body"]?.ToString();
//if (string.Compare(tag_name, App.VersionStr, StringComparison.OrdinalIgnoreCase) > 0)
- if (App.Version.CompareTo(checkVersion) < 0)
+ if (About.Version.CompareTo(checkVersion) < 0)
{
Debug.WriteLine($"New version detected: {DownloadLink}\n" +
$"{_changelog}");
@@ -246,7 +246,7 @@ public class AppVersionChecker : BindableBase
{
stream.NewLine = "\n";
await stream.WriteLineAsync("#!/bin/bash");
- await stream.WriteLineAsync($"echo {About.Software} v{App.Version} updater script");
+ await stream.WriteLineAsync($"echo {About.Software} v{About.Version} updater script");
await stream.WriteLineAsync($"cd '{App.ApplicationPath}'");
await stream.WriteLineAsync($"killall {About.Software}");
await stream.WriteLineAsync("sleep 0.5");
diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj
index b41492a..b688f5d 100644
--- a/UVtools.WPF/UVtools.WPF.csproj
+++ b/UVtools.WPF/UVtools.WPF.csproj
@@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<AssemblyName>UVtools</AssemblyName>
<ApplicationIcon>UVtools.ico</ApplicationIcon>
- <Authors>Tiago Conceição</Authors>
+ <Authors>Tiago Conceição, sn4k3</Authors>
<Company>PTRTECH</Company>
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
@@ -12,7 +12,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
- <Version>3.2.1</Version>
+ <Version>3.2.2</Version>
<Platforms>AnyCPU;x64</Platforms>
<PackageIcon>UVtools.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
@@ -44,9 +44,9 @@
<PackageReference Include="Avalonia.Desktop" Version="0.10.13" />
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.13" />
<PackageReference Include="MessageBox.Avalonia" Version="2.0.0" />
- <PackageReference Include="Projektanker.Icons.Avalonia" Version="4.3.0" />
- <PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="4.3.0" />
- <PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="4.3.0" />
+ <PackageReference Include="Projektanker.Icons.Avalonia" Version="4.4.0" />
+ <PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="4.4.0" />
+ <PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="4.4.0" />
<PackageReference Include="ThemeEditor.Controls.ColorPicker" Version="0.10.12" />
</ItemGroup>
<ItemGroup>
@@ -76,11 +76,11 @@
</None>
<None Include="..\README.md" Link="README.md">
<Pack>True</Pack>
- <PackagePath>\</PackagePath>
+ <PackagePath></PackagePath>
</None>
<None Include="..\UVtools.CAD\UVtools.png">
<Pack>True</Pack>
- <PackagePath>\</PackagePath>
+ <PackagePath></PackagePath>
</None>
<None Include="..\UVtools.CAD\UVtools_demo_file.sl1" Link="UVtools_demo_file.sl1">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
diff --git a/UVtools.WPF/UserSettings.cs b/UVtools.WPF/UserSettings.cs
index 72591dd..898fd6f 100644
--- a/UVtools.WPF/UserSettings.cs
+++ b/UVtools.WPF/UserSettings.cs
@@ -43,13 +43,12 @@ public sealed class UserSettings : BindableBase
private bool _loadDemoFileOnStartup = true;
private bool _loadLastRecentFileOnStartup;
private int _maxDegreeOfParallelism = -1;
- private Layer.LayerCompressionCodec _layerCompressionCodec = CoreSettings.DefaultLayerCompressionCodec;
-
+ private LayerCompressionCodec _layerCompressionCodec = CoreSettings.DefaultLayerCompressionCodec;
+ private float _averageResin1000MlBottleCost = CoreSettings.AverageResin1000MlBottleCost;
private bool _windowsCanResize;
private bool _windowsTakeIntoAccountScreenScaling = true;
private ushort _windowsHorizontalMargin = 100;
private ushort _windowsVerticalMargin = 60;
- private bool _expandDescriptions = true;
private byte _defaultOpenFileExtensionIndex;
private string _defaultDirectoryOpenFile;
private string _defaultDirectorySaveFile;
@@ -102,12 +101,18 @@ public sealed class UserSettings : BindableBase
set => RaiseAndSetIfChanged(ref _maxDegreeOfParallelism, Math.Min(value, Environment.ProcessorCount));
}
- public Layer.LayerCompressionCodec LayerCompressionCodec
+ public LayerCompressionCodec LayerCompressionCodec
{
get => _layerCompressionCodec;
set => RaiseAndSetIfChanged(ref _layerCompressionCodec, value);
}
+ public float AverageResin1000MlBottleCost
+ {
+ get => _averageResin1000MlBottleCost;
+ set => RaiseAndSetIfChanged(ref _averageResin1000MlBottleCost, value);
+ }
+
public bool WindowsCanResize
{
get => _windowsCanResize;
@@ -132,12 +137,6 @@ public sealed class UserSettings : BindableBase
set => RaiseAndSetIfChanged(ref _windowsVerticalMargin, value);
}
- public bool ExpandDescriptions
- {
- get => _expandDescriptions;
- set => RaiseAndSetIfChanged(ref _expandDescriptions, value);
- }
-
public byte DefaultOpenFileExtensionIndex
{
get => _defaultOpenFileExtensionIndex;
@@ -1372,10 +1371,17 @@ public sealed class UserSettings : BindableBase
[Serializable]
public sealed class ToolsUserSettings : BindableBase
{
+ private bool _expandDescriptions = true;
private bool _restoreLastUsedSettings;
private bool _lastUsedSettingsKeepOnCloseFile = true;
private bool _lastUsedSettingsPriorityOverDefaultProfile = true;
+ public bool ExpandDescriptions
+ {
+ get => _expandDescriptions;
+ set => RaiseAndSetIfChanged(ref _expandDescriptions, value);
+ }
+
public bool RestoreLastUsedSettings
{
get => _restoreLastUsedSettings;
@@ -1571,7 +1577,7 @@ public sealed class UserSettings : BindableBase
[NotNull]
public string AppVersion
{
- get => _appVersion ??= App.Version.ToString();
+ get => _appVersion ??= About.VersionStr;
set => RaiseAndSetIfChanged(ref _appVersion, value);
}
@@ -1656,6 +1662,7 @@ public sealed class UserSettings : BindableBase
CoreSettings.MaxDegreeOfParallelism = _instance.General.MaxDegreeOfParallelism;
CoreSettings.DefaultLayerCompressionCodec = _instance.General.LayerCompressionCodec;
+ CoreSettings.AverageResin1000MlBottleCost = _instance.General.AverageResin1000MlBottleCost;
if (_instance.Network.RemotePrinters.Count == 0)
{
@@ -1879,6 +1886,7 @@ public sealed class UserSettings : BindableBase
_instance.ModifiedDateTime = DateTime.Now;
CoreSettings.MaxDegreeOfParallelism = _instance.General.MaxDegreeOfParallelism;
CoreSettings.DefaultLayerCompressionCodec = _instance.General.LayerCompressionCodec;
+ CoreSettings.AverageResin1000MlBottleCost = _instance.General.AverageResin1000MlBottleCost;
try
{
XmlExtensions.SerializeToFile(_instance, FilePath, XmlExtensions.SettingsIndent);
@@ -1891,7 +1899,7 @@ public sealed class UserSettings : BindableBase
public static void SetVersion()
{
- Instance.AppVersion = App.Version.ToString();
+ Instance.AppVersion = About.VersionStr;
}
public static object[] PackObjects =>
diff --git a/UVtools.WPF/Windows/AboutWindow.axaml b/UVtools.WPF/Windows/AboutWindow.axaml
index 0e85338..c39f539 100644
--- a/UVtools.WPF/Windows/AboutWindow.axaml
+++ b/UVtools.WPF/Windows/AboutWindow.axaml
@@ -3,6 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="clr-namespace:UVtools.WPF.Controls"
+ xmlns:core="clr-namespace:UVtools.Core;assembly=UVtools.Core"
mc:Ignorable="d" d:DesignWidth="960" d:DesignHeight="700"
x:Class="UVtools.WPF.Windows.AboutWindow"
Width="960" Height="710"
@@ -18,7 +19,7 @@
<Grid ColumnDefinitions="Auto,*">
<controls:ButtonWithIcon
Grid.Column="0"
- Command="{Binding CopyInformationToClipboard}"
+ Command="{Binding CopyEssentialInformation}"
Padding="10"
VerticalContentAlignment="Center"
HorizontalAlignment="Right"
@@ -144,16 +145,17 @@
<Border>
<Grid
- RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,*"
+ RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto,5,*"
Margin="20">
- <TextBlock Grid.Row="0" Text="{Binding Software}" FontWeight="Bold"/>
- <TextBlock Grid.Row="2" Text="{Binding Version}"/>
- <TextBlock Grid.Row="4" Text="{Binding Copyright}"/>
- <TextBlock Grid.Row="6" Text="{Binding Company}"/>
+ <TextBlock Grid.Row="0" Text="{Binding Source={x:Static core:About.Software}}" FontWeight="Bold"/>
+ <TextBlock Grid.Row="2" Text="{Binding Source={x:Static core:About.VersionArch}, StringFormat=Version: {0}}"/>
+ <TextBlock Grid.Row="4" Text="{Binding Source={x:Static core:About.AssemblyCopyright}}"/>
+ <TextBlock Grid.Row="6" Text="{Binding Source={x:Static core:About.Author}}"/>
+ <!--<TextBlock Grid.Row="8" Text="{Binding AgeStr, StringFormat=Age: {0}}"/>-->
<controls:ButtonWithIcon Grid.Row="8" VerticalAlignment="Center"
Command="{Binding OpenLicense}"
- Text="{Binding License}"
+ Text="{Binding Source={x:Static core:About.License}}"
Icon="fas fa-balance-scale"/>
<TabControl Grid.Row="10">
@@ -162,7 +164,7 @@
IsReadOnly="True"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
- Text="{Binding Description}"/>
+ Text="{Binding Source={x:Static core:About.AssemblyDescription}}"/>
</TabItem>
<TabItem Header="OpenCV">
diff --git a/UVtools.WPF/Windows/AboutWindow.axaml.cs b/UVtools.WPF/Windows/AboutWindow.axaml.cs
index c0c3919..a4a8966 100644
--- a/UVtools.WPF/Windows/AboutWindow.axaml.cs
+++ b/UVtools.WPF/Windows/AboutWindow.axaml.cs
@@ -13,14 +13,8 @@ namespace UVtools.WPF.Windows;
public class AboutWindow : WindowEx
{
- public string Software => About.Software;
- public string Version => $"Version: {App.VersionStr} {RuntimeInformation.ProcessArchitecture}";
- public string Copyright => App.AssemblyCopyright;
- public string Company => App.AssemblyCompany;
- public string License => About.License;
- public string Description => App.AssemblyDescription;
- public string OpenCVBuildInformation => CvInvoke.BuildInformation;
- public string LoadedAssemblies
+ public static string OpenCVBuildInformation => CvInvoke.BuildInformation;
+ public static string LoadedAssemblies
{
get
{
@@ -36,14 +30,14 @@ public class AboutWindow : WindowEx
}
}
- public string OSDescription => $"{RuntimeInformation.OSDescription} {RuntimeInformation.OSArchitecture}";
+ public static string OSDescription => $"{RuntimeInformation.OSDescription} {RuntimeInformation.OSArchitecture}";
- public string RuntimeDescription => RuntimeInformation.RuntimeIdentifier;
+ public static string RuntimeDescription => RuntimeInformation.RuntimeIdentifier;
- public string FrameworkDescription => RuntimeInformation.FrameworkDescription;
- public string AvaloniaUIDescription => typeof(AvaloniaObject).Assembly.GetName().Version.ToString(3);
+ public static string FrameworkDescription => RuntimeInformation.FrameworkDescription;
+ public static string AvaloniaUIDescription => typeof(AvaloniaObject).Assembly.GetName().Version!.ToString(3);
- public string OpenCVVersion
+ public static string OpenCVVersion
{
get
{
@@ -56,11 +50,11 @@ public class AboutWindow : WindowEx
}
}
- public string ProcessorName => SystemAware.GetProcessorName();
+ public static string ProcessorName => SystemAware.GetProcessorName();
- public int ProcessorCount => Environment.ProcessorCount;
+ public static int ProcessorCount => Environment.ProcessorCount;
- public string MemoryRAMDescription
+ public static string MemoryRAMDescription
{
get
{
@@ -85,7 +79,7 @@ public class AboutWindow : WindowEx
get
{
var result = new StringBuilder();
- for (int i = 0; i < Screens.All.Count; i++)
+ for (var i = 0; i < Screens.All.Count; i++)
{
var onScreen = Screens.ScreenFromVisual(App.MainWindow);
var screen = Screens.All[i];
@@ -116,7 +110,7 @@ public class AboutWindow : WindowEx
private string GetEssentialInformation()
{
var message = new StringBuilder();
- message.AppendLine($"{About.SoftwareWithVersion}");
+ message.AppendLine($"{About.SoftwareWithVersionArch}");
message.AppendLine($"Operative system: {OSDescription}");
message.AppendLine($"Processor: {ProcessorName}");
message.AppendLine($"Processor cores: {ProcessorCount}");
@@ -129,24 +123,25 @@ public class AboutWindow : WindowEx
message.AppendLine("Sreens, resolution, working area, usable area:");
message.AppendLine(ScreensDescription);
message.AppendLine();
- message.AppendLine($"Path: {App.ApplicationPath}");
+ message.AppendLine($"Path: {App.ApplicationPath}");
+ message.AppendLine($"Executable: {App.AppExecutable}");
return message.ToString();
}
public void CopyEssentialInformation()
{
- Application.Current.Clipboard.SetTextAsync(GetEssentialInformation());
+ Application.Current?.Clipboard?.SetTextAsync(GetEssentialInformation());
}
public void CopyOpenCVInformationToClipboard()
{
- Application.Current.Clipboard.SetTextAsync(CvInvoke.BuildInformation);
+ Application.Current?.Clipboard?.SetTextAsync(CvInvoke.BuildInformation);
}
public void CopyLoadedAssembliesToClipboard()
{
- Application.Current.Clipboard.SetTextAsync(LoadedAssemblies);
+ Application.Current?.Clipboard?.SetTextAsync(LoadedAssemblies);
}
public async void CopyInformationToClipboard()
@@ -156,6 +151,6 @@ public class AboutWindow : WindowEx
message.AppendLine(CvInvoke.BuildInformation);
message.AppendLine("Loaded Assemblies:");
message.AppendLine(LoadedAssemblies);
- await Application.Current.Clipboard.SetTextAsync(message.ToString());
+ await Application.Current?.Clipboard?.SetTextAsync(message.ToString())!;
}
} \ No newline at end of file
diff --git a/UVtools.WPF/Windows/BenchmarkWindow.axaml.cs b/UVtools.WPF/Windows/BenchmarkWindow.axaml.cs
index 46ead58..b7686e6 100644
--- a/UVtools.WPF/Windows/BenchmarkWindow.axaml.cs
+++ b/UVtools.WPF/Windows/BenchmarkWindow.axaml.cs
@@ -526,7 +526,7 @@ public class BenchmarkWindow : WindowEx
public void TestPNGCompress(BenchmarkResolution resolution)
{
- Layer.CompressMat(Mats[resolution], Layer.LayerCompressionCodec.Png);
+ Layer.CompressMat(Mats[resolution], LayerCompressionCodec.Png);
}
public void TestPNGDecompress(BenchmarkResolution resolution)
@@ -534,7 +534,7 @@ public class BenchmarkWindow : WindowEx
public void TestGZipCompress(BenchmarkResolution resolution)
{
- Layer.CompressMat(Mats[resolution], Layer.LayerCompressionCodec.GZip);
+ Layer.CompressMat(Mats[resolution], LayerCompressionCodec.GZip);
}
public void TestGZipDecompress(BenchmarkResolution resolution)
@@ -542,7 +542,7 @@ public class BenchmarkWindow : WindowEx
public void TestDeflateCompress(BenchmarkResolution resolution)
{
- Layer.CompressMat(Mats[resolution], Layer.LayerCompressionCodec.Deflate);
+ Layer.CompressMat(Mats[resolution], LayerCompressionCodec.Deflate);
}
public void TestDeflateDecompress(BenchmarkResolution resolution)
@@ -550,7 +550,7 @@ public class BenchmarkWindow : WindowEx
public void TestLZ4Compress(BenchmarkResolution resolution)
{
- Layer.CompressMat(Mats[resolution], Layer.LayerCompressionCodec.Lz4);
+ Layer.CompressMat(Mats[resolution], LayerCompressionCodec.Lz4);
}
public void TestLZ4Decompress(BenchmarkResolution resolution)
diff --git a/UVtools.WPF/Windows/SettingsWindow.axaml b/UVtools.WPF/Windows/SettingsWindow.axaml
index 9740d8b..e5b44ab 100644
--- a/UVtools.WPF/Windows/SettingsWindow.axaml
+++ b/UVtools.WPF/Windows/SettingsWindow.axaml
@@ -50,8 +50,8 @@
<StackPanel Orientation="Vertical">
<TextBlock Classes="GroupBoxHeader" Text="Tasks"/>
<StackPanel Margin="10" Orientation="Vertical" Spacing="10">
- <Grid RowDefinitions="Auto,10,Auto"
- ColumnDefinitions="Auto,10,150,5,Auto,20,Auto,2,Auto,2,Auto,2,Auto,2,Auto,2,Auto,2,Auto">
+ <Grid RowDefinitions="Auto,10,Auto,10,Auto"
+ ColumnDefinitions="Auto,10,180,5,Auto,20,Auto,2,Auto,2,Auto,2,Auto,2,Auto,2,Auto,2,Auto">
<TextBlock Grid.Row="0" Grid.Column="0"
VerticalAlignment="Center"
@@ -135,6 +135,29 @@
HorizontalAlignment="Stretch"
Items="{Binding Settings.General.LayerCompressionCodec, Converter={StaticResource EnumToCollectionConverter}, Mode=OneTime}"
SelectedItem="{Binding Settings.General.LayerCompressionCodec, Converter={StaticResource FromValueDescriptionToEnumConverter}}"/>
+
+ <TextBlock Grid.Row="4" Grid.Column="0"
+ VerticalAlignment="Center"
+ ToolTip.Tip="The average cost per one resin bottle of 1000ml.
+&#x0a;Used to calculate the material cost when the file lacks that information.
+&#x0a;Use 0 to disable this feature and only show the cost if file have that information.
+&#x0a;If this value is changed, you need to reload the current file to update the cost."
+ Text="Average resin bottle cost:"/>
+
+ <NumericUpDown Grid.Row="4" Grid.Column="2"
+ Classes="ValueLabel ValueLabel_euro"
+ VerticalAlignment="Center"
+ ToolTip.Tip="The average cost per one resin bottle of 1000ml.
+&#x0a;Used to calculate the material cost when the file lacks that information.
+&#x0a;Use 0 to disable this feature and only show the cost if file have that information.
+&#x0a;If this value is changed, you need to reload the current file to update the cost."
+ Minimum="0"
+ Maximum="10000"
+ Increment="1"
+ Value="{Binding Settings.General.AverageResin1000MlBottleCost}"/>
+ <TextBlock Grid.Row="4" Grid.Column="4" Grid.ColumnSpan="15"
+ VerticalAlignment="Center"
+ Text="/ 1000ml bottle"/>
</Grid>
</StackPanel>
@@ -188,10 +211,6 @@
Increment="1"
Value="{Binding Settings.General.WindowsVerticalMargin}"/>
</Grid>
-
- <CheckBox IsChecked="{Binding Settings.General.ExpandDescriptions}"
- ToolTip.Tip="Disable this if you want to gain some vertical space for windows, you can still toggle the descriptions and read them if required."
- Content="Expand and show tool descriptions by default"/>
</StackPanel>
</StackPanel>
@@ -1848,8 +1867,12 @@
<StackPanel Orientation="Vertical">
<TextBlock Classes="GroupBoxHeader" Text="Common"/>
<StackPanel Margin="10" Orientation="Vertical" Spacing="10">
- <CheckBox IsChecked="{Binding Settings.Tools.RestoreLastUsedSettings}"
- Content="Keep and restore the last used settings on operations per user session/instance"/>
+ <CheckBox IsChecked="{Binding Settings.Tools.ExpandDescriptions}"
+ ToolTip.Tip="Disable this if you want to gain some vertical space for windows, you can still toggle the descriptions and read them if required."
+ Content="Expand and show descriptions by default"/>
+
+ <CheckBox IsChecked="{Binding Settings.Tools.RestoreLastUsedSettings}"
+ Content="Keep and restore the last used settings on operations per user session/instance"/>
<ToggleSwitch IsChecked="{Binding Settings.Tools.LastUsedSettingsKeepOnCloseFile}"
OffContent="Discard the session when closing or loading files"
diff --git a/UVtools.WPF/Windows/SettingsWindow.axaml.cs b/UVtools.WPF/Windows/SettingsWindow.axaml.cs
index ca2f68b..bd6d512 100644
--- a/UVtools.WPF/Windows/SettingsWindow.axaml.cs
+++ b/UVtools.WPF/Windows/SettingsWindow.axaml.cs
@@ -8,6 +8,7 @@ using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using MessageBox.Avalonia.Enums;
+using UVtools.Core;
using UVtools.Core.FileFormats;
using UVtools.Core.Network;
using UVtools.Core.Objects;
@@ -63,7 +64,7 @@ public class SettingsWindow : WindowEx
public SettingsWindow()
{
- Title += $" [v{App.VersionStr}]";
+ Title += $" [v{About.VersionStr}]";
SettingsBackup = UserSettings.Instance.Clone();
var fileFormats = new List<string>
diff --git a/UVtools.WPF/Windows/ToolWindow.axaml b/UVtools.WPF/Windows/ToolWindow.axaml
index 3ad837b..4f9a59f 100644
--- a/UVtools.WPF/Windows/ToolWindow.axaml
+++ b/UVtools.WPF/Windows/ToolWindow.axaml
@@ -20,7 +20,7 @@
Padding="10"
IsVisible="{Binding Description, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
<Expander
- IsExpanded="{Binding Settings.General.ExpandDescriptions}"
+ IsExpanded="{Binding Settings.Tools.ExpandDescriptions}"
Header="Description (Click to toggle)">
<TextBox Classes="TransparentReadOnly"
HorizontalAlignment="Left"
diff --git a/build/createRelease.ps1 b/build/createRelease.ps1
index 1726b7f..3b5a59f 100644
--- a/build/createRelease.ps1
+++ b/build/createRelease.ps1
@@ -298,7 +298,7 @@ foreach($line in $changelog) {
}
}
Write-Host $sb.ToString()
-Set-Content -Path "UVtools.Core/RELEASE_NOTES.md" -Value $sb.ToString()
+Set-Content -Path "$rootFolder/RELEASE_NOTES.md" -Value $sb.ToString()
if($null -ne $enableNugetPublish -and $enableNugetPublish)