mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-08 17:42:31 +02:00
v2.25.0
- **File formats:** - (Add) Allow to partial open the files for read and/or change properties, the layer images won't be read nor cached (Fast) - (Add) More abstraction on partial save - **Scripting:** - (Add) ScriptOpenFolderDialogInput - Selects a folder path - (Add) ScriptOpenFileDialogInput - Selectes a file to open - (Add) ScriptSaveFileDialogInput - Selects a file to save - (Add) [UNSAVED] tag to the title bar when there are unsaved changes on the current session - (Improvement) Better handling of empty images on the UI
This commit is contained in:
@@ -1,5 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
## 18/11/2021 - v2.25.0
|
||||
|
||||
- **File formats:**
|
||||
- (Add) Allow to partial open the files for read and/or change properties, the layer images won't be read nor cached (Fast)
|
||||
- (Add) More abstraction on partial save
|
||||
- **Scripting:**
|
||||
- (Add) ScriptOpenFolderDialogInput - Selects a folder path
|
||||
- (Add) ScriptOpenFileDialogInput - Selectes a file to open
|
||||
- (Add) ScriptSaveFileDialogInput - Selects a file to save
|
||||
- (Add) [UNSAVED] tag to the title bar when there are unsaved changes on the current session
|
||||
- (Improvement) Better handling of empty images on the UI
|
||||
|
||||
## 14/11/2021 - v2.24.4
|
||||
|
||||
- **File - Send to - Device**
|
||||
|
||||
@@ -2117,7 +2117,7 @@ namespace UVtools.AvaloniaControls
|
||||
/// <returns></returns>
|
||||
public Rect GetImageViewPort()
|
||||
{
|
||||
if (ViewPortSize.Width == 0 && ViewPortSize.Height == 0) return Rect.Empty;
|
||||
if (!IsImageLoaded || (ViewPortSize.Width == 0 && ViewPortSize.Height == 0)) return Rect.Empty;
|
||||
|
||||
double xOffset = 0;
|
||||
double yOffset = 0;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<PackageTags>Advanced image box</PackageTags>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<Description>AvaloniaUI Controls</Description>
|
||||
<Version>1.0.0</Version>
|
||||
<Version>1.0.1</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
|
||||
@@ -1097,15 +1097,15 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
Header = Helpers.Deserialize<FileHeader>(inputFile);
|
||||
Debug.WriteLine($"Header: {Header}");
|
||||
|
||||
if (Header.Magic is not MAGIC_CBT_ENCRYPTED)
|
||||
{
|
||||
throw new FileLoadException($"Not a valid CTB encrypted file! Magic Value: {Header.Magic}", fileFullPath);
|
||||
throw new FileLoadException($"Not a valid CTB encrypted file! Magic Value: {Header.Magic}", FileFullPath);
|
||||
}
|
||||
|
||||
inputFile.Seek(Header.SettingsOffset, SeekOrigin.Begin);
|
||||
@@ -1127,7 +1127,7 @@ namespace UVtools.Core.FileFormats
|
||||
var hash = inputFile.ReadBytes(HASH_LENGTH);
|
||||
if (!hash.SequenceEqual(encryptedHash))
|
||||
{
|
||||
throw new FileLoadException("The file checksum does not match, malformed file.", fileFullPath);
|
||||
throw new FileLoadException("The file checksum does not match, malformed file.", FileFullPath);
|
||||
}
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodePreviews, ThumbnailsCount);
|
||||
@@ -1174,7 +1174,7 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, Settings.LayerCount);
|
||||
LayerManager.Init(Settings.LayerCount);
|
||||
LayerManager.Init(Settings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
LayersDefinition = new LayerDef[LayerCount];
|
||||
var buggyLayers = new ConcurrentBag<uint>();
|
||||
|
||||
@@ -1187,43 +1187,48 @@ namespace UVtools.Core.FileFormats
|
||||
inputFile.Seek(LayersPointer[layerIndex].LayerOffset, SeekOrigin.Begin);
|
||||
LayersDefinition[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
|
||||
LayersDefinition[layerIndex].Parent = this;
|
||||
LayersDefinition[layerIndex].RLEData = inputFile.ReadBytes(LayersDefinition[layerIndex].DataLength);
|
||||
if (DecodeType == FileDecodeType.Full) LayersDefinition[layerIndex].RLEData = inputFile.ReadBytes(LayersDefinition[layerIndex].DataLength);
|
||||
Debug.WriteLine($"layer[{layerIndex}]: {LayersDefinition[layerIndex]}");
|
||||
}
|
||||
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
|
||||
var layerDef = LayersDefinition[layerIndex];
|
||||
|
||||
if (layerDef.EncryptedDataLength > 0)
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
/* Decrypt RLE data here */
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
|
||||
var byteBuffer = new byte[layerDef.EncryptedDataLength];
|
||||
Array.Copy(layerDef.RLEData, (int)layerDef.EncryptedDataOffset, byteBuffer, 0, (int)layerDef.EncryptedDataLength);
|
||||
var layerDef = LayersDefinition[layerIndex];
|
||||
|
||||
byteBuffer = CryptExtensions.AesCryptBytes(byteBuffer, Bigfoot, CipherMode.CBC, PaddingMode.None, false, CookieMonster);
|
||||
Array.Copy(byteBuffer, 0, layerDef.RLEData, layerDef.EncryptedDataOffset, layerDef.EncryptedDataLength);
|
||||
}
|
||||
|
||||
bool isBugged = false;
|
||||
/* bug fix for Chitubox when a small layer RLE data is encrypted */
|
||||
if (layerDef.EncryptedDataLength > 0 && layerDef.RLEData.Length < RLEEncryptedMinimumLength && layerDef.RLEData.Length % 16 != 0)
|
||||
{
|
||||
buggyLayers.Add((uint)layerIndex);
|
||||
isBugged = true;
|
||||
layerDef.RLEData = null; /* clean up RLE data */
|
||||
}
|
||||
if (layerDef.EncryptedDataLength > 0)
|
||||
{
|
||||
/* Decrypt RLE data here */
|
||||
|
||||
var layer = new Layer((uint)layerIndex, isBugged ? null : layerDef.DecodeImage((uint)layerIndex), this);
|
||||
layerDef.CopyTo(layer);
|
||||
this[layerIndex] = layer;
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
var byteBuffer = new byte[layerDef.EncryptedDataLength];
|
||||
Array.Copy(layerDef.RLEData, (int)layerDef.EncryptedDataOffset, byteBuffer, 0,
|
||||
(int)layerDef.EncryptedDataLength);
|
||||
|
||||
byteBuffer = CryptExtensions.AesCryptBytes(byteBuffer, Bigfoot, CipherMode.CBC,
|
||||
PaddingMode.None, false, CookieMonster);
|
||||
Array.Copy(byteBuffer, 0, layerDef.RLEData, layerDef.EncryptedDataOffset,
|
||||
layerDef.EncryptedDataLength);
|
||||
}
|
||||
|
||||
bool isBugged = false;
|
||||
/* bug fix for Chitubox when a small layer RLE data is encrypted */
|
||||
if (layerDef.EncryptedDataLength > 0 && layerDef.RLEData.Length < RLEEncryptedMinimumLength &&
|
||||
layerDef.RLEData.Length % 16 != 0)
|
||||
{
|
||||
buggyLayers.Add((uint)layerIndex);
|
||||
isBugged = true;
|
||||
layerDef.RLEData = null; /* clean up RLE data */
|
||||
}
|
||||
|
||||
this[layerIndex] = new Layer((uint)layerIndex, isBugged ? null : layerDef.DecodeImage((uint)layerIndex), this);
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (buggyLayers.Count == LayerCount)
|
||||
@@ -1231,7 +1236,12 @@ namespace UVtools.Core.FileFormats
|
||||
throw new FileLoadException("Unable to load this file due to Chitubox bug affecting every layer." +
|
||||
"Please increase the portion of the plate in use and reslice the file.");
|
||||
}
|
||||
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
LayersDefinition[layerIndex].CopyTo(this[layerIndex]);
|
||||
}
|
||||
|
||||
if (!buggyLayers.IsEmpty)
|
||||
{
|
||||
var sortedLayerIndexes = buggyLayers.ToArray();
|
||||
@@ -1267,13 +1277,13 @@ namespace UVtools.Core.FileFormats
|
||||
//inputFile.ReadBytes(HashLength);
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
#if !DEBUG
|
||||
throw new NotSupportedException(Preamble);
|
||||
#endif
|
||||
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
|
||||
//uint currentOffset = 0;
|
||||
|
||||
/* Create the file header and fill out what we can. SignatureOffset will have to be populated later
|
||||
@@ -1401,25 +1411,8 @@ namespace UVtools.Core.FileFormats
|
||||
Helpers.SerializeWriteFileStream(outputFile, Header);
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
SanitizeProperties();
|
||||
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
|
||||
|
||||
@@ -575,7 +575,7 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
//var filename = fileFullPath.EndsWith(TemporaryFileAppend) ? Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(fileFullPath)) : Path.GetFileNameWithoutExtension(fileFullPath);
|
||||
|
||||
@@ -610,7 +610,7 @@ namespace UVtools.Core.FileFormats
|
||||
throw new InvalidOperationException($"Filename for this format should not end with a digit: {filename}");
|
||||
}
|
||||
|
||||
using ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create);
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
|
||||
if (Printer == PrinterType.Wanhao)
|
||||
{
|
||||
var manifest = new CWSManifest
|
||||
@@ -703,9 +703,9 @@ namespace UVtools.Core.FileFormats
|
||||
outputFile.PutFileContent($"{filename}.gcode", GCodeStr, ZipArchiveMode.Create);
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Read);
|
||||
using var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read);
|
||||
var entry = inputFile.GetEntry("manifest.xml");
|
||||
if (entry is not null) // Wanhao
|
||||
{
|
||||
@@ -722,7 +722,7 @@ namespace UVtools.Core.FileFormats
|
||||
catch (Exception e)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", fileFullPath);
|
||||
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", FileFullPath);
|
||||
}
|
||||
|
||||
|
||||
@@ -741,7 +741,7 @@ namespace UVtools.Core.FileFormats
|
||||
catch (Exception e)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", fileFullPath);
|
||||
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", FileFullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -751,7 +751,7 @@ namespace UVtools.Core.FileFormats
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException("slice.conf not found", fileFullPath);
|
||||
throw new FileLoadException("slice.conf not found", FileFullPath);
|
||||
}
|
||||
|
||||
using TextReader tr = new StreamReader(entry.Open());
|
||||
@@ -780,8 +780,7 @@ namespace UVtools.Core.FileFormats
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException("Unable to find .gcode file",
|
||||
fileFullPath);
|
||||
throw new FileLoadException("Unable to find .gcode file", FileFullPath);
|
||||
}
|
||||
|
||||
using (TextReader tr = new StreamReader(entry.Open()))
|
||||
@@ -821,32 +820,36 @@ namespace UVtools.Core.FileFormats
|
||||
tr.Close();
|
||||
}
|
||||
|
||||
LayerManager.Init(OutputSettings.LayersNum);
|
||||
LayerManager.Init(OutputSettings.LayersNum, DecodeType == FileDecodeType.Partial);
|
||||
|
||||
progress.ItemCount = OutputSettings.LayersNum;
|
||||
|
||||
if(LayerCount > 0)
|
||||
{
|
||||
var inputFilename = Path.GetFileNameWithoutExtension(fileFullPath);
|
||||
foreach (var pngEntry in inputFile.Entries)
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
if (!pngEntry.Name.EndsWith(".png")) continue;
|
||||
var filename = Path.GetFileNameWithoutExtension(pngEntry.Name).Replace(inputFilename, string.Empty, StringComparison.Ordinal);
|
||||
|
||||
var layerIndexStr = string.Empty;
|
||||
var layerStr = filename;
|
||||
for (int i = layerStr.Length - 1; i >= 0; i--)
|
||||
var inputFilename = Path.GetFileNameWithoutExtension(FileFullPath);
|
||||
foreach (var pngEntry in inputFile.Entries)
|
||||
{
|
||||
if (layerStr[i] < '0' || layerStr[i] > '9') break;
|
||||
layerIndexStr = $"{layerStr[i]}{layerIndexStr}";
|
||||
if (!pngEntry.Name.EndsWith(".png")) continue;
|
||||
var filename = Path.GetFileNameWithoutExtension(pngEntry.Name)
|
||||
.Replace(inputFilename, string.Empty, StringComparison.Ordinal);
|
||||
|
||||
var layerIndexStr = string.Empty;
|
||||
var layerStr = filename;
|
||||
for (int i = layerStr.Length - 1; i >= 0; i--)
|
||||
{
|
||||
if (layerStr[i] < '0' || layerStr[i] > '9') break;
|
||||
layerIndexStr = $"{layerStr[i]}{layerIndexStr}";
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(layerIndexStr)) continue;
|
||||
if (!uint.TryParse(layerIndexStr, out var layerIndex)) continue;
|
||||
using var stream = pngEntry.Open();
|
||||
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(layerIndexStr)) continue;
|
||||
if (!uint.TryParse(layerIndexStr, out var layerIndex)) continue;
|
||||
using var stream = pngEntry.Open();
|
||||
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
|
||||
}
|
||||
|
||||
|
||||
GCode.ParseLayersFromGCode(this);
|
||||
|
||||
var firstLayer = FirstLayer;
|
||||
@@ -993,61 +996,43 @@ namespace UVtools.Core.FileFormats
|
||||
RaisePropertyChanged(nameof(GCodeStr));
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
|
||||
var arch = Environment.Is64BitOperatingSystem ? "64-bits" : "32-bits";
|
||||
var entry = outputFile.GetPutFile("slice.conf");
|
||||
var stream = entry.Open();
|
||||
stream.SetLength(0);
|
||||
|
||||
using (TextWriter tw = new StreamWriter(stream))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
|
||||
tw.WriteLine($"# {About.Website} {About.Software} {Assembly.GetExecutingAssembly().GetName().Version} {arch} {DateTime.UtcNow}");
|
||||
tw.WriteLine("# conf version 1.0");
|
||||
tw.WriteLine("");
|
||||
|
||||
foreach (var propertyInfo in SliceSettings.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
var displayNameAttribute = propertyInfo.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault();
|
||||
if (displayNameAttribute is null) continue;
|
||||
tw.WriteLine($"{displayNameAttribute.DisplayName.PadRight(24)}= {propertyInfo.GetValue(SliceSettings)}");
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
var entriesToRemove = outputFile.Entries.Where(zipEntry => zipEntry.Name.EndsWith(".gcode")).ToArray();
|
||||
foreach (var zipEntry in entriesToRemove)
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
zipEntry.Delete();
|
||||
}
|
||||
|
||||
using (var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update))
|
||||
{
|
||||
string arch = Environment.Is64BitOperatingSystem ? "64-bits" : "32-bits";
|
||||
var entry = outputFile.GetPutFile("slice.conf");
|
||||
var stream = entry.Open();
|
||||
stream.SetLength(0);
|
||||
outputFile.PutFileContent($"{About.Software}.gcode", GCodeStr, ZipArchiveMode.Update);
|
||||
|
||||
using (TextWriter tw = new StreamWriter(stream))
|
||||
{
|
||||
|
||||
tw.WriteLine($"# {About.Website} {About.Software} {Assembly.GetExecutingAssembly().GetName().Version} {arch} {DateTime.UtcNow}");
|
||||
tw.WriteLine("# conf version 1.0");
|
||||
tw.WriteLine("");
|
||||
|
||||
foreach (var propertyInfo in SliceSettings.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
var displayNameAttribute = propertyInfo.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault();
|
||||
if (displayNameAttribute is null) continue;
|
||||
tw.WriteLine($"{displayNameAttribute.DisplayName.PadRight(24)}= {propertyInfo.GetValue(SliceSettings)}");
|
||||
}
|
||||
}
|
||||
|
||||
var entriesToRemove = outputFile.Entries.Where(zipEntry => zipEntry.Name.EndsWith(".gcode")).ToArray();
|
||||
foreach (var zipEntry in entriesToRemove)
|
||||
{
|
||||
zipEntry.Delete();
|
||||
}
|
||||
|
||||
outputFile.PutFileContent($"{About.Software}.gcode", GCodeStr, ZipArchiveMode.Update);
|
||||
|
||||
/*foreach (var layer in this)
|
||||
/*foreach (var layer in this)
|
||||
{
|
||||
if (!layer.IsModified) continue;
|
||||
outputFile.PutFileContent(layer.Filename, layer.CompressedBytes, ZipArchiveMode.Update);
|
||||
layer.IsModified = false;
|
||||
}*/
|
||||
}
|
||||
|
||||
//Decode(FileFullPath, progress);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BinarySerialization;
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Structure;
|
||||
using MoreLinq;
|
||||
using UVtools.Core.Extensions;
|
||||
@@ -571,9 +570,9 @@ namespace UVtools.Core.FileFormats
|
||||
SlicerInfoSettings.WaitTimeBeforeCure = (ushort)Math.Max(1, WaitTimeBeforeCure);
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.ReadWrite);
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.ReadWrite);
|
||||
|
||||
if (ResolutionX == 1620 && ResolutionY == 2560)
|
||||
{
|
||||
@@ -790,9 +789,9 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.WriteLine("-End-");
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
|
||||
inputFile.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
@@ -812,10 +811,10 @@ namespace UVtools.Core.FileFormats
|
||||
if (expectedCheckSum != checkSum)
|
||||
{
|
||||
throw new FileLoadException($"Checksum fails, expecting: {expectedCheckSum} but got: {checkSum}.\n" +
|
||||
$"Try to reslice the file.", fileFullPath);
|
||||
$"Try to reslice the file.", FileFullPath);
|
||||
}
|
||||
|
||||
byte[][] previews = new byte[ThumbnailsOriginalSize.Length][];
|
||||
var previews = new byte[ThumbnailsOriginalSize.Length][];
|
||||
for (int i = 0; i < ThumbnailsOriginalSize.Length; i++)
|
||||
{
|
||||
previews[i] = new byte[ThumbnailsOriginalSize[i].Area() * 2];
|
||||
@@ -833,116 +832,80 @@ namespace UVtools.Core.FileFormats
|
||||
SlicerInfoSettings = Helpers.Deserialize<SlicerInfo>(inputFile);
|
||||
Debug.WriteLine(SlicerInfoSettings);
|
||||
|
||||
LayerManager.Init(HeaderSettings.LayerCount);
|
||||
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
inputFile.Seek(LayerCount * 4 + 2, SeekOrigin.Current); // Skip pre layers
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
/*var preLayers = new PreLayer[LayerCount];
|
||||
for (int layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
preLayers[layerIndex] = Helpers.Deserialize<PreLayer>(inputFile);
|
||||
progress++;
|
||||
}*/
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
|
||||
//inputFile.Seek(2, SeekOrigin.Current);
|
||||
|
||||
var linesBytes = new byte[LayerCount][];
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
foreach (var layerIndex in batch)
|
||||
var linesBytes = new byte[LayerCount][];
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
{
|
||||
inputFile.Seek(4, SeekOrigin.Current);
|
||||
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
||||
|
||||
linesBytes[layerIndex] = new byte[lineCount * 6];
|
||||
inputFile.ReadBytes(linesBytes[layerIndex]);
|
||||
inputFile.Seek(2, SeekOrigin.Current);
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = EmguExtensions.InitMat(Resolution))
|
||||
foreach (var layerIndex in batch)
|
||||
{
|
||||
inputFile.Seek(4, SeekOrigin.Current);
|
||||
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
||||
|
||||
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
|
||||
{
|
||||
LayerLine line = new()
|
||||
{
|
||||
Coordinates =
|
||||
{
|
||||
[0] = linesBytes[layerIndex][i++],
|
||||
[1] = linesBytes[layerIndex][i++],
|
||||
[2] = linesBytes[layerIndex][i++],
|
||||
[3] = linesBytes[layerIndex][i++],
|
||||
[4] = linesBytes[layerIndex][i++]
|
||||
},
|
||||
Gray = linesBytes[layerIndex][i]
|
||||
};
|
||||
linesBytes[layerIndex] = new byte[lineCount * 6];
|
||||
inputFile.ReadBytes(linesBytes[layerIndex]);
|
||||
inputFile.Seek(2, SeekOrigin.Current);
|
||||
|
||||
CvInvoke.Line(mat, new Point(line.StartX, line.StartY), new Point(line.StartX, line.EndY),
|
||||
new MCvScalar(line.Gray));
|
||||
}
|
||||
|
||||
linesBytes[layerIndex] = null;
|
||||
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = EmguExtensions.InitMat(Resolution))
|
||||
{
|
||||
|
||||
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
|
||||
{
|
||||
LayerLine line = new()
|
||||
{
|
||||
Coordinates =
|
||||
{
|
||||
[0] = linesBytes[layerIndex][i++],
|
||||
[1] = linesBytes[layerIndex][i++],
|
||||
[2] = linesBytes[layerIndex][i++],
|
||||
[3] = linesBytes[layerIndex][i++],
|
||||
[4] = linesBytes[layerIndex][i++]
|
||||
},
|
||||
Gray = linesBytes[layerIndex][i]
|
||||
};
|
||||
|
||||
CvInvoke.Line(mat, new Point(line.StartX, line.StartY),
|
||||
new Point(line.StartX, line.EndY),
|
||||
new MCvScalar(line.Gray));
|
||||
}
|
||||
|
||||
linesBytes[layerIndex] = null;
|
||||
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
}
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
else // Partial read
|
||||
{
|
||||
inputFile.Seek(-Helpers.Serializer.SizeOf(FooterSettings), SeekOrigin.End);
|
||||
}
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
/*var layerDefs = new LayerDef[LayerCount];
|
||||
for (int layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
layerDefs[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
|
||||
progress++;
|
||||
}
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
Parallel.For(0, LayerCount, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using var mat = EmguExtensions.InitMat(Resolution);
|
||||
foreach (var line in layerDefs[layerIndex].Lines)
|
||||
{
|
||||
CvInvoke.Line(mat, new Point(line.StartX, line.StartY), new Point(line.StartX, line.EndY), new MCvScalar(line.Gray));
|
||||
}
|
||||
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
progress.LockAndIncrement();
|
||||
});*/
|
||||
|
||||
FooterSettings = Helpers.Deserialize<Footer>(inputFile);
|
||||
FooterSettings.Validate();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
var offset = Helpers.Serializer.SizeOf(HeaderSettings);
|
||||
foreach (var size in ThumbnailsOriginalSize)
|
||||
{
|
||||
|
||||
@@ -499,9 +499,9 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
|
||||
|
||||
if (ResolutionX == 2560 && ResolutionY == 1620)
|
||||
{
|
||||
@@ -628,9 +628,9 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.WriteLine("-End-");
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
HeaderSettings.Validate();
|
||||
|
||||
@@ -654,62 +654,67 @@ namespace UVtools.Core.FileFormats
|
||||
SlicerInfoSettings = Helpers.Deserialize<SlicerInfo>(inputFile);
|
||||
Debug.WriteLine(SlicerInfoSettings);
|
||||
|
||||
LayerManager.Init(HeaderSettings.LayerCount);
|
||||
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
inputFile.Seek(LayerCount * 4 + 2, SeekOrigin.Current); // Skip pre layers
|
||||
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
|
||||
var range = Enumerable.Range(0, (int)LayerCount);
|
||||
|
||||
var linesBytes = new byte[LayerCount][];
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
foreach (var layerIndex in batch)
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
var linesBytes = new byte[LayerCount][];
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
{
|
||||
inputFile.Seek(4, SeekOrigin.Current);
|
||||
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
||||
|
||||
linesBytes[layerIndex] = new byte[lineCount * 6];
|
||||
inputFile.ReadBytes(linesBytes[layerIndex]);
|
||||
inputFile.Seek(2, SeekOrigin.Current);
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = EmguExtensions.InitMat(Resolution))
|
||||
foreach (var layerIndex in batch)
|
||||
{
|
||||
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
|
||||
{
|
||||
LayerLine line = new()
|
||||
{
|
||||
Coordinates =
|
||||
{
|
||||
[0] = linesBytes[layerIndex][i++],
|
||||
[1] = linesBytes[layerIndex][i++],
|
||||
[2] = linesBytes[layerIndex][i++],
|
||||
[3] = linesBytes[layerIndex][i++],
|
||||
[4] = linesBytes[layerIndex][i++]
|
||||
},
|
||||
Gray = linesBytes[layerIndex][i]
|
||||
};
|
||||
inputFile.Seek(4, SeekOrigin.Current);
|
||||
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
||||
|
||||
CvInvoke.Line(mat, new Point(line.StartX, line.StartY), new Point(line.StartX, line.EndY),
|
||||
new MCvScalar(line.Gray));
|
||||
}
|
||||
linesBytes[layerIndex] = new byte[lineCount * 6];
|
||||
inputFile.ReadBytes(linesBytes[layerIndex]);
|
||||
inputFile.Seek(2, SeekOrigin.Current);
|
||||
|
||||
linesBytes[layerIndex] = null;
|
||||
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = EmguExtensions.InitMat(Resolution))
|
||||
{
|
||||
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
|
||||
{
|
||||
LayerLine line = new()
|
||||
{
|
||||
Coordinates =
|
||||
{
|
||||
[0] = linesBytes[layerIndex][i++],
|
||||
[1] = linesBytes[layerIndex][i++],
|
||||
[2] = linesBytes[layerIndex][i++],
|
||||
[3] = linesBytes[layerIndex][i++],
|
||||
[4] = linesBytes[layerIndex][i++]
|
||||
},
|
||||
Gray = linesBytes[layerIndex][i]
|
||||
};
|
||||
|
||||
CvInvoke.Line(mat, new Point(line.StartX, line.StartY),
|
||||
new Point(line.StartX, line.EndY),
|
||||
new MCvScalar(line.Gray));
|
||||
}
|
||||
|
||||
linesBytes[layerIndex] = null;
|
||||
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
}
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
else // Partial read
|
||||
{
|
||||
inputFile.Seek(-Helpers.Serializer.SizeOf(FooterSettings), SeekOrigin.End);
|
||||
}
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
@@ -718,24 +723,8 @@ namespace UVtools.Core.FileFormats
|
||||
FooterSettings.Validate();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
var offset = Helpers.Serializer.SizeOf(HeaderSettings);
|
||||
foreach (var size in ThumbnailsOriginalSize)
|
||||
{
|
||||
|
||||
@@ -1775,7 +1775,7 @@ namespace UVtools.Core.FileFormats
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
SanitizeMagicVersion();
|
||||
SanitizeProperties();
|
||||
@@ -1799,7 +1799,7 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
//uint currentOffset = (uint)Helpers.Serializer.SizeOf(HeaderSettings);
|
||||
LayerDefinitions = new LayerDef[HeaderSettings.AntiAliasLevel, HeaderSettings.LayerCount];
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
|
||||
outputFile.Seek(Helpers.Serializer.SizeOf(HeaderSettings), SeekOrigin.Begin);
|
||||
|
||||
Mat[] thumbnails = {GetThumbnail(true), GetThumbnail(false)};
|
||||
@@ -1956,16 +1956,16 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
//HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile);
|
||||
//HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header))));
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
|
||||
if (HeaderSettings.Magic is not MAGIC_CBDDLP and not MAGIC_CTB and not MAGIC_CTBv4)
|
||||
{
|
||||
throw new FileLoadException($"Not a valid PHOTON nor CBDDLP nor CTB file! Magic Value: {HeaderSettings.Magic}", fileFullPath);
|
||||
throw new FileLoadException($"Not a valid PHOTON nor CBDDLP nor CTB file! Magic Value: {HeaderSettings.Magic}", FileFullPath);
|
||||
}
|
||||
|
||||
if (HeaderSettings.Version == 1 || HeaderSettings.AntiAliasLevel == 0)
|
||||
@@ -1973,8 +1973,6 @@ namespace UVtools.Core.FileFormats
|
||||
HeaderSettings.AntiAliasLevel = 1;
|
||||
}
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodePreviews, ThumbnailsCount);
|
||||
|
||||
Debug.Write("Header -> ");
|
||||
@@ -2031,7 +2029,7 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
throw new FileLoadException(
|
||||
$"Malformed file, PrintParametersV4Address is missing",
|
||||
fileFullPath);
|
||||
FileFullPath);
|
||||
}
|
||||
|
||||
inputFile.Seek(SlicerInfoSettings.PrintParametersV4Address, SeekOrigin.Begin);
|
||||
@@ -2044,7 +2042,7 @@ namespace UVtools.Core.FileFormats
|
||||
throw new FileLoadException(
|
||||
$"Malformed file, PrintParametersV4 found invalid validation values, expected (4, 4) " +
|
||||
$"but got ({PrintParametersV4Settings.Four1}, {PrintParametersV4Settings.Four2})",
|
||||
fileFullPath);
|
||||
FileFullPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2053,8 +2051,7 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
uint layerOffset = HeaderSettings.LayersDefinitionOffsetAddress;
|
||||
|
||||
progress.Reset(OperationProgress.StatusGatherLayers,
|
||||
HeaderSettings.AntiAliasLevel * HeaderSettings.LayerCount);
|
||||
progress.Reset(OperationProgress.StatusGatherLayers, HeaderSettings.AntiAliasLevel * HeaderSettings.LayerCount);
|
||||
|
||||
for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++)
|
||||
{
|
||||
@@ -2089,65 +2086,52 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
LayerManager.Init(HeaderSettings.LayerCount);
|
||||
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
foreach (var layerIndex in batch)
|
||||
{
|
||||
for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++)
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
|
||||
inputFile.Seek(LayerDefinitions[aaIndex, layerIndex].DataAddress, SeekOrigin.Begin);
|
||||
LayerDefinitions[aaIndex, layerIndex].EncodedRle = inputFile.ReadBytes(LayerDefinitions[aaIndex, layerIndex].DataSize);
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
{
|
||||
foreach (var layerIndex in batch)
|
||||
{
|
||||
for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++)
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
inputFile.Seek(LayerDefinitions[aaIndex, layerIndex].DataAddress, SeekOrigin.Begin);
|
||||
LayerDefinitions[aaIndex, layerIndex].EncodedRle = inputFile.ReadBytes(LayerDefinitions[aaIndex, layerIndex].DataSize);
|
||||
}
|
||||
}
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using var mat = LayerDefinitions[0, layerIndex].Decode((uint)layerIndex);
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = LayerDefinitions[0, layerIndex].Decode((uint)layerIndex))
|
||||
{
|
||||
var layer = new Layer((uint)layerIndex, mat, this);
|
||||
if (layerDefinitionsEx is not null) // CTBv4
|
||||
{
|
||||
layerDefinitionsEx[layerIndex].CopyTo(layer);
|
||||
}
|
||||
else // others
|
||||
{
|
||||
LayerDefinitions[0, layerIndex].CopyTo(layer);
|
||||
}
|
||||
|
||||
this[layerIndex] = layer;
|
||||
}
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
if (layerDefinitionsEx is not null) // CTBv4
|
||||
{
|
||||
layerDefinitionsEx[layerIndex].CopyTo(this[layerIndex]);
|
||||
}
|
||||
else // others
|
||||
{
|
||||
LayerDefinitions[0, layerIndex].CopyTo(this[layerIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
SanitizeProperties();
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
|
||||
outputFile.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
@@ -401,9 +401,9 @@ namespace UVtools.Core.FileFormats
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create))
|
||||
using (ZipArchive outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create))
|
||||
{
|
||||
if (Thumbnails.Length > 0 && Thumbnails[0] is not null)
|
||||
{
|
||||
@@ -416,14 +416,10 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
if (Thumbnails.Length > 1 && Thumbnails[1] is not null)
|
||||
{
|
||||
using (Stream stream = outputFile.CreateEntry("preview_cropping.png").Open())
|
||||
{
|
||||
using (var vec = new VectorOfByte())
|
||||
{
|
||||
stream.WriteBytes(Thumbnails[1].GetPngByes());
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
using Stream stream = outputFile.CreateEntry("preview_cropping.png").Open();
|
||||
using var vec = new VectorOfByte();
|
||||
stream.WriteBytes(Thumbnails[1].GetPngByes());
|
||||
stream.Close();
|
||||
}
|
||||
|
||||
if (!IsPHZZip)
|
||||
@@ -443,7 +439,7 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
|
||||
{
|
||||
@@ -497,24 +493,27 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
LayerManager.Init(HeaderSettings.LayerCount);
|
||||
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
|
||||
progress.ItemCount = LayerCount;
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) break;
|
||||
entry = inputFile.GetEntry($"{layerIndex+1}.png");
|
||||
if (entry is null)
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"Layer {layerIndex+1} not found", fileFullPath);
|
||||
if (progress.Token.IsCancellationRequested) break;
|
||||
entry = inputFile.GetEntry($"{layerIndex + 1}.png");
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"Layer {layerIndex + 1} not found", FileFullPath);
|
||||
}
|
||||
|
||||
using var stream = entry.Open();
|
||||
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
|
||||
|
||||
progress++;
|
||||
}
|
||||
|
||||
using var stream = entry.Open();
|
||||
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
|
||||
|
||||
progress++;
|
||||
}
|
||||
|
||||
if (IsPHZZip) // PHZ file
|
||||
@@ -561,24 +560,8 @@ namespace UVtools.Core.FileFormats
|
||||
RaisePropertyChanged(nameof(GCodeStr));
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
|
||||
var entriesToRemove = outputFile.Entries.Where(zipEntry => zipEntry.Name.EndsWith(".gcode")).ToArray();
|
||||
foreach (var zipEntry in entriesToRemove)
|
||||
|
||||
@@ -904,7 +904,7 @@ namespace UVtools.Core.FileFormats
|
||||
LayersDefinitions = null;
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
/*if (HeaderSettings.EncryptionKey == 0)
|
||||
{
|
||||
@@ -912,7 +912,7 @@ namespace UVtools.Core.FileFormats
|
||||
HeaderSettings.EncryptionKey = (uint)rnd.Next(short.MaxValue, int.MaxValue);
|
||||
}*/
|
||||
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
|
||||
outputFile.Seek(Helpers.Serializer.SizeOf(HeaderSettings), SeekOrigin.Begin);
|
||||
|
||||
for (byte i = 0; i < ThumbnailsCount; i++)
|
||||
@@ -1021,22 +1021,19 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.WriteLine("-End-");
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
//HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile);
|
||||
//HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header))));
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
if (HeaderSettings.Magic != MAGIC)
|
||||
{
|
||||
throw new FileLoadException("Not a valid FDG file!", fileFullPath);
|
||||
throw new FileLoadException("Not a valid FDG file!", FileFullPath);
|
||||
}
|
||||
|
||||
HeaderSettings.AntiAliasLevel = 1;
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodePreviews, ThumbnailsCount);
|
||||
Debug.Write("Header -> ");
|
||||
Debug.WriteLine(HeaderSettings);
|
||||
@@ -1070,7 +1067,7 @@ namespace UVtools.Core.FileFormats
|
||||
HeaderSettings.MachineName = Encoding.ASCII.GetString(buffer);
|
||||
}
|
||||
|
||||
LayerManager.Init(HeaderSettings.LayerCount);
|
||||
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
LayersDefinitions = new LayerDef[HeaderSettings.LayerCount];
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, HeaderSettings.LayerCount);
|
||||
@@ -1087,45 +1084,37 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.Write($"LAYER {layerIndex} -> ");
|
||||
Debug.WriteLine(layerDef);
|
||||
|
||||
inputFile.SeekDoWorkAndRewind(layerDef.DataAddress, () =>
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
layerDef.EncodedRle = inputFile.ReadBytes(layerDef.DataSize);
|
||||
});
|
||||
inputFile.SeekDoWorkAndRewind(layerDef.DataAddress,
|
||||
() => { layerDef.EncodedRle = inputFile.ReadBytes(layerDef.DataSize); });
|
||||
}
|
||||
}
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex))
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
var layer = new Layer((uint)layerIndex, mat, this);
|
||||
LayersDefinitions[layerIndex].CopyTo(layer);
|
||||
this[layerIndex] = layer;
|
||||
}
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
using var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex);
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
}
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
LayersDefinitions[layerIndex].CopyTo(this[layerIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
|
||||
outputFile.Seek(0, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
|
||||
@@ -121,6 +121,19 @@ namespace UVtools.Core.FileFormats
|
||||
Small = 0,
|
||||
Large
|
||||
}
|
||||
|
||||
public enum FileDecodeType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Decodes all the file information and caches layer images
|
||||
/// </summary>
|
||||
Full,
|
||||
|
||||
/// <summary>
|
||||
/// Decodes only the information in the file and thumbnails, no layer image is read nor cached, fast
|
||||
/// </summary>
|
||||
Partial,
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Sub Classes
|
||||
@@ -441,6 +454,17 @@ namespace UVtools.Core.FileFormats
|
||||
return PathExtensions.GetFileNameStripExtensions(filepath, AllFileExtensionsString.OrderByDescending(s => s.Length).ToList(), out strippedExtension);
|
||||
}
|
||||
|
||||
public static FileFormat Open(string fileFullPath, FileDecodeType decodeType, OperationProgress progress = null)
|
||||
{
|
||||
var slicerFile = FindByExtensionOrFilePath(fileFullPath, true);
|
||||
if (slicerFile is null) return null;
|
||||
slicerFile.Decode(fileFullPath, decodeType, progress);
|
||||
return slicerFile;
|
||||
}
|
||||
|
||||
public static FileFormat Open(string fileFullPath, OperationProgress progress = null) =>
|
||||
Open(fileFullPath, FileDecodeType.Full, progress);
|
||||
|
||||
|
||||
public static byte[] EncodeImage(string dataType, Mat mat)
|
||||
{
|
||||
@@ -762,6 +786,8 @@ namespace UVtools.Core.FileFormats
|
||||
/// </summary>
|
||||
public abstract FileExtension[] FileExtensions { get; }
|
||||
|
||||
public FileDecodeType DecodeType { get; private set; } = FileDecodeType.Full;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available <see cref="PrintParameterModifier"/>
|
||||
/// </summary>
|
||||
@@ -847,6 +873,7 @@ namespace UVtools.Core.FileFormats
|
||||
/// </summary>
|
||||
public string FileFullPath { get; set; }
|
||||
|
||||
public string FileDirectoryPath => Path.GetDirectoryName(FileFullPath);
|
||||
public string Filename => Path.GetFileName(FileFullPath);
|
||||
public string FileExtension => Path.GetExtension(FileFullPath);
|
||||
public string FilenameNoExt => GetFileNameStripExtensions(FileFullPath);
|
||||
@@ -2520,9 +2547,8 @@ namespace UVtools.Core.FileFormats
|
||||
/// <summary>
|
||||
/// Encode to an output file
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath">Output file</param>
|
||||
/// <param name="progress"></param>
|
||||
protected abstract void EncodeInternally(string fileFullPath, OperationProgress progress);
|
||||
protected abstract void EncodeInternally(OperationProgress progress);
|
||||
|
||||
/// <summary>
|
||||
/// Encode to an output file
|
||||
@@ -2531,6 +2557,11 @@ namespace UVtools.Core.FileFormats
|
||||
/// <param name="progress"></param>
|
||||
public void Encode(string fileFullPath, OperationProgress progress = null)
|
||||
{
|
||||
if (DecodeType == FileDecodeType.Partial)
|
||||
{
|
||||
throw new InvalidOperationException("File was partial decoded, a full encode is not possible.");
|
||||
}
|
||||
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount);
|
||||
|
||||
@@ -2543,12 +2574,9 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
LayerManager.Sanitize();
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
if (File.Exists(fileFullPath)) File.Delete(fileFullPath);
|
||||
|
||||
if (File.Exists(fileFullPath))
|
||||
{
|
||||
File.Delete(fileFullPath);
|
||||
}
|
||||
FileFullPath = fileFullPath;
|
||||
|
||||
for (var i = 0; i < Thumbnails.Length; i++)
|
||||
{
|
||||
@@ -2557,7 +2585,7 @@ namespace UVtools.Core.FileFormats
|
||||
CvInvoke.Resize(Thumbnails[i], Thumbnails[i], new Size(ThumbnailsOriginalSize[i].Width, ThumbnailsOriginalSize[i].Height));
|
||||
}
|
||||
|
||||
EncodeInternally(fileFullPath, progress);
|
||||
EncodeInternally(progress);
|
||||
|
||||
LayerManager.SetAllIsModified(false);
|
||||
RequireFullEncode = false;
|
||||
@@ -2566,24 +2594,32 @@ namespace UVtools.Core.FileFormats
|
||||
/// <summary>
|
||||
/// Decode a slicer file
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath"></param>
|
||||
/// <param name="progress"></param>
|
||||
protected abstract void DecodeInternally(string fileFullPath, OperationProgress progress);
|
||||
protected abstract void DecodeInternally(OperationProgress progress);
|
||||
|
||||
/// <summary>
|
||||
/// Decode a slicer file
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath"></param>
|
||||
/// <param name="progress"></param>
|
||||
public void Decode(string fileFullPath, OperationProgress progress = null)
|
||||
public void Decode(string fileFullPath, OperationProgress progress = null) => Decode(fileFullPath, FileDecodeType.Full, progress);
|
||||
|
||||
/// <summary>
|
||||
/// Decode a slicer file
|
||||
/// </summary>
|
||||
/// <param name="fileFullPath"></param>
|
||||
/// <param name="fileDecodeType"></param>
|
||||
/// <param name="progress"></param>
|
||||
public void Decode(string fileFullPath, FileDecodeType fileDecodeType, OperationProgress progress = null)
|
||||
{
|
||||
Clear();
|
||||
FileValidation(fileFullPath);
|
||||
FileFullPath = fileFullPath;
|
||||
DecodeType = fileDecodeType;
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(OperationProgress.StatusGatherLayers, LayerCount);
|
||||
|
||||
DecodeInternally(fileFullPath, progress);
|
||||
DecodeInternally(progress);
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
@@ -2745,20 +2781,15 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
if (LayerCount > 0)
|
||||
if (LayerCount > 0 && DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
Parallel.ForEach(this, CoreSettings.ParallelOptions, layer =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
var byteArr = layer.CompressedBytes;
|
||||
using var stream = File.Create(Path.Combine(path, layer.Filename),
|
||||
byteArr.Length);
|
||||
if (byteArr is null) return;
|
||||
using var stream = new FileStream(Path.Combine(path, layer.Filename), FileMode.Create, FileAccess.Write);
|
||||
stream.Write(byteArr, 0, byteArr.Length);
|
||||
stream.Close();
|
||||
|
||||
//using var mat = layer.LayerMat;
|
||||
//mat.Save(Path.Combine(path, $"{layer.Filename}.jpg"));
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
@@ -3343,7 +3374,34 @@ namespace UVtools.Core.FileFormats
|
||||
/// </summary>
|
||||
/// <param name="filePath">File path to save copy as, use null to overwrite active file (Same as <see cref="Save"/>)</param>
|
||||
/// <param name="progress"></param>
|
||||
public abstract void SaveAs(string filePath = null, OperationProgress progress = null);
|
||||
public void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
|
||||
}
|
||||
|
||||
PartialSaveInternally(progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Partial save of the file, this is the file information only.
|
||||
/// When this function is called it's already ready to save to file
|
||||
/// </summary>
|
||||
/// <param name="progress"></param>
|
||||
protected abstract void PartialSaveInternally(OperationProgress progress);
|
||||
|
||||
/// <summary>
|
||||
/// Triggers when a conversion is valid and before start converting values
|
||||
|
||||
@@ -446,17 +446,17 @@ namespace UVtools.Core.FileFormats
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
if (SVGDocument.PrintParameters.ResolutionX == 0 || SVGDocument.PrintParameters.ResolutionY == 0 ||
|
||||
SVGDocument.PrintParameters.DisplayWidth == 0 || SVGDocument.PrintParameters.DisplayHeight == 0)
|
||||
{
|
||||
throw new FileLoadException("This file does not contain a resolution and/or display size information needed to generate the layer images.\n" +
|
||||
"Note that FlashDLPrint slicer is unable to output files with the required information to load in here.\n" +
|
||||
"Please use other compatible slicer capable of output the correct information to load the file in here.", fileFullPath);
|
||||
"Please use other compatible slicer capable of output the correct information to load the file in here.", FileFullPath);
|
||||
}
|
||||
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
|
||||
outputFile.Seek(Helpers.Serializer.SizeOf(HeaderSettings), SeekOrigin.Begin);
|
||||
|
||||
HeaderSettings.Preview1Address = 0;
|
||||
@@ -594,13 +594,13 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.WriteLine("-End-");
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
if (HeaderSettings.Identifier != Header.IdentifierText)
|
||||
{
|
||||
throw new FileLoadException("Not a valid Flashforge SVGX file!", fileFullPath);
|
||||
throw new FileLoadException("Not a valid Flashforge SVGX file!", FileFullPath);
|
||||
}
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodePreviews, ThumbnailsCount);
|
||||
@@ -644,15 +644,16 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
throw new FileLoadException("This file does not contain a resolution and/or display size information needed to generate the layer images.\n" +
|
||||
"Note that FlashDLPrint slicer is unable to output files with the required information to load in here.\n" +
|
||||
"Please use other compatible slicer capable of output the correct information to load the file in here.", fileFullPath);
|
||||
"Please use other compatible slicer capable of output the correct information to load the file in here.", FileFullPath);
|
||||
}
|
||||
|
||||
var halfDisplay = Display.Half();
|
||||
var ppmm = Ppmm;
|
||||
|
||||
LayerManager.Init(SVGDocument.PrintParameters.LayerCount);
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
LayerManager.Init(SVGDocument.PrintParameters.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
|
||||
if (DecodeType != FileDecodeType.Full) return;
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
Parallel.For(0, LayerCount, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
@@ -661,14 +662,15 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
var group = SVGDocument.Groups.FirstOrDefault(g => g.Id == $"layer-{layerIndex}");
|
||||
|
||||
if (group is not null)
|
||||
if (@group is not null)
|
||||
{
|
||||
var pointsOfPoints = new List<Point[]>();
|
||||
var points = new List<Point>();
|
||||
foreach (var path in group.Paths)
|
||||
foreach (var path in @group.Paths)
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) break;
|
||||
var spaceSplit = path.Value.Split(' ', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
||||
var spaceSplit = path.Value.Split(' ',
|
||||
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
for (int i = 0; i < spaceSplit.Length; i++)
|
||||
{
|
||||
@@ -679,8 +681,10 @@ namespace UVtools.Core.FileFormats
|
||||
pointsOfPoints.Add(points.ToArray());
|
||||
points.Clear();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spaceSplit[i] == "Z")
|
||||
{
|
||||
if (points.Count > 0)
|
||||
@@ -688,9 +692,12 @@ namespace UVtools.Core.FileFormats
|
||||
pointsOfPoints.Add(points.ToArray());
|
||||
points.Clear();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if (spaceSplit[i].Length == 1 && !char.IsDigit(spaceSplit[i][0])) continue; // Ignore any other not processed 1 char that's not a digit (L)
|
||||
|
||||
if (spaceSplit[i].Length == 1 && !char.IsDigit(spaceSplit[i][0]))
|
||||
continue; // Ignore any other not processed 1 char that's not a digit (L)
|
||||
|
||||
if (i + 1 >= spaceSplit.Length) break; // No more to see
|
||||
|
||||
@@ -730,24 +737,8 @@ namespace UVtools.Core.FileFormats
|
||||
});
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
|
||||
outputFile.Seek(HeaderSettings.SVGDocumentAddress, SeekOrigin.Begin);
|
||||
outputFile.SetLength(outputFile.Position);
|
||||
|
||||
@@ -354,9 +354,9 @@ namespace UVtools.Core.FileFormats
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
|
||||
var pageBreak = PageBreak.Bytes;
|
||||
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
@@ -465,13 +465,13 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
if (HeaderSettings.HeaderValue != Header.HEADER_VALUE)
|
||||
{
|
||||
throw new FileLoadException("Not a valid Makerbase file!", fileFullPath);
|
||||
throw new FileLoadException("Not a valid Makerbase file!", FileFullPath);
|
||||
}
|
||||
|
||||
byte[][] previews = new byte[ThumbnailsOriginalSize.Length][];
|
||||
@@ -491,77 +491,65 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
SlicerInfoSettings = Helpers.Deserialize<SlicerInfo>(inputFile);
|
||||
|
||||
LayerManager.Init(SlicerInfoSettings.LayerCount);
|
||||
LayerManager.Init(SlicerInfoSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
|
||||
var range = Enumerable.Range(0, (int)LayerCount);
|
||||
|
||||
var linesBytes = new byte[LayerCount][];
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
foreach (var layerIndex in batch)
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
var linesBytes = new byte[LayerCount][];
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
{
|
||||
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
||||
|
||||
linesBytes[layerIndex] = new byte[lineCount * 6];
|
||||
inputFile.ReadBytes(linesBytes[layerIndex]);
|
||||
inputFile.Seek(2, SeekOrigin.Current);
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using var mat = EmguExtensions.InitMat(Resolution);
|
||||
|
||||
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
|
||||
foreach (var layerIndex in batch)
|
||||
{
|
||||
var startY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
|
||||
var endY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
|
||||
var startX = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i]);
|
||||
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
||||
|
||||
CvInvoke.Line(mat, new Point(startX, startY), new Point(startX, endY), EmguExtensions.WhiteColor);
|
||||
linesBytes[layerIndex] = new byte[lineCount * 6];
|
||||
inputFile.ReadBytes(linesBytes[layerIndex]);
|
||||
inputFile.Seek(2, SeekOrigin.Current);
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
linesBytes[layerIndex] = null;
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using var mat = EmguExtensions.InitMat(Resolution);
|
||||
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
|
||||
{
|
||||
var startY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
|
||||
var endY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
|
||||
var startX = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i]);
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
CvInvoke.Line(mat, new Point(startX, startY), new Point(startX, endY),
|
||||
EmguExtensions.WhiteColor);
|
||||
}
|
||||
|
||||
linesBytes[layerIndex] = null;
|
||||
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
else // Partial read
|
||||
{
|
||||
inputFile.Seek(-Helpers.Serializer.SizeOf(HeaderSettings), SeekOrigin.End);
|
||||
}
|
||||
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
if (HeaderSettings.HeaderValue != Header.HEADER_VALUE)
|
||||
{
|
||||
throw new FileLoadException("Not a valid Makerbase file!", fileFullPath);
|
||||
throw new FileLoadException("Not a valid Makerbase file!", FileFullPath);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
|
||||
outputFile.Seek(SlicerInfoAddress, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, SlicerInfoSettings);
|
||||
|
||||
@@ -77,14 +77,14 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
private Mat ImageMat { get; set; }
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
this[0].LayerMat.Save(FileFullPath);
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
ImageMat = CvInvoke.Imread(fileFullPath, ImreadModes.Grayscale);
|
||||
ImageMat = CvInvoke.Imread(FileFullPath, ImreadModes.Grayscale);
|
||||
const byte startDivisor = 2;
|
||||
for (int i = 0; i < ThumbnailsCount; i++)
|
||||
{
|
||||
@@ -102,9 +102,9 @@ namespace UVtools.Core.FileFormats
|
||||
this[0] = new Layer(0, ImageMat, LayerManager);
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
this[0].LayerMat.Save(filePath ?? FileFullPath);
|
||||
this[0].LayerMat.Save(FileFullPath);
|
||||
}
|
||||
|
||||
public override FileFormat Convert(Type to, string fileFullPath, OperationProgress progress = null)
|
||||
|
||||
@@ -487,7 +487,7 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
if (FileEndsWith(".lgs")) // Longer Orange 10
|
||||
{
|
||||
@@ -511,7 +511,7 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
|
||||
//uint currentOffset = (uint)Helpers.Serializer.SizeOf(HeaderSettings);
|
||||
using (var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write))
|
||||
using (var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
outputFile.WriteSerialize(HeaderSettings);
|
||||
outputFile.WriteBytes(EncodeImage(DATATYPE_RGB565_BE, Thumbnails[0]));
|
||||
@@ -566,13 +566,13 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.WriteLine("-End-");
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
if (HeaderSettings.Name != Header.NameValue)
|
||||
{
|
||||
throw new FileLoadException("Not a valid LGS file!", fileFullPath);
|
||||
throw new FileLoadException("Not a valid LGS file!", FileFullPath);
|
||||
}
|
||||
|
||||
//if (HeaderSettings.PrinterModel is 10 or 30 or 120)
|
||||
@@ -594,54 +594,38 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
|
||||
|
||||
LayerManager.Init(HeaderSettings.LayerCount);
|
||||
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
var layerData = new LayerDef[LayerCount];
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
foreach (var layerIndex in batch)
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
layerData[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
|
||||
layerData[layerIndex].Parent = this;
|
||||
}
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = layerData[layerIndex].Decode())
|
||||
foreach (var layerIndex in batch)
|
||||
{
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
layerData[layerIndex] = Helpers.Deserialize<LayerDef>(inputFile);
|
||||
layerData[layerIndex].Parent = this;
|
||||
}
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using var mat = layerData[layerIndex].Decode();
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
LayerManager.RebuildLayersProperties();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
|
||||
outputFile.Seek(0, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
|
||||
@@ -315,9 +315,9 @@ namespace UVtools.Core.FileFormats
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
|
||||
var pageBreak = PageBreak.Bytes;
|
||||
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
@@ -425,9 +425,9 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
//HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile);
|
||||
//HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header))));
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
@@ -450,76 +450,62 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
SlicerInfoSettings = Helpers.Deserialize<SlicerInfo>(inputFile);
|
||||
|
||||
LayerManager.Init(SlicerInfoSettings.LayerCount);
|
||||
LayerManager.Init(SlicerInfoSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
|
||||
var range = Enumerable.Range(0, (int)LayerCount);
|
||||
|
||||
var linesBytes = new byte[LayerCount][];
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
foreach (var layerIndex in batch)
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
var linesBytes = new byte[LayerCount][];
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
{
|
||||
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
||||
|
||||
linesBytes[layerIndex] = new byte[lineCount * 6];
|
||||
inputFile.ReadBytes(linesBytes[layerIndex]);
|
||||
inputFile.Seek(2, SeekOrigin.Current);
|
||||
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = EmguExtensions.InitMat(Resolution))
|
||||
foreach (var layerIndex in batch)
|
||||
{
|
||||
var lineCount = BitExtensions.ToUIntBigEndian(inputFile.ReadBytes(4));
|
||||
|
||||
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
|
||||
{
|
||||
var startY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
|
||||
var endY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
|
||||
var startX = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i]);
|
||||
linesBytes[layerIndex] = new byte[lineCount * 6];
|
||||
inputFile.ReadBytes(linesBytes[layerIndex]);
|
||||
inputFile.Seek(2, SeekOrigin.Current);
|
||||
|
||||
CvInvoke.Line(mat, new Point(startX, startY), new Point(startX, endY), EmguExtensions.WhiteColor);
|
||||
}
|
||||
|
||||
linesBytes[layerIndex] = null;
|
||||
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = EmguExtensions.InitMat(Resolution))
|
||||
{
|
||||
|
||||
for (int i = 0; i < linesBytes[layerIndex].Length; i++)
|
||||
{
|
||||
var startY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
|
||||
var endY = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i++]);
|
||||
var startX = BitExtensions.ToUShortBigEndian(linesBytes[layerIndex][i++], linesBytes[layerIndex][i]);
|
||||
|
||||
CvInvoke.Line(mat, new Point(startX, startY), new Point(startX, endY), EmguExtensions.WhiteColor);
|
||||
}
|
||||
|
||||
linesBytes[layerIndex] = null;
|
||||
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
}
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
else // Partial read
|
||||
{
|
||||
inputFile.Seek(-Helpers.Serializer.SizeOf(HeaderSettings), SeekOrigin.End);
|
||||
}
|
||||
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
HeaderSettings.Validate();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
|
||||
outputFile.Seek(SlicerInfoAddress, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, SlicerInfoSettings);
|
||||
|
||||
@@ -465,9 +465,9 @@ namespace UVtools.Core.FileFormats
|
||||
Previews = null;
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
|
||||
FileSettings.Update();
|
||||
var fileDefSize = Helpers.SerializeWriteFileStream(outputFile, FileSettings);
|
||||
HeaderSettings.TableSize = (uint)Helpers.Serializer.SizeOf(HeaderSettings);
|
||||
@@ -598,9 +598,9 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.WriteLine("-End-");
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
FileSettings = Helpers.Deserialize<FileDef>(inputFile);
|
||||
Debug.Write("File -> ");
|
||||
Debug.WriteLine(FileSettings);
|
||||
@@ -646,7 +646,7 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
inputFile.Seek(HeaderSettings.LayerDefinitionsAddress, SeekOrigin.Begin);
|
||||
|
||||
LayerManager.Init(HeaderSettings.LayerCount);
|
||||
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
var layerDef = new LayerDef[LayerCount];
|
||||
|
||||
|
||||
@@ -672,34 +672,37 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
|
||||
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, HeaderSettings.LayerCount);
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
var layerBytes = new byte[LayerCount][];
|
||||
|
||||
foreach (var layerIndex in batch)
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, HeaderSettings.LayerCount);
|
||||
foreach (var batch in BatchLayersIndexes())
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
var layerBytes = new byte[LayerCount][];
|
||||
|
||||
inputFile.Seek(layerDataAddresses[layerIndex], SeekOrigin.Begin);
|
||||
layerBytes[layerIndex] = inputFile.ReadBytes(inputFile.ReadUIntLittleEndian());
|
||||
}
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = DecodeImage(HeaderSettings.LayerDataType, layerBytes[layerIndex], Resolution))
|
||||
foreach (var layerIndex in batch)
|
||||
{
|
||||
layerBytes[layerIndex] = null; // Clean
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
var layer = new Layer((uint)layerIndex, mat, this);
|
||||
layerDef[layerIndex].CopyTo(layer);
|
||||
this[layerIndex] = layer;
|
||||
inputFile.Seek(layerDataAddresses[layerIndex], SeekOrigin.Begin);
|
||||
layerBytes[layerIndex] = inputFile.ReadBytes(inputFile.ReadUIntLittleEndian());
|
||||
}
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using var mat = DecodeImage(HeaderSettings.LayerDataType, layerBytes[layerIndex], Resolution);
|
||||
layerBytes[layerIndex] = null; // Clean
|
||||
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
layerDef[layerIndex].CopyTo(this[layerIndex]);
|
||||
}
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeGcode);
|
||||
@@ -711,24 +714,8 @@ namespace UVtools.Core.FileFormats
|
||||
UpdateGlobalPropertiesFromLayers();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
|
||||
outputFile.Seek(0, SeekOrigin.Begin);
|
||||
FileSettings.Update();
|
||||
|
||||
@@ -927,7 +927,7 @@ namespace UVtools.Core.FileFormats
|
||||
LayersDefinitions = null;
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
/*if (HeaderSettings.EncryptionKey == 0)
|
||||
{
|
||||
@@ -936,7 +936,7 @@ namespace UVtools.Core.FileFormats
|
||||
}*/
|
||||
|
||||
LayersDefinitions = new LayerDef[HeaderSettings.LayerCount];
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
|
||||
outputFile.Seek(Helpers.Serializer.SizeOf(HeaderSettings), SeekOrigin.Begin);
|
||||
|
||||
for (byte i = 0; i < ThumbnailsCount; i++)
|
||||
@@ -1046,15 +1046,15 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.WriteLine("-End-");
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
//HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile);
|
||||
//HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header))));
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
if (HeaderSettings.Magic != MAGIC_PHZ)
|
||||
{
|
||||
throw new FileLoadException("Not a valid PHZ file!", fileFullPath);
|
||||
throw new FileLoadException("Not a valid PHZ file!", FileFullPath);
|
||||
}
|
||||
|
||||
HeaderSettings.AntiAliasLevel = 1;
|
||||
@@ -1093,7 +1093,7 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
|
||||
|
||||
LayerManager.Init(HeaderSettings.LayerCount);
|
||||
LayerManager.Init(HeaderSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
LayersDefinitions = new LayerDef[HeaderSettings.LayerCount];
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, HeaderSettings.LayerCount);
|
||||
@@ -1110,45 +1110,34 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.Write($"LAYER {layerIndex} -> ");
|
||||
Debug.WriteLine(layerDef);
|
||||
|
||||
inputFile.SeekDoWorkAndRewind(layerDef.DataAddress, () =>
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
layerDef.EncodedRle = inputFile.ReadBytes(layerDef.DataSize);
|
||||
});
|
||||
inputFile.SeekDoWorkAndRewind(layerDef.DataAddress,
|
||||
() => { layerDef.EncodedRle = inputFile.ReadBytes(layerDef.DataSize); });
|
||||
}
|
||||
}
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex))
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
var layer = new Layer((uint)layerIndex, mat, this);
|
||||
LayersDefinitions[layerIndex].CopyTo(layer);
|
||||
this[layerIndex] = layer;
|
||||
}
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
using var mat = LayersDefinitions[layerIndex].Decode((uint)layerIndex);
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
LayersDefinitions[layerIndex].CopyTo(this[layerIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
|
||||
outputFile.Seek(0, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
|
||||
@@ -434,10 +434,10 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
//throw new NotSupportedException("PhotonS is read-only format, please use pws instead!");
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
|
||||
outputFile.WriteSerialize(HeaderSettings);
|
||||
outputFile.WriteBytes(EncodeImage(DATATYPE_BGR565, Thumbnails[0]));
|
||||
outputFile.WriteSerialize(LayerSettings);
|
||||
@@ -474,13 +474,13 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.WriteLine("-End-");
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
if (HeaderSettings.Tag1 != Header.TAG1 || HeaderSettings.Tag2 != Header.TAG2)
|
||||
{
|
||||
throw new FileLoadException("Not a valid PHOTONS file! TAGs doesn't match", fileFullPath);
|
||||
throw new FileLoadException("Not a valid PHOTONS file! TAGs doesn't match", FileFullPath);
|
||||
}
|
||||
|
||||
int previewSize = (int) (HeaderSettings.PreviewResolutionX * HeaderSettings.PreviewResolutionY * 2);
|
||||
@@ -495,7 +495,7 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.WriteLine(LayerSettings);
|
||||
|
||||
|
||||
LayerManager.Init(LayerSettings.LayerCount);
|
||||
LayerManager.Init(LayerSettings.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
var layersDefinitions = new LayerDef[LayerSettings.LayerCount];
|
||||
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
@@ -508,7 +508,8 @@ namespace UVtools.Core.FileFormats
|
||||
var layerDef = Helpers.Deserialize<LayerDef>(inputFile);
|
||||
layersDefinitions[layerIndex] = layerDef;
|
||||
|
||||
layerDef.EncodedRle = inputFile.ReadBytes(layerDef.RleDataSize);
|
||||
if (DecodeType == FileDecodeType.Full) layerDef.EncodedRle = inputFile.ReadBytes(layerDef.RleDataSize);
|
||||
else inputFile.Seek(layerDef.RleDataSize, SeekOrigin.Current);
|
||||
|
||||
Debug.Write($"LAYER {layerIndex} -> ");
|
||||
Debug.WriteLine(layerDef);
|
||||
@@ -521,40 +522,23 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = layersDefinitions[layerIndex].Decode())
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using var mat = layersDefinitions[layerIndex].Decode();
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this);
|
||||
}
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
LayerManager.RebuildLayersProperties();
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
|
||||
outputFile.Seek(0, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
|
||||
@@ -1256,7 +1256,7 @@ namespace UVtools.Core.FileFormats
|
||||
LayersDefinition = null;
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
HeaderSettings.PixelSizeUm = PixelSizeMicronsMax;
|
||||
|
||||
@@ -1277,7 +1277,7 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
|
||||
FileMarkSettings.HeaderAddress = (uint) Helpers.Serializer.SizeOf(FileMarkSettings);
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write);
|
||||
outputFile.Seek((int)FileMarkSettings.HeaderAddress, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
|
||||
@@ -1348,9 +1348,9 @@ namespace UVtools.Core.FileFormats
|
||||
Helpers.SerializeWriteFileStream(outputFile, FileMarkSettings);
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
|
||||
using var inputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Read);
|
||||
FileMarkSettings = Helpers.Deserialize<FileMark>(inputFile);
|
||||
|
||||
Debug.Write("FileMark -> ");
|
||||
@@ -1359,17 +1359,14 @@ namespace UVtools.Core.FileFormats
|
||||
if (!FileMarkSettings.Mark.Equals(FileMark.SectionMarkFile))
|
||||
{
|
||||
throw new FileLoadException(
|
||||
$"Invalid Filemark {FileMarkSettings.Mark}, expected {FileMark.SectionMarkFile}", fileFullPath);
|
||||
$"Invalid Filemark {FileMarkSettings.Mark}, expected {FileMark.SectionMarkFile}", FileFullPath);
|
||||
}
|
||||
|
||||
if (FileMarkSettings.Version is not VERSION_1 and not VERSION_515)
|
||||
{
|
||||
throw new FileLoadException($"Invalid Version {FileMarkSettings.Version}, expected {VERSION_1} or {VERSION_515}",
|
||||
fileFullPath);
|
||||
throw new FileLoadException($"Invalid Version {FileMarkSettings.Version}, expected {VERSION_1} or {VERSION_515}", FileFullPath);
|
||||
}
|
||||
|
||||
FileFullPath = fileFullPath;
|
||||
|
||||
inputFile.Seek(FileMarkSettings.HeaderAddress, SeekOrigin.Begin);
|
||||
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
|
||||
|
||||
@@ -1402,7 +1399,7 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.Write("LayersDefinition -> ");
|
||||
Debug.WriteLine(LayersDefinition);
|
||||
|
||||
LayerManager.Init(LayersDefinition.LayerCount);
|
||||
LayerManager.Init(LayersDefinition.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
LayersDefinition.Layers = new LayerDef[LayerCount];
|
||||
|
||||
LayersDefinition.Validate();
|
||||
@@ -1418,52 +1415,43 @@ namespace UVtools.Core.FileFormats
|
||||
LayersDefinition[layerIndex].Parent = this;
|
||||
Debug.WriteLine($"Layer {layerIndex}: {LayersDefinition[layerIndex]}");
|
||||
|
||||
|
||||
inputFile.SeekDoWorkAndRewind(LayersDefinition[layerIndex].DataAddress, () =>
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
LayersDefinition[layerIndex].EncodedRle = inputFile.ReadBytes(LayersDefinition[layerIndex].DataLength);
|
||||
});
|
||||
inputFile.SeekDoWorkAndRewind(LayersDefinition[layerIndex].DataAddress,
|
||||
() =>
|
||||
{
|
||||
LayersDefinition[layerIndex].EncodedRle = inputFile.ReadBytes(LayersDefinition[layerIndex].DataLength);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
using (var mat = LayersDefinition[layerIndex].Decode())
|
||||
Parallel.ForEach(batch, CoreSettings.ParallelOptions, layerIndex =>
|
||||
{
|
||||
var layer = new Layer((uint)layerIndex, mat, this)
|
||||
if (progress.Token.IsCancellationRequested) return;
|
||||
|
||||
using var mat = LayersDefinition[layerIndex].Decode();
|
||||
this[layerIndex] = new Layer((uint)layerIndex, mat, this)
|
||||
{
|
||||
PositionZ = LayersDefinition.Layers
|
||||
.Where((_, i) => i <= layerIndex)
|
||||
.Sum(def => def.LayerHeight),
|
||||
};
|
||||
LayersDefinition[layerIndex].CopyTo(layer);
|
||||
this[layerIndex] = layer;
|
||||
}
|
||||
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
LayersDefinition[layerIndex].CopyTo(this[layerIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
HeaderSettings.PerLayerOverride = LayerManager.AllLayersAreUsingGlobalParameters ? 0 : 1u;
|
||||
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
|
||||
|
||||
@@ -533,13 +533,13 @@ namespace UVtools.Core.FileFormats
|
||||
Statistics.Clear();
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
var filename = fileFullPath;
|
||||
var filename = FileFullPath;
|
||||
if (filename.EndsWith(TemporaryFileAppend)) filename = Path.GetFileNameWithoutExtension(filename); // tmp
|
||||
filename = Path.GetFileNameWithoutExtension(filename); // sl1
|
||||
OutputConfigSettings.JobDir = filename;
|
||||
using ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create);
|
||||
using ZipArchive outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
|
||||
var entry = outputFile.CreateEntry("config.ini");
|
||||
using (TextWriter tw = new StreamWriter(entry.Open()))
|
||||
{
|
||||
@@ -596,7 +596,7 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
PrinterSettings = new Printer();
|
||||
MaterialSettings = new Material();
|
||||
@@ -605,7 +605,7 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
Statistics.ExecutionTime.Restart();
|
||||
|
||||
using (var inputFile = ZipFile.OpenRead(fileFullPath))
|
||||
using (var inputFile = ZipFile.OpenRead(FileFullPath))
|
||||
{
|
||||
List<string> iniFiles = new();
|
||||
foreach (ZipArchiveEntry entity in inputFile.Entries)
|
||||
@@ -689,7 +689,7 @@ namespace UVtools.Core.FileFormats
|
||||
LightPWM = LookupCustomValue(Keyword_LightPWM, DefaultBottomLightPWM);
|
||||
});
|
||||
|
||||
LayerManager.Init(OutputConfigSettings.NumSlow + OutputConfigSettings.NumFast);
|
||||
LayerManager.Init(OutputConfigSettings.NumSlow + OutputConfigSettings.NumFast, DecodeType == FileDecodeType.Partial);
|
||||
|
||||
progress.ItemCount = LayerCount;
|
||||
|
||||
@@ -698,7 +698,7 @@ namespace UVtools.Core.FileFormats
|
||||
if (!entity.Name.EndsWith(".png")) continue;
|
||||
if (entity.Name.StartsWith("thumbnail"))
|
||||
{
|
||||
using Stream stream = entity.Open();
|
||||
using var stream = entity.Open();
|
||||
Mat image = new();
|
||||
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, image);
|
||||
byte thumbnailIndex =
|
||||
@@ -707,17 +707,21 @@ namespace UVtools.Core.FileFormats
|
||||
? FileThumbnailSize.Small
|
||||
: FileThumbnailSize.Large);
|
||||
Thumbnails[thumbnailIndex] = image;
|
||||
stream.Close();
|
||||
|
||||
//thumbnailIndex++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// - .png - 5 numbers
|
||||
string layerStr = entity.Name.Substring(entity.Name.Length - 4 - 5, 5);
|
||||
uint iLayer = uint.Parse(layerStr);
|
||||
this[iLayer] = new Layer(iLayer, entity.Open(), LayerManager);
|
||||
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
// - .png - 5 numbers
|
||||
string layerStr = entity.Name.Substring(entity.Name.Length - 4 - 5, 5);
|
||||
uint iLayer = uint.Parse(layerStr);
|
||||
using var stream = entity.Open();
|
||||
this[iLayer] = new Layer(iLayer, stream, LayerManager);
|
||||
}
|
||||
|
||||
progress.ProcessedItems++;
|
||||
}
|
||||
}
|
||||
@@ -729,26 +733,8 @@ namespace UVtools.Core.FileFormats
|
||||
Debug.WriteLine(Statistics);
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
|
||||
}
|
||||
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
|
||||
//InputFile.CreateEntry("Modified");
|
||||
using (TextWriter tw = new StreamWriter(outputFile.PutFileContent("config.ini", string.Empty, ZipArchiveMode.Update).Open()))
|
||||
|
||||
@@ -467,7 +467,7 @@ namespace UVtools.Core.FileFormats
|
||||
JsonSettings.Layers = new List<LayerDef>();
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
// Redo layer data
|
||||
if (JsonSettings.Layers is null)
|
||||
@@ -484,7 +484,7 @@ namespace UVtools.Core.FileFormats
|
||||
JsonSettings.Layers.Add(new LayerDef(this[layerIndex]));
|
||||
}
|
||||
|
||||
using var outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create);
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
|
||||
outputFile.PutFileContent(FileConfigName, JsonConvert.SerializeObject(JsonSettings, Formatting.Indented), ZipArchiveMode.Create);
|
||||
|
||||
if (CreatedThumbnailsCount > 0)
|
||||
@@ -514,20 +514,20 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using (var inputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Read))
|
||||
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
|
||||
{
|
||||
var entry = inputFile.GetEntry(FileConfigName);
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"{FileConfigName} not found", fileFullPath);
|
||||
throw new FileLoadException($"{FileConfigName} not found", FileFullPath);
|
||||
}
|
||||
|
||||
JsonSettings = Helpers.JsonDeserializeObject<Settings>(entry.Open());
|
||||
|
||||
LayerManager.Init(JsonSettings.Properties.Size.Layers);
|
||||
LayerManager.Init(JsonSettings.Properties.Size.Layers, DecodeType == FileDecodeType.Partial);
|
||||
|
||||
entry = inputFile.GetEntry(FilePreviewTinyName);
|
||||
if (entry is not null)
|
||||
@@ -554,15 +554,16 @@ namespace UVtools.Core.FileFormats
|
||||
entry = inputFile.GetEntry($"{FolderImageName}/{layerIndex:D8}.png");
|
||||
if (entry is null) continue;
|
||||
|
||||
using var stream = entry.Open();
|
||||
var layer = new Layer(layerIndex, stream, LayerManager);
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
using var stream = entry.Open();
|
||||
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
|
||||
}
|
||||
|
||||
if (JsonSettings.Layers?.Count > layerIndex)
|
||||
{
|
||||
JsonSettings.Layers[(int)layerIndex].CopyTo(layer);
|
||||
JsonSettings.Layers[(int)layerIndex].CopyTo(this[layerIndex]);
|
||||
}
|
||||
|
||||
this[layerIndex] = layer;
|
||||
}
|
||||
|
||||
progress.ProcessedItems++;
|
||||
@@ -571,25 +572,8 @@ namespace UVtools.Core.FileFormats
|
||||
LayerManager.GetBoundingRectangle(progress);
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
|
||||
}
|
||||
|
||||
if (JsonSettings.Layers is null)
|
||||
{
|
||||
JsonSettings.Layers = new List<LayerDef>();
|
||||
|
||||
@@ -302,10 +302,10 @@ namespace UVtools.Core.FileFormats
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create);
|
||||
var manifestFilename = Path.GetFileName(fileFullPath).
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
|
||||
var manifestFilename = Filename.
|
||||
Replace($".{FileExtensions[0].Extension}{TemporaryFileAppend}", ".xml").
|
||||
Replace($".{FileExtensions[0].Extension}", ".xml");
|
||||
|
||||
@@ -328,7 +328,7 @@ namespace UVtools.Core.FileFormats
|
||||
serializer.Serialize(stream, ManifestFile, ns);
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
|
||||
{
|
||||
@@ -336,7 +336,7 @@ namespace UVtools.Core.FileFormats
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($".xml manifest not found", fileFullPath);
|
||||
throw new FileLoadException($".xml manifest not found", FileFullPath);
|
||||
}
|
||||
|
||||
try
|
||||
@@ -348,11 +348,11 @@ namespace UVtools.Core.FileFormats
|
||||
catch (Exception e)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", fileFullPath);
|
||||
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", FileFullPath);
|
||||
}
|
||||
|
||||
|
||||
LayerManager.Init(ManifestFile.Slices.LayerCount);
|
||||
LayerManager.Init(ManifestFile.Slices.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
|
||||
|
||||
@@ -364,11 +364,14 @@ namespace UVtools.Core.FileFormats
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"Layer {filename} not found", fileFullPath);
|
||||
throw new FileLoadException($"Layer {filename} not found", FileFullPath);
|
||||
}
|
||||
|
||||
using var stream = entry.Open();
|
||||
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
using var stream = entry.Open();
|
||||
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
|
||||
}
|
||||
|
||||
progress++;
|
||||
}
|
||||
@@ -377,24 +380,8 @@ namespace UVtools.Core.FileFormats
|
||||
LayerManager.GetBoundingRectangle(progress);
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
|
||||
bool deleted;
|
||||
|
||||
|
||||
@@ -149,6 +149,42 @@ namespace UVtools.Core.FileFormats
|
||||
[JsonProperty("retract_distance2")] public float RetractHeight2 { get; set; } = DefaultRetractHeight2;
|
||||
[JsonProperty("retract_speed2")] public float RetractSpeed2 { get; set; } = DefaultRetractSpeed2;
|
||||
[JsonProperty("light_pwm")] public byte LightPWM { get; set; } = DefaultLightPWM;
|
||||
|
||||
public void SetFrom(Layer layer)
|
||||
{
|
||||
PositionZ = layer.PositionZ;
|
||||
LightOffDelay = layer.LightOffDelay;
|
||||
WaitTimeBeforeCure = layer.WaitTimeBeforeCure;
|
||||
ExposureTime = layer.ExposureTime;
|
||||
WaitTimeAfterCure = layer.WaitTimeAfterCure;
|
||||
LiftHeight = layer.LiftHeight;
|
||||
LiftSpeed = layer.LiftSpeed;
|
||||
LiftHeight2 = layer.LiftHeight2;
|
||||
LiftSpeed2 = layer.LiftSpeed2;
|
||||
WaitTimeAfterLift = layer.WaitTimeAfterLift;
|
||||
RetractSpeed = layer.RetractSpeed;
|
||||
RetractHeight2 = layer.RetractHeight2;
|
||||
RetractSpeed2 = layer.RetractSpeed2;
|
||||
LightPWM = layer.LightPWM;
|
||||
}
|
||||
|
||||
public void CopyTo(Layer layer)
|
||||
{
|
||||
layer.PositionZ = PositionZ;
|
||||
layer.LightOffDelay = LightOffDelay;
|
||||
layer.WaitTimeBeforeCure = WaitTimeBeforeCure;
|
||||
layer.ExposureTime = ExposureTime;
|
||||
layer.WaitTimeAfterCure = WaitTimeAfterCure;
|
||||
layer.LiftHeight = LiftHeight;
|
||||
layer.LiftSpeed = LiftSpeed;
|
||||
layer.LiftHeight2 = LiftHeight2;
|
||||
layer.LiftSpeed2 = LiftSpeed2;
|
||||
layer.WaitTimeAfterLift = WaitTimeAfterLift;
|
||||
layer.RetractSpeed = RetractSpeed;
|
||||
layer.RetractHeight2 = RetractHeight2;
|
||||
layer.RetractSpeed2 = RetractSpeed2;
|
||||
layer.LightPWM = LightPWM;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -566,12 +602,12 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
// Redo layer data
|
||||
RebuildVDTLayers();
|
||||
|
||||
using var outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create);
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
|
||||
outputFile.PutFileContent(FileManifestName, JsonConvert.SerializeObject(ManifestFile, Formatting.Indented), ZipArchiveMode.Create);
|
||||
|
||||
if (CreatedThumbnailsCount > 0)
|
||||
@@ -598,20 +634,20 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using (var inputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Read))
|
||||
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
|
||||
{
|
||||
var entry = inputFile.GetEntry(FileManifestName);
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"{FileManifestName} not found", fileFullPath);
|
||||
throw new FileLoadException($"{FileManifestName} not found", FileFullPath);
|
||||
}
|
||||
|
||||
ManifestFile = Helpers.JsonDeserializeObject<VDTManifest>(entry.Open());
|
||||
|
||||
LayerManager.Init((uint) ManifestFile.Layers.Length);
|
||||
LayerManager.Init((uint) ManifestFile.Layers.Length, DecodeType == FileDecodeType.Partial);
|
||||
|
||||
for (int i = 0; i < FilePreviewNames.Length; i++)
|
||||
{
|
||||
@@ -631,24 +667,14 @@ namespace UVtools.Core.FileFormats
|
||||
var manifestLayer = ManifestFile.Layers[layerIndex];
|
||||
entry = inputFile.GetEntry($"{layerIndex}.png");
|
||||
if (entry is null) continue;
|
||||
using var stream = entry.Open();
|
||||
this[layerIndex] = new Layer(layerIndex, stream, LayerManager)
|
||||
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
PositionZ = manifestLayer.PositionZ,
|
||||
LightOffDelay = manifestLayer.LightOffDelay,
|
||||
WaitTimeBeforeCure = manifestLayer.WaitTimeBeforeCure,
|
||||
ExposureTime = manifestLayer.ExposureTime,
|
||||
WaitTimeAfterCure = manifestLayer.WaitTimeAfterCure,
|
||||
LiftHeight = manifestLayer.LiftHeight,
|
||||
LiftSpeed = manifestLayer.LiftSpeed,
|
||||
LiftHeight2 = manifestLayer.LiftHeight2,
|
||||
LiftSpeed2 = manifestLayer.LiftSpeed2,
|
||||
WaitTimeAfterLift = manifestLayer.WaitTimeAfterLift,
|
||||
RetractSpeed = manifestLayer.RetractSpeed,
|
||||
RetractHeight2 = manifestLayer.RetractHeight2,
|
||||
RetractSpeed2 = manifestLayer.RetractSpeed2,
|
||||
LightPWM = manifestLayer.LightPWM,
|
||||
};
|
||||
using var stream = entry.Open();
|
||||
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
|
||||
}
|
||||
|
||||
manifestLayer.CopyTo(this[layerIndex]);
|
||||
}
|
||||
|
||||
progress.ProcessedItems++;
|
||||
@@ -657,25 +683,8 @@ namespace UVtools.Core.FileFormats
|
||||
LayerManager.GetBoundingRectangle(progress);
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
|
||||
}
|
||||
|
||||
RebuildVDTLayers();
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
|
||||
outputFile.PutFileContent(FileManifestName, JsonConvert.SerializeObject(ManifestFile, Formatting.Indented), ZipArchiveMode.Update);
|
||||
|
||||
@@ -467,9 +467,9 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
using ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create);
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
|
||||
if (Thumbnails.Length > 0 && Thumbnails[0] is not null)
|
||||
{
|
||||
using var thumbnailsStream = outputFile.CreateEntry(PreviewFilename).Open();
|
||||
@@ -497,14 +497,14 @@ namespace UVtools.Core.FileFormats
|
||||
outputFile.PutFileContent(GCodeFilename, EncryptGCode(progress), ZipArchiveMode.Create);
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read);
|
||||
var entry = inputFile.GetEntry(ManifestFilename);
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"{ManifestFilename} not found", fileFullPath);
|
||||
throw new FileLoadException($"{ManifestFilename} not found", FileFullPath);
|
||||
}
|
||||
|
||||
try
|
||||
@@ -516,14 +516,14 @@ namespace UVtools.Core.FileFormats
|
||||
catch (Exception e)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", fileFullPath);
|
||||
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", FileFullPath);
|
||||
}
|
||||
|
||||
entry = inputFile.GetEntry(GCodeFilename);
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"{GCodeFilename} not found", fileFullPath);
|
||||
throw new FileLoadException($"{GCodeFilename} not found", FileFullPath);
|
||||
}
|
||||
|
||||
var encryptEngine = new RsaEngine();
|
||||
@@ -551,7 +551,7 @@ namespace UVtools.Core.FileFormats
|
||||
tr.Close();
|
||||
}
|
||||
|
||||
LayerManager.Init(ManifestFile.Job.LayerCount);
|
||||
LayerManager.Init(ManifestFile.Job.LayerCount, DecodeType == FileDecodeType.Partial);
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
|
||||
//var gcode = GCode.ToString();
|
||||
@@ -564,12 +564,15 @@ namespace UVtools.Core.FileFormats
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"Layer {layerIndex+1} not found", fileFullPath);
|
||||
throw new FileLoadException($"Layer {layerIndex+1} not found", FileFullPath);
|
||||
}
|
||||
|
||||
using var stream = entry.Open();
|
||||
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
|
||||
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
using var stream = entry.Open();
|
||||
this[layerIndex] = new Layer(layerIndex, stream, LayerManager);
|
||||
}
|
||||
|
||||
progress++;
|
||||
}
|
||||
|
||||
@@ -585,24 +588,8 @@ namespace UVtools.Core.FileFormats
|
||||
LayerManager.GetBoundingRectangle(progress);
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
|
||||
|
||||
var entriesToRemove = outputFile.Entries.Where(zipEntry => zipEntry.Name.EndsWith(".gcode") || zipEntry.Name.EndsWith(".xml")).ToArray();
|
||||
|
||||
@@ -374,7 +374,7 @@ namespace UVtools.Core.FileFormats
|
||||
LayersSettings.Clear();
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void EncodeInternally(OperationProgress progress)
|
||||
{
|
||||
float usedMaterial = MaterialMilliliters / LayerCount;
|
||||
ResinMetadataSettings.Layers.Clear();
|
||||
@@ -387,87 +387,83 @@ namespace UVtools.Core.FileFormats
|
||||
});
|
||||
}
|
||||
|
||||
using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create))
|
||||
{
|
||||
outputFile.PutFileContent("ResinMetadata", JsonConvert.SerializeObject(ResinMetadataSettings, Formatting.Indented), ZipArchiveMode.Create);
|
||||
outputFile.PutFileContent("UserSettingsData", JsonConvert.SerializeObject(UserSettings, Formatting.Indented), ZipArchiveMode.Create);
|
||||
outputFile.PutFileContent("ZCodeMetadata", JsonConvert.SerializeObject(ZCodeMetadataSettings, Formatting.Indented), ZipArchiveMode.Create);
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Create);
|
||||
outputFile.PutFileContent("ResinMetadata", JsonConvert.SerializeObject(ResinMetadataSettings, Formatting.Indented), ZipArchiveMode.Create);
|
||||
outputFile.PutFileContent("UserSettingsData", JsonConvert.SerializeObject(UserSettings, Formatting.Indented), ZipArchiveMode.Create);
|
||||
outputFile.PutFileContent("ZCodeMetadata", JsonConvert.SerializeObject(ZCodeMetadataSettings, Formatting.Indented), ZipArchiveMode.Create);
|
||||
|
||||
if (CreatedThumbnailsCount > 0)
|
||||
if (CreatedThumbnailsCount > 0)
|
||||
{
|
||||
using var stream = outputFile.CreateEntry("Preview.png").Open();
|
||||
stream.WriteBytes(Thumbnails[0].GetPngByes());
|
||||
stream.Close();
|
||||
}
|
||||
|
||||
GCode.Clear();
|
||||
|
||||
float lastZPosition = 0;
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
var layer = this[layerIndex];
|
||||
GCode.AppendLine($"{GCodeKeywordSlice} {layerIndex}");
|
||||
|
||||
if (lastZPosition != layer.PositionZ)
|
||||
{
|
||||
using (var stream = outputFile.CreateEntry("Preview.png").Open())
|
||||
if (layer.LiftHeight > 0)
|
||||
{
|
||||
stream.WriteBytes(Thumbnails[0].GetPngByes());
|
||||
stream.Close();
|
||||
GCode.AppendLine($"G1 Z{layer.LiftHeight} F{layer.LiftSpeed}");
|
||||
GCode.AppendLine($"G1 Z-{Layer.RoundHeight(layer.LiftHeight - layer.PositionZ + lastZPosition)} F{layer.RetractSpeed}");
|
||||
}
|
||||
else
|
||||
{
|
||||
GCode.AppendLine($"G1 Z{Layer.RoundHeight(layer.PositionZ- lastZPosition)} F{layer.LiftSpeed}");
|
||||
}
|
||||
}
|
||||
|
||||
GCode.Clear();
|
||||
|
||||
float lastZPosition = 0;
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
Layer layer = this[layerIndex];
|
||||
GCode.AppendLine($"{GCodeKeywordSlice} {layerIndex}");
|
||||
|
||||
if (lastZPosition != layer.PositionZ)
|
||||
{
|
||||
if (layer.LiftHeight > 0)
|
||||
{
|
||||
GCode.AppendLine($"G1 Z{layer.LiftHeight} F{layer.LiftSpeed}");
|
||||
GCode.AppendLine($"G1 Z-{Layer.RoundHeight(layer.LiftHeight - layer.PositionZ + lastZPosition)} F{layer.RetractSpeed}");
|
||||
}
|
||||
else
|
||||
{
|
||||
GCode.AppendLine($"G1 Z{Layer.RoundHeight(layer.PositionZ- lastZPosition)} F{layer.LiftSpeed}");
|
||||
}
|
||||
}
|
||||
/*else
|
||||
/*else
|
||||
{
|
||||
//GCode.AppendLine($";G1 Z{LiftHeight} F{LiftSpeed}; Already here");
|
||||
//GCode.AppendLine($";G1 Z-{LiftHeight - layer.PositionZ + lastZPosition} F{RetractSpeed}; Already here");
|
||||
}*/
|
||||
|
||||
//GCode.AppendLine($"G1 Z{LiftHeight} F{LiftSpeed}");
|
||||
//GCode.AppendLine($"G1 Z-{LiftHeight - LayerHeight} F{RetractSpeed}");
|
||||
GCode.AppendLine(GCodeKeywordDelayBlank);
|
||||
GCode.AppendLine("M106 S255");
|
||||
GCode.AppendLine(GCodeKeywordDelayModel);
|
||||
GCode.AppendLine("M106 S0");
|
||||
//GCode.AppendLine($"G1 Z{LiftHeight} F{LiftSpeed}");
|
||||
//GCode.AppendLine($"G1 Z-{LiftHeight - LayerHeight} F{RetractSpeed}");
|
||||
GCode.AppendLine(GCodeKeywordDelayBlank);
|
||||
GCode.AppendLine("M106 S255");
|
||||
GCode.AppendLine(GCodeKeywordDelayModel);
|
||||
GCode.AppendLine("M106 S0");
|
||||
|
||||
|
||||
var layerimagePath = $"{FolderImages}/{FolderImageName}{layerIndex:D5}.png";
|
||||
using (Stream stream = outputFile.CreateEntry(layerimagePath).Open())
|
||||
{
|
||||
//image.Save(stream, Helpers.PngEncoder);
|
||||
var byteArr = this[layerIndex].CompressedBytes;
|
||||
stream.Write(byteArr, 0, byteArr.Length);
|
||||
stream.Close();
|
||||
}
|
||||
|
||||
lastZPosition = layer.PositionZ;
|
||||
|
||||
progress++;
|
||||
var layerimagePath = $"{FolderImages}/{FolderImageName}{layerIndex:D5}.png";
|
||||
using (var stream = outputFile.CreateEntry(layerimagePath).Open())
|
||||
{
|
||||
//image.Save(stream, Helpers.PngEncoder);
|
||||
var byteArr = this[layerIndex].CompressedBytes;
|
||||
stream.Write(byteArr, 0, byteArr.Length);
|
||||
stream.Close();
|
||||
}
|
||||
|
||||
GCode.AppendLine($"G1 Z40.0 F{UserSettings.ZLiftFeedRate}");
|
||||
GCode.AppendLine("M18");
|
||||
lastZPosition = layer.PositionZ;
|
||||
|
||||
outputFile.PutFileContent("ResinGCodeData", GCode.ToString(), ZipArchiveMode.Create);
|
||||
progress++;
|
||||
}
|
||||
|
||||
GCode.AppendLine($"G1 Z40.0 F{UserSettings.ZLiftFeedRate}");
|
||||
GCode.AppendLine("M18");
|
||||
|
||||
outputFile.PutFileContent("ResinGCodeData", GCode.ToString(), ZipArchiveMode.Create);
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
protected override void DecodeInternally(OperationProgress progress)
|
||||
{
|
||||
using (var inputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Read))
|
||||
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
|
||||
{
|
||||
var entry = inputFile.GetEntry("ResinMetadata");
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException("ResinMetadata not found", fileFullPath);
|
||||
throw new FileLoadException("ResinMetadata not found", FileFullPath);
|
||||
}
|
||||
|
||||
ResinMetadataSettings = Helpers.JsonDeserializeObject<ResinMetadata>(entry.Open());
|
||||
@@ -476,7 +472,7 @@ namespace UVtools.Core.FileFormats
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException("UserSettingsData not found", fileFullPath);
|
||||
throw new FileLoadException("UserSettingsData not found", FileFullPath);
|
||||
}
|
||||
|
||||
UserSettings = Helpers.JsonDeserializeObject<UserSettingsdata>(entry.Open());
|
||||
@@ -485,7 +481,7 @@ namespace UVtools.Core.FileFormats
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException("ZCodeMetadata not found", fileFullPath);
|
||||
throw new FileLoadException("ZCodeMetadata not found", FileFullPath);
|
||||
}
|
||||
|
||||
ZCodeMetadataSettings = Helpers.JsonDeserializeObject<ZCodeMetadata>(entry.Open());
|
||||
@@ -494,10 +490,10 @@ namespace UVtools.Core.FileFormats
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException("ResinGCodeData not found", fileFullPath);
|
||||
throw new FileLoadException("ResinGCodeData not found", FileFullPath);
|
||||
}
|
||||
|
||||
LayerManager.Init(ResinMetadataSettings.TotalLayersCount);
|
||||
LayerManager.Init(ResinMetadataSettings.TotalLayersCount, DecodeType == FileDecodeType.Partial);
|
||||
GCode.Clear();
|
||||
using (TextReader tr = new StreamReader(entry.Open()))
|
||||
{
|
||||
@@ -577,14 +573,18 @@ M106 S0
|
||||
|
||||
LayersSettings[layerIndex].LayerFileIndex = layerFileIndex;
|
||||
LayersSettings[layerIndex].LayerEntry = inputFile.GetEntry(layerimagePath);
|
||||
this[layerIndex] = new Layer((uint) layerIndex, LayersSettings[layerIndex].LayerEntry.Open(), LayerManager)
|
||||
|
||||
if (DecodeType == FileDecodeType.Full)
|
||||
{
|
||||
PositionZ = currentHeight,
|
||||
LiftHeight = liftHeight,
|
||||
LiftSpeed = liftSpeed,
|
||||
RetractSpeed = retractSpeed,
|
||||
LightPWM = pwm
|
||||
};
|
||||
using var stream = LayersSettings[layerIndex].LayerEntry.Open();
|
||||
this[layerIndex] = new Layer((uint)layerIndex, stream, LayerManager);
|
||||
}
|
||||
|
||||
this[layerIndex].PositionZ = currentHeight;
|
||||
this[layerIndex].LiftHeight = liftHeight;
|
||||
this[layerIndex].LiftSpeed = liftSpeed;
|
||||
this[layerIndex].RetractSpeed = retractSpeed;
|
||||
this[layerIndex].LightPWM = pwm;
|
||||
layerIndex++;
|
||||
|
||||
progress++;
|
||||
@@ -595,9 +595,9 @@ M106 S0
|
||||
}
|
||||
|
||||
entry = inputFile.GetEntry("Preview.png");
|
||||
if (!ReferenceEquals(entry, null))
|
||||
if (entry is not null)
|
||||
{
|
||||
using Stream stream = entry.Open();
|
||||
using var stream = entry.Open();
|
||||
CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, Thumbnails[0]);
|
||||
stream.Close();
|
||||
}
|
||||
@@ -622,36 +622,15 @@ M106 S0
|
||||
RaisePropertyChanged(nameof(GCodeStr));
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
protected override void PartialSaveInternally(OperationProgress progress)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
|
||||
}
|
||||
|
||||
using (var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update))
|
||||
{
|
||||
outputFile.PutFileContent("ResinMetadata", JsonConvert.SerializeObject(ResinMetadataSettings, Formatting.Indented), ZipArchiveMode.Update);
|
||||
outputFile.PutFileContent("UserSettingsData", JsonConvert.SerializeObject(UserSettings, Formatting.Indented), ZipArchiveMode.Update);
|
||||
outputFile.PutFileContent("ZCodeMetadata", JsonConvert.SerializeObject(ZCodeMetadataSettings, Formatting.Indented), ZipArchiveMode.Update);
|
||||
outputFile.PutFileContent("ResinGCodeData", GCodeStr, ZipArchiveMode.Update);
|
||||
}
|
||||
|
||||
//Decode(FileFullPath, progress);
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
|
||||
outputFile.PutFileContent("ResinMetadata", JsonConvert.SerializeObject(ResinMetadataSettings, Formatting.Indented), ZipArchiveMode.Update);
|
||||
outputFile.PutFileContent("UserSettingsData", JsonConvert.SerializeObject(UserSettings, Formatting.Indented), ZipArchiveMode.Update);
|
||||
outputFile.PutFileContent("ZCodeMetadata", JsonConvert.SerializeObject(ZCodeMetadataSettings, Formatting.Indented), ZipArchiveMode.Update);
|
||||
outputFile.PutFileContent("ResinGCodeData", GCodeStr, ZipArchiveMode.Update);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,6 +479,7 @@ namespace UVtools.Core.Layers
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!HaveImage) return null;
|
||||
Mat mat = new();
|
||||
CvInvoke.Imdecode(_compressedBytes, ImreadModes.Grayscale, mat);
|
||||
return mat;
|
||||
@@ -604,6 +605,8 @@ namespace UVtools.Core.Layers
|
||||
_lightPWM = SlicerFile.GetBottomOrNormalValue(this, SlicerFile.BottomLightPWM, SlicerFile.LightPWM);
|
||||
}
|
||||
|
||||
public Layer(uint index, FileFormat slicerFile) : this(index, slicerFile.LayerManager) {}
|
||||
|
||||
public Layer(uint index, byte[] compressedBytes, LayerManager parentLayerManager) : this(index, parentLayerManager)
|
||||
{
|
||||
CompressedBytes = compressedBytes;
|
||||
@@ -625,8 +628,8 @@ namespace UVtools.Core.Layers
|
||||
|
||||
public Layer(uint index, Mat layerMat, FileFormat slicerFile) : this(index, layerMat, slicerFile.LayerManager) { }
|
||||
|
||||
public Layer(uint index, Stream stream, LayerManager parentLayerManager) : this(index, stream.ToArray(), parentLayerManager) { }
|
||||
public Layer(uint index, Stream stream, FileFormat slicerFile) : this(index, stream.ToArray(), slicerFile.LayerManager) { }
|
||||
public Layer(uint index, Stream stream, LayerManager parentLayerManager) : this(index, stream?.ToArray(), parentLayerManager) { }
|
||||
public Layer(uint index, Stream stream, FileFormat slicerFile) : this(index, stream?.ToArray(), slicerFile.LayerManager) { }
|
||||
#endregion
|
||||
|
||||
#region Equatables
|
||||
@@ -671,7 +674,7 @@ namespace UVtools.Core.Layers
|
||||
if (other is null) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
if (_index != other._index) return false;
|
||||
if (_compressedBytes.Length != other._compressedBytes.Length) return false;
|
||||
if (_compressedBytes?.Length != other._compressedBytes?.Length) return false;
|
||||
return _compressedBytes.AsSpan().SequenceEqual(other._compressedBytes.AsSpan());
|
||||
//return Equals(_compressedBytes, other._compressedBytes);
|
||||
}
|
||||
@@ -1112,7 +1115,7 @@ namespace UVtools.Core.Layers
|
||||
//layer.CompressedBytes = _compressedBytes.ToArray();
|
||||
//Debug.WriteLine(ReferenceEquals(_compressedBytes, layer.CompressedBytes));
|
||||
//return layer;
|
||||
return new (_index, CompressedBytes.ToArray(), ParentLayerManager)
|
||||
return new (_index, CompressedBytes?.ToArray(), ParentLayerManager)
|
||||
{
|
||||
_positionZ = _positionZ,
|
||||
_lightOffDelay = _lightOffDelay,
|
||||
|
||||
@@ -176,9 +176,14 @@ namespace UVtools.Core
|
||||
}
|
||||
}
|
||||
|
||||
public void Init(uint layerCount)
|
||||
public void Init(uint layerCount, bool initializeLayers = false)
|
||||
{
|
||||
_layers = new Layer[layerCount];
|
||||
if (!initializeLayers) return;
|
||||
for (uint layerIndex = 0; layerIndex < layerCount; layerIndex++)
|
||||
{
|
||||
this[layerIndex] = new Layer(layerIndex, this);
|
||||
}
|
||||
}
|
||||
|
||||
public void Init(Layer[] layers)
|
||||
@@ -672,9 +677,10 @@ namespace UVtools.Core
|
||||
|
||||
public Rectangle GetBoundingRectangle(OperationProgress progress = null)
|
||||
{
|
||||
if (!_boundingRectangle.IsEmpty || LayerCount == 0 || this[0] is null) return _boundingRectangle;
|
||||
var firstLayer = FirstLayer;
|
||||
if (!_boundingRectangle.IsEmpty || LayerCount == 0 || firstLayer is null || !firstLayer.HaveImage) return _boundingRectangle;
|
||||
progress ??= new OperationProgress(OperationProgress.StatusOptimizingBounds, LayerCount - 1);
|
||||
_boundingRectangle = this[0].BoundingRectangle;
|
||||
_boundingRectangle = firstLayer.BoundingRectangle;
|
||||
if (_boundingRectangle.IsEmpty) // Safe checking
|
||||
{
|
||||
progress.Reset(OperationProgress.StatusOptimizingBounds, LayerCount-1);
|
||||
@@ -687,9 +693,9 @@ namespace UVtools.Core
|
||||
if (progress is null) return;
|
||||
progress.LockAndIncrement();
|
||||
});
|
||||
_boundingRectangle = this[0].BoundingRectangle;
|
||||
_boundingRectangle = firstLayer.BoundingRectangle;
|
||||
|
||||
if (progress is not null && progress.Token.IsCancellationRequested)
|
||||
if (progress.Token.IsCancellationRequested)
|
||||
{
|
||||
_boundingRectangle = Rectangle.Empty;
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
|
||||
@@ -275,11 +275,11 @@ namespace UVtools.Core.Managers
|
||||
/// <param name="slicerFile"></param>
|
||||
public void Init(FileFormat slicerFile)
|
||||
{
|
||||
Clear();
|
||||
SlicerFile = slicerFile;
|
||||
if (slicerFile is null || slicerFile.DecodeType == FileFormat.FileDecodeType.Partial) return;
|
||||
SuppressRestoreWork(() =>
|
||||
{
|
||||
Clear();
|
||||
SlicerFile = slicerFile;
|
||||
if (slicerFile is null) return;
|
||||
var clip = new ClipboardItem(SlicerFile, "Original layers", true);
|
||||
clip.AddRange(SlicerFile.LayerManager.CloneLayers());
|
||||
Add(clip);
|
||||
|
||||
@@ -124,6 +124,8 @@ namespace UVtools.Core.Managers
|
||||
bool emptyLayersConfig = true,
|
||||
OperationProgress progress = null)
|
||||
{
|
||||
if (SlicerFile.DecodeType == FileFormat.FileDecodeType.Partial) return null;
|
||||
|
||||
islandConfig ??= new IslandDetectionConfiguration();
|
||||
overhangConfig ??= new OverhangDetectionConfiguration();
|
||||
resinTrapConfig ??= new ResinTrapDetectionConfiguration();
|
||||
|
||||
@@ -7,15 +7,12 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.Cuda;
|
||||
using Emgu.CV.Util;
|
||||
using UVtools.Core.Extensions;
|
||||
using UVtools.Core.FileFormats;
|
||||
using UVtools.Core.Layers;
|
||||
@@ -120,6 +117,11 @@ namespace UVtools.Core.Operations
|
||||
/// </summary>
|
||||
public virtual bool PassActualLayerIndex => false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets if this operation can run in a file open as partial mode
|
||||
/// </summary>
|
||||
public virtual bool CanRunInPartialMode => false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets if this operation can make use of ROI
|
||||
/// </summary>
|
||||
@@ -502,6 +504,7 @@ namespace UVtools.Core.Operations
|
||||
public bool Execute(OperationProgress progress = null)
|
||||
{
|
||||
if (_slicerFile is null) throw new InvalidOperationException($"{Title} can't execute due the lacking of a file parent.");
|
||||
if (_slicerFile.DecodeType == FileFormat.FileDecodeType.Partial && !CanRunInPartialMode) throw new InvalidOperationException($"The file was open in partial mode and the tool \"{Title}\" is unable to run in this mode.\nPlease reload the file in full mode in order to use this tool.");
|
||||
if (!IsValidated)
|
||||
{
|
||||
var msg = Validate();
|
||||
|
||||
@@ -18,6 +18,9 @@ namespace UVtools.Core.Operations
|
||||
public class OperationCalculator : Operation
|
||||
{
|
||||
#region Overrides
|
||||
|
||||
public override bool CanRunInPartialMode => true;
|
||||
|
||||
public override string Title => "Calculator";
|
||||
public override string Description => null;
|
||||
|
||||
|
||||
@@ -65,6 +65,8 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Overrides
|
||||
|
||||
public override bool CanRunInPartialMode => true;
|
||||
|
||||
public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.Normal;
|
||||
|
||||
public override string Title => "Dynamic lifts";
|
||||
|
||||
@@ -9,10 +9,8 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using UVtools.Core.FileFormats;
|
||||
using UVtools.Core.Objects;
|
||||
|
||||
namespace UVtools.Core.Operations
|
||||
{
|
||||
@@ -29,6 +27,8 @@ namespace UVtools.Core.Operations
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
|
||||
public override bool CanRunInPartialMode => true;
|
||||
public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.None;
|
||||
|
||||
public override bool CanROI => false;
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace UVtools.Core.Operations
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
public override bool CanRunInPartialMode => true;
|
||||
public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.Normal;
|
||||
public override bool LayerIndexEndEnabled => false;
|
||||
public override string Title => "Fade exposure time";
|
||||
|
||||
@@ -27,6 +27,8 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Overrides
|
||||
|
||||
public override bool CanRunInPartialMode => true;
|
||||
|
||||
public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.None;
|
||||
|
||||
public override bool CanROI => false;
|
||||
|
||||
@@ -29,6 +29,9 @@ namespace UVtools.Core.Operations
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
|
||||
public override bool CanRunInPartialMode => true;
|
||||
|
||||
public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.None;
|
||||
|
||||
public override string Title => "Raise platform on print finish";
|
||||
|
||||
@@ -30,6 +30,8 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Overrides
|
||||
|
||||
public override bool CanRunInPartialMode => true;
|
||||
|
||||
public override bool CanHaveProfiles => false;
|
||||
|
||||
public override string Title => "Scripting";
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* Version 3, 19 November 2007
|
||||
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UVtools.Core.Scripting
|
||||
{
|
||||
public abstract class ScriptFileDialogInput : ScriptBaseInput<string>
|
||||
{
|
||||
public class ScriptFileDialogFilter
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public List<string> Extensions { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the title for the dialog
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default directory to open the dialog in
|
||||
/// </summary>
|
||||
public string Directory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the initial filename to be on the dialog
|
||||
/// </summary>
|
||||
public string InitialFilename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the file filters on the dropdown list
|
||||
/// </summary>
|
||||
public List<ScriptFileDialogFilter> Filters { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* Version 3, 19 November 2007
|
||||
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
namespace UVtools.Core.Scripting
|
||||
{
|
||||
public class ScriptOpenFileDialogInput : ScriptFileDialogInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets if allow multiple file selection
|
||||
/// </summary>
|
||||
public bool AllowMultiple { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selected files
|
||||
/// </summary>
|
||||
public string[] Files {get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* Version 3, 19 November 2007
|
||||
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
namespace UVtools.Core.Scripting
|
||||
{
|
||||
public class ScriptOpenFolderDialogInput : ScriptBaseInput<string>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the title for the dialog
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* Version 3, 19 November 2007
|
||||
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
namespace UVtools.Core.Scripting
|
||||
{
|
||||
public class ScriptSaveFileDialogInput : ScriptFileDialogInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the default extension for the dialog
|
||||
/// </summary>
|
||||
public string DefaultExtension { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
||||
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
|
||||
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
|
||||
<Version>2.24.4</Version>
|
||||
<Version>2.25.0</Version>
|
||||
<Copyright>Copyright © 2020 PTRTECH</Copyright>
|
||||
<PackageIcon>UVtools.png</PackageIcon>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
|
||||
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* Version 3, 19 November 2007
|
||||
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using UVtools.Core.Scripting;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using UVtools.Core.FileFormats;
|
||||
using System.Threading.Tasks;
|
||||
using UVtools.Core;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace UVtools.ScriptSample
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs a black inset around objects
|
||||
/// </summary>
|
||||
public class ScriptCloneSettings : ScriptGlobals
|
||||
{
|
||||
ScriptCheckBoxInput Recursive = new()
|
||||
{
|
||||
Label = "Recursive",
|
||||
ToolTip = "If unchecked, only files in the same folder are modified; if checked, files in all sub-folders are modified too",
|
||||
Value = true
|
||||
};
|
||||
|
||||
ScriptCheckBoxInput Report = new()
|
||||
{
|
||||
Label = "Generate report file",
|
||||
ToolTip = "Optionally generate a report file in the same directory as the open file",
|
||||
Value = true
|
||||
};
|
||||
|
||||
ScriptCheckBoxInput OpenReport = new()
|
||||
{
|
||||
Label = "Open report file",
|
||||
ToolTip = "Optionally open the result file when completed",
|
||||
Value = true
|
||||
};
|
||||
|
||||
ScriptOpenFolderDialogInput FolderPath = new()
|
||||
{
|
||||
Label = "Folder path",
|
||||
ToolTip = "The folder path to process",
|
||||
};
|
||||
|
||||
private enum ResultStatus
|
||||
{
|
||||
Exception,
|
||||
UnknownFileType,
|
||||
DifferentMachineTypes,
|
||||
Success,
|
||||
Unchanged,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set configurations here, this function trigger just after load a script
|
||||
/// </summary>
|
||||
public void ScriptInit()
|
||||
{
|
||||
Script.Name = "Clone Settings";
|
||||
Script.Description = "Copies the print settings from the current file to all files in the same directory and, optionally, recursively below it";
|
||||
Script.Author = "Gina Venolia";
|
||||
Script.Version = new Version(0, 2);
|
||||
Script.UserInputs.Add(Recursive);
|
||||
Script.UserInputs.Add(Report);
|
||||
Script.UserInputs.Add(OpenReport);
|
||||
Script.UserInputs.Add(FolderPath);
|
||||
FolderPath.Value = SlicerFile.FileDirectoryPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate user inputs here, this function trigger when user click on execute
|
||||
/// </summary>
|
||||
/// <returns>A error message, empty or null if validation passes.</returns>
|
||||
public string ScriptValidate()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the script, this function trigger when when user click on execute and validation passes
|
||||
/// </summary>
|
||||
/// <returns>True if executes successfully to the end, otherwise false.</returns>
|
||||
public bool ScriptExecute()
|
||||
{
|
||||
Progress.CanCancel = true;
|
||||
|
||||
// Gather the list of directories to operate on
|
||||
Progress.Reset("Processing files...");
|
||||
|
||||
var directoryPaths = new List<string>();
|
||||
directoryPaths.Add(Path.GetDirectoryName(SlicerFile.FileFullPath));
|
||||
|
||||
if (Recursive.Value)
|
||||
{
|
||||
for (var i = 0; i < directoryPaths.Count; i++)
|
||||
{
|
||||
directoryPaths.AddRange(Directory.EnumerateDirectories(directoryPaths[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// Gather the list of files to operate on
|
||||
var filePaths = new List<string>();
|
||||
foreach (var directoryPath in directoryPaths)
|
||||
{
|
||||
filePaths.AddRange(Directory.EnumerateFiles(directoryPath));
|
||||
}
|
||||
|
||||
// Except for the file we started with
|
||||
var normalizedFilePath = Path.GetFullPath(SlicerFile.FileFullPath);
|
||||
filePaths.RemoveAll(x => Path.GetFullPath(x) == normalizedFilePath);
|
||||
|
||||
// Process the files
|
||||
Progress.Reset("Processing files...", (uint)filePaths.Count, 0);
|
||||
|
||||
var results = new List<Tuple<ResultStatus, string, List<string>>>();
|
||||
foreach (var filePath in filePaths)
|
||||
{
|
||||
if (Progress.Token.IsCancellationRequested) return false;
|
||||
|
||||
Tuple<ResultStatus, string, List<string>> result;
|
||||
try
|
||||
{
|
||||
result = ProcessFile(filePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var deets = new List<string>();
|
||||
deets.Add(ex.GetType().Name);
|
||||
deets.Add(ex.Message);
|
||||
result = new Tuple<ResultStatus, string, List<string>>(ResultStatus.Exception, filePath, deets);
|
||||
}
|
||||
|
||||
results.Add(result);
|
||||
|
||||
Progress++;
|
||||
}
|
||||
|
||||
// Generate the report
|
||||
if (Report.Value)
|
||||
{
|
||||
var reportDirectory = Path.GetDirectoryName(SlicerFile.FileFullPath);
|
||||
var reportFilePath = Path.Combine(reportDirectory, "CloneSettingsReport.txt");
|
||||
using (var writer = new StreamWriter(reportFilePath))
|
||||
{
|
||||
writer.WriteLine(Script.Name + " " + Script.Version.ToString() + " by " + Script.Author);
|
||||
writer.WriteLine("Source file: " + SlicerFile.FileFullPath);
|
||||
writer.WriteLine(DateTime.Now.ToLongDateString() + ", " + DateTime.Now.ToLongTimeString());
|
||||
writer.WriteLine("Recursive: " + Recursive.Value.ToString());
|
||||
writer.WriteLine("Directories: " + directoryPaths.Count);
|
||||
writer.WriteLine("Files: " + filePaths.Count);
|
||||
writer.WriteLine();
|
||||
|
||||
foreach (var statusGroup in results.GroupBy(x => x.Item1))
|
||||
{
|
||||
writer.WriteLine(statusGroup.Key.ToString());
|
||||
foreach (var result in statusGroup.OrderBy(x => x.Item2))
|
||||
{
|
||||
writer.WriteLine("\t" + result.Item2);
|
||||
if (result.Item3 is not null)
|
||||
{
|
||||
foreach (var detail in result.Item3)
|
||||
{
|
||||
writer.WriteLine("\t\t" + detail);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OpenReport.Value)
|
||||
{
|
||||
var startInfo = new ProcessStartInfo(reportFilePath)
|
||||
{
|
||||
UseShellExecute = true
|
||||
};
|
||||
Process.Start(startInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// return true if not cancelled by user
|
||||
return true;
|
||||
}
|
||||
|
||||
private Tuple<ResultStatus, string, List<string>> ProcessFile(string filePath)
|
||||
{
|
||||
// Determine the type of file
|
||||
var file = FileFormat.FindByExtensionOrFilePath(filePath, true);
|
||||
if (file is null)
|
||||
{
|
||||
return new Tuple<ResultStatus, string, List<string>>(ResultStatus.UnknownFileType, filePath, null);
|
||||
}
|
||||
|
||||
// Load the file
|
||||
file.Decode(filePath);
|
||||
if (string.Compare(file.MachineName, SlicerFile.MachineName, true) != 0)
|
||||
{
|
||||
var deets = new List<string>();
|
||||
deets.Add("Source machine type: " + SlicerFile.MachineName);
|
||||
deets.Add("Destination machine type: " + file.MachineName);
|
||||
return new Tuple<ResultStatus, string, List<string>>(ResultStatus.DifferentMachineTypes, filePath, deets);
|
||||
}
|
||||
|
||||
// TODO: Validate that some parameters are the same in both files?
|
||||
|
||||
// Change the parameters
|
||||
var changed = false;
|
||||
var details = new List<string>();
|
||||
|
||||
if (file.CanUseBottomLayerCount && file.BottomLayerCount != SlicerFile.BottomLayerCount)
|
||||
{
|
||||
details.Add($"Bottom Layer Count: {file.BottomLayerCount} to {SlicerFile.BottomLayerCount}");
|
||||
file.BottomLayerCount = SlicerFile.BottomLayerCount;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomLightOffDelay && file.BottomLightOffDelay != SlicerFile.BottomLightOffDelay)
|
||||
{
|
||||
details.Add($"Bottom Light Off Delay: {file.BottomLightOffDelay} to {SlicerFile.BottomLightOffDelay}");
|
||||
file.BottomLightOffDelay = SlicerFile.BottomLightOffDelay;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseLightOffDelay && file.LightOffDelay != SlicerFile.LightOffDelay)
|
||||
{
|
||||
details.Add($"Light Off Delay: {file.LightOffDelay} to {SlicerFile.LightOffDelay}");
|
||||
file.LightOffDelay = SlicerFile.LightOffDelay;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomWaitTimeBeforeCure && file.BottomWaitTimeBeforeCure != SlicerFile.BottomWaitTimeBeforeCure)
|
||||
{
|
||||
details.Add($"Bottom Wait Time Before Cure: {file.BottomWaitTimeBeforeCure} to {SlicerFile.BottomWaitTimeBeforeCure}");
|
||||
file.BottomWaitTimeBeforeCure = SlicerFile.BottomWaitTimeBeforeCure;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseWaitTimeBeforeCure && file.WaitTimeBeforeCure != SlicerFile.WaitTimeBeforeCure)
|
||||
{
|
||||
details.Add($"Wait Time Before Cure: {file.WaitTimeBeforeCure} to {SlicerFile.WaitTimeBeforeCure}");
|
||||
file.WaitTimeBeforeCure = SlicerFile.WaitTimeBeforeCure;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomExposureTime && file.BottomExposureTime != SlicerFile.BottomExposureTime)
|
||||
{
|
||||
details.Add($"Bottom Exposure Time: {file.BottomExposureTime} to {SlicerFile.BottomExposureTime}");
|
||||
file.BottomExposureTime = SlicerFile.BottomExposureTime;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseExposureTime && file.ExposureTime != SlicerFile.ExposureTime)
|
||||
{
|
||||
details.Add($"Exposure Time: {file.ExposureTime} to {SlicerFile.ExposureTime}");
|
||||
file.ExposureTime = SlicerFile.ExposureTime;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomWaitTimeAfterCure && file.BottomWaitTimeAfterCure != SlicerFile.BottomWaitTimeAfterCure)
|
||||
{
|
||||
details.Add($"Bottom Wait Time After Cure: {file.BottomWaitTimeAfterCure} to {SlicerFile.BottomWaitTimeAfterCure}");
|
||||
file.BottomWaitTimeAfterCure = SlicerFile.BottomWaitTimeAfterCure;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseWaitTimeAfterCure && file.WaitTimeAfterCure != SlicerFile.WaitTimeAfterCure)
|
||||
{
|
||||
details.Add($"Wait Time After Cure: {file.WaitTimeAfterCure} to {SlicerFile.WaitTimeAfterCure}");
|
||||
file.WaitTimeAfterCure = SlicerFile.WaitTimeAfterCure;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomLiftHeight && file.BottomLiftHeight != SlicerFile.BottomLiftHeight)
|
||||
{
|
||||
details.Add($"Bottom Lift Height: {file.BottomLiftHeight} to {SlicerFile.BottomLiftHeight}");
|
||||
file.BottomLiftHeight = SlicerFile.BottomLiftHeight;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomLiftSpeed && file.BottomLiftSpeed != SlicerFile.BottomLiftSpeed)
|
||||
{
|
||||
details.Add($"Bottom Lift Speed: {file.BottomLiftSpeed} to {SlicerFile.BottomLiftSpeed}");
|
||||
file.BottomLiftSpeed = SlicerFile.BottomLiftSpeed;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseLiftHeight && file.LiftHeight != SlicerFile.LiftHeight)
|
||||
{
|
||||
details.Add($"Lift Height: {file.LiftHeight} to {SlicerFile.LiftHeight}");
|
||||
file.LiftHeight = SlicerFile.LiftHeight;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseLiftSpeed && file.LiftSpeed != SlicerFile.LiftSpeed)
|
||||
{
|
||||
details.Add($"Lift Speed: {file.LiftSpeed} to {SlicerFile.LiftSpeed}");
|
||||
file.LiftSpeed = SlicerFile.LiftSpeed;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomLiftHeight2 && file.BottomLiftHeight2 != SlicerFile.BottomLiftHeight2)
|
||||
{
|
||||
details.Add($"Bottom Lift Height 2: {file.BottomLiftHeight2} to {SlicerFile.BottomLiftHeight2}");
|
||||
file.BottomLiftHeight2 = SlicerFile.BottomLiftHeight2;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomLiftSpeed2 && file.BottomLiftSpeed2 != SlicerFile.BottomLiftSpeed2)
|
||||
{
|
||||
details.Add($"Bottom Lift Speed2: {file.BottomLiftSpeed2} to {SlicerFile.BottomLiftSpeed2}");
|
||||
file.BottomLiftSpeed2 = SlicerFile.BottomLiftSpeed2;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseLiftHeight2 && file.LiftHeight2 != SlicerFile.LiftHeight2)
|
||||
{
|
||||
details.Add($"Lift Height 2: {file.LiftHeight2} to {SlicerFile.LiftHeight2}");
|
||||
file.LiftHeight2 = SlicerFile.LiftHeight2;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseLiftSpeed2 && file.LiftSpeed2 != SlicerFile.LiftSpeed2)
|
||||
{
|
||||
details.Add($"Lift Speed 2: {file.LiftSpeed2} to {SlicerFile.LiftSpeed2}");
|
||||
file.LiftSpeed2 = SlicerFile.LiftSpeed2;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomWaitTimeAfterLift && file.BottomWaitTimeAfterLift != SlicerFile.BottomWaitTimeAfterLift)
|
||||
{
|
||||
details.Add($"Bottom Wait Time After Lift: {file.BottomWaitTimeAfterLift} to {SlicerFile.BottomWaitTimeAfterLift}");
|
||||
file.BottomWaitTimeAfterLift = SlicerFile.BottomWaitTimeAfterLift;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseWaitTimeAfterLift && file.WaitTimeAfterLift != SlicerFile.WaitTimeAfterLift)
|
||||
{
|
||||
details.Add($"Wait Time After Lift: {file.WaitTimeAfterLift} to {SlicerFile.WaitTimeAfterLift}");
|
||||
file.WaitTimeAfterLift = SlicerFile.WaitTimeAfterLift;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomRetractSpeed && file.BottomRetractSpeed != SlicerFile.BottomRetractSpeed)
|
||||
{
|
||||
details.Add($"Bottom Retract Speed: {file.BottomRetractSpeed} to {SlicerFile.BottomRetractSpeed}");
|
||||
file.BottomRetractSpeed = SlicerFile.BottomRetractSpeed;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseRetractSpeed && file.RetractSpeed != SlicerFile.RetractSpeed)
|
||||
{
|
||||
details.Add($"Retract Speed: {file.RetractSpeed} to {SlicerFile.RetractSpeed}");
|
||||
file.RetractSpeed = SlicerFile.RetractSpeed;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomRetractHeight2 && file.BottomRetractHeight2 != SlicerFile.BottomRetractHeight2)
|
||||
{
|
||||
details.Add($"Bottom Retract Height 2: {file.BottomRetractHeight2} to {SlicerFile.BottomRetractHeight2}");
|
||||
file.BottomRetractHeight2 = SlicerFile.BottomRetractHeight2;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomRetractSpeed2 && file.BottomRetractSpeed2 != SlicerFile.BottomRetractSpeed2)
|
||||
{
|
||||
details.Add($"Bottom Retract Speed2: {file.BottomRetractSpeed2} to {SlicerFile.BottomRetractSpeed2}");
|
||||
file.BottomRetractSpeed2 = SlicerFile.BottomRetractSpeed2;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseRetractHeight2 && file.RetractHeight2 != SlicerFile.RetractHeight2)
|
||||
{
|
||||
details.Add($"Retract Height 2: {file.RetractHeight2} to {SlicerFile.RetractHeight2}");
|
||||
file.RetractHeight2 = SlicerFile.RetractHeight2;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseRetractSpeed2 && file.RetractSpeed2 != SlicerFile.RetractSpeed2)
|
||||
{
|
||||
details.Add($"Retract Speed 2: {file.RetractSpeed2} to {SlicerFile.RetractSpeed2}");
|
||||
file.RetractSpeed2 = SlicerFile.RetractSpeed2;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseBottomLightPWM && file.BottomLightPWM != SlicerFile.BottomLightPWM)
|
||||
{
|
||||
details.Add($"Bottom Light PWM: {file.BottomLightPWM} to {SlicerFile.BottomLightPWM}");
|
||||
file.BottomLightPWM = SlicerFile.BottomLightPWM;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (file.CanUseLightPWM && file.LightPWM != SlicerFile.LightPWM)
|
||||
{
|
||||
details.Add($"Light PWM: {file.LightPWM} to {SlicerFile.LightPWM}");
|
||||
file.LightPWM = SlicerFile.LightPWM;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// if (file.CanUseXXX && file.XXX != SlicerFile.XXX)
|
||||
// {
|
||||
// details.Add($"XXX: {file.XXX} to {SlicerFile.XXX}");
|
||||
// file.XXX = SlicerFile.XXX;
|
||||
// changed = true;
|
||||
// }
|
||||
|
||||
// Bail out if not changed
|
||||
if (!changed)
|
||||
{
|
||||
return new Tuple<ResultStatus, string, List<string>>(ResultStatus.Unchanged, filePath, null);
|
||||
}
|
||||
|
||||
// Save the changed file
|
||||
file.Save();
|
||||
|
||||
return new Tuple<ResultStatus, string, List<string>>(ResultStatus.Success, filePath, details);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
@@ -39,7 +40,7 @@ namespace UVtools.WPF.Controls.Tools
|
||||
{
|
||||
case ToolWindow.Callbacks.Init:
|
||||
case ToolWindow.Callbacks.Loaded:
|
||||
ParentWindow.ButtonOkEnabled = Operation.CanExecute;
|
||||
if(ParentWindow is not null) ParentWindow.ButtonOkEnabled = Operation.CanExecute;
|
||||
ReloadGUI();
|
||||
Operation.PropertyChanged += (sender, e) =>
|
||||
{
|
||||
@@ -183,309 +184,309 @@ namespace UVtools.WPF.Controls.Tools
|
||||
switch (variable)
|
||||
{
|
||||
case ScriptNumericalInput<sbyte> numSBYTE:
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
Minimum = numSBYTE.Minimum,
|
||||
Maximum = numSBYTE.Maximum,
|
||||
Value = numSBYTE.Value,
|
||||
Increment = numSBYTE.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
Minimum = numSBYTE.Minimum,
|
||||
Maximum = numSBYTE.Maximum,
|
||||
Value = numSBYTE.Value,
|
||||
Increment = numSBYTE.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numSBYTE.Value = (sbyte)value;
|
||||
control.Value = numSBYTE.Value;
|
||||
});
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numSBYTE.Value = (sbyte)value;
|
||||
control.Value = numSBYTE.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case ScriptNumericalInput<byte> numBYTE:
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
Minimum = numBYTE.Minimum,
|
||||
Maximum = numBYTE.Maximum,
|
||||
Value = numBYTE.Value,
|
||||
Increment = numBYTE.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
Minimum = numBYTE.Minimum,
|
||||
Maximum = numBYTE.Maximum,
|
||||
Value = numBYTE.Value,
|
||||
Increment = numBYTE.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numBYTE.Value = (byte)value;
|
||||
control.Value = numBYTE.Value;
|
||||
});
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numBYTE.Value = (byte)value;
|
||||
control.Value = numBYTE.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case ScriptNumericalInput<short> numSHORT:
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
Minimum = numSHORT.Minimum,
|
||||
Maximum = numSHORT.Maximum,
|
||||
Value = numSHORT.Value,
|
||||
Increment = numSHORT.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
Minimum = numSHORT.Minimum,
|
||||
Maximum = numSHORT.Maximum,
|
||||
Value = numSHORT.Value,
|
||||
Increment = numSHORT.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numSHORT.Value = (short)value;
|
||||
control.Value = numSHORT.Value;
|
||||
});
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numSHORT.Value = (short)value;
|
||||
control.Value = numSHORT.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case ScriptNumericalInput<ushort> numUSHORT:
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
Minimum = numUSHORT.Minimum,
|
||||
Maximum = numUSHORT.Maximum,
|
||||
Value = numUSHORT.Value,
|
||||
Increment = numUSHORT.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
Minimum = numUSHORT.Minimum,
|
||||
Maximum = numUSHORT.Maximum,
|
||||
Value = numUSHORT.Value,
|
||||
Increment = numUSHORT.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numUSHORT.Value = (ushort)value;
|
||||
control.Value = numUSHORT.Value;
|
||||
});
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numUSHORT.Value = (ushort)value;
|
||||
control.Value = numUSHORT.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case ScriptNumericalInput<int> numINT:
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
Minimum = numINT.Minimum,
|
||||
Maximum = numINT.Maximum,
|
||||
Value = numINT.Value,
|
||||
Increment = numINT.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
Minimum = numINT.Minimum,
|
||||
Maximum = numINT.Maximum,
|
||||
Value = numINT.Value,
|
||||
Increment = numINT.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numINT.Value = (int)value;
|
||||
control.Value = numINT.Value;
|
||||
});
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numINT.Value = (int)value;
|
||||
control.Value = numINT.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case ScriptNumericalInput<uint> numUINT:
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
Minimum = numUINT.Minimum,
|
||||
Maximum = numUINT.Maximum,
|
||||
Value = numUINT.Value,
|
||||
Increment = numUINT.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
Minimum = numUINT.Minimum,
|
||||
Maximum = numUINT.Maximum,
|
||||
Value = numUINT.Value,
|
||||
Increment = numUINT.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numUINT.Value = (uint)value;
|
||||
control.Value = numUINT.Value;
|
||||
});
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numUINT.Value = (uint)value;
|
||||
control.Value = numUINT.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case ScriptNumericalInput<long> numLONG:
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
Minimum = numLONG.Minimum,
|
||||
Maximum = numLONG.Maximum,
|
||||
Value = numLONG.Value,
|
||||
Increment = numLONG.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
Minimum = numLONG.Minimum,
|
||||
Maximum = numLONG.Maximum,
|
||||
Value = numLONG.Value,
|
||||
Increment = numLONG.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numLONG.Value = (long)value;
|
||||
control.Value = numLONG.Value;
|
||||
});
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numLONG.Value = (long)value;
|
||||
control.Value = numLONG.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case ScriptNumericalInput<ulong> numULONG:
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
Minimum = numULONG.Minimum,
|
||||
Maximum = numULONG.Maximum,
|
||||
Value = numULONG.Value,
|
||||
Increment = numULONG.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
Minimum = numULONG.Minimum,
|
||||
Maximum = numULONG.Maximum,
|
||||
Value = numULONG.Value,
|
||||
Increment = numULONG.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numULONG.Value = (ulong)value;
|
||||
control.Value = numULONG.Value;
|
||||
});
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numULONG.Value = (ulong)value;
|
||||
control.Value = numULONG.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case ScriptNumericalInput<float> numFLOAT:
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
Minimum = numFLOAT.Minimum,
|
||||
Maximum = numFLOAT.Maximum,
|
||||
Value = numFLOAT.Value,
|
||||
Increment = numFLOAT.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
Minimum = numFLOAT.Minimum,
|
||||
Maximum = numFLOAT.Maximum,
|
||||
Value = numFLOAT.Value,
|
||||
Increment = numFLOAT.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
|
||||
if (numFLOAT.DecimalPlates > 0)
|
||||
{
|
||||
control.FormatString = $"F{numFLOAT.DecimalPlates}";
|
||||
}
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numFLOAT.Value = (float) Math.Round(value, numFLOAT.DecimalPlates);
|
||||
control.Value = numFLOAT.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
if (numFLOAT.DecimalPlates > 0)
|
||||
{
|
||||
control.FormatString = $"F{numFLOAT.DecimalPlates}";
|
||||
}
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numFLOAT.Value = (float) Math.Round(value, numFLOAT.DecimalPlates);
|
||||
control.Value = numFLOAT.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
case ScriptNumericalInput<double> numDOUBLE:
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
Minimum = numDOUBLE.Minimum,
|
||||
Maximum = numDOUBLE.Maximum,
|
||||
Value = numDOUBLE.Value,
|
||||
Increment = numDOUBLE.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
Minimum = numDOUBLE.Minimum,
|
||||
Maximum = numDOUBLE.Maximum,
|
||||
Value = numDOUBLE.Value,
|
||||
Increment = numDOUBLE.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
|
||||
if (numDOUBLE.DecimalPlates > 0)
|
||||
{
|
||||
control.FormatString = $"F{numDOUBLE.DecimalPlates}";
|
||||
}
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numDOUBLE.Value = Math.Round(value, numDOUBLE.DecimalPlates);
|
||||
control.Value = numDOUBLE.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
if (numDOUBLE.DecimalPlates > 0)
|
||||
{
|
||||
control.FormatString = $"F{numDOUBLE.DecimalPlates}";
|
||||
}
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numDOUBLE.Value = Math.Round(value, numDOUBLE.DecimalPlates);
|
||||
control.Value = numDOUBLE.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
case ScriptNumericalInput<decimal> numDECIMAL:
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
NumericUpDown control = new()
|
||||
{
|
||||
Minimum = (double)numDECIMAL.Minimum,
|
||||
Maximum = (double)numDECIMAL.Maximum,
|
||||
Value = (double)numDECIMAL.Value,
|
||||
Increment = (double)numDECIMAL.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
Minimum = (double)numDECIMAL.Minimum,
|
||||
Maximum = (double)numDECIMAL.Maximum,
|
||||
Value = (double)numDECIMAL.Value,
|
||||
Increment = (double)numDECIMAL.Increment,
|
||||
MinWidth = 150
|
||||
};
|
||||
|
||||
if (numDECIMAL.DecimalPlates > 0)
|
||||
{
|
||||
control.FormatString = $"F{numDECIMAL.DecimalPlates}";
|
||||
}
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numDECIMAL.Value = (decimal)Math.Round(value, numDECIMAL.DecimalPlates);
|
||||
control.Value = (double)numDECIMAL.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
if (numDECIMAL.DecimalPlates > 0)
|
||||
{
|
||||
control.FormatString = $"F{numDECIMAL.DecimalPlates}";
|
||||
}
|
||||
|
||||
var valueProperty = control.GetObservable(NumericUpDown.ValueProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
numDECIMAL.Value = (decimal)Math.Round(value, numDECIMAL.DecimalPlates);
|
||||
control.Value = (double)numDECIMAL.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
case ScriptCheckBoxInput inputCheckBox:
|
||||
{
|
||||
var control = new CheckBox
|
||||
{
|
||||
CheckBox control = new()
|
||||
{
|
||||
Content = variable.Label,
|
||||
IsChecked = inputCheckBox.Value
|
||||
};
|
||||
Content = variable.Label,
|
||||
IsChecked = inputCheckBox.Value
|
||||
};
|
||||
|
||||
var valueProperty = control.GetObservable(CheckBox.IsCheckedProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
if (value != null) inputCheckBox.Value = value.Value;
|
||||
});
|
||||
var valueProperty = control.GetObservable(CheckBox.IsCheckedProperty);
|
||||
valueProperty.Subscribe(value =>
|
||||
{
|
||||
if (value != null) inputCheckBox.Value = value.Value;
|
||||
});
|
||||
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
_scriptVariablesGrid.Children.Add(control);
|
||||
Grid.SetRow(control, i * 2);
|
||||
Grid.SetColumn(control, 2);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(variable.ToolTip))
|
||||
{
|
||||
ToolTip.SetTip(control, variable.ToolTip);
|
||||
}
|
||||
|
||||
continue;
|
||||
if (!string.IsNullOrWhiteSpace(variable.ToolTip))
|
||||
{
|
||||
ToolTip.SetTip(control, variable.ToolTip);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
case ScriptTextBoxInput inputTextBox:
|
||||
{
|
||||
TextBox control = new()
|
||||
@@ -506,10 +507,169 @@ namespace UVtools.WPF.Controls.Tools
|
||||
|
||||
continue;
|
||||
}
|
||||
case ScriptOpenFolderDialogInput inputOpenFolder:
|
||||
{
|
||||
var panel = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
Spacing = 5
|
||||
};
|
||||
|
||||
var control = new TextBox
|
||||
{
|
||||
IsReadOnly = true,
|
||||
Text = inputOpenFolder.Value,
|
||||
};
|
||||
|
||||
var button = new Button
|
||||
{
|
||||
Content = "Select",
|
||||
};
|
||||
|
||||
button.Click += async (sender, args) =>
|
||||
{
|
||||
var dialog = new OpenFolderDialog
|
||||
{
|
||||
Directory = inputOpenFolder.Value,
|
||||
Title = inputOpenFolder.Title
|
||||
};
|
||||
var result = await dialog.ShowAsync(ParentWindow);
|
||||
if (!string.IsNullOrWhiteSpace(result))
|
||||
{
|
||||
inputOpenFolder.Value = result;
|
||||
control.Text = result;
|
||||
}
|
||||
};
|
||||
|
||||
panel.Children.Add(control);
|
||||
panel.Children.Add(button);
|
||||
|
||||
_scriptVariablesGrid.Children.Add(panel);
|
||||
Grid.SetRow(panel, i * 2);
|
||||
Grid.SetColumn(panel, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
case ScriptSaveFileDialogInput inputSaveFile:
|
||||
{
|
||||
var panel = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
Spacing = 5
|
||||
};
|
||||
|
||||
var control = new TextBox
|
||||
{
|
||||
IsReadOnly = true,
|
||||
Text = inputSaveFile.Value,
|
||||
};
|
||||
|
||||
var button = new Button
|
||||
{
|
||||
Content = "Select",
|
||||
};
|
||||
|
||||
button.Click += async (sender, args) =>
|
||||
{
|
||||
var dialog = new SaveFileDialog
|
||||
{
|
||||
Directory = inputSaveFile.Value,
|
||||
Title = inputSaveFile.Title,
|
||||
DefaultExtension = inputSaveFile.DefaultExtension,
|
||||
InitialFileName = inputSaveFile.InitialFilename
|
||||
};
|
||||
|
||||
if (inputSaveFile.Filters is not null)
|
||||
{
|
||||
foreach (var filter in inputSaveFile.Filters)
|
||||
{
|
||||
dialog.Filters.Add(new FileDialogFilter
|
||||
{
|
||||
Extensions = filter.Extensions,
|
||||
Name = filter.Name
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var result = await dialog.ShowAsync(ParentWindow);
|
||||
if (!string.IsNullOrWhiteSpace(result))
|
||||
{
|
||||
inputSaveFile.Value = result;
|
||||
control.Text = result;
|
||||
}
|
||||
};
|
||||
|
||||
panel.Children.Add(control);
|
||||
panel.Children.Add(button);
|
||||
|
||||
_scriptVariablesGrid.Children.Add(panel);
|
||||
Grid.SetRow(panel, i * 2);
|
||||
Grid.SetColumn(panel, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
case ScriptOpenFileDialogInput inputOpenFile:
|
||||
{
|
||||
var panel = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
Spacing = 5
|
||||
};
|
||||
|
||||
var control = new TextBox
|
||||
{
|
||||
IsReadOnly = true,
|
||||
Text = inputOpenFile.Value,
|
||||
AcceptsReturn = true,
|
||||
};
|
||||
|
||||
var button = new Button
|
||||
{
|
||||
Content = "Select",
|
||||
};
|
||||
|
||||
button.Click += async (sender, args) =>
|
||||
{
|
||||
var dialog = new OpenFileDialog
|
||||
{
|
||||
Directory = inputOpenFile.Value,
|
||||
Title = inputOpenFile.Title,
|
||||
AllowMultiple = inputOpenFile.AllowMultiple,
|
||||
InitialFileName = inputOpenFile.InitialFilename
|
||||
};
|
||||
|
||||
if (inputOpenFile.Filters is not null)
|
||||
{
|
||||
foreach (var filter in inputOpenFile.Filters)
|
||||
{
|
||||
dialog.Filters.Add(new FileDialogFilter
|
||||
{
|
||||
Extensions = filter.Extensions,
|
||||
Name = filter.Name
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var result = await dialog.ShowAsync(ParentWindow);
|
||||
if (result is null || result.Length == 0) return;
|
||||
inputOpenFile.Value = result[0];
|
||||
inputOpenFile.Files = result;
|
||||
control.Text = string.Join('\n', result);
|
||||
};
|
||||
|
||||
panel.Children.Add(control);
|
||||
panel.Children.Add(button);
|
||||
|
||||
_scriptVariablesGrid.Children.Add(panel);
|
||||
Grid.SetRow(panel, i * 2);
|
||||
Grid.SetColumn(panel, 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParentWindow.FitToSize();
|
||||
ParentWindow?.FitToSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace UVtools.WPF
|
||||
Clear();
|
||||
_layer = value;
|
||||
Image = _layer.LayerMat;
|
||||
if (Image is null) return;
|
||||
ImageBgr = new Mat();
|
||||
CvInvoke.CvtColor(Image, ImageBgr, ColorConversion.Gray2Bgr);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ using MoreLinq;
|
||||
using UVtools.Core;
|
||||
using UVtools.Core.EmguCV;
|
||||
using UVtools.Core.Extensions;
|
||||
using UVtools.Core.FileFormats;
|
||||
using UVtools.Core.Layers;
|
||||
using UVtools.Core.Operations;
|
||||
using UVtools.WPF.Extensions;
|
||||
@@ -467,6 +468,13 @@ namespace UVtools.WPF
|
||||
public async Task OnClickDetectIssues()
|
||||
{
|
||||
if (!IsFileLoaded) return;
|
||||
if (SlicerFile.DecodeType == FileFormat.FileDecodeType.Partial)
|
||||
{
|
||||
await this.MessageBoxError("The file was open in partial mode and the detect issues is unable to run in this mode.\n" +
|
||||
"Please reload the file in full mode in order to use detect issues.", "Unable to run in partial mode");
|
||||
return;
|
||||
|
||||
}
|
||||
await ComputeIssues(
|
||||
GetIslandDetectionConfiguration(),
|
||||
GetOverhangDetectionConfiguration(),
|
||||
|
||||
@@ -799,7 +799,11 @@ namespace UVtools.WPF
|
||||
|
||||
var watch = Stopwatch.StartNew();
|
||||
LayerCache.Layer = SlicerFile[_actualLayer];
|
||||
|
||||
if (LayerCache.Image is null)
|
||||
{
|
||||
RefreshCurrentLayerData();
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
//var imageSpan = LayerCache.Image.GetPixelSpan<byte>();
|
||||
@@ -1304,9 +1308,6 @@ namespace UVtools.WPF
|
||||
CvInvoke.Rotate(LayerCache.ImageBgr, LayerCache.ImageBgr, _showLayerImageRotateCcwDirection ? RotateFlags.Rotate90CounterClockwise : RotateFlags.Rotate90Clockwise);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LayerImageBox.Image = LayerCache.Bitmap = LayerCache.ImageBgr.ToBitmap();
|
||||
|
||||
RefreshCurrentLayerData();
|
||||
|
||||
@@ -43,6 +43,13 @@
|
||||
<Image Source="\Assets\Icons\file-import-16x16.png"/>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Name="MainMenu.File.OpenInPartialMode" Header="Open in partial mode" Command="{Binding MenuFileOpenInPartialModeClicked}"
|
||||
ToolTip.Tip="Open a file only to see and/or edit properties.
|
||||

Layer images won't be loaded and most tools won't run in this mode.">
|
||||
<MenuItem.Icon>
|
||||
<Image Source="\Assets\Icons\file-import-16x16.png"/>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
Name="MainMenu.File.Reload"
|
||||
Header="_Reload"
|
||||
|
||||
@@ -584,8 +584,7 @@ namespace UVtools.WPF
|
||||
menuTool.Click += async (sender, args) => await ShowRunOperation(operation.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*LayerSlider.PropertyChanged += (sender, args) =>
|
||||
{
|
||||
Debug.WriteLine(args.Property.Name);
|
||||
@@ -1146,6 +1145,7 @@ namespace UVtools.WPF
|
||||
|
||||
public void MenuFileOpenClicked() => OpenFile();
|
||||
public void MenuFileOpenNewWindowClicked() => OpenFile(true);
|
||||
public void MenuFileOpenInPartialModeClicked() => OpenFile(false, FileFormat.FileDecodeType.Partial);
|
||||
|
||||
public void MenuFileOpenCurrentFileFolderClicked()
|
||||
{
|
||||
@@ -1196,7 +1196,7 @@ namespace UVtools.WPF
|
||||
await SaveFile(file);
|
||||
}
|
||||
|
||||
public async void OpenFile(bool newWindow = false)
|
||||
public async void OpenFile(bool newWindow = false, FileFormat.FileDecodeType fileDecodeType = FileFormat.FileDecodeType.Full)
|
||||
{
|
||||
var filters = Helpers.ToAvaloniaFileFilter(FileFormat.AllFileFiltersAvalonia);
|
||||
var orderedFilters = new List<FileDialogFilter> {filters[Settings.General.DefaultOpenFileExtensionIndex]};
|
||||
@@ -1213,7 +1213,7 @@ namespace UVtools.WPF
|
||||
Directory = Settings.General.DefaultDirectoryOpenFile
|
||||
};
|
||||
var files = await dialog.ShowAsync(this);
|
||||
ProcessFiles(files, newWindow);
|
||||
ProcessFiles(files, newWindow, fileDecodeType);
|
||||
}
|
||||
|
||||
public async void OnMenuFileCloseFile()
|
||||
@@ -1386,19 +1386,36 @@ namespace UVtools.WPF
|
||||
|
||||
private void UpdateTitle()
|
||||
{
|
||||
Title = SlicerFile is null
|
||||
? $"{About.Software} Version: {App.VersionStr}"
|
||||
: $"{About.Software} File: {Path.GetFileName(SlicerFile.FileFullPath)} ({Math.Round(LastStopWatch.ElapsedMilliseconds / 1000m, 2)}s) Version: {App.VersionStr}"
|
||||
;
|
||||
var title = $"{About.Software} ";
|
||||
|
||||
Title += $" RAM: {SizeExtensions.SizeSuffix(Environment.WorkingSet)}";
|
||||
if (IsFileLoaded)
|
||||
{
|
||||
title += $"File: {Path.GetFileName(SlicerFile.FileFullPath)} ({Math.Round(LastStopWatch.ElapsedMilliseconds / 1000m, 2)}s) ";
|
||||
}
|
||||
|
||||
title += $"Version: {App.VersionStr} RAM: {SizeExtensions.SizeSuffix(Environment.WorkingSet)}";
|
||||
|
||||
if (IsFileLoaded)
|
||||
{
|
||||
if (CanSave)
|
||||
{
|
||||
title += " [UNSAVED]";
|
||||
}
|
||||
|
||||
if (SlicerFile.DecodeType == FileFormat.FileDecodeType.Partial)
|
||||
{
|
||||
title += " [PARTIAL MODE]";
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
Title += " [DEBUG]";
|
||||
title += " [DEBUG]";
|
||||
#endif
|
||||
|
||||
Title = title;
|
||||
}
|
||||
|
||||
public async void ProcessFiles(string[] files, bool openNewWindow = false)
|
||||
public async void ProcessFiles(string[] files, bool openNewWindow = false, FileFormat.FileDecodeType fileDecodeType = FileFormat.FileDecodeType.Full)
|
||||
{
|
||||
if (files is null || files.Length == 0) return;
|
||||
|
||||
@@ -1436,7 +1453,7 @@ namespace UVtools.WPF
|
||||
|
||||
if (i == 0 && !openNewWindow && (_globalModifiers & KeyModifiers.Shift) == 0)
|
||||
{
|
||||
ProcessFile(files[i]);
|
||||
ProcessFile(files[i], fileDecodeType);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1450,10 +1467,11 @@ namespace UVtools.WPF
|
||||
void ReloadFile(uint actualLayer)
|
||||
{
|
||||
if (App.SlicerFile is null) return;
|
||||
ProcessFile(SlicerFile.FileFullPath, _actualLayer);
|
||||
ProcessFile(SlicerFile.FileFullPath, SlicerFile.DecodeType, _actualLayer);
|
||||
}
|
||||
|
||||
async void ProcessFile(string fileName, uint actualLayer = 0)
|
||||
void ProcessFile(string fileName, uint actualLayer = 0) => ProcessFile(fileName, FileFormat.FileDecodeType.Full, actualLayer);
|
||||
async void ProcessFile(string fileName, FileFormat.FileDecodeType fileDecodeType, uint actualLayer = 0)
|
||||
{
|
||||
if (!File.Exists(fileName)) return;
|
||||
CloseFile();
|
||||
@@ -1468,7 +1486,7 @@ namespace UVtools.WPF
|
||||
{
|
||||
try
|
||||
{
|
||||
SlicerFile.Decode(fileName, Progress);
|
||||
SlicerFile.Decode(fileName, fileDecodeType, Progress);
|
||||
return true;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@@ -1507,7 +1525,7 @@ namespace UVtools.WPF
|
||||
return;
|
||||
}
|
||||
|
||||
if (Settings.Automations.AutoConvertFiles)
|
||||
if (Settings.Automations.AutoConvertFiles && SlicerFile.DecodeType == FileFormat.FileDecodeType.Full)
|
||||
{
|
||||
string convertFileExtension = SlicerFile switch
|
||||
{
|
||||
@@ -1626,7 +1644,7 @@ namespace UVtools.WPF
|
||||
|
||||
Clipboard.Init(SlicerFile);
|
||||
|
||||
if (SlicerFile is not ImageFile)
|
||||
if (SlicerFile is not ImageFile && SlicerFile.DecodeType == FileFormat.FileDecodeType.Full)
|
||||
{
|
||||
List<MenuItem> menuItems = new();
|
||||
foreach (var fileFormat in FileFormat.AvailableFormats)
|
||||
@@ -1664,7 +1682,7 @@ namespace UVtools.WPF
|
||||
MenuFileConvertItems = menuItems.ToArray();
|
||||
}
|
||||
|
||||
using var mat = SlicerFile[0].LayerMat;
|
||||
using var mat = SlicerFile.FirstLayer?.LayerMat;
|
||||
|
||||
VisibleThumbnailIndex = 1;
|
||||
|
||||
@@ -1672,7 +1690,6 @@ namespace UVtools.WPF
|
||||
|
||||
UpdateTitle();
|
||||
|
||||
|
||||
if (mat is not null)
|
||||
{
|
||||
if (Settings.LayerPreview.AutoRotateLayerBestView)
|
||||
@@ -1726,7 +1743,7 @@ namespace UVtools.WPF
|
||||
"Incorrect image ratio detected");
|
||||
}
|
||||
|
||||
if (mat.Size != SlicerFile.Resolution)
|
||||
if (mat is not null && mat.Size != SlicerFile.Resolution)
|
||||
{
|
||||
var result = await this.MessageBoxWaring($"Layer image resolution of {mat.Size} mismatch with printer resolution of {SlicerFile.Resolution}.\n" +
|
||||
"1) Printing this file can lead to problems or malformed model, please verify your slicer printer settings;\n" +
|
||||
@@ -1747,29 +1764,32 @@ namespace UVtools.WPF
|
||||
UpdateLayerTrackerHighlightIssues();
|
||||
};
|
||||
|
||||
if (Settings.Issues.ComputeIssuesOnLoad)
|
||||
if (SlicerFile.DecodeType == FileFormat.FileDecodeType.Full)
|
||||
{
|
||||
_firstTimeOnIssues = false;
|
||||
await OnClickDetectIssues();
|
||||
if (SlicerFile.IssueManager.Count > 0)
|
||||
if (Settings.Issues.ComputeIssuesOnLoad)
|
||||
{
|
||||
SelectedTabItem = TabIssues;
|
||||
if(Settings.Issues.AutoRepairIssuesOnLoad)
|
||||
await RunOperation(ToolRepairLayersControl.GetOperationRepairLayers());
|
||||
_firstTimeOnIssues = false;
|
||||
await OnClickDetectIssues();
|
||||
if (SlicerFile.IssueManager.Count > 0)
|
||||
{
|
||||
SelectedTabItem = TabIssues;
|
||||
if (Settings.Issues.AutoRepairIssuesOnLoad)
|
||||
await RunOperation(ToolRepairLayersControl.GetOperationRepairLayers());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await ComputeIssues(
|
||||
GetIslandDetectionConfiguration(false),
|
||||
GetOverhangDetectionConfiguration(false),
|
||||
GetResinTrapDetectionConfiguration(false),
|
||||
GetTouchingBoundsDetectionConfiguration(false),
|
||||
GetPrintHeightDetectionConfiguration(true),
|
||||
true);
|
||||
if (SlicerFile.IssueManager.Count > 0)
|
||||
else
|
||||
{
|
||||
SelectedTabItem = TabIssues;
|
||||
await ComputeIssues(
|
||||
GetIslandDetectionConfiguration(false),
|
||||
GetOverhangDetectionConfiguration(false),
|
||||
GetResinTrapDetectionConfiguration(false),
|
||||
GetTouchingBoundsDetectionConfiguration(false),
|
||||
GetPrintHeightDetectionConfiguration(true),
|
||||
true);
|
||||
if (SlicerFile.IssueManager.Count > 0)
|
||||
{
|
||||
SelectedTabItem = TabIssues;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2066,6 +2086,13 @@ namespace UVtools.WPF
|
||||
return null;
|
||||
}
|
||||
|
||||
if (SlicerFile.DecodeType == FileFormat.FileDecodeType.Partial && !control.BaseOperation.CanRunInPartialMode)
|
||||
{
|
||||
await this.MessageBoxError($"The file was open in partial mode and the tool \"{control.BaseOperation.Title}\" is unable to run in this mode.\n" +
|
||||
"Please reload the file in full mode in order to use this tool.", "Unable to run in partial mode");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (removeContent)
|
||||
{
|
||||
control.IsVisible = false;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<Version>2.24.4</Version>
|
||||
<Version>2.25.0</Version>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user