diff --git a/CHANGELOG.md b/CHANGELOG.md
index d4efb8f1..26e62d33 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog
+## 03/12/2022 - v3.9.1
+
+- (Improvement) Performance on pixel editor when using high count of layers below and/or above
+- (Fix) Unable to disable specific issues detection
+
## 01/12/2022 - v3.9.0
- **File formats:**
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 92cc23a7..89d2cea0 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,33 +1,3 @@
-- **File formats:**
- - (Add) File extension: .gktwo.ctb to `ChituboxFile` to be able to convert files for UniFormation GKtwo under special CTB format
- - (Add) UniFormation GKtwo compatibility under CTB format, if exporting JXS rename to CTB before open
- - (Fix) CTB, CBDDLP, PHOTON, FDG, PHZ: Read and write files larger then 4GB (#608)
-- **PCB Exposure:**
- - (Add) Offset X/Y to offset the PCB from it origin
- - (Add) Allow to toggle between "Show preview image cropped by it bounds" and "Show full preview image (The final result)"
- - (Improvement) Use rectangle instead of line for center line primitive (#607)
- - (Fix) Implement rotation to polygon and center line primitives (#607)
- - (Fix) Macros in a single line was not being parsed (#607)
- - (Fix) Invert color per file was not affecting primitives
-- **Network printers:**
- - (Add) Socket requests with TCP and UDP
- - (Add) AnyCubic printer preset (However it can't upload a file)
- - (Add) Scripts in request path to allow a first request to fetch data to the final request:
- - A script starts with **<\?** and ends with **?>**
- - First parameter is the first request to get response content from
- - Second parameter is the regex pattern to match content with
- - Third parameter is the final request that supports a parameter from regex matching group, eg: **{#1}** is match Group[1] value
- - **Example:** <\? getfiles > {0}\/(\d+\.[\da-zA-Z]+), > printfile,{#1} ?>
- - (Change) Allow to print a filename without send it when upload request path is empty
- - (Fix) Do not show printers with empty requests
-- (Change) Default layer compression to Lz4 instead of Png
-- (Improvement) Application is now culture aware but set part of `NumberFormat` to the `InvariantCulture.NumberFormat`
-- (Improvement) Material cost now show with the current culture currency symbol due previous change
-- (Improvement) Better submit of bug reports using sections and forms
-- (Improvement) Linux: AppImage now have a help manual with possible arguments and parameters
-- (Improvement) macOS: Codesign app on auto-installer and auto-upgrade to bypass arm64 run restriction (#431)
-- (Improvement) macOS: Rebuilt arm64 libcvextern.dylib to run with less dependencies (#431)
-- (Improvement) macOS: Try to show missing dependencies from openCV (if any) on the error message
-- (Fix) UI: layers sorted lexicographically instead of numerically in the issues list view (#611)
-- (Fix) PrusaSlicer printer parameters: UniFormation GKtwo
+- (Improvement) Performance on pixel editor when using high count of layers below and/or above
+- (Fix) Unable to disable specific issues detection
diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs
index 0b74d6c4..effe3e1b 100644
--- a/UVtools.Core/FileFormats/FileFormat.cs
+++ b/UVtools.Core/FileFormats/FileFormat.cs
@@ -5729,6 +5729,18 @@ public bool TryParseLayerIndexRange(string value, out uint layerIndexStart, out
return layerIndexStart <= layerIndexEnd;
}
+ ///
+ /// Constrains a layer index to be inside the range between 0 and
+ ///
+ /// Layer index to sanitize
+ /// True if sanitized, otherwise false
+ public bool SanitizeLayerIndex(ref int layerIndex)
+ {
+ var originalValue = layerIndex;
+ layerIndex = Math.Clamp(layerIndex, 0, (int)LastLayerIndex);
+ return originalValue != layerIndex;
+ }
+
///
/// Constrains a layer index to be inside the range between 0 and
///
@@ -5741,11 +5753,25 @@ public bool SanitizeLayerIndex(ref uint layerIndex)
return originalValue != layerIndex;
}
+ ///
+ /// Constrains a layer index to be inside the range between 0 and
+ ///
+ /// Layer index to sanitize
+ public uint SanitizeLayerIndex(int layerIndex)
+ {
+ return (uint)Math.Clamp(layerIndex, 0, LastLayerIndex);
+ }
+
+ ///
+ /// Constrains a layer index to be inside the range between 0 and
+ ///
+ /// Layer index to sanitize
public uint SanitizeLayerIndex(uint layerIndex)
{
return Math.Min(layerIndex, LastLayerIndex);
}
+
///
/// Re-assign layer indexes and parent
///
diff --git a/UVtools.Core/Operations/Operation.cs b/UVtools.Core/Operations/Operation.cs
index d545cf4b..7daab2c1 100644
--- a/UVtools.Core/Operations/Operation.cs
+++ b/UVtools.Core/Operations/Operation.cs
@@ -217,7 +217,7 @@ public virtual uint LayerIndexStart
{
if (SlicerFile is not null)
{
- value = Math.Min(value, SlicerFile.LastLayerIndex);
+ SlicerFile.SanitizeLayerIndex(ref value);
}
if (!RaiseAndSetIfChanged(ref _layerIndexStart, value)) return;
RaisePropertyChanged(nameof(LayerRangeCount));
@@ -235,7 +235,7 @@ public virtual uint LayerIndexEnd
{
if (SlicerFile is not null)
{
- value = Math.Min(value, SlicerFile.LastLayerIndex);
+ SlicerFile.SanitizeLayerIndex(ref value);
}
if(!RaiseAndSetIfChanged(ref _layerIndexEnd, value)) return;
RaisePropertyChanged(nameof(LayerRangeCount));
@@ -463,7 +463,7 @@ public void SelectLastLayer()
public void SelectFirstToCurrentLayer(uint currentLayerIndex)
{
LayerIndexStart = 0;
- LayerIndexEnd = Math.Min(currentLayerIndex, SlicerFile.LastLayerIndex);
+ LayerIndexEnd = SlicerFile.SanitizeLayerIndex(currentLayerIndex);
}
///
@@ -472,7 +472,7 @@ public void SelectFirstToCurrentLayer(uint currentLayerIndex)
/// From layer index to select
public void SelectCurrentToLastLayer(uint currentLayerIndex)
{
- LayerIndexStart = Math.Min(currentLayerIndex, SlicerFile.LastLayerIndex);
+ LayerIndexStart = SlicerFile.SanitizeLayerIndex(currentLayerIndex);
LayerIndexEnd = SlicerFile.LastLayerIndex;
}
diff --git a/UVtools.Core/Operations/OperationLayerArithmetic.cs b/UVtools.Core/Operations/OperationLayerArithmetic.cs
index 748194bf..925d784c 100644
--- a/UVtools.Core/Operations/OperationLayerArithmetic.cs
+++ b/UVtools.Core/Operations/OperationLayerArithmetic.cs
@@ -163,7 +163,7 @@ public bool Parse()
{
uint.TryParse(rangeSplit[0], out var startLayer);
if (!uint.TryParse(rangeSplit[1], out var endLayer)) endLayer = SlicerFile.LastLayerIndex;
- endLayer = Math.Min(endLayer, SlicerFile.LastLayerIndex);
+ SlicerFile.SanitizeLayerIndex(ref endLayer);
for (var index = startLayer; index <= endLayer; index++)
{
if (group.SetLayers.Contains(index)) continue;
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index 1d48b58f..eca31b9f 100644
--- a/UVtools.Core/UVtools.Core.csproj
+++ b/UVtools.Core/UVtools.Core.csproj
@@ -10,7 +10,7 @@
https://github.com/sn4k3/UVtools
https://github.com/sn4k3/UVtools
MSLA/DLP, file analysis, calibration, repair, conversion and manipulation
- 3.9.0
+ 3.9.1
Copyright © 2020 PTRTECH
UVtools.png
AnyCPU;x64
diff --git a/UVtools.WPF/MainWindow.Issues.cs b/UVtools.WPF/MainWindow.Issues.cs
index 2a1273c1..c1823f72 100644
--- a/UVtools.WPF/MainWindow.Issues.cs
+++ b/UVtools.WPF/MainWindow.Issues.cs
@@ -232,7 +232,7 @@ public async void RemoveRepairIssues(IEnumerable issues, bool promptC
Clipboard.Snapshot();
- var task = await Task.Factory.StartNew(() =>
+ var task = await Task.Run(() =>
{
Progress.Reset("Removing selected issues", (uint)processParallelIssues.Count);
try
@@ -448,7 +448,7 @@ private async Task UpdateIslandsOverhangs(List whiteListLayers)
}*/
- var resultIssues = await Task.Factory.StartNew(() =>
+ var resultIssues = await Task.Run(() =>
{
try
{
@@ -636,7 +636,7 @@ private async Task ComputeIssues(IssuesDetectionConfiguration config)
IsGUIEnabled = false;
ShowProgressWindow("Computing Issues");
- var resultIssues = await Task.Factory.StartNew(() =>
+ var resultIssues = await Task.Run(() =>
{
try
{
@@ -825,7 +825,19 @@ public void SetResinTrapDetectionStartLayer(char which)
}
}
- public IssuesDetectionConfiguration GetIssuesDetectionConfiguration(bool enable = true)
+ public IssuesDetectionConfiguration GetIssuesDetectionConfiguration()
+ {
+ return new IssuesDetectionConfiguration(
+ GetIslandDetectionConfiguration(),
+ GetOverhangDetectionConfiguration(),
+ GetResinTrapDetectionConfiguration(),
+ GetTouchingBoundsDetectionConfiguration(),
+ GetPrintHeightDetectionConfiguration(),
+ GetEmptyLayerDetectionConfiguration()
+ );
+ }
+
+ public IssuesDetectionConfiguration GetIssuesDetectionConfiguration(bool enable)
{
return new IssuesDetectionConfiguration(
GetIslandDetectionConfiguration(enable),
diff --git a/UVtools.WPF/MainWindow.LayerPreview.cs b/UVtools.WPF/MainWindow.LayerPreview.cs
index 91fe0240..33a3fc93 100644
--- a/UVtools.WPF/MainWindow.LayerPreview.cs
+++ b/UVtools.WPF/MainWindow.LayerPreview.cs
@@ -813,13 +813,13 @@ public void GoLastLayer()
public void GoUpLayers(uint layers)
{
if (!IsFileLoaded) return;
- ActualLayer = Math.Min(SlicerFile.LastLayerIndex, ActualLayer + layers);
+ ActualLayer = SlicerFile.SanitizeLayerIndex(ActualLayer + layers);
}
public void GoDownLayers(uint layers)
{
if (!IsFileLoaded) return;
- ActualLayer = (uint)Math.Max(0, (int)ActualLayer - layers);
+ ActualLayer = SlicerFile.SanitizeLayerIndex((int)ActualLayer - (int)layers);
}
public void GoMassLayer(string which)
diff --git a/UVtools.WPF/MainWindow.PixelEditor.cs b/UVtools.WPF/MainWindow.PixelEditor.cs
index c46e6e1f..2c1a3246 100644
--- a/UVtools.WPF/MainWindow.PixelEditor.cs
+++ b/UVtools.WPF/MainWindow.PixelEditor.cs
@@ -174,19 +174,21 @@ void DrawPixel(bool isAdd, Point location, KeyModifiers keyModifiers)
WriteableBitmap bitmap = (WriteableBitmap)LayerImageBox.Image;
//var context = CreateRenderTarget().CreateDrawingContext(bitmap);
-
+
//Bitmap bmp = pbLayer.Image as Bitmap;
if (SelectedPixelOperationTabIndex == (byte)PixelOperation.PixelOperationType.Drawing)
{
- uint minLayer = (uint) Math.Max(0, (int)_actualLayer - DrawingPixelDrawing.LayersBelow);
- uint maxLayer = Math.Min(SlicerFile.LastLayerIndex, _actualLayer + DrawingPixelDrawing.LayersAbove);
+ var drawings = new List();
+ uint minLayer = SlicerFile.SanitizeLayerIndex((int)ActualLayer - (int)DrawingPixelDrawing.LayersBelow);
+ uint maxLayer = SlicerFile.SanitizeLayerIndex(ActualLayer + DrawingPixelDrawing.LayersAbove);
for (uint layerIndex = minLayer; layerIndex <= maxLayer; layerIndex++)
{
var operationDrawing = new PixelDrawing(layerIndex, realLocation, DrawingPixelDrawing.LineType,
DrawingPixelDrawing.BrushShape, DrawingPixelDrawing.RotationAngle, DrawingPixelDrawing.BrushSize, DrawingPixelDrawing.Thickness, DrawingPixelDrawing.RemovePixelBrightness, DrawingPixelDrawing.PixelBrightness, isAdd);
//if (PixelHistory.Contains(operation)) continue;
- AddDrawing(operationDrawing);
+ //AddDrawing(operationDrawing);
+ drawings.Add(operationDrawing);
if (layerIndex == _actualLayer)
{
@@ -386,13 +388,18 @@ void DrawPixel(bool isAdd, Point location, KeyModifiers keyModifiers)
//RefreshLayerImage();
}
}
+
+ AddDrawings(drawings);
+ return;
}
else if (SelectedPixelOperationTabIndex == (byte)PixelOperation.PixelOperationType.Text)
{
if (string.IsNullOrEmpty(DrawingPixelText.Text) || DrawingPixelText.FontScale < 0.2) return;
- uint minLayer = (uint) Math.Max(0, (int)ActualLayer - DrawingPixelText.LayersBelow);
- uint maxLayer = Math.Min(SlicerFile.LastLayerIndex, ActualLayer + DrawingPixelText.LayersAbove);
+ var drawings = new List();
+ uint minLayer = SlicerFile.SanitizeLayerIndex((int)ActualLayer - (int)DrawingPixelText.LayersBelow);
+ uint maxLayer = SlicerFile.SanitizeLayerIndex(ActualLayer + DrawingPixelText.LayersAbove);
+
for (uint layerIndex = minLayer; layerIndex <= maxLayer; layerIndex++)
{
var operationText = new PixelText(layerIndex, realLocation, DrawingPixelText.LineType,
@@ -401,8 +408,9 @@ void DrawPixel(bool isAdd, Point location, KeyModifiers keyModifiers)
//if (PixelHistory.Contains(operation)) continue;
//PixelHistory.Add(operation);
- AddDrawing(operationText);
-
+ //AddDrawing(operationText);
+ drawings.Add(operationText);
+
/*var color = isAdd
? Settings.PixelEditor.AddPixelColor : Settings.PixelEditor.RemovePixelColor;
@@ -415,20 +423,24 @@ void DrawPixel(bool isAdd, Point location, KeyModifiers keyModifiers)
}*/
}
+ AddDrawings(drawings);
ShowLayer();
return;
}
else if (SelectedPixelOperationTabIndex == (byte)PixelOperation.PixelOperationType.Eraser)
{
if (LayerCache.Image.GetByte(realLocation) < 10) return;
- uint minLayer = (uint) Math.Max(0, (int)ActualLayer - DrawingPixelEraser.LayersBelow);
- uint maxLayer = Math.Min(SlicerFile.LastLayerIndex, ActualLayer + DrawingPixelEraser.LayersAbove);
+
+ var drawings = new List();
+ uint minLayer = SlicerFile.SanitizeLayerIndex((int)ActualLayer - (int)DrawingPixelEraser.LayersBelow);
+ uint maxLayer = SlicerFile.SanitizeLayerIndex(ActualLayer + DrawingPixelEraser.LayersAbove);
for (uint layerIndex = minLayer; layerIndex <= maxLayer; layerIndex++)
{
var operationEraser = new PixelEraser(layerIndex, realLocation, DrawingPixelEraser.PixelBrightness);
//if (PixelHistory.Contains(operation)) continue;
- AddDrawing(operationEraser);
+ //AddDrawing(operationEraser);
+ drawings.Add(operationEraser);
/*if (layerIndex == _actualLayer)
{
@@ -445,6 +457,7 @@ void DrawPixel(bool isAdd, Point location, KeyModifiers keyModifiers)
}*/
}
+ AddDrawings(drawings);
ShowLayer();
return;
}
@@ -461,6 +474,7 @@ void DrawPixel(bool isAdd, Point location, KeyModifiers keyModifiers)
CvInvoke.Circle(LayerCache.ImageBgr, location, operationSupport.TipDiameter / 2,
new MCvScalar(Settings.PixelEditor.SupportsColor.B, Settings.PixelEditor.SupportsColor.G, Settings.PixelEditor.SupportsColor.R), -1);
RefreshLayerImage();
+ return;
}
else if (SelectedPixelOperationTabIndex == (byte)PixelOperation.PixelOperationType.DrainHole)
{
@@ -473,6 +487,7 @@ void DrawPixel(bool isAdd, Point location, KeyModifiers keyModifiers)
CvInvoke.Circle(LayerCache.ImageBgr, location, operationDrainHole.Diameter / 2,
new MCvScalar(Settings.PixelEditor.DrainHoleColor.B, Settings.PixelEditor.DrainHoleColor.G, Settings.PixelEditor.DrainHoleColor.R), -1);
RefreshLayerImage();
+ return;
}
else
{
@@ -482,11 +497,18 @@ void DrawPixel(bool isAdd, Point location, KeyModifiers keyModifiers)
public void AddDrawing(PixelOperation operation)
{
+ operation.Index = (uint)Drawings.Count;
Drawings.Insert(0, operation);
- for (int i = 0; i < Drawings.Count; i++)
+ }
+
+ public void AddDrawings(IEnumerable operations)
+ {
+ uint count = (uint)Drawings.Count;
+ foreach (var operation in operations)
{
- Drawings[i].Index = (uint) (Drawings.Count - i);
+ operation.Index = count++;
}
+ Drawings.InsertRange(0, operations);
}
public async void DrawModifications(bool exitEditor)
@@ -534,12 +556,12 @@ public async void DrawModifications(bool exitEditor)
ShowProgressWindow("Drawing pixels");
Clipboard.Snapshot();
- var task = await Task.Factory.StartNew(async () =>
+ var task = await Task.Run(() =>
{
try
{
SlicerFile.DrawModifications(Drawings, Progress);
- return true;
+ return Task.FromResult(true);
}
catch (OperationCanceledException)
{
@@ -547,18 +569,18 @@ public async void DrawModifications(bool exitEditor)
}
catch (Exception ex)
{
- await Dispatcher.UIThread.InvokeAsync(async () =>
+ Dispatcher.UIThread.InvokeAsync(async () =>
{
await this.MessageBoxError(ex.ToString(), "Drawing operation failed!");
});
}
- return false;
+ return Task.FromResult(false);
});
IsGUIEnabled = true;
- if (!task.Result)
+ if (!task)
{
Clipboard.RestoreSnapshot();
ShowLayer();
diff --git a/UVtools.WPF/MainWindow.Suggestions.cs b/UVtools.WPF/MainWindow.Suggestions.cs
index 62a85a6e..84b0605e 100644
--- a/UVtools.WPF/MainWindow.Suggestions.cs
+++ b/UVtools.WPF/MainWindow.Suggestions.cs
@@ -93,7 +93,7 @@ public async void ApplySuggestionsClicked()
IsGUIEnabled = false;
ShowProgressWindow($"Applying {suggestions.Length} suggestions", false);
- var executed = await Task.Factory.StartNew(() =>
+ var executed = await Task.Run(() =>
{
uint executed = 0;
@@ -141,7 +141,7 @@ public async void ApplySuggestionClicked(Suggestion suggestion)
IsGUIEnabled = false;
ShowProgressWindow(suggestion.Title, false);
- var result = await Task.Factory.StartNew(() =>
+ var result = await Task.Run(() =>
{
try
{
diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs
index 8f98c8ac..a05513b9 100644
--- a/UVtools.WPF/MainWindow.axaml.cs
+++ b/UVtools.WPF/MainWindow.axaml.cs
@@ -201,6 +201,7 @@ public TabItem SelectedTabItem
if (ReferenceEquals(_selectedTabItem, TabIssues) && Settings.Issues.ComputeIssuesOnClickTab)
{
Dispatcher.UIThread.InvokeAsync(async () => await OnClickDetectIssues());
+
}
}
}
@@ -641,7 +642,7 @@ await this.MessageBoxError($"The device {drive.Name} is not ready/available at t
{
Progress.ResetAll($"Ejecting {removableDrive.Name}");
- var ejectResult = await Task.Factory.StartNew(() =>
+ var ejectResult = await Task.Run(() =>
{
try
{
@@ -704,7 +705,7 @@ protected override void OnOpened(EventArgs e)
if (Settings.General.CheckForUpdatesOnStartup)
{
- Task.Factory.StartNew(() => VersionChecker.Check());
+ Task.Run(() => VersionChecker.Check());
}
ProcessFiles(Program.Args);
@@ -1047,7 +1048,7 @@ public async void MenuFileSettingsClicked()
IsGUIEnabled = false;
ShowProgressWindow($"Changing layers compression codec from {oldLayerCompressionCodec.ToString().ToUpper()} to {Settings.General.LayerCompressionCodec.ToString().ToUpper()}");
- await Task.Factory.StartNew(() =>
+ await Task.Run(() =>
{
try
{
@@ -1335,7 +1336,7 @@ async void ProcessFile(string fileName, FileFormat.FileDecodeType fileDecodeType
await this.MessageBoxError(exception.ToString(), "Error opening the file");
}*/
- var task = await Task.Factory.StartNew( () =>
+ var task = await Task.Run( () =>
{
try
{
@@ -1461,7 +1462,7 @@ await this.MessageBoxError("It seems this file has no layers. Possible causes c
ShowProgressWindow(
$"Converting {Path.GetFileName(SlicerFile.FileFullPath)} to {convertFileExtension}");
- task = await Task.Factory.StartNew(() =>
+ task = await Task.Run(() =>
{
try
{
@@ -1831,7 +1832,7 @@ private async void ConvertToOnTapped(object? sender, RoutedEventArgs e)
var oldFile = SlicerFile.FileFullPath!;
ShowProgressWindow($"Converting {oldFileName} to {Path.GetExtension(newFilePath)}");
- var task = await Task.Factory.StartNew(() =>
+ var task = await Task.Run(() =>
{
try
{
@@ -1926,7 +1927,7 @@ public async Task SaveFile(string filepath = null, bool ignoreOverwriteWar
var oldFile = SlicerFile.FileFullPath;
- var task = await Task.Factory.StartNew( () =>
+ var task = await Task.Run( () =>
{
try
{
@@ -2114,7 +2115,7 @@ public async Task RunOperation(Operation baseOperation)
if (config.IslandConfig.Enabled || config.ResinTrapConfig.Enabled)
{
- await ComputeIssues(config);
+ ComputeIssues(config);
}
}
@@ -2127,7 +2128,7 @@ public async Task RunOperation(Operation baseOperation)
Clipboard.Snapshot();
- var result = await Task.Factory.StartNew(() =>
+ var result = await Task.Run(() =>
{
try
{
diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj
index a669366b..0b39ead6 100644
--- a/UVtools.WPF/UVtools.WPF.csproj
+++ b/UVtools.WPF/UVtools.WPF.csproj
@@ -12,7 +12,7 @@
LICENSE
https://github.com/sn4k3/UVtools
Git
- 3.9.0
+ 3.9.1
AnyCPU;x64
UVtools.png
README.md
diff --git a/UVtools.WPF/Windows/ToolWindow.axaml.cs b/UVtools.WPF/Windows/ToolWindow.axaml.cs
index 1df71e98..ce6cfbc2 100644
--- a/UVtools.WPF/Windows/ToolWindow.axaml.cs
+++ b/UVtools.WPF/Windows/ToolWindow.axaml.cs
@@ -118,7 +118,7 @@ public uint LayerIndexStart
get => _layerIndexStart;
set
{
- value = Math.Min(value, SlicerFile.LastLayerIndex);
+ SlicerFile.SanitizeLayerIndex(ref value);
if (ToolControl?.BaseOperation is not null)
{
@@ -146,7 +146,7 @@ public uint LayerIndexEnd
get => _layerIndexEnd;
set
{
- value = Math.Min(value, SlicerFile.LastLayerIndex);
+ SlicerFile.SanitizeLayerIndex(ref value);
if (ToolControl?.BaseOperation is not null)
{
diff --git a/documentation/UVtools.Core.xml b/documentation/UVtools.Core.xml
index 85bbf504..2dcc83c0 100644
--- a/documentation/UVtools.Core.xml
+++ b/documentation/UVtools.Core.xml
@@ -3667,6 +3667,13 @@
Parsed ending layer index
+
+
+ Constrains a layer index to be inside the range between 0 and
+
+ Layer index to sanitize
+ True if sanitized, otherwise false
+
Constrains a layer index to be inside the range between 0 and
@@ -3674,6 +3681,18 @@
Layer index to sanitize
True if sanitized, otherwise false
+
+
+ Constrains a layer index to be inside the range between 0 and
+
+ Layer index to sanitize
+
+
+
+ Constrains a layer index to be inside the range between 0 and
+
+ Layer index to sanitize
+
Re-assign layer indexes and parent