diff --git a/UVtools.Core/Layers/Issue.cs b/UVtools.Core/Layers/Issue.cs
index 217d4ce..cff3109 100644
--- a/UVtools.Core/Layers/Issue.cs
+++ b/UVtools.Core/Layers/Issue.cs
@@ -8,15 +8,20 @@
using System;
using System.Drawing;
+using System.Text.Json.Serialization;
using UVtools.Core.Extensions;
namespace UVtools.Core.Layers;
+//[JsonDerivedType(typeof(Issue))]
+//[JsonDerivedType(typeof(IssueOfPoints))]
+//[JsonDerivedType(typeof(IssueOfContours))]
public class Issue
{
///
/// Gets the issue type associated
///
+ [JsonIgnore]
public MainIssue? Parent { get; internal set; }
public MainIssue.IssueType? Type => Parent?.Type;
@@ -24,6 +29,7 @@ public class Issue
///
/// Gets the layer where this issue is present
///
+ [JsonIgnore]
public Layer Layer { get; init; }
///
diff --git a/UVtools.Core/Layers/MainIssue.cs b/UVtools.Core/Layers/MainIssue.cs
index 8b7cf7e..be4435d 100644
--- a/UVtools.Core/Layers/MainIssue.cs
+++ b/UVtools.Core/Layers/MainIssue.cs
@@ -11,6 +11,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
+using System.Text.Json.Serialization;
using UVtools.Core.Extensions;
namespace UVtools.Core.Layers;
@@ -47,11 +48,13 @@ public class MainIssue : IReadOnlyList
///
/// Gets the layer where issue is present and starts
///
+ [JsonIgnore]
public Layer StartLayer => Childs[0].Layer;
///
/// Gets the layer where issue ends
///
+ [JsonIgnore]
public Layer EndLayer => Childs[^1].Layer;
///
diff --git a/UVtools.Core/Managers/IssueManager.cs b/UVtools.Core/Managers/IssueManager.cs
index c2fe015..14156c7 100644
--- a/UVtools.Core/Managers/IssueManager.cs
+++ b/UVtools.Core/Managers/IssueManager.cs
@@ -23,6 +23,8 @@ public sealed class IssueManager : RangeObservableCollection
public List IgnoredIssues { get; } = new();
+ public bool HaveIssues => Count > 0;
+
public IssueManager(FileFormat slicerFile)
{
SlicerFile = slicerFile;
diff --git a/UVtools.Core/Objects/SerializableIssuesDocument.cs b/UVtools.Core/Objects/SerializableIssuesDocument.cs
new file mode 100644
index 0000000..73d5972
--- /dev/null
+++ b/UVtools.Core/Objects/SerializableIssuesDocument.cs
@@ -0,0 +1,67 @@
+/*
+ * GNU AFFERO GENERAL PUBLIC LICENSE
+ * Version 3, 19 November 2007
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ * Everyone is permitted to copy and distribute verbatim copies
+ * of this license document, but changing it is not allowed.
+ */
+
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text.Json;
+using UVtools.Core.Extensions;
+using UVtools.Core.FileFormats;
+using UVtools.Core.Layers;
+
+namespace UVtools.Core.Objects;
+
+public sealed class SerializableIssuesDocument : IReadOnlyList
+{
+ public string? FileFullPath { get; init; }
+ public string? MachineName { get; init; }
+ public uint ResolutionX { get; init; }
+ public uint ResolutionY { get; init; }
+ public float DisplayWidth { get; init; }
+ public float DisplayHeight { get; init; }
+ public FlipDirection DisplayMirror { get; init; }
+ public float PrintHeight { get; init; }
+ public uint LayerCount { get; init; }
+ public MainIssue[] Issues { get; init; }
+
+ public SerializableIssuesDocument(FileFormat slicerFile)
+ {
+ FileFullPath = slicerFile.FileFullPath;
+ MachineName = slicerFile.MachineName;
+ ResolutionX = slicerFile.ResolutionX;
+ ResolutionY = slicerFile.ResolutionY;
+ DisplayWidth = slicerFile.DisplayWidth;
+ DisplayHeight = slicerFile.DisplayHeight;
+ PrintHeight = slicerFile.PrintHeight;
+ LayerCount = slicerFile.LayerCount;
+ DisplayMirror = slicerFile.DisplayMirror;
+
+ Issues = slicerFile.IssueManager.ToArray();
+ }
+
+ public async void SerializeAsync(string path)
+ {
+ await using var stream = File.Create(path);
+ await JsonSerializer.SerializeAsync(stream, this, JsonExtensions.SettingsIndent);
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return ((IEnumerable)Issues).GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return Issues.GetEnumerator();
+ }
+
+ public int Count => Issues.Length;
+
+ public MainIssue this[int index] => Issues[index];
+}
\ No newline at end of file
diff --git a/UVtools.WPF/MainWindow.Issues.cs b/UVtools.WPF/MainWindow.Issues.cs
index 08435ff..380525c 100644
--- a/UVtools.WPF/MainWindow.Issues.cs
+++ b/UVtools.WPF/MainWindow.Issues.cs
@@ -8,6 +8,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Collections;
@@ -24,6 +26,7 @@ using UVtools.Core;
using UVtools.Core.Extensions;
using UVtools.Core.FileFormats;
using UVtools.Core.Layers;
+using UVtools.Core.Objects;
using UVtools.Core.Operations;
using UVtools.WPF.Extensions;
using Brushes = Avalonia.Media.Brushes;
@@ -582,6 +585,43 @@ public partial class MainWindow
await ShowRunOperation(typeof(OperationRepairLayers));
}
+ public async void OnClickExportIssues()
+ {
+ if (!SlicerFile.IssueManager.HaveIssues) return;
+ var dialog = new SaveFileDialog
+ {
+ DefaultExtension = ".uvtissues",
+ Filters = new List
+ {
+ new()
+ {
+ Name = "UVtools issues files",
+ Extensions = new List {"uvtissues"}
+ }
+ },
+ InitialFileName = SlicerFile.FilenameNoExt,
+ Directory = SlicerFile.DirectoryPath
+ };
+
+ var path = await dialog.ShowAsync(this);
+ if (string.IsNullOrWhiteSpace(path)) return;
+
+ IsGUIEnabled = false;
+ try
+ {
+ var exportIssues = new SerializableIssuesDocument(SlicerFile);
+ exportIssues.SerializeAsync(path);
+ }
+ catch (Exception e)
+ {
+ await this.MessageBoxError(e.ToString());
+ Debug.WriteLine(e);
+ if(File.Exists(path)) File.Delete(path);
+ }
+
+ IsGUIEnabled = true;
+ }
+
public async Task OnClickDetectIssues()
{
if (!IsFileLoaded) return;
diff --git a/UVtools.WPF/MainWindow.axaml b/UVtools.WPF/MainWindow.axaml
index 2223d30..9d8ef54 100644
--- a/UVtools.WPF/MainWindow.axaml
+++ b/UVtools.WPF/MainWindow.axaml
@@ -675,7 +675,22 @@
ToolTip.Tip="Attempt to repair issues"
VerticalAlignment="Stretch"
i:Attached.Icon="fa-solid fa-toolbox"
- Command="{Binding OnClickRepairIssues}"/>
+ Command="{Binding OnClickRepairIssues}">
+
+