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-08-17 23:23:51 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2022-08-17 23:23:51 +0300
commit57f077f444f847e4ca81abe057f1782ee630effd (patch)
treed555bb0f7fdfef47193b85e9794ab5b076d9643e
parent247ed74aa7d4520370493646c0486f2eb8783767 (diff)
v3.6.0v3.6.0
- **File formats:** - (Add) OSF (Vlare Open File Format) - (Fix) CTB Encrypted: Bottom Retract Height for TSMC was constraining incorrectly with the normal total retract height - (Fix) CWS: Only issue `;<Slice>` command when the exposure is about to happen (#514) - **GCode:** - (Add) Command `CommandWaitSyncDelay` for movement wait sync delay instead of depending on G4 wait command - (Fix) Wrong parsing and set of wait times when using a wait after lift / wait before retract - (Improvement) Auto update: Make sure the download url exists before attempt the download, if not, instead it will prompt for manual download and update - (Improvement) MacOS: Remove `com.apple.quarantine` flag from the auto downloaded files - (Upgrade) .NET from 6.0.7 to 6.0.8 - (Upgrade) AvaloniaUI from 0.10.17 to 0.10.18
-rw-r--r--CHANGELOG.md16
-rw-r--r--README.md31
-rw-r--r--RELEASE_NOTES.md21
-rw-r--r--Scripts/010 Editor/osf.bt6
-rw-r--r--UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj2
-rw-r--r--UVtools.Core/Extensions/CompressionExtensions.cs181
-rw-r--r--UVtools.Core/Extensions/EmguExtensions.cs2
-rw-r--r--UVtools.Core/FileFormats/CTBEncryptedFile.cs2
-rw-r--r--UVtools.Core/FileFormats/CWSFile.cs33
-rw-r--r--UVtools.Core/FileFormats/ChituboxFile.cs2
-rw-r--r--UVtools.Core/FileFormats/FileFormat.cs36
-rw-r--r--UVtools.Core/FileFormats/JXSFile.cs9
-rw-r--r--UVtools.Core/FileFormats/LGSFile.cs8
-rw-r--r--UVtools.Core/FileFormats/OSFFile.cs778
-rw-r--r--UVtools.Core/FileFormats/OSLAFile.cs2
-rw-r--r--UVtools.Core/FileFormats/UVJFile.cs2
-rw-r--r--UVtools.Core/FileFormats/VDTFile.cs2
-rw-r--r--UVtools.Core/GCode/GCodeBuilder.cs128
-rw-r--r--UVtools.Core/GCode/GCodeLayer.cs2
-rw-r--r--UVtools.Core/Layers/Layer.cs9
-rw-r--r--UVtools.Core/Objects/UInt24BigEndian.cs9
-rw-r--r--UVtools.Core/Slicer/Slicer.cs2
-rw-r--r--UVtools.Core/UVtools.Core.csproj4
-rw-r--r--UVtools.Installer/Code/Product.wxs2
-rw-r--r--UVtools.InstallerMM/UVtools.InstallerMM.wxs10
-rw-r--r--UVtools.WPF/MainWindow.axaml.cs73
-rw-r--r--UVtools.WPF/Structures/AppVersionChecker.cs63
-rw-r--r--UVtools.WPF/UVtools.WPF.csproj18
-rw-r--r--UVtools.WPF/Windows/MissingInformationWindow.axaml1
29 files changed, 946 insertions, 508 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 35c6894..585c824 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,19 @@
# Changelog
+## 17/08/2022 - v3.6.0
+
+- **File formats:**
+ - (Add) OSF (Vlare Open File Format)
+ - (Fix) CTB Encrypted: Bottom Retract Height for TSMC was constraining incorrectly with the normal total retract height
+ - (Fix) CWS: Only issue `;<Slice>` command when the exposure is about to happen (#514)
+- **GCode:**
+ - (Add) Command `CommandWaitSyncDelay` for movement wait sync delay instead of depending on G4 wait command
+ - (Fix) Wrong parsing and set of wait times when using a wait after lift / wait before retract
+- (Improvement) Auto update: Make sure the download url exists before attempt the download, if not, instead it will prompt for manual download and update
+- (Improvement) MacOS: Remove `com.apple.quarantine` flag from the auto downloaded files
+- (Upgrade) .NET from 6.0.7 to 6.0.8
+- (Upgrade) AvaloniaUI from 0.10.17 to 0.10.18
+
## 29/07/2022 - v3.5.6
- **Tools**
@@ -7,7 +21,7 @@
- (Add) Able to choose the size midpoint rounding method (#520)
- (Fix) Allow to flash alone D03 commands (#520)
- (Fix) Correct line thickness to have at least 1px error (#523)
- - (Improvement) Layer arithmetic: Use ; to split and start a new arithmetic operation
+ - (Improvement) Layer arithmetic: Use ; to split and start a new arithmetic operation (#519)
- (Add) Cmd: Convert command now allow to pass 'auto' as target type to auto convert specific files, valid for SL1 files configured with FILEFORMAT_xxx (#522)
- (Add) GCode: Command to sync and wait for movement completion [Only enabled for cws format] (#514)
- (Add) VDT: Transition layer count
diff --git a/README.md b/README.md
index dcf730a..c537974 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,14 @@
# UVtools
-[![License](https://img.shields.io/github/license/sn4k3/UVtools?style=flat-square)](https://github.com/sn4k3/UVtools/blob/master/LICENSE)
-[![GitHub repo size](https://img.shields.io/github/repo-size/sn4k3/UVtools?style=flat-square)](#)
-[![Code size](https://img.shields.io/github/languages/code-size/sn4k3/UVtools?style=flat-square)](#)
-[![Total code](https://img.shields.io/tokei/lines/github/sn4k3/UVtools?style=flat-square)](#)
-[![Nuget](https://img.shields.io/nuget/v/UVtools.Core?style=flat-square)](https://www.nuget.org/packages/UVtools.Core)
-[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/sn4k3/UVtools?include_prereleases&style=flat-square)](https://github.com/sn4k3/UVtools/releases)
-[![Downloads](https://img.shields.io/github/downloads/sn4k3/UVtools/total?style=flat-square)](https://github.com/sn4k3/UVtools/releases)
-[![Chocolatey](https://img.shields.io/chocolatey/dt/uvtools?color=brown&label=Chocolatey&style=flat-square)](https://community.chocolatey.org/packages/uvtools)
+[![License](https://img.shields.io/github/license/sn4k3/UVtools?style=for-the-badge)](https://github.com/sn4k3/UVtools/blob/master/LICENSE)
+[![GitHub repo size](https://img.shields.io/github/repo-size/sn4k3/UVtools?style=for-the-badge)](#)
+[![Code size](https://img.shields.io/github/languages/code-size/sn4k3/UVtools?style=for-the-badge)](#)
+[![Total code](https://img.shields.io/tokei/lines/github/sn4k3/UVtools?style=for-the-badge)](#)
+[![Nuget](https://img.shields.io/nuget/v/UVtools.Core?style=for-the-badge)](https://www.nuget.org/packages/UVtools.Core)
+[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/sn4k3/UVtools?include_prereleases&style=for-the-badge)](https://github.com/sn4k3/UVtools/releases)
+[![Downloads](https://img.shields.io/github/downloads/sn4k3/UVtools/total?style=for-the-badge)](https://github.com/sn4k3/UVtools/releases)
+[![Chocolatey](https://img.shields.io/chocolatey/dt/uvtools?color=brown&label=Chocolatey&style=for-the-badge)](https://community.chocolatey.org/packages/uvtools)
+[![GitHub Sponsors](https://img.shields.io/github/sponsors/sn4k3?color=red&style=for-the-badge)](https://github.com/sponsors/sn4k3)
## Download the latest version at:
https://github.com/sn4k3/UVtools/releases/latest
@@ -106,6 +107,7 @@ But also, i need victims for test subject. Proceed at your own risk!
- ZIP (Generic / Phrozen Zip)
- VDA.ZIP (Voxeldance Additive)
- VDT (Voxeldance Tango)
+- OSF (Vlare Open File Format)
- UVJ (Zip file format for manual manipulation)
- Image files (png, jpg, jpeg, jp2, tif, bmp, pbm, pgm, ras, sr)
@@ -339,7 +341,7 @@ Easy to use calls that allow you work with the formats. For more information nav
Nuget package: https://www.nuget.org/packages/UVtools.Core
-[![Nuget](https://img.shields.io/nuget/v/UVtools.Core?style=flat-square)](https://www.nuget.org/packages/UVtools.Core)
+[![Nuget](https://img.shields.io/nuget/v/UVtools.Core?style=for-the-badge)](https://www.nuget.org/packages/UVtools.Core)
```powershell
dotnet add package UVtools.Core
@@ -376,13 +378,12 @@ The fastest way to compile the project is by run the `build/compile.bat`, howeve
# Support my work / Donate
All my work here is given for free (OpenSource), it took some hours to build, test and polish the program.
-If you're happy to contribute for a better program and for my work i will appreciate the tip.
-
-- Sponsor: https://github.com/sponsors/sn4k3
-- PayPal: https://paypal.me/SkillTournament
+If you're happy to contribute for a better program and for my work i will appreciate the tip.
+Use one of the following methods:
+[![GitHub Sponsors](https://img.shields.io/badge/Donate-Sponsor-red?style=for-the-badge)](https://github.com/sponsors/sn4k3)
+[![Donate PayPal](https://img.shields.io/badge/Donate-PayPal-blue?style=for-the-badge)](https://paypal.me/SkillTournament)
# Contributors
-
+[![GitHub contributors](https://img.shields.io/github/contributors/sn4k3/UVtools?style=for-the-badge)](https://github.com/sn4k3/UVtools/graphs/contributors)
[![Contributors](https://contrib.rocks/image?repo=sn4k3/UVtools)](https://github.com/sn4k3/UVtools/graphs/contributors)
-
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 9fe95e0..73c7297 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,11 +1,12 @@
-- **Tools**
- - **PCB Exposure:**
- - (Add) Able to choose the size midpoint rounding method (#520)
- - (Fix) Allow to flash alone D03 commands (#520)
- - (Fix) Correct line thickness to have at least 1px error (#523)
- - (Improvement) Layer arithmetic: Use ; to split and start a new arithmetic operation
-- (Add) Cmd: Convert command now allow to pass 'auto' as target type to auto convert specific files, valid for SL1 files configured with FILEFORMAT_xxx (#522)
-- (Add) GCode: Command to sync and wait for movement completion [Only enabled for cws format] (#514)
-- (Add) VDT: Transition layer count
-- (Upgrade) AvaloniaUI from 0.10.16 to 0.10.17
+- **File formats:**
+ - (Add) OSF (Vlare Open File Format)
+ - (Fix) CTB Encrypted: Bottom Retract Height for TSMC was constraining incorrectly with the normal total retract height
+ - (Fix) CWS: Only issue `;<Slice>` command when the exposure is about to happen (#514)
+- **GCode:**
+ - (Add) Command `CommandWaitSyncDelay` for movement wait sync delay instead of depending on G4 wait command
+ - (Fix) Wrong parsing and set of wait times when using a wait after lift / wait before retract
+- (Improvement) Auto update: Make sure the download url exists before attempt the download, if not, instead it will prompt for manual download and update
+- (Improvement) MacOS: Remove `com.apple.quarantine` flag from the auto downloaded files
+- (Upgrade) .NET from 6.0.7 to 6.0.8
+- (Upgrade) AvaloniaUI from 0.10.17 to 0.10.18
diff --git a/Scripts/010 Editor/osf.bt b/Scripts/010 Editor/osf.bt
index bbe1cc1..c8b9638 100644
--- a/Scripts/010 Editor/osf.bt
+++ b/Scripts/010 Editor/osf.bt
@@ -98,7 +98,11 @@ struct HEADER {
ushort RetractSpeedEnd <fgcolor=cBlack, bgcolor=cRed>; // 7
ubyte RetractDecelerationChange <fgcolor=cBlack, bgcolor=cRed>; // 5
- ubyte Unknown[8] <fgcolor=cWhite, bgcolor=cBlack>;
+ ushort BottomWaitTimeAfterCureMagnified100Times <fgcolor=cBlack, bgcolor=cRed>; // s * 100
+ ushort BottomWaitTimeAfterLiftMagnified100Times <fgcolor=cBlack, bgcolor=cRed>; // s * 100
+ ushort BottomWaitTimeBeforeCureMagnified100Times <fgcolor=cBlack, bgcolor=cRed>; // s * 100
+
+ ushort Reserved <fgcolor=cWhite, bgcolor=cBlack>;
ubyte ProtocolType <fgcolor=cBlack, bgcolor=cRed>; // 0
} header;
diff --git a/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj b/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj
index a47c56e..d7f6add 100644
--- a/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj
+++ b/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj
@@ -38,7 +38,7 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Avalonia" Version="0.10.17" />
+ <PackageReference Include="Avalonia" Version="0.10.18" />
</ItemGroup>
<ItemGroup>
diff --git a/UVtools.Core/Extensions/CompressionExtensions.cs b/UVtools.Core/Extensions/CompressionExtensions.cs
index 210c0e2..d21de95 100644
--- a/UVtools.Core/Extensions/CompressionExtensions.cs
+++ b/UVtools.Core/Extensions/CompressionExtensions.cs
@@ -10,123 +10,122 @@ using System;
using System.IO;
using System.IO.Compression;
using System.Runtime.CompilerServices;
-using Microsoft.Toolkit.HighPerformance;
+using CommunityToolkit.HighPerformance;
-namespace UVtools.Core.Extensions
+namespace UVtools.Core.Extensions;
+
+public static class CompressionExtensions
{
- public static class CompressionExtensions
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int GetGzipUncompressedLength(ReadOnlyMemory<byte> compressedData)
{
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int GetGzipUncompressedLength(ReadOnlyMemory<byte> compressedData)
- {
- return BitConverter.ToInt32(compressedData.Slice(compressedData.Length - 4, 4).Span);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int GetGzipUncompressedLength(Stream stream)
- {
- Span<byte> uncompressedLength = stackalloc byte[4];
- stream.Position = stream.Length - 4;
- stream.Read(uncompressedLength);
- stream.Seek(0, SeekOrigin.Begin);
- return BitConverter.ToInt32(uncompressedLength);
- }
+ return BitConverter.ToInt32(compressedData.Slice(compressedData.Length - 4, 4).Span);
+ }
- public static MemoryStream GZipCompress(Stream inputStream, CompressionLevel compressionLevel, bool leaveStreamOpen = false)
- {
- if (inputStream.Position == inputStream.Length) { inputStream.Seek(0, SeekOrigin.Begin); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int GetGzipUncompressedLength(Stream stream)
+ {
+ Span<byte> uncompressedLength = stackalloc byte[4];
+ stream.Position = stream.Length - 4;
+ stream.Read(uncompressedLength);
+ stream.Seek(0, SeekOrigin.Begin);
+ return BitConverter.ToInt32(uncompressedLength);
+ }
- var compressedStream = new MemoryStream();
- using (var gzipStream = new GZipStream(compressedStream, compressionLevel, true))
- {
- inputStream.CopyTo(gzipStream);
- }
- if (!leaveStreamOpen) { inputStream.Close(); }
+ public static MemoryStream GZipCompress(Stream inputStream, CompressionLevel compressionLevel, bool leaveStreamOpen = false)
+ {
+ if (inputStream.Position == inputStream.Length) { inputStream.Seek(0, SeekOrigin.Begin); }
- compressedStream.Seek(0, SeekOrigin.Begin);
- return compressedStream;
+ var compressedStream = new MemoryStream();
+ using (var gzipStream = new GZipStream(compressedStream, compressionLevel, true))
+ {
+ inputStream.CopyTo(gzipStream);
}
+ if (!leaveStreamOpen) { inputStream.Close(); }
- public static MemoryStream GZipCompress(byte[] inputStream, CompressionLevel compressionLevel) =>
- GZipCompress(new ReadOnlyMemory<byte>(inputStream).AsStream(), compressionLevel);
+ compressedStream.Seek(0, SeekOrigin.Begin);
+ return compressedStream;
+ }
- public static byte[] GZipCompressToBytes(byte[] inputStream, CompressionLevel compressionLevel)
- {
- using var ms = GZipCompress(new ReadOnlyMemory<byte>(inputStream).AsStream(), compressionLevel);
- return ms.ToArray();
- }
+ public static MemoryStream GZipCompress(byte[] inputStream, CompressionLevel compressionLevel) =>
+ GZipCompress(new ReadOnlyMemory<byte>(inputStream).AsStream(), compressionLevel);
+
+ public static byte[] GZipCompressToBytes(byte[] inputStream, CompressionLevel compressionLevel)
+ {
+ using var ms = GZipCompress(new ReadOnlyMemory<byte>(inputStream).AsStream(), compressionLevel);
+ return ms.ToArray();
+ }
- public static MemoryStream GZipDecompress(Stream compressedStream, bool leaveStreamOpen = false)
- {
- if (compressedStream.Position == compressedStream.Length) { compressedStream.Seek(0, SeekOrigin.Begin); }
+ public static MemoryStream GZipDecompress(Stream compressedStream, bool leaveStreamOpen = false)
+ {
+ if (compressedStream.Position == compressedStream.Length) { compressedStream.Seek(0, SeekOrigin.Begin); }
- var uncompressedStream = new MemoryStream(GetGzipUncompressedLength(compressedStream));
- using var gzipStream = new GZipStream(compressedStream, CompressionMode.Decompress, leaveStreamOpen);
- gzipStream.CopyTo(uncompressedStream);
+ var uncompressedStream = new MemoryStream(GetGzipUncompressedLength(compressedStream));
+ using var gzipStream = new GZipStream(compressedStream, CompressionMode.Decompress, leaveStreamOpen);
+ gzipStream.CopyTo(uncompressedStream);
- return uncompressedStream;
- }
+ return uncompressedStream;
+ }
- public static ArraySegment<byte> GZipDecompress(ReadOnlyMemory<byte> compressedData)
+ public static ArraySegment<byte> GZipDecompress(ReadOnlyMemory<byte> compressedData)
+ {
+ using var uncompressedStream = new MemoryStream(GetGzipUncompressedLength(compressedData));
+ using (var gzipStream = new GZipStream(compressedData.AsStream(), CompressionMode.Decompress, false))
{
- using var uncompressedStream = new MemoryStream(GetGzipUncompressedLength(compressedData));
- using (var gzipStream = new GZipStream(compressedData.AsStream(), CompressionMode.Decompress, false))
- {
- gzipStream.CopyTo(uncompressedStream);
- }
-
- return uncompressedStream.TryGetBuffer(out var buffer)
- ? buffer
- : uncompressedStream.ToArray();
+ gzipStream.CopyTo(uncompressedStream);
}
- public static MemoryStream DeflateCompress(Stream inputStream, CompressionLevel compressionLevel, bool leaveStreamOpen = false)
- {
- if (inputStream.Position == inputStream.Length) { inputStream.Seek(0, SeekOrigin.Begin); }
+ return uncompressedStream.TryGetBuffer(out var buffer)
+ ? buffer
+ : uncompressedStream.ToArray();
+ }
- var compressedStream = new MemoryStream();
- using (var gzipStream = new DeflateStream(compressedStream, compressionLevel, true))
- {
- inputStream.CopyTo(gzipStream);
- }
- if (!leaveStreamOpen) { inputStream.Close(); }
+ public static MemoryStream DeflateCompress(Stream inputStream, CompressionLevel compressionLevel, bool leaveStreamOpen = false)
+ {
+ if (inputStream.Position == inputStream.Length) { inputStream.Seek(0, SeekOrigin.Begin); }
- compressedStream.Seek(0, SeekOrigin.Begin);
- return compressedStream;
+ var compressedStream = new MemoryStream();
+ using (var gzipStream = new DeflateStream(compressedStream, compressionLevel, true))
+ {
+ inputStream.CopyTo(gzipStream);
}
+ if (!leaveStreamOpen) { inputStream.Close(); }
- public static MemoryStream DeflateCompress(byte[] inputStream, CompressionLevel compressionLevel) =>
- DeflateCompress(new ReadOnlyMemory<byte>(inputStream).AsStream(), compressionLevel);
+ compressedStream.Seek(0, SeekOrigin.Begin);
+ return compressedStream;
+ }
- public static byte[] DeflateCompressToBytes(byte[] inputStream, CompressionLevel compressionLevel)
- {
- using var ms = DeflateCompress(new ReadOnlyMemory<byte>(inputStream).AsStream(), compressionLevel);
- return ms.ToArray();
- }
+ public static MemoryStream DeflateCompress(byte[] inputStream, CompressionLevel compressionLevel) =>
+ DeflateCompress(new ReadOnlyMemory<byte>(inputStream).AsStream(), compressionLevel);
- public static MemoryStream DeflateDecompress(Stream compressedStream, bool leaveStreamOpen = false)
- {
- if (compressedStream.Position == compressedStream.Length) { compressedStream.Seek(0, SeekOrigin.Begin); }
+ public static byte[] DeflateCompressToBytes(byte[] inputStream, CompressionLevel compressionLevel)
+ {
+ using var ms = DeflateCompress(new ReadOnlyMemory<byte>(inputStream).AsStream(), compressionLevel);
+ return ms.ToArray();
+ }
- var uncompressedStream = new MemoryStream();
- using var gzipStream = new DeflateStream(compressedStream, CompressionMode.Decompress, leaveStreamOpen);
- gzipStream.CopyTo(uncompressedStream);
+ public static MemoryStream DeflateDecompress(Stream compressedStream, bool leaveStreamOpen = false)
+ {
+ if (compressedStream.Position == compressedStream.Length) { compressedStream.Seek(0, SeekOrigin.Begin); }
- return uncompressedStream;
- }
+ var uncompressedStream = new MemoryStream();
+ using var gzipStream = new DeflateStream(compressedStream, CompressionMode.Decompress, leaveStreamOpen);
+ gzipStream.CopyTo(uncompressedStream);
- public static ArraySegment<byte> DeflateDecompress(ReadOnlyMemory<byte> compressedData)
+ return uncompressedStream;
+ }
+
+ public static ArraySegment<byte> DeflateDecompress(ReadOnlyMemory<byte> compressedData)
+ {
+ using var uncompressedStream = new MemoryStream();
+ using (var gzipStream = new DeflateStream(compressedData.AsStream(), CompressionMode.Decompress, false))
{
- using var uncompressedStream = new MemoryStream();
- using (var gzipStream = new DeflateStream(compressedData.AsStream(), CompressionMode.Decompress, false))
- {
- gzipStream.CopyTo(uncompressedStream);
- }
-
- return uncompressedStream.TryGetBuffer(out var buffer)
- ? buffer
- : uncompressedStream.ToArray();
+ gzipStream.CopyTo(uncompressedStream);
}
+
+ return uncompressedStream.TryGetBuffer(out var buffer)
+ ? buffer
+ : uncompressedStream.ToArray();
}
-}
+} \ No newline at end of file
diff --git a/UVtools.Core/Extensions/EmguExtensions.cs b/UVtools.Core/Extensions/EmguExtensions.cs
index bb12f39..abf84de 100644
--- a/UVtools.Core/Extensions/EmguExtensions.cs
+++ b/UVtools.Core/Extensions/EmguExtensions.cs
@@ -15,7 +15,7 @@ using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
-using Microsoft.Toolkit.HighPerformance;
+using CommunityToolkit.HighPerformance;
using UVtools.Core.EmguCV;
using UVtools.Core.Objects;
diff --git a/UVtools.Core/FileFormats/CTBEncryptedFile.cs b/UVtools.Core/FileFormats/CTBEncryptedFile.cs
index b19f122..0af2e2f 100644
--- a/UVtools.Core/FileFormats/CTBEncryptedFile.cs
+++ b/UVtools.Core/FileFormats/CTBEncryptedFile.cs
@@ -955,7 +955,7 @@ public class CTBEncryptedFile : FileFormat
get => Settings.BottomRetractHeight2;
set
{
- value = Math.Clamp((float)Math.Round(value, 2), 0, RetractHeightTotal);
+ value = Math.Clamp((float)Math.Round(value, 2), 0, BottomRetractHeightTotal);
base.BottomRetractHeight2 = Settings.BottomRetractHeight2 = value;
}
}
diff --git a/UVtools.Core/FileFormats/CWSFile.cs b/UVtools.Core/FileFormats/CWSFile.cs
index 91417d5..1cf7fc7 100644
--- a/UVtools.Core/FileFormats/CWSFile.cs
+++ b/UVtools.Core/FileFormats/CWSFile.cs
@@ -570,23 +570,33 @@ public class CWSFile : FileFormat
{
GCode = new GCodeBuilder
{
- SyncMovementsWithDelay = true,
UseComments = true,
GCodePositioningType = GCodeBuilder.GCodePositioningTypes.Relative,
GCodeSpeedUnit = GCodeBuilder.GCodeSpeedUnits.MillimetersPerMinute,
GCodeTimeUnit = GCodeBuilder.GCodeTimeUnits.Milliseconds,
GCodeShowImageType = GCodeBuilder.GCodeShowImageTypes.LayerIndex0Started,
+ GCodeShowImagePosition = GCodeBuilder.GCodeShowImagePositions.WhenRequired,
LayerMoveCommand = GCodeBuilder.GCodeMoveCommands.G1,
- EndGCodeMoveCommand = GCodeBuilder.GCodeMoveCommands.G1
+ EndGCodeMoveCommand = GCodeBuilder.GCodeMoveCommands.G1,
+ CommandSyncMovements =
+ {
+ Enabled = true
+ },
+ CommandWaitSyncDelay =
+ {
+ Enabled = true,
+ }
};
+
GCode.CommandShowImageM6054.Set(";<Slice>", "{0}");
+ GCode.CommandWaitSyncDelay.Set(";<Delay>", "0{0}");
GCode.CommandWaitG4.Set(";<Delay>", "{0}");
- GCode.CommandSyncMovements.Enabled = true;
+
}
#endregion
#region Methods
-
+
protected override void EncodeInternally(OperationProgress progress)
{
//var filename = fileFullPath.EndsWith(TemporaryFileAppend) ? Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(fileFullPath)) : Path.GetFileNameWithoutExtension(fileFullPath);
@@ -799,7 +809,7 @@ public class CWSFile : FileFormat
// Must discover png depth grayscale or color
if (DecodeType == FileDecodeType.Full && Printer == PrinterType.Unknown)
{
- var inputFilename = Path.GetFileNameWithoutExtension(FileFullPath)!;
+ //var inputFilename = Path.GetFileNameWithoutExtension(FileFullPath)!;
foreach (var pngEntry in inputFile.Entries)
{
if (!pngEntry.Name.EndsWith(".png")) continue;
@@ -836,6 +846,17 @@ public class CWSFile : FileFormat
public override void RebuildGCode()
{
if (!SupportsGCode || SuppressRebuildGCode) return;
+
+ switch (Printer)
+ {
+ case PrinterType.Wanhao:
+ GCode!.CommandWaitSyncDelay.Command = ";<Takes>";
+ break;
+ default:
+ GCode!.CommandWaitSyncDelay.Command = ";<Delay>";
+ break;
+ }
+
//string arch = Environment.Is64BitOperatingSystem ? "64-bits" : "32-bits";
//GCode.Clear();
//GCode.AppendLine($"; {About.Website} {About.Software} {Assembly.GetExecutingAssembly().GetName().Version} {arch} {DateTime.UtcNow}");
@@ -981,5 +1002,7 @@ public class CWSFile : FileFormat
//Decode(FileFullPath, progress);
}
+
+
#endregion
} \ No newline at end of file
diff --git a/UVtools.Core/FileFormats/ChituboxFile.cs b/UVtools.Core/FileFormats/ChituboxFile.cs
index 8c09d8a..9c78dc7 100644
--- a/UVtools.Core/FileFormats/ChituboxFile.cs
+++ b/UVtools.Core/FileFormats/ChituboxFile.cs
@@ -29,7 +29,7 @@ public class ChituboxFile : FileFormat
{
#region Constants
- public const byte USED_VERSION = 3; // 318570521
+ public const byte USED_VERSION = 3;
public const uint MAGIC_CBDDLP = 0x12FD0019; // 318570521
public const uint MAGIC_CTB = 0x12FD0086; // 318570630
diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs
index 322cfd1..d1796be 100644
--- a/UVtools.Core/FileFormats/FileFormat.cs
+++ b/UVtools.Core/FileFormats/FileFormat.cs
@@ -384,11 +384,11 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
//new CXDLPv1File(), // Creality Box v1
new CXDLPFile(), // Creality Box
new LGSFile(), // LGS, LGS30
- //new OSFFile(), // OSF
new FlashForgeSVGXFile(), // SVGX
new GenericZIPFile(), // Generic zip files
new VDAFile(), // VDA
new VDTFile(), // VDT
+ new OSFFile(), // OSF
new UVJFile(), // UVJ
new ImageFile(), // images
};
@@ -1505,9 +1505,21 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
ResolutionX = (uint) value.Width;
ResolutionY = (uint) value.Height;
RaisePropertyChanged();
+ RaisePropertyChanged(nameof(DisplayAspectRatio));
+ RaisePropertyChanged(nameof(DisplayAspectRatioStr));
RaisePropertyChanged(nameof(Xppmm));
RaisePropertyChanged(nameof(Yppmm));
RaisePropertyChanged(nameof(Ppmm));
+ RaisePropertyChanged(nameof(PpmmMax));
+ RaisePropertyChanged(nameof(PixelSizeMicrons));
+ RaisePropertyChanged(nameof(PixelArea));
+ RaisePropertyChanged(nameof(PixelAreaMicrons));
+ RaisePropertyChanged(nameof(PixelHeight));
+ RaisePropertyChanged(nameof(PixelHeightMicrons));
+ RaisePropertyChanged(nameof(PixelSize));
+ RaisePropertyChanged(nameof(PixelSizeMax));
+ RaisePropertyChanged(nameof(PixelWidth));
+ RaisePropertyChanged(nameof(PixelWidthMicrons));
}
}
@@ -1534,9 +1546,25 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
get => new(DisplayWidth, DisplayHeight);
set
{
- DisplayWidth = value.Width;
- DisplayHeight = value.Height;
+ DisplayWidth = (float)Math.Round(value.Width, 4);
+ DisplayHeight = (float)Math.Round(value.Height, 4);
RaisePropertyChanged();
+ RaisePropertyChanged(nameof(DisplayAspectRatio));
+ RaisePropertyChanged(nameof(DisplayAspectRatioStr));
+ RaisePropertyChanged(nameof(DisplayDiagonal));
+ RaisePropertyChanged(nameof(DisplayDiagonalInches));
+ RaisePropertyChanged(nameof(Xppmm));
+ RaisePropertyChanged(nameof(Yppmm));
+ RaisePropertyChanged(nameof(Ppmm));
+ RaisePropertyChanged(nameof(PpmmMax));
+ RaisePropertyChanged(nameof(PixelSizeMicrons));
+ RaisePropertyChanged(nameof(PixelArea));
+ RaisePropertyChanged(nameof(PixelAreaMicrons));
+ RaisePropertyChanged(nameof(PixelHeight));
+ RaisePropertyChanged(nameof(PixelHeightMicrons));
+ RaisePropertyChanged(nameof(PixelSize));
+ RaisePropertyChanged(nameof(PixelSizeMax));
+ RaisePropertyChanged(nameof(PixelWidth));
}
}
@@ -5266,7 +5294,7 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor
if (differenceLayerCount > 0 && initBlack)
{
- using var blackMat = EmguExtensions.InitMat(Resolution);
+ using var blackMat = CreateMat(false);
var pngBytes = blackMat.GetPngByes();
for (var layerIndex = oldLayerCount; layerIndex < newLayerCount; layerIndex++)
{
diff --git a/UVtools.Core/FileFormats/JXSFile.cs b/UVtools.Core/FileFormats/JXSFile.cs
index 27631c1..a9a9557 100644
--- a/UVtools.Core/FileFormats/JXSFile.cs
+++ b/UVtools.Core/FileFormats/JXSFile.cs
@@ -327,7 +327,10 @@ public class JXSFile : FileFormat
GCodeShowImageType = GCodeBuilder.GCodeShowImageTypes.FilenamePng0Started,
LayerMoveCommand = GCodeBuilder.GCodeMoveCommands.G0,
EndGCodeMoveCommand = GCodeBuilder.GCodeMoveCommands.G0,
- SyncMovementsWithDelay = true
+ CommandWaitSyncDelay =
+ {
+ Enabled = true
+ }
};
}
#endregion
@@ -528,7 +531,7 @@ public class JXSFile : FileFormat
{
case "gcode":
lastCommand = value;
- if (value.StartsWith("M106 S") && value.StartsWith("M106 S0")) GCode.AppendWaitG4(0);
+ if (value.StartsWith("M106 S0")) GCode.AppendWaitG4(0);
GCode.AppendLine(value);
break;
case "slice":
@@ -545,7 +548,7 @@ public class JXSFile : FileFormat
if (lastCommand.StartsWith("G0") || lastCommand.StartsWith("G1"))
{
lastCommand = $"G4 0{value}";
- GCode.AppendWaitG4($"0{value}");
+ GCode.AppendWaitSyncDelay(value);
break;
}
GCode.AppendWaitG4(value);
diff --git a/UVtools.Core/FileFormats/LGSFile.cs b/UVtools.Core/FileFormats/LGSFile.cs
index c4da12a..9e40f47 100644
--- a/UVtools.Core/FileFormats/LGSFile.cs
+++ b/UVtools.Core/FileFormats/LGSFile.cs
@@ -263,10 +263,10 @@ public class LGSFile : FileFormat
public override FileFormatType FileType => FileFormatType.Binary;
public override FileExtension[] FileExtensions { get; } = {
- new (typeof(LGSFile), "lgs", "Longer Orange 10"),
- new (typeof(LGSFile), "lgs30", "Longer Orange 30"),
- new (typeof(LGSFile), "lgs120", "Longer Orange 120"),
- new (typeof(LGSFile), "lgs4k", "Longer Orange 4k"),
+ new (typeof(LGSFile), "lgs", "Longer Orange 10 (LGS)"),
+ new (typeof(LGSFile), "lgs30", "Longer Orange 30 (LGS30)"),
+ new (typeof(LGSFile), "lgs120", "Longer Orange 120 (LGS120)"),
+ new (typeof(LGSFile), "lgs4k", "Longer Orange 4k (LGS4K)"),
};
public override PrintParameterModifier[]? PrintParameterModifiers { get; } =
diff --git a/UVtools.Core/FileFormats/OSFFile.cs b/UVtools.Core/FileFormats/OSFFile.cs
index 2fb3f7f..a7ddde5 100644
--- a/UVtools.Core/FileFormats/OSFFile.cs
+++ b/UVtools.Core/FileFormats/OSFFile.cs
@@ -8,14 +8,12 @@
using BinarySerialization;
using Emgu.CV;
-using Emgu.CV.CvEnum;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading.Tasks;
-using UVtools.Core.Converters;
using UVtools.Core.Extensions;
using UVtools.Core.Layers;
using UVtools.Core.Objects;
@@ -25,22 +23,37 @@ namespace UVtools.Core.FileFormats;
public class OSFFile : FileFormat
{
+ #region Constants
+ public const ushort USED_VERSION = 4;
+ #endregion
#region Sub Classes
-
+
#region Header
- public class Header
+ public class OSFHeader
{
- [FieldOrder(0)] [FieldEndianness(Endianness.Big)] public uint HeaderLength { get; set; } = 350001;
- [FieldOrder(1)] [FieldEndianness(Endianness.Big)] public ushort Version { get; set; } = 4;
- [FieldOrder(2)] [FieldEndianness(Endianness.Big)] public byte ImageLog { get; set; } = 2;
+ [FieldOrder(0)]
+ [FieldEndianness(Endianness.Big)]
+ public uint HeaderLength { get; set; } = 350001;
+
+ [FieldOrder(1)]
+ [FieldEndianness(Endianness.Big)]
+ public ushort Version { get; set; } = USED_VERSION;
+
+ [FieldOrder(2)]
+ [FieldEndianness(Endianness.Big)]
+ public byte ImageLog { get; set; } = 2;
/// <summary>
/// 148 * 80 * 2
/// </summary>
- //[FieldOrder(3)] public Uint24BitBigEndian Preview1Length { get; set; } = new(23680);
- [FieldOrder(3)] [FieldEndianness(Endianness.Big)] [FieldBitLength(24)] public uint Preview1Length { get; set; } = 23680;
-
+ //[FieldOrder(3)] public UInt24BigEndian Preview1Length { get; set; } = new(23680);
+ //[FieldOrder(3)] [FieldCount(nameof(UInt24BigEndian.Value), )] public UInt24BigEndian Preview1sssLength { get; set; } = new(23680);
+ /*[FieldOrder(3)]
+ [FieldEndianness(Endianness.Big)]
+ [FieldBitLength(24)]
+ public uint Preview1Length { get; set; } = 23680;
+ */
/// <summary>
/// RGB565
/// </summary>
@@ -56,202 +69,258 @@ public class OSFFile : FileFormat
/// </summary>
[FieldOrder(6)] [FieldLength(nameof(Preview2Length))] public byte[] Preview2Data { get; set; }*/
-
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort ResolutionX { get; set; }
- [FieldOrder(11)] [FieldEndianness(Endianness.Big)] public ushort ResolutionY { get; set; }
- [FieldOrder(12)] [FieldEndianness(Endianness.Big)] public ushort PixelUmMagnified100Times { get; set; }
+ public override string ToString()
+ {
+ return $"{nameof(HeaderLength)}: {HeaderLength}, {nameof(Version)}: {Version}, {nameof(ImageLog)}: {ImageLog}";
+ }
+ }
+
+ public sealed class OSFSettings
+ {
+ [FieldOrder(0)] [FieldEndianness(Endianness.Big)] public ushort ResolutionX { get; set; }
+ [FieldOrder(1)] [FieldEndianness(Endianness.Big)] public ushort ResolutionY { get; set; }
+ [FieldOrder(2)] [FieldEndianness(Endianness.Big)] public ushort PixelUmMagnified100Times { get; set; }
/// <summary>
/// (0x00 not mirrored, 0x01 X-axis mirroring, 0x02 Y-axis mirroring, 0x03 XY-axis mirroring)
/// </summary>
- [FieldOrder(13)] [FieldEndianness(Endianness.Big)] public byte Mirror { get; set; }
- [FieldOrder(14)] [FieldEndianness(Endianness.Big)] public byte BottomLightPWM { get; set; } = DefaultBottomLightPWM;
- [FieldOrder(15)] [FieldEndianness(Endianness.Big)] public byte LightPWM { get; set; } = DefaultLightPWM;
- [FieldOrder(16)] [FieldEndianness(Endianness.Big)] public byte AntiAliasEnabled { get; set; }
- [FieldOrder(17)] [FieldEndianness(Endianness.Big)] public byte DistortionEnabled { get; set; }
- [FieldOrder(18)] [FieldEndianness(Endianness.Big)] public byte DelayedExposureActivationEnabled { get; set; }
- [FieldOrder(19)] [FieldEndianness(Endianness.Big)] public uint LayerCount { get; set; }
- [FieldOrder(20)] [FieldEndianness(Endianness.Big)] public ushort NumberParameterSets { get; set; } = 1;
- [FieldOrder(21)] [FieldEndianness(Endianness.Big)] public uint LastLayerIndex { set; get; }
- [FieldOrder(22)] [FieldEndianness(Endianness.Big)] public uint LayerHeightUmMagnified100Times { set; get; }
- [FieldOrder(23)] [FieldEndianness(Endianness.Big)] public byte BottomLayerCount { set; get; }
- [FieldOrder(24)] [FieldEndianness(Endianness.Big)] public uint ExposureTimeMagnified100Times { set; get; }
- [FieldOrder(25)] [FieldEndianness(Endianness.Big)] public uint BottomExposureTimeMagnified100Times { set; get; }
- [FieldOrder(26)] [FieldEndianness(Endianness.Big)] public uint SupportDelayTimeMagnified100Times { set; get; }
- [FieldOrder(27)] [FieldEndianness(Endianness.Big)] public uint BottomSupportDelayTimeMagnified100Times { set; get; }
- [FieldOrder(28)] [FieldEndianness(Endianness.Big)] public byte TransitionLayers { set; get; }
+ [FieldOrder(3)] [FieldEndianness(Endianness.Big)] public byte Mirror { get; set; }
+ [FieldOrder(4)] [FieldEndianness(Endianness.Big)] public byte BottomLightPWM { get; set; } = DefaultBottomLightPWM;
+ [FieldOrder(5)] [FieldEndianness(Endianness.Big)] public byte LightPWM { get; set; } = DefaultLightPWM;
+ [FieldOrder(6)] [FieldEndianness(Endianness.Big)] public bool AntiAliasEnabled { get; set; }
+ [FieldOrder(7)] [FieldEndianness(Endianness.Big)] public bool DistortionEnabled { get; set; }
+ [FieldOrder(8)] [FieldEndianness(Endianness.Big)] public bool DelayedExposureActivationEnabled { get; set; }
+ [FieldOrder(9)] [FieldEndianness(Endianness.Big)] public uint LayerCount { get; set; }
+ [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort NumberParameterSets { get; set; } = 1;
+ [FieldOrder(11)] [FieldEndianness(Endianness.Big)] public uint LastLayerIndex { set; get; }
+ [FieldOrder(12)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian LayerHeightUmMagnified100Times { set; get; } = new();
+ [FieldOrder(13)] [FieldEndianness(Endianness.Big)] public byte BottomLayerCount { set; get; }
+ [FieldOrder(14)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian ExposureTimeMagnified100Times { set; get; } = new((uint) (DefaultExposureTime*1000));
+ [FieldOrder(15)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian BottomExposureTimeMagnified100Times { set; get; } = new((uint)(DefaultBottomExposureTime * 1000));
+ [FieldOrder(16)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian SupportDelayTimeMagnified100Times { set; get; } = new(50);
+ [FieldOrder(17)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian BottomSupportDelayTimeMagnified100Times { set; get; } = new(50);
+ [FieldOrder(18)] [FieldEndianness(Endianness.Big)] public byte TransitionLayerCount { set; get; }
+
/// <summary>
/// (0x00 linear transition)
/// </summary>
- [FieldOrder(29)] [FieldEndianness(Endianness.Big)] public byte TransitionType { set; get; }
- /*
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public uint TransitionLayerIntervalTimeDifferenceMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public uint WaitTimeAfterCureMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public uint WaitTimeAfterLiftMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public uint WaitTimeBeforeCureMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public uint BottomLiftHeightSlowMagnified1000Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public uint BottomLiftHeightTotalMagnified1000Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public uint LiftHeightSlowMagnified1000Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public uint LiftHeightTotalMagnified1000Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public uint BottomRetractHeightTotalMagnified1000Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public uint RetractHeightSlowMagnified1000Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public uint RetractHeightTotalMagnified1000Times { set; get; }
+ [FieldOrder(19)] [FieldEndianness(Endianness.Big)] public byte TransitionType { set; get; }
+
+ [FieldOrder(20)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian TransitionLayerIntervalTimeDifferenceMagnified100Times { set; get; } = new();
+ [FieldOrder(21)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian WaitTimeAfterCureMagnified100Times { set; get; } = new();
+ [FieldOrder(22)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian WaitTimeAfterLiftMagnified100Times { set; get; } = new();
+ [FieldOrder(23)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian WaitTimeBeforeCureMagnified100Times { set; get; } = new();
+ [FieldOrder(24)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian BottomLiftHeightSlowMagnified1000Times { set; get; } = new();
+ [FieldOrder(25)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian BottomLiftHeightTotalMagnified1000Times { set; get; } = new((uint)(DefaultBottomLiftHeight * 1000));
+ [FieldOrder(26)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian LiftHeightSlowMagnified1000Times { set; get; } = new();
+ [FieldOrder(27)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian LiftHeightTotalMagnified1000Times { set; get; } = new((uint)(DefaultLiftHeight * 1000));
+ [FieldOrder(28)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian BottomRetractHeightSlowMagnified1000Times { set; get; } = new();
+ [FieldOrder(29)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian BottomRetractHeightTotalMagnified1000Times { set; get; } = new((uint)(DefaultBottomLiftHeight * 1000));
+ [FieldOrder(30)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian RetractHeightSlowMagnified1000Times { set; get; } = new();
+ [FieldOrder(31)] [FieldEndianness(Endianness.Big)] public UInt24BigEndian RetractHeightTotalMagnified1000Times { set; get; } = new((uint)(DefaultLiftHeight * 1000));
/// <summary>
/// (0x00: S-shaped acceleration, 0x01: T-shaped acceleration, Default Value: S-shaped acceleration, currently only supports S-shaped acceleration)
/// </summary>
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public byte AccelerationType { set; get; }
-
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort BottomLiftSpeedStartMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort BottomLiftSpeedSlowMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort BottomLiftSpeedFastMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public byte BottomLiftAccelerationChange { set; get; } // 5
-
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort LiftSpeedStartMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort LiftSpeedSlowMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort LiftSpeedFastMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public byte LiftAccelerationChange { set; get; } // 5
-
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort BottomRetractSpeedStartMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort BottomRetractSpeedSlowMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort BottomRetractFastMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public byte BottomRetractAccelerationChange { set; get; } // 5
-
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort RetractSpeedStartMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort RetractSpeedSlowMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public ushort RetractFastMagnified100Times { set; get; }
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public byte RetractAccelerationChange { set; get; } // 5
-
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] [FieldCount(23)] public byte[] Reserved { set; get; } = new byte[23]; // 23
- [FieldOrder(10)] [FieldEndianness(Endianness.Big)] public byte ProtocolType { set; get; } // 0
- */
+ [FieldOrder(32)] [FieldEndianness(Endianness.Big)] public byte AccelerationType { set; get; }
+
+ [FieldOrder(33)] [FieldEndianness(Endianness.Big)] public ushort BottomLiftSpeedStart { set; get; } = 80;
+ [FieldOrder(34)] [FieldEndianness(Endianness.Big)] public ushort BottomLiftSpeedSlow { set; get; } = (ushort)DefaultBottomLiftSpeed;
+ [FieldOrder(35)] [FieldEndianness(Endianness.Big)] public ushort BottomLiftSpeedFast { set; get; } = (ushort)DefaultBottomLiftSpeed2;
+ [FieldOrder(36)] [FieldEndianness(Endianness.Big)] public byte BottomLiftAccelerationChange { set; get; } = 5;
+
+ [FieldOrder(37)] [FieldEndianness(Endianness.Big)] public ushort LiftSpeedStart { set; get; } = 80;
+ [FieldOrder(38)] [FieldEndianness(Endianness.Big)] public ushort LiftSpeedSlow { set; get; } = (ushort)DefaultLiftSpeed;
+ [FieldOrder(39)] [FieldEndianness(Endianness.Big)] public ushort LiftSpeedFast { set; get; } = (ushort)DefaultLiftSpeed2;
+ [FieldOrder(40)] [FieldEndianness(Endianness.Big)] public byte LiftAccelerationChange { set; get; } = 5;
+
+ [FieldOrder(41)] [FieldEndianness(Endianness.Big)] public ushort BottomRetractSpeedStart { set; get; } = 80;
+ [FieldOrder(42)] [FieldEndianness(Endianness.Big)] public ushort BottomRetractSpeedSlow { set; get; } = (ushort)DefaultBottomRetractSpeed2;
+ [FieldOrder(43)] [FieldEndianness(Endianness.Big)] public ushort BottomRetractSpeedFast { set; get; } = (ushort)DefaultBottomRetractSpeed;
+ [FieldOrder(44)] [FieldEndianness(Endianness.Big)] public byte BottomRetractAccelerationChange { set; get; } = 5;
+
+ [FieldOrder(45)] [FieldEndianness(Endianness.Big)] public ushort RetractSpeedStart { set; get; } = 80;
+ [FieldOrder(46)] [FieldEndianness(Endianness.Big)] public ushort RetractSpeedSlow { set; get; } = (ushort)DefaultRetractSpeed2;
+ [FieldOrder(47)] [FieldEndianness(Endianness.Big)] public ushort RetractSpeedFast { set; get; } = (ushort)DefaultRetractSpeed;
+ [FieldOrder(48)] [FieldEndianness(Endianness.Big)] public byte RetractAccelerationChange { set; get; } = 5;
+
+ [FieldOrder(49)][FieldEndianness(Endianness.Big)] public ushort BottomLiftSpeedEnd { set; get; } = 7;
+ [FieldOrder(50)][FieldEndianness(Endianness.Big)] public byte BottomLiftDecelerationChange { set; get; } = 5;
+
+ [FieldOrder(51)][FieldEndianness(Endianness.Big)] public ushort LiftSpeedEnd { set; get; } = 7;
+ [FieldOrder(52)][FieldEndianness(Endianness.Big)] public byte LiftDecelerationChange { set; get; } = 5;
+
+ [FieldOrder(53)][FieldEndianness(Endianness.Big)] public ushort BottomRetractSpeedEnd { set; get; } = 7;
+ [FieldOrder(54)][FieldEndianness(Endianness.Big)] public byte BottomRetractDecelerationChange { set; get; } = 5;
+ [FieldOrder(55)][FieldEndianness(Endianness.Big)] public ushort RetractSpeedEnd { set; get; } = 7;
+ [FieldOrder(56)][FieldEndianness(Endianness.Big)] public byte RetractDecelerationChange { set; get; } = 5;
+
+ [FieldOrder(57)][FieldEndianness(Endianness.Big)] public ushort BottomWaitTimeAfterCureMagnified100Times { set; get; }
+ [FieldOrder(58)][FieldEndianness(Endianness.Big)] public ushort BottomWaitTimeAfterLiftMagnified100Times { set; get; }
+ [FieldOrder(59)][FieldEndianness(Endianness.Big)] public ushort BottomWaitTimeBeforeCureMagnified100Times { set; get; }
+
+ [FieldOrder(60)] [FieldEndianness(Endianness.Big)] public ushort Reserved { set; get; }
+ [FieldOrder(61)] [FieldEndianness(Endianness.Big)] public byte ProtocolType { set; get; } // 0
+
+ public override string ToString()
+ {
+ return $"{nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(PixelUmMagnified100Times)}: {PixelUmMagnified100Times}, {nameof(Mirror)}: {Mirror}, {nameof(BottomLightPWM)}: {BottomLightPWM}, {nameof(LightPWM)}: {LightPWM}, {nameof(AntiAliasEnabled)}: {AntiAliasEnabled}, {nameof(DistortionEnabled)}: {DistortionEnabled}, {nameof(DelayedExposureActivationEnabled)}: {DelayedExposureActivationEnabled}, {nameof(LayerCount)}: {LayerCount}, {nameof(NumberParameterSets)}: {NumberParameterSets}, {nameof(LastLayerIndex)}: {LastLayerIndex}, {nameof(LayerHeightUmMagnified100Times)}: {LayerHeightUmMagnified100Times}, {nameof(BottomLayerCount)}: {BottomLayerCount}, {nameof(ExposureTimeMagnified100Times)}: {ExposureTimeMagnified100Times}, {nameof(BottomExposureTimeMagnified100Times)}: {BottomExposureTimeMagnified100Times}, {nameof(SupportDelayTimeMagnified100Times)}: {SupportDelayTimeMagnified100Times}, {nameof(BottomSupportDelayTimeMagnified100Times)}: {BottomSupportDelayTimeMagnified100Times}, {nameof(TransitionLayerCount)}: {TransitionLayerCount}, {nameof(TransitionType)}: {TransitionType}, {nameof(TransitionLayerIntervalTimeDifferenceMagnified100Times)}: {TransitionLayerIntervalTimeDifferenceMagnified100Times}, {nameof(WaitTimeAfterCureMagnified100Times)}: {WaitTimeAfterCureMagnified100Times}, {nameof(WaitTimeAfterLiftMagnified100Times)}: {WaitTimeAfterLiftMagnified100Times}, {nameof(WaitTimeBeforeCureMagnified100Times)}: {WaitTimeBeforeCureMagnified100Times}, {nameof(BottomLiftHeightSlowMagnified1000Times)}: {BottomLiftHeightSlowMagnified1000Times}, {nameof(BottomLiftHeightTotalMagnified1000Times)}: {BottomLiftHeightTotalMagnified1000Times}, {nameof(LiftHeightSlowMagnified1000Times)}: {LiftHeightSlowMagnified1000Times}, {nameof(LiftHeightTotalMagnified1000Times)}: {LiftHeightTotalMagnified1000Times}, {nameof(BottomRetractHeightSlowMagnified1000Times)}: {BottomRetractHeightSlowMagnified1000Times}, {nameof(BottomRetractHeightTotalMagnified1000Times)}: {BottomRetractHeightTotalMagnified1000Times}, {nameof(RetractHeightSlowMagnified1000Times)}: {RetractHeightSlowMagnified1000Times}, {nameof(RetractHeightTotalMagnified1000Times)}: {RetractHeightTotalMagnified1000Times}, {nameof(AccelerationType)}: {AccelerationType}, {nameof(BottomLiftSpeedStart)}: {BottomLiftSpeedStart}, {nameof(BottomLiftSpeedSlow)}: {BottomLiftSpeedSlow}, {nameof(BottomLiftSpeedFast)}: {BottomLiftSpeedFast}, {nameof(BottomLiftAccelerationChange)}: {BottomLiftAccelerationChange}, {nameof(LiftSpeedStart)}: {LiftSpeedStart}, {nameof(LiftSpeedSlow)}: {LiftSpeedSlow}, {nameof(LiftSpeedFast)}: {LiftSpeedFast}, {nameof(LiftAccelerationChange)}: {LiftAccelerationChange}, {nameof(BottomRetractSpeedStart)}: {BottomRetractSpeedStart}, {nameof(BottomRetractSpeedSlow)}: {BottomRetractSpeedSlow}, {nameof(BottomRetractSpeedFast)}: {BottomRetractSpeedFast}, {nameof(BottomRetractAccelerationChange)}: {BottomRetractAccelerationChange}, {nameof(RetractSpeedStart)}: {RetractSpeedStart}, {nameof(RetractSpeedSlow)}: {RetractSpeedSlow}, {nameof(RetractSpeedFast)}: {RetractSpeedFast}, {nameof(RetractAccelerationChange)}: {RetractAccelerationChange}, {nameof(BottomLiftSpeedEnd)}: {BottomLiftSpeedEnd}, {nameof(BottomLiftDecelerationChange)}: {BottomLiftDecelerationChange}, {nameof(LiftSpeedEnd)}: {LiftSpeedEnd}, {nameof(LiftDecelerationChange)}: {LiftDecelerationChange}, {nameof(BottomRetractSpeedEnd)}: {BottomRetractSpeedEnd}, {nameof(BottomRetractDecelerationChange)}: {BottomRetractDecelerationChange}, {nameof(RetractSpeedEnd)}: {RetractSpeedEnd}, {nameof(RetractDecelerationChange)}: {RetractDecelerationChange}, {nameof(BottomWaitTimeAfterCureMagnified100Times)}: {BottomWaitTimeAfterCureMagnified100Times}, {nameof(BottomWaitTimeAfterLiftMagnified100Times)}: {BottomWaitTimeAfterLiftMagnified100Times}, {nameof(BottomWaitTimeBeforeCureMagnified100Times)}: {BottomWaitTimeBeforeCureMagnified100Times}, {nameof(Reserved)}: {Reserved}, {nameof(ProtocolType)}: {ProtocolType}";
+ }
}
#endregion
#region LayerDef
- public class LayerDef
+ public class OSFLayerDef
{
- [Ignore] public LGSFile Parent { get; set; } = null!;
-
- [FieldOrder(0)]
- public uint DataSize { get; set; }
+ /// <summary>
+ /// OD OA begins, indicating that the model + support is included; the beginning of 0D 0B, indicating that the layer only has support data
+ /// </summary>
+ [FieldOrder(0)] [FieldEndianness(Endianness.Big)] public ushort Mark { get; set; } = 0x0D_0A;
- [FieldOrder(1)]
- [FieldLength(nameof(DataSize))]
- public byte[] EncodedRle { get; set; } = null!;
+ [FieldOrder(1)] [FieldEndianness(Endianness.Big)] public uint NumberOfPixels { get; set; }
+ [FieldOrder(2)] [FieldEndianness(Endianness.Big)] public ushort StartY { get; set; }
+ [Ignore] public byte[] EncodedRle { get; set; } = Array.Empty<byte>();
- public LayerDef() { }
+ public OSFLayerDef() { }
- public LayerDef(LGSFile parent)
+ public override string ToString()
{
- Parent = parent;
+ return $"{nameof(Mark)}: {Mark}, {nameof(NumberOfPixels)}: {NumberOfPixels}, {nameof(StartY)}: {StartY}";
}
- public unsafe byte[] Encode(Mat mat)
+ internal unsafe void EncodeImage(Mat mat)
{
List<byte> rawData = new();
- List<byte> chunk = new();
+ byte color = byte.MaxValue >> 1;
+ uint stride = 0;
+ var span = mat.GetBytePointer();
+ var imageLength = mat.GetLength();
- if (Parent.HeaderSettings.PrinterModel is 4000 or 4500)
+ void AddRep()
{
- CvInvoke.Rotate(mat, mat, RotateFlags.Rotate90Clockwise);
- }
+ switch (stride)
+ {
+ case 0:
+ return;
+ case 1:
+ color &= 0xfe;
+ break;
+ case > 1:
+ color |= 0x01;
+ break;
+ }
- var spanMat = mat.GetBytePointer();
- var imageLength = mat.GetLength();
+ rawData.Add(color);
- uint span = 0;
- byte lc = 0;
+ if (stride <= 1)
+ {
+ // no run needed
+ return;
+ }
- void addSpan(){
- chunk.Clear();
- for (; span > 0; span >>= 4) {
- chunk.Insert(0, (byte)((byte)(span & 0xf) | (lc & 0xf0)));
+ if (stride <= 0x7f)
+ {
+ rawData.Add((byte)stride);
+ return;
}
- rawData.AddRange(chunk.ToArray());
- }
- for (int i = 0; i < imageLength; i++)
- {
- byte c = (byte) (spanMat[i] & 0xf0);
-
- if (c == lc)
+ if (stride <= 0x3fff)
{
- span++;
+ rawData.Add((byte)((stride >> 8) | 0x80));
+ rawData.Add((byte)stride);
+ return;
}
- else
+
+ if (stride <= 0x1fffff)
{
- addSpan();
- span = 1;
+ rawData.Add((byte)((stride >> 16) | 0xc0));
+ rawData.Add((byte)(stride >> 8));
+ rawData.Add((byte)stride);
+ return;
}
- lc = c;
+ if (stride <= 0xfffffff)
+ {
+ rawData.Add((byte)((stride >> 24) | 0xe0));
+ rawData.Add((byte)(stride >> 16));
+ rawData.Add((byte)(stride >> 8));
+ rawData.Add((byte)stride);
+ }
}
- addSpan();
- EncodedRle = rawData.ToArray();
- DataSize = (uint) EncodedRle.Length;
- if (Parent.HeaderSettings.PrinterModel is 4000 or 4500)
+ for (int pixel = StartY * mat.GetRealStep(); pixel < imageLength; pixel++)
{
- CvInvoke.Rotate(mat, mat, RotateFlags.Rotate90CounterClockwise);
+ var grey = span[pixel];
+
+ if (grey == color)
+ {
+ stride++;
+ }
+ else
+ {
+ AddRep();
+ color = grey;
+ stride = 1;
+ }
}
- return EncodedRle;
+ EncodedRle = rawData.ToArray();
}
- public Mat Decode(bool consumeRle = true)
+ internal Mat DecodeImage(OSFFile parent)
{
- // lgs10/30 -------->
- // lgs120/4k From Y bottom to top Y
- var mat = EmguExtensions.InitMat(Parent.HeaderSettings.PrinterModel is 4000 or 4500 ? Parent.Resolution.Exchange() : Parent.Resolution);
- //var matSpan = mat.GetBytePointer();
- var imageLength = mat.GetLength();
-
- int pixelPos = 0;
+ var mat = parent.CreateMat();
- for (var i = 0; i < EncodedRle.Length; i++)
+ int pixel = (int)(StartY * parent.ResolutionX);
+ for (var n = 0; n < EncodedRle.Length; n++)
{
- var b = EncodedRle[i];
- byte colorNibble = (byte)(b >> 4);
- byte color = (byte)(colorNibble << 4 | colorNibble);
- int repeat = b & 0xf;
+ byte code = EncodedRle[n];
+ int stride = 1;
- while (i + 1 < EncodedRle.Length && (EncodedRle[i + 1] >> 4) == colorNibble)
+ if ((code & 0x01) == 0x01) // It's a run
{
- i++;
- repeat = (repeat << 4) | (EncodedRle[i] & 0xf);
+ code &= 0xfe; // Get the grey value
+ n++;
+
+ var slen = EncodedRle[n];
+
+ if ((slen & 0x80) == 0)
+ {
+ stride = slen;
+ }
+ else if ((slen & 0xc0) == 0x80)
+ {
+ stride = ((slen & 0x3f) << 8) + EncodedRle[n + 1];
+ n++;
+ }
+ else if ((slen & 0xe0) == 0xc0)
+ {
+ stride = ((slen & 0x1f) << 16) + (EncodedRle[n + 1] << 8) + EncodedRle[n + 2];
+ n += 2;
+ }
+ else if ((slen & 0xf0) == 0xe0)
+ {
+ stride = ((slen & 0xf) << 24) + (EncodedRle[n + 1] << 16) + (EncodedRle[n + 2] << 8) + EncodedRle[n + 3];
+ n += 3;
+ }
+ else
+ {
+ mat.Dispose();
+ throw new FileLoadException("Corrupted RLE data");
+ }
}
- if (pixelPos >= imageLength)
+ // Bit extend from 7-bit to 8-bit greymap
+ if (code != 0)
{
- throw new FileLoadException($"Too much buffer, expected: {imageLength}, got: {pixelPos}");
+ code = (byte)(code | 1);
}
- mat.FillSpan(ref pixelPos, repeat, color);
-
- //if (repeat <= 0) continue;
- /*while (repeat-- > 0)
- {
- matSpan[pixel++] = color;
- }*/
-
- }
-
- if (pixelPos != imageLength)
- {
- throw new FileLoadException($"Incomplete buffer, expected: {imageLength}, got: {pixelPos}");
- }
-
- if (consumeRle)
- EncodedRle = null!;
-
- if (Parent.HeaderSettings.PrinterModel is 4000 or 4500)
- {
- CvInvoke.Rotate(mat, mat, RotateFlags.Rotate90CounterClockwise);
+ mat.FillSpan(ref pixel, stride, code);
}
return mat;
@@ -263,28 +332,50 @@ public class OSFFile : FileFormat
#region Properties
- public Header HeaderSettings { get; protected internal set; } = new();
+ public OSFHeader Header { get; protected internal set; } = new();
+ public OSFSettings Settings { get; protected internal set; } = new();
public override FileFormatType FileType => FileFormatType.Binary;
public override FileExtension[] FileExtensions { get; } = {
- new (typeof(OSFFile), "osf", "Vlare Open File Format"),
+ new (typeof(OSFFile), "osf", "Vlare Open File Format (OSF)"),
};
public override PrintParameterModifier[]? PrintParameterModifiers { get; } =
{
PrintParameterModifier.BottomLayerCount,
+ PrintParameterModifier.TransitionLayerCount,
- PrintParameterModifier.BottomLightOffDelay,
- PrintParameterModifier.LightOffDelay,
-
+ PrintParameterModifier.BottomWaitTimeBeforeCure,
+ PrintParameterModifier.WaitTimeBeforeCure,
+
PrintParameterModifier.BottomExposureTime,
PrintParameterModifier.ExposureTime,
+ PrintParameterModifier.BottomWaitTimeAfterCure,
+ PrintParameterModifier.WaitTimeAfterCure,
+
PrintParameterModifier.BottomLiftHeight,
PrintParameterModifier.BottomLiftSpeed,
PrintParameterModifier.LiftHeight,
PrintParameterModifier.LiftSpeed,
-
+
+ PrintParameterModifier.BottomLiftHeight2,
+ PrintParameterModifier.BottomLiftSpeed2,
+ PrintParameterModifier.LiftHeight2,
+ PrintParameterModifier.LiftSpeed2,
+
+ PrintParameterModifier.BottomWaitTimeAfterLift,
+ PrintParameterModifier.WaitTimeAfterLift,
+
+ PrintParameterModifier.BottomRetractSpeed,
+ PrintParameterModifier.RetractSpeed,
+ PrintParameterModifier.BottomRetractHeight2,
+ PrintParameterModifier.BottomRetractSpeed2,
+ PrintParameterModifier.RetractHeight2,
+ PrintParameterModifier.RetractSpeed2,
+
+ PrintParameterModifier.BottomLightPWM,
+ PrintParameterModifier.LightPWM,
};
public override Size[]? ThumbnailsOriginalSize { get; } =
@@ -295,22 +386,36 @@ public class OSFFile : FileFormat
new(404, 240),
};
+ public override uint[] AvailableVersions { get; } = { 4 };
+
+ public override uint DefaultVersion => USED_VERSION;
+
+ public override uint Version
+ {
+ get => Header.Version;
+ set
+ {
+ base.Version = value;
+ Header.Version = (ushort) base.Version;
+ }
+ }
+
public override uint ResolutionX
{
- get => HeaderSettings.ResolutionX;
+ get => Settings.ResolutionX;
set
{
- HeaderSettings.ResolutionX = (ushort) value;
+ Settings.ResolutionX = (ushort) value;
RaisePropertyChanged();
}
}
public override uint ResolutionY
{
- get => (uint)HeaderSettings.ResolutionY;
+ get => Settings.ResolutionY;
set
{
- HeaderSettings.ResolutionY = (ushort)value;
+ Settings.ResolutionY = (ushort)value;
RaisePropertyChanged();
}
}
@@ -319,7 +424,7 @@ public class OSFFile : FileFormat
public override FlipDirection DisplayMirror
{
- get => HeaderSettings.Mirror switch
+ get => Settings.Mirror switch
{
1 => FlipDirection.Horizontally,
2 => FlipDirection.Vertically,
@@ -328,7 +433,7 @@ public class OSFFile : FileFormat
};
set
{
- HeaderSettings.Mirror = value switch
+ Settings.Mirror = value switch
{
FlipDirection.None => 0,
FlipDirection.Horizontally => 1,
@@ -341,10 +446,10 @@ public class OSFFile : FileFormat
public override float LayerHeight
{
- get => Layer.RoundHeight(HeaderSettings.LayerHeightUmMagnified100Times / 100000f);
+ get => Layer.RoundHeight(Settings.LayerHeightUmMagnified100Times.Value / 1000_00f);
set
{
- HeaderSettings.LayerHeightUmMagnified100Times = (ushort)(value * 100000);
+ Settings.LayerHeightUmMagnified100Times.Value = (ushort)(value * 1000_00f);
RaisePropertyChanged();
}
}
@@ -354,197 +459,390 @@ public class OSFFile : FileFormat
get => base.LayerCount;
set
{
- base.LayerCount = HeaderSettings.LayerCount = base.LayerCount;
- HeaderSettings.LastLayerIndex = HeaderSettings.LayerCount - 1;
+ base.LayerCount = Settings.LayerCount = base.LayerCount;
+ Settings.LastLayerIndex = Settings.LayerCount - 1;
}
}
public override ushort BottomLayerCount
{
- get => HeaderSettings.BottomLayerCount;
+ get => Settings.BottomLayerCount;
set
{
- HeaderSettings.BottomLayerCount = (byte)value;
+ Settings.BottomLayerCount = (byte)value;
base.BottomLayerCount = value;
}
}
- /*public override float BottomLightOffDelay
+ public override TransitionLayerTypes TransitionLayerType => TransitionLayerTypes.Software;
+
+ public override ushort TransitionLayerCount
+ {
+ get => Settings.TransitionLayerCount;
+ set => base.TransitionLayerCount = Settings.TransitionLayerCount = (byte)Math.Min(byte.MaxValue, Math.Min(value, MaximumPossibleTransitionLayerCount));
+ }
+
+ public override float BottomLightOffDelay => BottomWaitTimeBeforeCure;
+
+ public override float LightOffDelay => WaitTimeBeforeCure;
+
+ public override float BottomWaitTimeBeforeCure
{
- get => TimeConverter.MillisecondsToSeconds(HeaderSettings.BottomLightOffDelayMs);
+ get => (float)Math.Round(Settings.BottomWaitTimeBeforeCureMagnified100Times / 100f, 2);
set
{
- HeaderSettings.BottomLightOffDelayMs = TimeConverter.SecondsToMilliseconds(value);
- base.BottomLightOffDelay = value;
+ Settings.BottomWaitTimeBeforeCureMagnified100Times = (ushort) (value * 100);
+ base.BottomWaitTimeBeforeCure = (float)Math.Round(value, 2);
}
}
- public override float LightOffDelay
+ public override float WaitTimeBeforeCure
{
- get => TimeConverter.MillisecondsToSeconds(HeaderSettings.LightOffDelayMs);
+ get => (float)Math.Round(Settings.WaitTimeBeforeCureMagnified100Times.Value / 100f, 2);
set
{
- HeaderSettings.LightOffDelayMs = TimeConverter.SecondsToMilliseconds(value);
- base.LightOffDelay = value;
+ Settings.WaitTimeBeforeCureMagnified100Times.Value = (uint)(value * 100);
+ base.WaitTimeBeforeCure = (float)Math.Round(value, 2);
}
}
- public override float BottomWaitTimeBeforeCure
+ public override float BottomExposureTime
{
- get => base.BottomWaitTimeBeforeCure;
+ get => (float)Math.Round(Settings.BottomExposureTimeMagnified100Times.Value / 100f, 2);
set
{
- SetBottomLightOffDelay(value);
- base.BottomWaitTimeBeforeCure = value;
+ Settings.BottomExposureTimeMagnified100Times.Value = (uint)(value * 100);
+ base.BottomExposureTime = (float)Math.Round(value, 2);
}
}
- public override float WaitTimeBeforeCure
+ public override float ExposureTime
{
- get => base.WaitTimeBeforeCure;
+ get => (float)Math.Round(Settings.ExposureTimeMagnified100Times.Value / 100f, 2);
set
{
- SetNormalLightOffDelay(value);
- base.WaitTimeBeforeCure = value;
+ Settings.ExposureTimeMagnified100Times.Value = (uint)(value * 100);
+ base.ExposureTime = (float)Math.Round(value, 2);
}
}
- public override float BottomExposureTime
+ public override float BottomWaitTimeAfterCure
{
- get => TimeConverter.MillisecondsToSeconds(HeaderSettings.BottomExposureTimeMs);
+ get => (float)Math.Round(Settings.BottomWaitTimeAfterCureMagnified100Times / 100f, 2);
set
{
- HeaderSettings.BottomExposureTimeMs = TimeConverter.SecondsToMilliseconds(value);
- base.BottomExposureTime = value;
+ Settings.BottomWaitTimeAfterCureMagnified100Times = (ushort)(value * 100);
+ base.BottomWaitTimeAfterCure = (float)Math.Round(value, 2);
}
}
- public override float ExposureTime
+ public override float WaitTimeAfterCure
{
- get => TimeConverter.MillisecondsToSeconds(HeaderSettings.ExposureTimeMs);
+ get => (float)Math.Round(Settings.WaitTimeAfterCureMagnified100Times.Value / 100f, 2);
set
{
- HeaderSettings.ExposureTimeMs = TimeConverter.SecondsToMilliseconds(value);
- base.ExposureTime = value;
+ Settings.WaitTimeAfterCureMagnified100Times.Value = (uint)(value * 100);
+ base.WaitTimeAfterCure = (float)Math.Round(value, 2);
}
}
-
+
public override float BottomLiftHeight
{
- get => HeaderSettings.BottomLiftHeight;
- set => base.BottomLiftHeight = HeaderSettings.BottomLiftHeight = value;
+ get => (float)Math.Round(Settings.BottomLiftHeightSlowMagnified1000Times.Value / 1000f, 2);
+ set
+ {
+ value = (float)Math.Round(value, 2);
+ Settings.BottomLiftHeightTotalMagnified1000Times.Value -= Settings.BottomLiftHeightSlowMagnified1000Times.Value;
+ Settings.BottomLiftHeightSlowMagnified1000Times.Value = (uint)(value * 1000);
+ Settings.BottomLiftHeightTotalMagnified1000Times.Value += Settings.BottomLiftHeightSlowMagnified1000Times.Value;
+ base.BottomLiftHeight = value;
+ }
}
public override float LiftHeight
{
- get => HeaderSettings.LiftHeight;
- set => base.LiftHeight = HeaderSettings.LiftHeight = value;
+ get => (float)Math.Round(Settings.LiftHeightSlowMagnified1000Times.Value / 1000f, 2);
+ set
+ {
+ value = (float)Math.Round(value, 2);
+ Settings.LiftHeightTotalMagnified1000Times.Value -= Settings.LiftHeightSlowMagnified1000Times.Value;
+ Settings.LiftHeightSlowMagnified1000Times.Value = (uint)(value * 1000);
+ Settings.LiftHeightTotalMagnified1000Times.Value += Settings.LiftHeightSlowMagnified1000Times.Value;
+ base.LiftHeight = value;
+ }
}
public override float BottomLiftSpeed
{
- get => HeaderSettings.BottomLiftSpeed;
- set => base.BottomLiftSpeed = HeaderSettings.BottomLiftSpeed = HeaderSettings.BottomLiftSpeed_ = value;
+ get => Settings.BottomLiftSpeedSlow;
+ set => base.BottomLiftSpeed = Settings.BottomLiftSpeedSlow = (ushort)value;
}
public override float LiftSpeed
{
- get => HeaderSettings.LiftSpeed;
- set => base.LiftSpeed = HeaderSettings.LiftSpeed = HeaderSettings.LiftSpeed_ = value;
+ get => Settings.LiftSpeedSlow;
+ set => base.LiftSpeed = Settings.LiftSpeedSlow = (ushort)value;
}
- */
- public override float BottomRetractSpeed => RetractSpeed;
- public override float RetractSpeed => LiftSpeed;
+ public override float BottomLiftHeight2
+ {
+ get => (float)Math.Max(0, Math.Round((Settings.BottomLiftHeightTotalMagnified1000Times - Settings.BottomLiftHeightSlowMagnified1000Times) / 1000f, 2));
+ set
+ {
+ value = (float)Math.Round(value, 2);
+ Settings.BottomLiftHeightTotalMagnified1000Times.Value = Settings.BottomLiftHeightSlowMagnified1000Times.Value + (uint)(value * 1000);
+ base.BottomLiftHeight2 = value;
+ }
+ }
+ public override float BottomLiftSpeed2
+ {
+ get =>Settings.BottomLiftSpeedFast;
+ set => base.BottomLiftSpeed2 = Settings.BottomLiftSpeedFast = (ushort) value;
+ }
- public override object[] Configs => new object[] { HeaderSettings };
+ public override float LiftHeight2
+ {
+ get => (float)Math.Max(0, Math.Round((Settings.LiftHeightTotalMagnified1000Times - Settings.LiftHeightSlowMagnified1000Times) / 1000f, 2));
+ set
+ {
+ value = (float)Math.Round(value, 2);
+ Settings.LiftHeightTotalMagnified1000Times.Value = Settings.LiftHeightSlowMagnified1000Times.Value + (uint)(value * 1000);
+ base.LiftHeight2 = value;
+ }
+ }
- #endregion
+ public override float LiftSpeed2
+ {
+ get => Settings.LiftSpeedFast;
+ set => base.LiftSpeed2 = Settings.LiftSpeedFast = (ushort)value;
+ }
- #region Constructors
- public OSFFile()
+ public override float BottomWaitTimeAfterLift {
+ get => (float)Math.Round(Settings.BottomWaitTimeAfterLiftMagnified100Times / 100f, 2);
+ set
+ {
+ Settings.BottomWaitTimeAfterLiftMagnified100Times = (ushort)(value * 100);
+ base.BottomWaitTimeAfterLift = (float)Math.Round(value, 2);
+ }
+ }
+
+ public override float WaitTimeAfterLift
+ {
+ get => (float)Math.Round(Settings.WaitTimeAfterLiftMagnified100Times.Value / 100f, 2);
+ set
+ {
+ Settings.WaitTimeAfterLiftMagnified100Times.Value = (uint)(value * 100);
+ base.WaitTimeAfterLift = (float)Math.Round(value, 2);
+ }
+ }
+
+ public override float BottomRetractSpeed
+ {
+ get => Settings.BottomRetractSpeedFast;
+ set => base.BottomRetractSpeed = Settings.BottomRetractSpeedFast = (ushort)value;
+ }
+
+ public override float RetractSpeed
+ {
+ get => Settings.RetractSpeedFast;
+ set => base.RetractSpeed = Settings.RetractSpeedFast = (ushort)value;
+ }
+
+ public override float BottomRetractHeight2
+ {
+ get => (float)Math.Round(Settings.BottomRetractHeightSlowMagnified1000Times.Value / 1000f, 2);
+ set
+ {
+ value = Math.Clamp((float)Math.Round(value, 2), 0, BottomRetractHeightTotal);
+ Settings.BottomRetractHeightSlowMagnified1000Times.Value = (uint)(value * 1000);
+ Settings.BottomRetractHeightTotalMagnified1000Times.Value = (uint)(BottomRetractHeightTotal * 1000);
+ base.BottomRetractHeight2 = value;
+ }
+ }
+
+ public override float BottomRetractSpeed2
{
+ get => Settings.BottomRetractSpeedSlow;
+ set => base.BottomRetractSpeed2 = Settings.BottomRetractSpeedSlow = (ushort)value;
}
+
+ public override float RetractHeight2
+ {
+ get => (float)Math.Round(Settings.RetractHeightSlowMagnified1000Times.Value / 1000f, 2);
+ set
+ {
+ value = Math.Clamp((float)Math.Round(value, 2), 0, RetractHeightTotal);
+ Settings.RetractHeightSlowMagnified1000Times.Value = (uint)(value * 1000);
+ Settings.RetractHeightTotalMagnified1000Times.Value = (uint)(RetractHeightTotal * 1000);
+ base.RetractHeight2 = value;
+ }
+ }
+
+ public override float RetractSpeed2
+ {
+ get => Settings.RetractSpeedSlow;
+ set => base.RetractSpeed2 = Settings.RetractSpeedSlow = (ushort)value;
+ }
+
+ public override byte BottomLightPWM
+ {
+ get => Settings.BottomLightPWM;
+ set => base.BottomLightPWM = Settings.BottomLightPWM = value;
+ }
+
+ public override byte LightPWM
+ {
+ get => Settings.LightPWM;
+ set => base.LightPWM = Settings.LightPWM = value;
+ }
+
+
+ public override object[] Configs => new object[] { Settings };
+
#endregion
- #region Methods
+ #region Constructors
+ public OSFFile() { }
+ #endregion
+ #region Methods
+
protected override void EncodeInternally(OperationProgress progress)
{
using var outputFile = new FileStream(TemporaryOutputFileFullPath, FileMode.Create, FileAccess.Write);
- outputFile.WriteSerialize(HeaderSettings);
- outputFile.WriteBytes(EncodeImage(DATATYPE_RGB565_BE, Thumbnails[0]!));
+
+ Settings.PixelUmMagnified100Times = (ushort)(PixelSizeMicronsMax * 100);
+
+ Header.HeaderLength = (uint) (Helpers.Serializer.SizeOf(Header) + Helpers.Serializer.SizeOf(Settings) + 3 * 4);
+
+ var previews = new[]
+ {
+ Array.Empty<byte>(),
+ Array.Empty<byte>(),
+ Array.Empty<byte>(),
+ Array.Empty<byte>()
+ };
+
+ for (var i = 0; i < previews.Length; i++)
+ {
+ if (Thumbnails[i] is null) continue;
+ previews[i] = EncodeImage(DATATYPE_RGB565, Thumbnails[i]!);
+ Header.HeaderLength += (uint)previews[i].Length;
+ }
+
+ outputFile.WriteSerialize(Header);
+
+ for (var i = 0; i < previews.Length; i++)
+ {
+ outputFile.WriteSerialize(new UInt24BigEndian((uint) previews[i].Length));
+ outputFile.WriteBytes(previews[i]);
+ }
+
+ outputFile.WriteSerialize(Settings);
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
- var layerData = new LayerDef[LayerCount];
+ var layerDef = new OSFLayerDef[LayerCount];
foreach (var batch in BatchLayersIndexes())
{
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
{
- /*using (var mat = this[layerIndex].LayerMat)
+ var layer = this[layerIndex];
+
+ using (var mat = layer.LayerMat)
{
- layerData[layerIndex] = new LayerDef(this);
- layerData[layerIndex].Encode(mat);
- }*/
+ layerDef[layerIndex] = new OSFLayerDef
+ {
+ NumberOfPixels = layer.NonZeroPixelCount,
+ StartY = (ushort)layer.BoundingRectangle.Y,
+ };
+ layerDef[layerIndex].EncodeImage(mat);
+ }
progress.LockAndIncrement();
});
foreach (var layerIndex in batch)
{
progress.ThrowIfCancellationRequested();
- outputFile.WriteSerialize(layerData[layerIndex]);
- layerData[layerIndex].EncodedRle = null!; // Free this
+ outputFile.WriteSerialize(layerDef[layerIndex]);
+ outputFile.WriteBytes(layerDef[layerIndex].EncodedRle);
+ layerDef[layerIndex].EncodedRle = null!; // Free this
}
}
- progress.ItemName = "Saving layers";
- progress.ProcessedItems = 0;
-
- for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
- {
- progress.ThrowIfCancellationRequested();
- outputFile.WriteSerialize(layerData[layerIndex]);
- progress++;
- }
-
Debug.WriteLine("Encode Results:");
- Debug.WriteLine(HeaderSettings);
+ Debug.WriteLine(Header);
+ Debug.WriteLine(Settings);
Debug.WriteLine("-End-");
}
protected override void DecodeInternally(OperationProgress progress)
{
using var inputFile = new FileStream(FileFullPath!, FileMode.Open, FileAccess.Read);
- HeaderSettings = Helpers.Deserialize<Header>(inputFile);
+ Header = Helpers.Deserialize<OSFHeader>(inputFile);
+
+ Debug.WriteLine(Header);
+
+ for (byte i = 0; i < ThumbnailsOriginalSize!.Length; i++)
+ {
+ var previewSize = Helpers.Deserialize<UInt24BigEndian>(inputFile);
+ var previewData = inputFile.ReadBytes(previewSize.Value);
+ Thumbnails[i] = DecodeImage(DATATYPE_RGB565, previewData, ThumbnailsOriginalSize[i]);
+ }
+
- //var previewSize = HeaderSettings.PreviewSizeX * HeaderSettings.PreviewSizeY * 2;
- //var previewData = inputFile.ReadBytes(previewSize);
- //Thumbnails[0] = DecodeImage(DATATYPE_RGB565_BE, previewData, HeaderSettings.PreviewSizeX, HeaderSettings.PreviewSizeY);
+ Settings = Helpers.Deserialize<OSFSettings>(inputFile);
+ Debug.WriteLine(Settings);
-
- Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
- var layerData = new LayerDef[LayerCount];
+ Display = new SizeF(
+ ResolutionX * (Settings.PixelUmMagnified100Times / 100_000f),
+ ResolutionY * (Settings.PixelUmMagnified100Times / 100_000f)
+ );
+
+ Init(Settings.LayerCount, DecodeType == FileDecodeType.Partial);
+
if (DecodeType == FileDecodeType.Full)
{
+ inputFile.Seek(Header.HeaderLength, SeekOrigin.Begin);
+ var layerDef = new OSFLayerDef[LayerCount];
+ int buffer;
+ var rle = new List<byte>();
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
foreach (var batch in BatchLayersIndexes())
{
foreach (var layerIndex in batch)
{
progress.ThrowIfCancellationRequested();
-
- layerData[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
+ layerDef[layerIndex] = Helpers.Deserialize<OSFLayerDef>(inputFile);
+ while ((buffer = inputFile.ReadByte()) > -1)
+ {
+ if (buffer == 0x0D)
+ {
+ if ((buffer = inputFile.ReadByte()) >= -1 && buffer is 0x0A or 0x0B)
+ {
+ inputFile.Seek(-2, SeekOrigin.Current);
+ break;
+ }
+
+ rle.Add(0x0D);
+ }
+
+ rle.Add((byte)buffer);
+ }
+
+ layerDef[layerIndex].EncodedRle = rle.ToArray();
+ rle.Clear();
}
Parallel.ForEach(batch, CoreSettings.GetParallelOptions(progress), layerIndex =>
{
- using var mat = layerData[layerIndex].Decode();
+ using var mat = layerDef[layerIndex].DecodeImage(this);
_layers[layerIndex] = new Layer((uint)layerIndex, mat, this);
+ layerDef[layerIndex].EncodedRle = null!;
progress.LockAndIncrement();
});
@@ -557,8 +855,8 @@ public class OSFFile : FileFormat
protected override void PartialSaveInternally(OperationProgress progress)
{
using var outputFile = new FileStream(TemporaryOutputFileFullPath, FileMode.Open, FileAccess.Write);
- outputFile.Seek(0, SeekOrigin.Begin);
- Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
+ outputFile.Seek(Header.HeaderLength - Helpers.Serializer.SizeOf(Settings), SeekOrigin.Begin);
+ Helpers.SerializeWriteFileStream(outputFile, Settings);
}
#endregion
diff --git a/UVtools.Core/FileFormats/OSLAFile.cs b/UVtools.Core/FileFormats/OSLAFile.cs
index a195bb8..47e3342 100644
--- a/UVtools.Core/FileFormats/OSLAFile.cs
+++ b/UVtools.Core/FileFormats/OSLAFile.cs
@@ -248,7 +248,7 @@ public class OSLAFile : FileFormat
public override FileFormatType FileType => FileFormatType.Binary;
public override FileExtension[] FileExtensions { get; } = {
- new (typeof(OSLAFile), "osla", "Open SLA universal binary file"),
+ new (typeof(OSLAFile), "osla", "Open SLA universal binary file (OSLA)"),
//new ("omsla", "Open mSLA universal binary file"),
//new ("odlp", "Open DLP universal binary file"),
};
diff --git a/UVtools.Core/FileFormats/UVJFile.cs b/UVtools.Core/FileFormats/UVJFile.cs
index ebd7dc4..650a141 100644
--- a/UVtools.Core/FileFormats/UVJFile.cs
+++ b/UVtools.Core/FileFormats/UVJFile.cs
@@ -177,7 +177,7 @@ public class UVJFile : FileFormat
public override FileFormatType FileType => FileFormatType.Archive;
public override FileExtension[] FileExtensions { get; } = {
- new(typeof(UVJFile), "uvj", "UVJ")
+ new(typeof(UVJFile), "uvj", "Vendor-neutral format (UVJ)")
};
public override PrintParameterModifier[]? PrintParameterModifiers { get; } = {
diff --git a/UVtools.Core/FileFormats/VDTFile.cs b/UVtools.Core/FileFormats/VDTFile.cs
index b82145b..f63a821 100644
--- a/UVtools.Core/FileFormats/VDTFile.cs
+++ b/UVtools.Core/FileFormats/VDTFile.cs
@@ -198,7 +198,7 @@ public class VDTFile : FileFormat
public override FileFormatType FileType => FileFormatType.Archive;
public override FileExtension[] FileExtensions { get; } = {
- new(typeof(VDTFile), "vdt", "Voxeldance Tango VDT")
+ new(typeof(VDTFile), "vdt", "Voxeldance Tango (VDT)")
};
public override PrintParameterModifier[]? PrintParameterModifiers { get; } = {
diff --git a/UVtools.Core/GCode/GCodeBuilder.cs b/UVtools.Core/GCode/GCodeBuilder.cs
index 04b0fe6..382a60e 100644
--- a/UVtools.Core/GCode/GCodeBuilder.cs
+++ b/UVtools.Core/GCode/GCodeBuilder.cs
@@ -26,6 +26,20 @@ namespace UVtools.Core.GCode;
public class GCodeBuilder : BindableBase
{
+ #region Events
+ public event EventHandler? BeforeRebuildGCode;
+ protected virtual void OnBeforeRebuildGCode()
+ {
+ BeforeRebuildGCode?.Invoke(this, EventArgs.Empty);
+ }
+
+ public event EventHandler? AfterRebuildGCode;
+ protected virtual void OnAfterRebuildGCode()
+ {
+ AfterRebuildGCode?.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
#region Commands
public GCodeCommand CommandUnitsMillimetersG21 { get; } = new("G21", null, "Set units to be mm");
@@ -42,6 +56,7 @@ public class GCodeBuilder : BindableBase
public GCodeCommand CommandSyncMovements { get; } = new("G4", "P0", "Sync movements", false);
+ public GCodeCommand CommandWaitSyncDelay { get; } = new("G4", "P0{0}", "Sync movement", false);
public GCodeCommand CommandWaitG4 { get; } = new("G4", "P{0}", "Delay");
public GCodeCommand CommandShowImageM6054 = new("M6054", "\"{0}\"", "Show image");
@@ -98,6 +113,20 @@ public class GCodeBuilder : BindableBase
LayerIndex0Started,
LayerIndex1Started,
}
+
+ public enum GCodeShowImagePositions : byte
+ {
+ /// <summary>
+ /// Show image at start of each layer block commands
+ /// </summary>
+ FirstLine,
+
+ /// <summary>
+ /// Show image just before exposing / turning LED ON
+ /// </summary>
+ WhenRequired
+ }
+
#endregion
#region Members
@@ -108,13 +137,13 @@ public class GCodeBuilder : BindableBase
private GCodeTimeUnits _gCodeTimeUnit = GCodeTimeUnits.Milliseconds;
private GCodeSpeedUnits _gCodeSpeedUnit = GCodeSpeedUnits.MillimetersPerMinute;
private GCodeShowImageTypes _gCodeShowImageType = GCodeShowImageTypes.FilenamePng1Started;
- private bool _syncMovementsWithDelay;
private bool _useTailComma = true;
private bool _useComments = true;
private ushort _maxLedPower = byte.MaxValue;
private uint _lineCount;
private GCodeMoveCommands _layerMoveCommand;
private GCodeMoveCommands _endGCodeMoveCommand;
+ private GCodeShowImagePositions _gCodeShowImagePosition = GCodeShowImagePositions.FirstLine;
#endregion
@@ -144,6 +173,12 @@ public class GCodeBuilder : BindableBase
set => RaiseAndSetIfChanged(ref _gCodeShowImageType, value);
}
+ public GCodeShowImagePositions GCodeShowImagePosition
+ {
+ get => _gCodeShowImagePosition;
+ set => RaiseAndSetIfChanged(ref _gCodeShowImagePosition, value);
+ }
+
public GCodeMoveCommands LayerMoveCommand
{
get => _layerMoveCommand;
@@ -156,12 +191,6 @@ public class GCodeBuilder : BindableBase
set => RaiseAndSetIfChanged(ref _endGCodeMoveCommand, value);
}
- public bool SyncMovementsWithDelay
- {
- get => _syncMovementsWithDelay;
- set => RaiseAndSetIfChanged(ref _syncMovementsWithDelay, value);
- }
-
public bool UseTailComma
{
get => _useTailComma;
@@ -183,14 +212,12 @@ public class GCodeBuilder : BindableBase
public string BeginStartGCodeComments { get; set; } = ";START_GCODE_BEGIN";
public string EndStartGCodeComments { get; set; } = ";END_GCODE_BEGIN";
- public string BeginLayerComments { get; set; } = ";LAYER_START:{0}" + Environment.NewLine +
- ";PositionZ:{1}mm";
+ public string BeginLayerComments { get; set; } = $";LAYER_START:{{0}}{Environment.NewLine};PositionZ:{{1}}mm";
public string EndLayerComments { get; set; } = ";LAYER_END";
public string BeginEndGCodeComments { get; set; } = ";START_GCODE_END";
- public string EndEndGCodeComments { get; set; } = ";END_GCODE_END" + Environment.NewLine +
- ";<Completed>";
+ public string EndEndGCodeComments { get; set; } = $";END_GCODE_END{Environment.NewLine};<Completed>";
public uint LineCount
{
@@ -373,12 +400,12 @@ public class GCodeBuilder : BindableBase
else
AppendMoveG1(finalRaiseZPosition, ConvertFromMillimetersPerMinute(slicerFile.MaximumSpeed));
- if (_syncMovementsWithDelay)
+ if (CommandWaitSyncDelay.Enabled)
{
var seconds = OperationCalculator.LightOffDelayC.CalculateSecondsLiftOnly(
finalRaiseZPositionRelative + lastLiftHeight, slicerFile.MaximumSpeed, 0.75f);
var time = ConvertFromSeconds(seconds);
- if (seconds > 0) AppendWaitG4($"0{time}", "Sync movement");
+ if (seconds > 0) AppendWaitSyncDelay(time);
}
AppendSyncMovements();
@@ -401,11 +428,11 @@ public class GCodeBuilder : BindableBase
else
AppendMoveG1(raiseZ, feedRate);
- if (_syncMovementsWithDelay)
+ if (CommandWaitSyncDelay.Enabled)
{
var seconds = OperationCalculator.LightOffDelayC.CalculateSecondsLiftOnly(absRaiseZ, rawSpeed, 0.75f);
var time = ConvertFromSeconds(seconds);
- AppendWaitG4($"0{time}", "Sync movement");
+ AppendWaitSyncDelay(time);
}
}
@@ -495,11 +522,11 @@ public class GCodeBuilder : BindableBase
AppendLineOverrideComment(CommandMoveG0, $"Z Lift ({i+1})", lifts[i].z, lifts[i].feedrate); // Z Lift
}
- if (_syncMovementsWithDelay && layer is not null)
+ if (CommandWaitSyncDelay.Enabled && layer is not null)
{
var seconds = OperationCalculator.LightOffDelayC.CalculateSecondsLiftOnly(layer, 0.75f);
var time = ConvertFromSeconds(seconds);
- AppendWaitG4($"0{time}", "Sync movement");
+ AppendWaitSyncDelay(time);
}
AppendSyncMovements();
@@ -517,11 +544,11 @@ public class GCodeBuilder : BindableBase
AppendLineOverrideComment(CommandMoveG0, $"Retract ({i+1})", retracts[i].z, retracts[i].feedrate);
}
- if (_syncMovementsWithDelay && layer is not null)
+ if (CommandWaitSyncDelay.Enabled && layer is not null)
{
var seconds = OperationCalculator.LightOffDelayC.CalculateSecondsLiftOnly(layer.RetractHeight, layer.RetractSpeed, layer.RetractHeight2, layer.RetractSpeed2, 0.75f);
var time = ConvertFromSeconds(seconds);
- AppendWaitG4($"0{time}", "Sync movement");
+ AppendWaitSyncDelay(time);
}
AppendSyncMovements();
@@ -556,11 +583,11 @@ public class GCodeBuilder : BindableBase
AppendLineOverrideComment(CommandMoveG1, $"Z Lift ({i+1})", lifts[i].z, lifts[i].feedrate); // Z Lift
}
- if (_syncMovementsWithDelay && layer is not null)
+ if (CommandWaitSyncDelay.Enabled && layer is not null)
{
var seconds = OperationCalculator.LightOffDelayC.CalculateSecondsLiftOnly(layer, 0.75f);
var time = ConvertFromSeconds(seconds);
- AppendWaitG4($"0{time}", "Sync movement");
+ AppendWaitSyncDelay(time);
}
AppendSyncMovements();
@@ -578,11 +605,11 @@ public class GCodeBuilder : BindableBase
AppendLineOverrideComment(CommandMoveG1, $"Retract ({i+1})", retracts[i].z, retracts[i].feedrate);
}
- if (_syncMovementsWithDelay && layer is not null)
+ if (CommandWaitSyncDelay.Enabled && layer is not null)
{
var seconds = OperationCalculator.LightOffDelayC.CalculateSecondsLiftOnly(layer.RetractHeight, layer.RetractSpeed, layer.RetractHeight2, layer.RetractSpeed2, 0.75f);
var time = ConvertFromSeconds(seconds);
- AppendWaitG4($"0{time}", "Sync movement");
+ AppendWaitSyncDelay(time);
}
AppendSyncMovements();
@@ -601,6 +628,19 @@ public class GCodeBuilder : BindableBase
new List<(float, float)> { new(downZ, downFeedrate) },
waitAfterLift, waitAfterRetract, layer);
+ public void AppendWaitSyncDelay(float time, string? comment = null)
+ {
+ if (time < 0) return;
+ AppendLineOverrideComment(CommandWaitSyncDelay, comment, time);
+ }
+
+ public void AppendWaitSyncDelay(string timeStr, string? comment = null)
+ {
+ if (!float.TryParse(timeStr, out var time)) return;
+ if (time < 0) return;
+ AppendLineOverrideComment(CommandWaitSyncDelay, comment, timeStr);
+ }
+
public void AppendWaitG4(float time, string? comment = null)
{
if (time < 0) return;
@@ -668,6 +708,8 @@ public class GCodeBuilder : BindableBase
public void RebuildGCode(FileFormat slicerFile, StringBuilder? header) => RebuildGCode(slicerFile, header?.ToString());
public void RebuildGCode(FileFormat slicerFile, string? header = null)
{
+ OnBeforeRebuildGCode();
+
Clear();
AppendUVtools();
@@ -752,7 +794,10 @@ public class GCodeBuilder : BindableBase
//if (layer.CanExpose)
//{ Dont check this for compability
- AppendShowImageM6054(GetShowImageString(layerIndex));
+ if (_gCodeShowImagePosition == GCodeShowImagePositions.FirstLine)
+ {
+ AppendShowImageM6054(GetShowImageString(layerIndex));
+ }
//}
if (liftHeightTotal > 0 && Layer.RoundHeight(liftHeightTotal + layer.PositionZ) > layer.PositionZ)
@@ -774,6 +819,10 @@ public class GCodeBuilder : BindableBase
}
AppendWaitG4(waitBeforeCure, "Wait before cure"); // Safer to parse if present
+ if (_gCodeShowImagePosition == GCodeShowImagePositions.WhenRequired && layer.CanExpose)
+ {
+ AppendShowImageM6054(GetShowImageString(layerIndex));
+ }
AppendExposure(exposureTime, pwmValue);
if(waitAfterCure > 0) AppendWaitG4(waitAfterCure, "Wait after cure");
@@ -784,6 +833,7 @@ public class GCodeBuilder : BindableBase
}
AppendEndGCode(slicerFile);
+ OnAfterRebuildGCode();
}
public void RebuildGCode(FileFormat slicerFile, object[]? configs, string separator = ":")
@@ -879,6 +929,23 @@ public class GCodeBuilder : BindableBase
Match match;
+ if (line[0] == ';')
+ {
+ match = Regex.Match(line, @"^;.*(layer\s+|layer:\s*|LAYER_START:\s*)(\d+)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
+ if (match.Success && match.Groups.Count > 2 && uint.TryParse(match.Groups[2].Value, out var layerIndex))
+ {
+ if (layerIndex > slicerFile.LayerCount)
+ {
+ throw new FileLoadException(
+ $"GCode parser detected the layer {layerIndex}, but the file was sliced to {slicerFile.LayerCount} layers.",
+ slicerFile.FileFullPath);
+ }
+ layerBlock.SetLayer(true);
+ layerBlock.LayerIndex = layerIndex;
+ continue;
+ }
+ }
+
// Display image
if (line.StartsWith(CommandShowImageM6054.Command))
{
@@ -888,8 +955,7 @@ public class GCodeBuilder : BindableBase
if (match.Success && match.Groups.Count >= 2) // Begin new layer
{
var layerIndex = uint.Parse(match.Groups[1].Value);
- if (_gCodeShowImageType is GCodeShowImageTypes.FilenamePng1Started or GCodeShowImageTypes
- .LayerIndex1Started) layerIndex--;
+ if (_gCodeShowImageType is GCodeShowImageTypes.FilenamePng1Started or GCodeShowImageTypes.LayerIndex1Started) layerIndex--;
if (layerIndex > slicerFile.LayerCount)
{
throw new FileLoadException(
@@ -898,7 +964,11 @@ public class GCodeBuilder : BindableBase
}
// Propagate values before switch to the new layer
- layerBlock.SetLayer(true);
+ if (_gCodeShowImagePosition == GCodeShowImagePositions.FirstLine && layerBlock.LayerIndex != layerIndex)
+ {
+ layerBlock.SetLayer(true);
+ }
+
layerBlock.LayerIndex = layerIndex;
continue;
@@ -970,12 +1040,12 @@ public class GCodeBuilder : BindableBase
RegexOptions.IgnoreCase);
if (match.Success && match.Groups.Count >= 2)
{
- if (_syncMovementsWithDelay && match.Groups[1].Value.StartsWith('0')) continue; // Sync movement delay, skip
+ if (/*CommandWaitSyncDelay.Enabled && */match.Groups[1].Value.StartsWith('0')) continue; // Sync movement delay, skip
var waitTime = float.Parse(match.Groups[1].Value);
if (layerBlock.PositionZ.HasValue &&
- layerBlock.LiftHeight.HasValue &&
+ //layerBlock.LiftHeight.HasValue &&
!layerBlock.RetractSpeed.HasValue) // Must be wait time after lift, if not, don't blame me!
{
layerBlock.WaitTimeAfterLift ??= 0;
diff --git a/UVtools.Core/GCode/GCodeLayer.cs b/UVtools.Core/GCode/GCodeLayer.cs
index 3f9501e..afbbcf2 100644
--- a/UVtools.Core/GCode/GCodeLayer.cs
+++ b/UVtools.Core/GCode/GCodeLayer.cs
@@ -304,7 +304,7 @@ public class GCodeLayer
layer.RetractSpeed2 = RetractSpeed2 ?? SlicerFile.GetBottomOrNormalValue(layer, SlicerFile.BottomRetractSpeed2, SlicerFile.RetractSpeed2);
layer.LightPWM = LightPWM ?? 0;//SlicerFile.GetInitialLayerValueOrNormal(layerIndex, SlicerFile.BottomLightPWM, SlicerFile.LightPWM);
- if (SlicerFile.GCode!.SyncMovementsWithDelay) // Dirty fix of the value
+ if (SlicerFile.GCode!.CommandWaitSyncDelay.Enabled) // Dirty fix of the value
{
var syncTime = OperationCalculator.LightOffDelayC.CalculateSeconds(layer, 1.5f);
if (syncTime < layer.WaitTimeBeforeCure)
diff --git a/UVtools.Core/Layers/Layer.cs b/UVtools.Core/Layers/Layer.cs
index 3c5071a..2f2ea02 100644
--- a/UVtools.Core/Layers/Layer.cs
+++ b/UVtools.Core/Layers/Layer.cs
@@ -756,12 +756,12 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
CvInvoke.Imdecode(_compressedBytes, ImreadModes.Grayscale, mat);
break;
case LayerCompressionCodec.Lz4:
- mat = new Mat(SlicerFile.Resolution, DepthType.Cv8U, 1);
+ mat = SlicerFile.CreateMat(false);
LZ4Codec.Decode(_compressedBytes.AsSpan(), mat.GetDataByteSpan());
break;
case LayerCompressionCodec.GZip:
{
- mat = new(SlicerFile.Resolution, DepthType.Cv8U, 1);
+ mat = SlicerFile.CreateMat(false);
unsafe
{
fixed (byte* pBuffer = _compressedBytes)
@@ -777,7 +777,7 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
}
case LayerCompressionCodec.Deflate:
{
- mat = new(SlicerFile.Resolution, DepthType.Cv8U, 1);
+ mat = SlicerFile.CreateMat(false);
unsafe
{
fixed (byte* pBuffer = _compressedBytes)
@@ -1619,7 +1619,8 @@ public class Layer : BindableBase, IEquatable<Layer>, IEquatable<uint>
var span = mat.GetDataByteSpan();
var target = new byte[LZ4Codec.MaximumOutputSize(span.Length)];
var encodedLength = LZ4Codec.Encode(span, target.AsSpan());
- return target[..encodedLength];
+ Array.Resize(ref target, encodedLength);
+ return target;
}
case LayerCompressionCodec.GZip:
{
diff --git a/UVtools.Core/Objects/UInt24BigEndian.cs b/UVtools.Core/Objects/UInt24BigEndian.cs
index 9515ea3..c1bf3a6 100644
--- a/UVtools.Core/Objects/UInt24BigEndian.cs
+++ b/UVtools.Core/Objects/UInt24BigEndian.cs
@@ -56,4 +56,13 @@ public sealed class UInt24BigEndian
{
return (int)Value;
}
+
+
+ public static uint operator +(UInt24BigEndian a, UInt24BigEndian b) => a.Value + b.Value;
+
+ public static uint operator -(UInt24BigEndian a, UInt24BigEndian b) => a.Value - b.Value;
+
+ public static uint operator *(UInt24BigEndian a, UInt24BigEndian b) => a.Value * b.Value;
+
+ public static uint operator /(UInt24BigEndian a, UInt24BigEndian b) => a.Value / b.Value;
} \ No newline at end of file
diff --git a/UVtools.Core/Slicer/Slicer.cs b/UVtools.Core/Slicer/Slicer.cs
index aa6727a..848e347 100644
--- a/UVtools.Core/Slicer/Slicer.cs
+++ b/UVtools.Core/Slicer/Slicer.cs
@@ -202,7 +202,7 @@ public class Slicer
public static uint MillimetersToLayers(float millimeters, float layerHeight) => (uint)(millimeters / layerHeight);
public static uint MillimetersToLayers(double millimeters, double layerHeight) => (uint)(millimeters / layerHeight);
- public static uint MillimetersToLayers(decimal millimeters, decimal layerHeight) => (uint)(millimeters / layerHeight);
+ public static uint MillimetersToLayers(decimal millimeters, decimal layerHeight) => layerHeight > 0 ? (uint)(millimeters / layerHeight) : 0;
public static uint LayersToMillimeters(uint layers, float layerHeight) => (uint)(layers * layerHeight);
public static uint LayersToMillimeters(uint layers, double layerHeight) => (uint)(layers * layerHeight);
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index 783bd22..f870d8e 100644
--- a/UVtools.Core/UVtools.Core.csproj
+++ b/UVtools.Core/UVtools.Core.csproj
@@ -10,7 +10,7 @@
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
- <Version>3.5.6</Version>
+ <Version>3.6.0</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
@@ -61,13 +61,13 @@
<ItemGroup>
<PackageReference Include="AnimatedGif" Version="1.0.5" />
<PackageReference Include="BinarySerializer" Version="8.6.2.2" />
+ <PackageReference Include="CommunityToolkit.HighPerformance" Version="8.0.0" />
<PackageReference Include="Emgu.CV" Version="4.5.5.4823" />
<PackageReference Include="Emgu.CV.runtime.ubuntu.20.04-x64" Version="4.5.4.4788" />
<PackageReference Include="Emgu.CV.runtime.windows" Version="4.5.5.4823" />
<PackageReference Include="K4os.Compression.LZ4" Version="1.2.16" />
<PackageReference Include="KdTree" Version="1.4.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.2.0" />
- <PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.1.2" />
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
<PackageReference Include="System.Memory" Version="4.5.5" />
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.7.0" />
diff --git a/UVtools.Installer/Code/Product.wxs b/UVtools.Installer/Code/Product.wxs
index b14c5f7..ce6a4b4 100644
--- a/UVtools.Installer/Code/Product.wxs
+++ b/UVtools.Installer/Code/Product.wxs
@@ -42,7 +42,7 @@
<RegistryValue Root="HKCR" Key="*\shell\UVtools" Value="Open with UVtools" Type="string" />
<RegistryValue Root="HKCR" Key="*\shell\UVtools" Name="Icon" Value="[INSTALLLOCATION]UVtools.exe" Type="string" />
<RegistryValue Root="HKCR" Key="*\shell\UVtools" Name="Position" Value="Top" Type="string" />
- <RegistryValue Root="HKCR" Key="*\shell\UVtools" Name="AppliesTo" Value="System.FileName:&quot;*.sl1&quot; OR System.FileName:&quot;*.sl1s&quot; OR System.FileName:&quot;*.zip&quot; OR System.FileName:&quot;*.photon&quot; OR System.FileName:&quot;*.cbddlp&quot; OR System.FileName:&quot;*.ctb&quot; OR System.FileName:&quot;*.photons&quot; OR System.FileName:&quot;*.phz&quot; OR System.FileName:&quot;*.fdg&quot; OR System.FileName:&quot;*.pws&quot; OR System.FileName:&quot;*.pw0&quot; OR System.FileName:&quot;*.pwx&quot; OR System.FileName:&quot;*.dlp&quot; OR System.FileName:&quot;*.pwmx&quot; OR System.FileName:&quot;*.pwmb&quot; OR System.FileName:&quot;*.pwmo&quot; OR System.FileName:&quot;*.pwms&quot; OR System.FileName:&quot;*.pwma&quot; OR System.FileName:&quot;*.pmsq&quot; OR System.FileName:&quot;*.pm3&quot; OR System.FileName:&quot;*.pm3m&quot; OR System.FileName:&quot;*.cws&quot; OR System.FileName:&quot;*.osla&quot; OR System.FileName:&quot;*.jxs&quot; OR System.FileName:&quot;*.zcode&quot; OR System.FileName:&quot;*.zcodex&quot; OR System.FileName:&quot;*.mdlp&quot; OR System.FileName:&quot;*.gr1&quot; OR System.FileName:&quot;*.cxdlp&quot; OR System.FileName:&quot;*.lgs&quot; OR System.FileName:&quot;*.lgs30&quot; OR System.FileName:&quot;*.lgs120&quot; OR System.FileName:&quot;*.lgs4k&quot; OR System.FileName:&quot;*.svgx&quot; OR System.FileName:&quot;*.vdt&quot; OR System.FileName:&quot;*.uvj&quot; OR System.FileName:&quot;*.png&quot; OR System.FileName:&quot;*.jpg&quot; OR System.FileName:&quot;*.jpeg&quot; OR System.FileName:&quot;*.jp2&quot; OR System.FileName:&quot;*.tif&quot; OR System.FileName:&quot;*.tiff&quot; OR System.FileName:&quot;*.bmp&quot; OR System.FileName:&quot;*.pbm&quot; OR System.FileName:&quot;*.pgm&quot; OR System.FileName:&quot;*.sr&quot; OR System.FileName:&quot;*.ras&quot;" Type="string" />
+ <RegistryValue Root="HKCR" Key="*\shell\UVtools" Name="AppliesTo" Value="System.FileName:&quot;*.sl1&quot; OR System.FileName:&quot;*.sl1s&quot; OR System.FileName:&quot;*.zip&quot; OR System.FileName:&quot;*.photon&quot; OR System.FileName:&quot;*.cbddlp&quot; OR System.FileName:&quot;*.ctb&quot; OR System.FileName:&quot;*.photons&quot; OR System.FileName:&quot;*.phz&quot; OR System.FileName:&quot;*.fdg&quot; OR System.FileName:&quot;*.pws&quot; OR System.FileName:&quot;*.pw0&quot; OR System.FileName:&quot;*.pwx&quot; OR System.FileName:&quot;*.dlp&quot; OR System.FileName:&quot;*.pwmx&quot; OR System.FileName:&quot;*.pwmb&quot; OR System.FileName:&quot;*.pwmo&quot; OR System.FileName:&quot;*.pwms&quot; OR System.FileName:&quot;*.pwma&quot; OR System.FileName:&quot;*.pmsq&quot; OR System.FileName:&quot;*.pm3&quot; OR System.FileName:&quot;*.pm3m&quot; OR System.FileName:&quot;*.cws&quot; OR System.FileName:&quot;*.osla&quot; OR System.FileName:&quot;*.jxs&quot; OR System.FileName:&quot;*.zcode&quot; OR System.FileName:&quot;*.zcodex&quot; OR System.FileName:&quot;*.mdlp&quot; OR System.FileName:&quot;*.gr1&quot; OR System.FileName:&quot;*.cxdlp&quot; OR System.FileName:&quot;*.lgs&quot; OR System.FileName:&quot;*.lgs30&quot; OR System.FileName:&quot;*.lgs120&quot; OR System.FileName:&quot;*.lgs4k&quot; OR System.FileName:&quot;*.svgx&quot; OR System.FileName:&quot;*.vdt&quot; OR System.FileName:&quot;*.osf&quot; OR System.FileName:&quot;*.uvj&quot; OR System.FileName:&quot;*.png&quot; OR System.FileName:&quot;*.jpg&quot; OR System.FileName:&quot;*.jpeg&quot; OR System.FileName:&quot;*.jp2&quot; OR System.FileName:&quot;*.tif&quot; OR System.FileName:&quot;*.tiff&quot; OR System.FileName:&quot;*.bmp&quot; OR System.FileName:&quot;*.pbm&quot; OR System.FileName:&quot;*.pgm&quot; OR System.FileName:&quot;*.sr&quot; OR System.FileName:&quot;*.ras&quot;" Type="string" />
<RegistryKey Root="HKCR" Key="*\shell\UVtools\command" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes" />
<RegistryValue Root="HKCR" Key="*\shell\UVtools\command" Value="&quot;[INSTALLLOCATION]UVtools.exe&quot; &quot;%1&quot;" Type="string" />
</Component>
diff --git a/UVtools.InstallerMM/UVtools.InstallerMM.wxs b/UVtools.InstallerMM/UVtools.InstallerMM.wxs
index afa2e14..7784883 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.5.6"?>
+ <?define SourceDir="..\publish\UVtools_win-x64_v3.6.0"?>
<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">
@@ -1554,11 +1554,11 @@
<Component Id="owcD2245B900E5C448485AD96FE57629D9D" Guid="D2245B90-0E5C-4484-85AD-96FE57629D9D">
<File Id="owfD2245B900E5C448485AD96FE57629D9D" Source="$(var.SourceDir)\UVtoolsCmd.runtimeconfig.json" KeyPath="yes" />
</Component>
- <Component Id="owc3110926C9437495884D1A256F611E7C5" Guid="3110926C-9437-4958-84D1-A256F611E7C5">
- <File Id="owf3110926C9437495884D1A256F611E7C5" Source="$(var.SourceDir)\Microsoft.Toolkit.HighPerformance.dll" KeyPath="yes" />
+ <Component Id="owc1AE8795C4CF24718B9BFE67B19A54931" Guid="1AE8795C-4CF2-4718-B9BF-E67B19A54931">
+ <File Id="owf1AE8795C4CF24718B9BFE67B19A54931" Source="$(var.SourceDir)\CommunityToolkit.HighPerformance.dll" KeyPath="yes" />
</Component>
- <Component Id="owc6FEB071413A045D9BB5F9C092F36EA8A" Guid="6FEB0714-13A0-45D9-BB5F-9C092F36EA8A">
- <File Id="owf6FEB071413A045D9BB5F9C092F36EA8A" Source="$(var.SourceDir)\mscordaccore_amd64_amd64_6.0.722.32202.dll" KeyPath="yes" />
+ <Component Id="owcFD966BCC9E7C4739A03A214ED65F3A9F" Guid="FD966BCC-9E7C-4739-A03A-214ED65F3A9F">
+ <File Id="owfFD966BCC9E7C4739A03A214ED65F3A9F" Source="$(var.SourceDir)\mscordaccore_amd64_amd64_6.0.822.36306.dll" KeyPath="yes" />
</Component>
</Directory>
<Directory Id="ProgramMenuFolder">
diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs
index e5c7d0c..2227fad 100644
--- a/UVtools.WPF/MainWindow.axaml.cs
+++ b/UVtools.WPF/MainWindow.axaml.cs
@@ -1178,55 +1178,48 @@ public partial class MainWindow : WindowEx
public async void MenuNewVersionClicked()
{
- var result =
- await this.MessageBoxWithHeaderQuestion(
- $"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" +
- "Changelog: \n\n" +
- $"{VersionChecker.Changelog}",
+ if (string.IsNullOrWhiteSpace(VersionChecker.DownloadLink))
+ {
+ var result = await this.MessageBoxWithHeaderQuestion(
+ $"Do you like to manually download and update {About.Software} v{About.VersionStr} to v{VersionChecker.Version}?",
+ "## Changelog: \n\n" +
+ $"{VersionChecker.Changelog}",
$"Update UVtools to v{VersionChecker.Version}?",
-
- ButtonEnum.YesNoCancel, true);
+ ButtonEnum.YesNoCancel, true);
- if (result == ButtonResult.No)
- {
- SystemAware.OpenBrowser(VersionChecker.UrlLatestRelease);
- return;
+ if (result == ButtonResult.Yes)
+ {
+ SystemAware.OpenBrowser(VersionChecker.UrlLatestRelease);
+ }
}
- if (result == ButtonResult.Yes)
+ else
{
- IsGUIEnabled = false;
- ShowProgressWindow($"Downloading: {VersionChecker.Filename}");
+ var result = await this.MessageBoxWithHeaderQuestion(
+ $"Do you like to auto-update {About.Software} v{About.VersionStr} to v{VersionChecker.Version}?",
+ "Yes: Auto update \n" +
+ "No: Manual download and update \n" +
+ "Cancel: No action \n\n" +
+ "## Changelog: \n\n" +
+ $"{VersionChecker.Changelog}",
+ $"Update UVtools to v{VersionChecker.Version}?",
- await VersionChecker.AutoUpgrade(Progress);
+ ButtonEnum.YesNoCancel, true);
- /*var task = await Task.Factory.StartNew( () =>
- {
- try
- {
- VersionChecker.AutoUpgrade(Progress);
- return true;
- }
- catch (OperationCanceledException)
- {
- }
- catch (Exception exception)
- {
- Dispatcher.UIThread.InvokeAsync(async () =>
- await this.MessageBoxError(exception.ToString(), "Error opening the file"));
- }
- return false;
- });
- */
- IsGUIEnabled = true;
-
- return;
+ switch (result)
+ {
+ case ButtonResult.No:
+ SystemAware.OpenBrowser(VersionChecker.UrlLatestRelease);
+ break;
+ case ButtonResult.Yes:
+ IsGUIEnabled = false;
+ ShowProgressWindow($"Downloading: {VersionChecker.Filename}");
+ await VersionChecker.AutoUpgrade(Progress);
+ IsGUIEnabled = true;
+ break;
+ }
}
-
}
#endregion
diff --git a/UVtools.WPF/Structures/AppVersionChecker.cs b/UVtools.WPF/Structures/AppVersionChecker.cs
index d12d733..e4018b8 100644
--- a/UVtools.WPF/Structures/AppVersionChecker.cs
+++ b/UVtools.WPF/Structures/AppVersionChecker.cs
@@ -16,6 +16,7 @@ using System.Text.Json.Nodes;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
+using System.Xml.Linq;
using Avalonia.Threading;
using UVtools.Core;
using UVtools.Core.Extensions;
@@ -42,15 +43,12 @@ public class AppVersionChecker : BindableBase
{
try
{
- var package = File.ReadAllText(file);
+ var package = File.ReadAllText(file).Trim();
if (!string.IsNullOrWhiteSpace(package) && (package.EndsWith("-x64") || package.EndsWith("-arm64")))
{
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- return $"{About.Software}_{package}_v{_version}.msi";
-
- return SystemAware.IsRunningLinuxAppImage()
- ? $"{About.Software}_{package}_v{_version}.AppImage"
- : $"{About.Software}_{package}_v{_version}.zip";
+ if (OperatingSystem.IsWindows()) return $"{About.Software}_{package}_v{_version}.msi";
+ if (SystemAware.IsRunningLinuxAppImage()) return $"{About.Software}_{package}_v{_version}.AppImage";
+ return $"{About.Software}_{package}_v{_version}.zip";
}
}
catch (Exception e)
@@ -59,17 +57,17 @@ public class AppVersionChecker : BindableBase
}
}
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ if (OperatingSystem.IsWindows())
{
return $"{About.Software}_win-x64_v{_version}.msi";
}
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ if (OperatingSystem.IsLinux())
{
return SystemAware.IsRunningLinuxAppImage()
? $"{About.Software}_linux-x64_v{_version}.AppImage"
: $"{About.Software}_linux-x64_v{_version}.zip";
}
- if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ if (OperatingSystem.IsMacOS())
{
return RuntimeInformation.ProcessArchitecture is Architecture.Arm or Architecture.Arm64
? $"{About.Software}_osx-arm64_v{_version}.zip"
@@ -122,7 +120,7 @@ public class AppVersionChecker : BindableBase
public string UrlLatestRelease = $"{About.Website}/releases/latest";
- public string DownloadLink => string.IsNullOrEmpty(Filename) ? null : $"{About.Website}/releases/download/v{_version}/{Filename}";
+ public string DownloadLink { get; private set; }
public bool HaveNewVersion => !string.IsNullOrEmpty(Version);
@@ -132,6 +130,8 @@ public class AppVersionChecker : BindableBase
{
try
{
+ _version = null;
+ DownloadLink = null;
var request = new HttpRequestMessage
{
RequestUri = new Uri(GitHubReleaseApi),
@@ -149,31 +149,23 @@ public class AppVersionChecker : BindableBase
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 (About.Version.CompareTo(checkVersion) < 0)
{
- Debug.WriteLine($"New version detected: {DownloadLink}\n" +
- $"{_changelog}");
- Dispatcher.UIThread.InvokeAsync(() =>
+ var assets = json["assets"].AsArray();
+
+ Version = tag_name;
+ var fileName = Filename;
+ foreach (var asset in assets)
{
- Version = tag_name;
- });
+ if (asset["name"]!.ToString() != fileName) continue;
+ DownloadLink = asset["browser_download_url"]!.ToString();
+ break;
+ }
+
+ Debug.WriteLine($"New version detected: {DownloadLink}\n{_changelog}");
+
return true;
}
- /*string htmlCode = client.DownloadString($"{About.Website}/releases");
- const string searchFor = "/releases/tag/";
- var startIndex = htmlCode.IndexOf(searchFor, StringComparison.InvariantCultureIgnoreCase) +
- searchFor.Length;
- var endIndex = htmlCode.IndexOf("\"", startIndex, StringComparison.InvariantCultureIgnoreCase);
- var version = htmlCode.Substring(startIndex, endIndex - startIndex);
- if (string.Compare(version, $"v{AppSettings.VersionStr}", StringComparison.OrdinalIgnoreCase) > 0)
- {
- Dispatcher.UIThread.InvokeAsync(() =>
- {
- Version = version;;
- });
- return true;
- }*/
}
catch (Exception e)
{
@@ -185,7 +177,7 @@ public class AppVersionChecker : BindableBase
public async Task<bool> AutoUpgrade(OperationProgress progress)
{
- if (!HaveNewVersion) return false;
+ if (!HaveNewVersion || string.IsNullOrWhiteSpace(DownloadLink)) return false;
progress.ItemName = "Megabytes";
try
{
@@ -228,7 +220,7 @@ public class AppVersionChecker : BindableBase
Thread.Sleep(500);
SystemAware.StartProcess(newFullPath);
}
- else // others
+ else // MacOS and generic linux (no AppImage)
{
var upgradeFolder = "UPDATED_VERSION";
var targetDir = Path.Combine(App.ApplicationPath, upgradeFolder);
@@ -249,16 +241,17 @@ public class AppVersionChecker : BindableBase
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");
+ await stream.WriteLineAsync("sleep 1");
//stream.WriteLine($"[ -f {About.Software} ] && {App.AppExecutableQuoted} & || dotnet {About.Software}.dll &");
if (SystemAware.IsRunningMacOSApp)
{
+ await stream.WriteLineAsync($"find {upgradeFolder} -print0 | xargs -0 xattr -d com.apple.quarantine");
await stream.WriteLineAsync($"cp -fR {upgradeFolder}/* ../../../");
await stream.WriteLineAsync($"open ../../../{About.Software}.app");
}
- else
+ else // Linux generic
{
await stream.WriteLineAsync($"cp -fR {upgradeFolder}/* .");
await stream.WriteLineAsync($"if [ -f '{About.Software}' ]; then");
diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj
index 988e66a..8c2eca6 100644
--- a/UVtools.WPF/UVtools.WPF.csproj
+++ b/UVtools.WPF/UVtools.WPF.csproj
@@ -12,7 +12,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
- <Version>3.5.6</Version>
+ <Version>3.6.0</Version>
<Platforms>AnyCPU;x64</Platforms>
<PackageIcon>UVtools.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
@@ -39,15 +39,15 @@
<NoWarn>1701;1702;</NoWarn>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Avalonia" Version="0.10.17" />
- <PackageReference Include="Avalonia.Controls.DataGrid" Version="0.10.17" />
- <PackageReference Include="Avalonia.Desktop" Version="0.10.17" />
- <PackageReference Include="Avalonia.Diagnostics" Version="0.10.17" />
+ <PackageReference Include="Avalonia" Version="0.10.18" />
+ <PackageReference Include="Avalonia.Controls.DataGrid" Version="0.10.18" />
+ <PackageReference Include="Avalonia.Desktop" Version="0.10.18" />
+ <PackageReference Include="Avalonia.Diagnostics" Version="0.10.18" />
<PackageReference Include="MessageBox.Avalonia" Version="2.0.2" />
- <PackageReference Include="Projektanker.Icons.Avalonia" Version="5.2.0" />
- <PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="5.2.0" />
- <PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="5.2.0" />
- <PackageReference Include="ThemeEditor.Controls.ColorPicker" Version="0.10.14" />
+ <PackageReference Include="Projektanker.Icons.Avalonia" Version="5.3.0" />
+ <PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="5.3.0" />
+ <PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="5.3.0" />
+ <PackageReference Include="ThemeEditor.Controls.ColorPicker" Version="0.10.17" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\UVtools.AvaloniaControls\UVtools.AvaloniaControls.csproj" />
diff --git a/UVtools.WPF/Windows/MissingInformationWindow.axaml b/UVtools.WPF/Windows/MissingInformationWindow.axaml
index 1d1f9cd..7923aa9 100644
--- a/UVtools.WPF/Windows/MissingInformationWindow.axaml
+++ b/UVtools.WPF/Windows/MissingInformationWindow.axaml
@@ -36,6 +36,7 @@
Minimum="0"
Maximum="0.200"
Increment="0.01"
+ FormatString="F3"
Value="{Binding LayerHeight}"/>
<TextBlock Grid.Row="0" Grid.Column="4"