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

github.com/sn4k3/UVtools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiago Conceição <Tiago_caza@hotmail.com>2021-02-19 07:21:53 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2021-02-19 07:21:53 +0300
commit9dffbd77b957c95c475ea35ad20d4410fa0f2378 (patch)
treeebc481a9b7c0e128f259bd2dad682723ce649e47
parent9c9540646c2ed8e3eac17cfddfc05aba209084a6 (diff)
v2.4.9v2.4.9
* **(Fix) PhotonWorkshop files: (#149)** * CurrencySymbol to show the correct symbol and don't convert unknown values to prevent hacking * Set PerLayerOverride to 1 only if any layer contains modified parameters that are not shared with the globals * **(Fix) Clipboard:** * Initing the clipboard for the first time was calling Undo and reseting parameters from layers with base settings * Undo and redo make layer parameters to reset and recalculate position z, making invalid files when using with advanced tools * (Fix) Tool - Edit print parameters: When editing per a layer range and reopen the tool it will show the previous set values
-rw-r--r--.gitignore2
-rw-r--r--CHANGELOG.md10
-rw-r--r--UVtools.Core/FileFormats/FileFormat.cs45
-rw-r--r--UVtools.Core/FileFormats/IFileFormat.cs510
-rw-r--r--UVtools.Core/FileFormats/PhotonWorkshopFile.cs136
-rw-r--r--UVtools.Core/Layer/Layer.cs37
-rw-r--r--UVtools.Core/Layer/LayerManager.cs23
-rw-r--r--UVtools.Core/Managers/ClipboardManager.cs2
-rw-r--r--UVtools.Core/Objects/Material.cs220
-rw-r--r--UVtools.Core/Operations/OperationEditParameters.cs4
-rw-r--r--UVtools.Core/UVtools.Core.csproj2
-rw-r--r--UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml2
-rw-r--r--UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs15
-rw-r--r--UVtools.WPF/Structures/OperationProfiles.cs2
-rw-r--r--UVtools.WPF/UVtools.WPF.csproj2
15 files changed, 958 insertions, 54 deletions
diff --git a/.gitignore b/.gitignore
index 029334f..6dd7de9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -353,3 +353,5 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
+UVtools.Platforms/linux-x64/libcvextern.so
+UVtools.Platforms/rhel-x64/libcvextern.so
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8a6b0ae..f9999cb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,15 @@
# Changelog
+## 19/02/2021 - v2.4.9
+
+* **(Fix) PhotonWorkshop files: (#149)**
+ * CurrencySymbol to show the correct symbol and don't convert unknown values to prevent hacking
+ * Set PerLayerOverride to 1 only if any layer contains modified parameters that are not shared with the globals
+* **(Fix) Clipboard:**
+ * Initing the clipboard for the first time was calling Undo and reseting parameters from layers with base settings
+ * Undo and redo make layer parameters to reset and recalculate position z, making invalid files when using with advanced tools
+* (Fix) Tool - Edit print parameters: When editing per a layer range and reopen the tool it will show the previous set values
+
## 18/02/2021 - v2.4.8
* (Improvement) Cache per layer and global used material for faster calculations
diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs
index 4e8d3f8..66ff0f4 100644
--- a/UVtools.Core/FileFormats/FileFormat.cs
+++ b/UVtools.Core/FileFormats/FileFormat.cs
@@ -469,12 +469,10 @@ namespace UVtools.Core.FileFormats
if (oldLayerManager.Count != LayerCount)
{
LayerCount = _layerManager.Count;
+ if (SuppressRebuildProperties) return;
+ if (LayerCount == 0 || this[LayerCount - 1] is null) return; // Not initialized
+ LayerManager.RebuildLayersProperties();
}
-
- if (SuppressRebuildProperties) return;
- if (LayerCount == 0 || this[LayerCount - 1] is null) return; // Not initialized
- LayerManager.RebuildLayersProperties();
- RebuildGCode();
}
}
@@ -939,7 +937,6 @@ namespace UVtools.Core.FileFormats
)
{
LayerManager.RebuildLayersProperties(false, e.PropertyName);
- RebuildGCode();
if(e.PropertyName != nameof(BottomLightPWM) && e.PropertyName != nameof(LightPWM))
PrintTime = PrintTimeComputed;
return;
@@ -1398,62 +1395,62 @@ namespace UVtools.Core.FileFormats
if (PrintParameterModifiers is null) return;
if (PrintParameterModifiers.Contains(PrintParameterModifier.BottomLayerCount))
{
- PrintParameterModifier.BottomLayerCount.OldValue = BottomLayerCount;
+ PrintParameterModifier.BottomLayerCount.Value = BottomLayerCount;
}
if (PrintParameterModifiers.Contains(PrintParameterModifier.BottomExposureSeconds))
{
- PrintParameterModifier.BottomExposureSeconds.OldValue = (decimal) BottomExposureTime;
+ PrintParameterModifier.BottomExposureSeconds.Value = (decimal) BottomExposureTime;
}
if (PrintParameterModifiers.Contains(PrintParameterModifier.ExposureSeconds))
{
- PrintParameterModifier.ExposureSeconds.OldValue = (decimal)ExposureTime;
+ PrintParameterModifier.ExposureSeconds.Value = (decimal)ExposureTime;
}
if (PrintParameterModifiers.Contains(PrintParameterModifier.BottomLightOffDelay))
{
- PrintParameterModifier.BottomLightOffDelay.OldValue = (decimal)BottomLightOffDelay;
+ PrintParameterModifier.BottomLightOffDelay.Value = (decimal)BottomLightOffDelay;
}
if (PrintParameterModifiers.Contains(PrintParameterModifier.LightOffDelay))
{
- PrintParameterModifier.LightOffDelay.OldValue = (decimal)LightOffDelay;
+ PrintParameterModifier.LightOffDelay.Value = (decimal)LightOffDelay;
}
if (PrintParameterModifiers.Contains(PrintParameterModifier.BottomLiftHeight))
{
- PrintParameterModifier.BottomLiftHeight.OldValue = (decimal)BottomLiftHeight;
+ PrintParameterModifier.BottomLiftHeight.Value = (decimal)BottomLiftHeight;
}
if (PrintParameterModifiers.Contains(PrintParameterModifier.LiftHeight))
{
- PrintParameterModifier.LiftHeight.OldValue = (decimal)LiftHeight;
+ PrintParameterModifier.LiftHeight.Value = (decimal)LiftHeight;
}
if (PrintParameterModifiers.Contains(PrintParameterModifier.BottomLiftSpeed))
{
- PrintParameterModifier.BottomLiftSpeed.OldValue = (decimal)BottomLiftSpeed;
+ PrintParameterModifier.BottomLiftSpeed.Value = (decimal)BottomLiftSpeed;
}
if (PrintParameterModifiers.Contains(PrintParameterModifier.LiftSpeed))
{
- PrintParameterModifier.LiftSpeed.OldValue = (decimal)LiftSpeed;
+ PrintParameterModifier.LiftSpeed.Value = (decimal)LiftSpeed;
}
if (PrintParameterModifiers.Contains(PrintParameterModifier.RetractSpeed))
{
- PrintParameterModifier.RetractSpeed.OldValue = (decimal)RetractSpeed;
+ PrintParameterModifier.RetractSpeed.Value = (decimal)RetractSpeed;
}
if (PrintParameterModifiers.Contains(PrintParameterModifier.BottomLightPWM))
{
- PrintParameterModifier.BottomLightPWM.OldValue = BottomLightPWM;
+ PrintParameterModifier.BottomLightPWM.Value = BottomLightPWM;
}
if (PrintParameterModifiers.Contains(PrintParameterModifier.LightPWM))
{
- PrintParameterModifier.LightPWM.OldValue = LightPWM;
+ PrintParameterModifier.LightPWM.Value = LightPWM;
}
}
@@ -1467,32 +1464,32 @@ namespace UVtools.Core.FileFormats
if (PrintParameterPerLayerModifiers.Contains(PrintParameterModifier.ExposureSeconds))
{
- PrintParameterModifier.ExposureSeconds.OldValue = (decimal)layer.ExposureTime;
+ PrintParameterModifier.ExposureSeconds.Value = (decimal)layer.ExposureTime;
}
if (PrintParameterPerLayerModifiers.Contains(PrintParameterModifier.LightOffDelay))
{
- PrintParameterModifier.LightOffDelay.OldValue = (decimal)layer.LightOffDelay;
+ PrintParameterModifier.LightOffDelay.Value = (decimal)layer.LightOffDelay;
}
if (PrintParameterPerLayerModifiers.Contains(PrintParameterModifier.LiftHeight))
{
- PrintParameterModifier.LiftHeight.OldValue = (decimal)layer.LiftHeight;
+ PrintParameterModifier.LiftHeight.Value = (decimal)layer.LiftHeight;
}
if (PrintParameterPerLayerModifiers.Contains(PrintParameterModifier.LiftSpeed))
{
- PrintParameterModifier.LiftSpeed.OldValue = (decimal)layer.LiftSpeed;
+ PrintParameterModifier.LiftSpeed.Value = (decimal)layer.LiftSpeed;
}
if (PrintParameterPerLayerModifiers.Contains(PrintParameterModifier.RetractSpeed))
{
- PrintParameterModifier.RetractSpeed.OldValue = (decimal)layer.RetractSpeed;
+ PrintParameterModifier.RetractSpeed.Value = (decimal)layer.RetractSpeed;
}
if (PrintParameterPerLayerModifiers.Contains(PrintParameterModifier.LightPWM))
{
- PrintParameterModifier.LightPWM.OldValue = layer.LightPWM;
+ PrintParameterModifier.LightPWM.Value = layer.LightPWM;
}
}
diff --git a/UVtools.Core/FileFormats/IFileFormat.cs b/UVtools.Core/FileFormats/IFileFormat.cs
new file mode 100644
index 0000000..e96bb0a
--- /dev/null
+++ b/UVtools.Core/FileFormats/IFileFormat.cs
@@ -0,0 +1,510 @@
+/*
+ * 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 System.Drawing;
+using System.Text;
+using Emgu.CV;
+using UVtools.Core.Operations;
+
+namespace UVtools.Core.FileFormats
+{
+ /// <summary>
+ /// Slicer file format representation interface
+ /// </summary>
+ public interface IFileFormat
+ {
+ #region Properties
+ /// <summary>
+ /// Gets the file format type
+ /// </summary>
+ FileFormat.FileFormatType FileType { get; }
+
+ /// <summary>
+ /// Gets the valid file extensions for this <see cref="FileFormat"/>
+ /// </summary>
+ FileExtension[] FileExtensions { get; }
+
+ /// <summary>
+ /// Gets the available <see cref="FileFormat.PrintParameterModifier"/>
+ /// </summary>
+ FileFormat.PrintParameterModifier[] PrintParameterModifiers { get; }
+
+ /// <summary>
+ /// Gets the available <see cref="FileFormat.PrintParameterModifier"/> per layer
+ /// </summary>
+ FileFormat.PrintParameterModifier[] PrintParameterPerLayerModifiers { get; }
+
+ /// <summary>
+ /// Gets the file filter for open and save dialogs
+ /// </summary>
+ string FileFilter { get; }
+
+ /// <summary>
+ /// Gets all valid file extensions in "*.extension1;*.extension2" format
+ /// </summary>
+
+ string FileFilterExtensionsOnly { get; }
+
+ /// <summary>
+ /// Gets or sets if change a global property should rebuild every layer data based on them
+ /// </summary>
+ bool SuppressRebuildProperties { get; set; }
+
+ /// <summary>
+ /// Gets the input file path loaded into this <see cref="FileFormat"/>
+ /// </summary>
+ string FileFullPath { get; set; }
+
+ /// <summary>
+ /// Gets the thumbnails count present in this file format
+ /// </summary>
+ byte ThumbnailsCount { get; }
+
+ /// <summary>
+ /// Gets the number of created thumbnails
+ /// </summary>
+ byte CreatedThumbnailsCount { get; }
+
+ /// <summary>
+ /// Gets the original thumbnail sizes
+ /// </summary>
+ System.Drawing.Size[] ThumbnailsOriginalSize { get; }
+
+ /// <summary>
+ /// Gets the thumbnails for this <see cref="FileFormat"/>
+ /// </summary>
+ Mat[] Thumbnails { get; set; }
+
+ /// <summary>
+ /// Gets the cached layers into compressed bytes
+ /// </summary>
+ LayerManager LayerManager { get; set; }
+
+ Size Resolution { get; set; }
+
+ /// <summary>
+ /// Gets the image width resolution
+ /// </summary>
+ uint ResolutionX { get; set; }
+
+ /// <summary>
+ /// Gets the image height resolution
+ /// </summary>
+ uint ResolutionY { get; set; }
+
+ /// <summary>
+ /// Gets the size of display in millimeters
+ /// </summary>
+ SizeF Display { get; set; }
+
+ /// <summary>
+ /// Gets or sets the display width in millimeters
+ /// </summary>
+ float DisplayWidth { get; set; }
+
+ /// <summary>
+ /// Gets or sets the display height in millimeters
+ /// </summary>
+ float DisplayHeight { get; set; }
+
+ /// <summary>
+ /// Gets or sets if images need to be mirrored on lcd to print on the correct orientation
+ /// </summary>
+ bool MirrorDisplay { get; set; }
+
+ /// <summary>
+ /// Gets or sets the maximum printer build Z volume
+ /// </summary>
+ float MaxPrintHeight { get; set; }
+
+ /// <summary>
+ /// Gets or sets the pixels per mm on X direction
+ /// </summary>
+ float Xppmm { get; set; }
+
+ /// <summary>
+ /// Gets or sets the pixels per mm on Y direction
+ /// </summary>
+ float Yppmm { get; set; }
+
+ /// <summary>
+ /// Gets or sets the pixels per mm
+ /// </summary>
+ SizeF Ppmm { get; set; }
+
+ /// <summary>
+ /// Gets the printer XY pixel resolution
+ /// </summary>
+ decimal XYResolution { get; }
+
+ /// <summary>
+ /// Gets the printer XY pixel resolution in microns
+ /// </summary>
+ decimal XYResolutionUm { get; }
+
+ bool HaveAntiAliasing { get; }
+
+ /// <summary>
+ /// Gets or sets the AntiAliasing level
+ /// </summary>
+ byte AntiAliasing { get; set; }
+
+ /// <summary>
+ /// Gets Layer Height in mm
+ /// </summary>
+ float LayerHeight { get; set; }
+
+ /// <summary>
+ /// Gets or sets the print height in mm
+ /// </summary>
+ float PrintHeight { get; set; }
+
+ /// <summary>
+ /// Gets the last layer index
+ /// </summary>
+ uint LastLayerIndex { get; }
+
+ #region Universal Properties
+
+ /// <summary>
+ /// Gets if this format support per layer override settings
+ /// </summary>
+ bool SupportPerLayerSettings { get; }
+
+ /// <summary>
+ /// Gets the number of layers present in this file
+ /// </summary>
+ uint LayerCount { get; set; }
+
+ /// <summary>
+ /// Gets or sets the number of initial layer count
+ /// </summary>
+ ushort BottomLayerCount { get; set; }
+
+ /// <summary>
+ /// Gets the number of normal layer count
+ /// </summary>
+ uint NormalLayerCount { get; }
+
+ /// <summary>
+ /// Gets or sets the initial exposure time for <see cref="BottomLayerCount"/> in seconds
+ /// </summary>
+ float BottomExposureTime { get; set; }
+
+ /// <summary>
+ /// Gets or sets the normal layer exposure time in seconds
+ /// </summary>
+ float ExposureTime { get; set; }
+
+ /// <summary>
+ /// Gets or sets the bottom layer off time in seconds
+ /// </summary>
+ float BottomLightOffDelay { get; set; }
+
+ /// <summary>
+ /// Gets or sets the layer off time in seconds
+ /// </summary>
+ float LightOffDelay { get; set; }
+
+ /// <summary>
+ /// Gets or sets the bottom lift height in mm
+ /// </summary>
+ float BottomLiftHeight { get; set; }
+
+ /// <summary>
+ /// Gets or sets the lift height in mm
+ /// </summary>
+ float LiftHeight { get; set; }
+
+ /// <summary>
+ /// Gets or sets the bottom lift speed in mm/min
+ /// </summary>
+ float BottomLiftSpeed { get; set; }
+
+ /// <summary>
+ /// Gets or sets the speed in mm/min
+ /// </summary>
+ float LiftSpeed { get; set; }
+
+ /// <summary>
+ /// Gets the speed in mm/min for the retracts
+ /// </summary>
+ float RetractSpeed { get; set; }
+
+ /// <summary>
+ /// Gets or sets the bottom pwm value from 0 to 255
+ /// </summary>
+ byte BottomLightPWM { get; set; }
+
+ /// <summary>
+ /// Gets or sets the pwm value from 0 to 255
+ /// </summary>
+ byte LightPWM { get; set; }
+ #endregion
+
+ /// <summary>
+ /// Gets the estimate print time in seconds
+ /// </summary>
+ float PrintTime { get; set; }
+
+ /// <summary>
+ /// Gets the estimate print time in seconds, if print doesn't support it it will be calculated
+ /// </summary>
+ float PrintTimeOrComputed { get; }
+
+ /// <summary>
+ /// Gets the calculated estimate print time in seconds
+ /// </summary>
+ float PrintTimeComputed { get; }
+
+ /// <summary>
+ /// Gets the estimate print time in hours
+ /// </summary>
+ float PrintTimeHours { get; }
+
+ /// <summary>
+ /// Gets the estimate print time in hours and minutes formatted
+ /// </summary>
+ string PrintTimeString { get; }
+
+ /// <summary>
+ /// Gets the estimate used material in ml
+ /// </summary>
+ float MaterialMilliliters { get; set; }
+
+ /// <summary>
+ /// Gets the estimate material in grams
+ /// </summary>
+ float MaterialGrams { get; set; }
+
+ /// <summary>
+ /// Gets the estimate material cost
+ /// </summary>
+ float MaterialCost { get; set; }
+
+ /// <summary>
+ /// Gets the material name
+ /// </summary>
+ string MaterialName { get; set; }
+
+ /// <summary>
+ /// Gets the machine name
+ /// </summary>
+ string MachineName { get; set; }
+
+ /// <summary>
+ /// Gets the GCode, returns null if not supported
+ /// </summary>
+ StringBuilder GCode { get; set; }
+ string GCodeStr { get; }
+
+ /// <summary>
+ /// Gets if this file have available gcode
+ /// </summary>
+ bool HaveGCode { get; }
+
+ /// <summary>
+ /// Get all configuration objects with properties and values
+ /// </summary>
+ object[] Configs { get; }
+
+ /// <summary>
+ /// Gets if this file is valid to read
+ /// </summary>
+ bool IsValid { get; }
+
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Clears all definitions and properties, it also dispose valid candidates
+ /// </summary>
+ void Clear();
+
+ /// <summary>
+ /// Validate if a file is a valid <see cref="FileFormat"/>
+ /// </summary>
+ /// <param name="fileFullPath">Full file path</param>
+ void FileValidation(string fileFullPath);
+
+ /// <summary>
+ /// Checks if a extension is valid under the <see cref="FileFormat"/>
+ /// </summary>
+ /// <param name="extension">Extension to check</param>
+ /// <param name="isFilePath">True if <see cref="extension"/> is a full file path, otherwise false for extension only</param>
+ /// <returns>True if valid, otherwise false</returns>
+ bool IsExtensionValid(string extension, bool isFilePath = false);
+
+ /// <summary>
+ /// Gets all valid file extensions in a specified format
+ /// </summary>
+
+ string GetFileExtensions(string prepend = ".", string separator = ", ");
+
+ /// <summary>
+ /// Gets a thumbnail by it height or lower
+ /// </summary>
+ /// <param name="maxHeight">Max height allowed</param>
+ /// <returns></returns>
+ Mat GetThumbnail(uint maxHeight = 400);
+
+ /// <summary>
+ /// Gets a thumbnail by the largest or smallest
+ /// </summary>
+ /// <param name="largest">True to get the largest, otherwise false</param>
+ /// <returns></returns>
+ Mat GetThumbnail(bool largest);
+
+ /// <summary>
+ /// Sets thumbnails from a list of thumbnails and clone them
+ /// </summary>
+ /// <param name="images"></param>
+ void SetThumbnails(Mat[] images);
+
+ /// <summary>
+ /// Sets all thumbnails the same image
+ /// </summary>
+ /// <param name="images">Image to set</param>
+ void SetThumbnails(Mat images);
+
+ /// <summary>
+ /// Sets a thumbnail from a disk file
+ /// </summary>
+ /// <param name="index">Thumbnail index</param>
+ /// <param name="filePath"></param>
+ void SetThumbnail(int index, string filePath);
+
+ /// <summary>
+ /// Encode to an output file
+ /// </summary>
+ /// <param name="fileFullPath">Output file</param>
+ /// <param name="progress"></param>
+ void Encode(string fileFullPath, OperationProgress progress = null);
+ void AfterEncode();
+
+ /*
+ /// <summary>
+ /// Begin encode to an output file
+ /// </summary>
+ /// <param name="fileFullPath">Output file</param>
+ //void BeginEncode(string fileFullPath);
+
+ /// <summary>
+ /// Insert a layer image to be encoded
+ /// </summary>
+ /// <param name="image"></param>
+ /// <param name="layerIndex"></param>
+ //void InsertLayerImageEncode(Image<L8> image, uint layerIndex);
+
+ /// <summary>
+ /// Finish the encoding procedure
+ /// </summary>
+ //void EndEncode();*/
+
+ /// <summary>
+ /// Decode a slicer file
+ /// </summary>
+ /// <param name="fileFullPath"></param>
+ /// <param name="progress"></param>
+ void Decode(string fileFullPath, OperationProgress progress = null);
+
+ /// <summary>
+ /// Extract contents to a folder
+ /// </summary>
+ /// <param name="path">Path to folder where content will be extracted</param>
+ /// <param name="genericConfigExtract"></param>
+ /// <param name="genericLayersExtract"></param>
+ /// <param name="progress"></param>
+ void Extract(string path, bool genericConfigExtract = true, bool genericLayersExtract = true,
+ OperationProgress progress = null);
+
+ /// <summary>
+ /// Get height in mm from layer height
+ /// </summary>
+ /// <param name="layerIndex"></param>
+ /// <param name="realHeight"></param>
+ /// <returns>The height in mm</returns>
+ float GetHeightFromLayer(uint layerIndex, bool realHeight = true);
+
+ /// <summary>
+ /// Gets the value for initial layer or normal layers based on layer index
+ /// </summary>
+ /// <typeparam name="T">Type of value</typeparam>
+ /// <param name="layerIndex">Layer index</param>
+ /// <param name="initialLayerValue">Initial value</param>
+ /// <param name="normalLayerValue">Normal value</param>
+ /// <returns></returns>
+ T GetInitialLayerValueOrNormal<T>(uint layerIndex, T initialLayerValue, T normalLayerValue);
+
+ void RefreshPrintParametersModifiersValues();
+ void RefreshPrintParametersPerLayerModifiersValues(uint layerIndex);
+
+ /// <summary>
+ /// Gets the value attributed to <see cref="FileFormat.PrintParameterModifier"/>
+ /// </summary>
+ /// <param name="modifier">Modifier to use</param>
+ /// <returns>A value</returns>
+ object GetValueFromPrintParameterModifier(FileFormat.PrintParameterModifier modifier);
+
+ /// <summary>
+ /// Sets a property value attributed to <see cref="modifier"/>
+ /// </summary>
+ /// <param name="modifier">Modifier to use</param>
+ /// <param name="value">Value to set</param>
+ /// <returns>True if set, otherwise false = <see cref="modifier"/> not found</returns>
+ bool SetValueFromPrintParameterModifier(FileFormat.PrintParameterModifier modifier, decimal value);
+
+ byte SetValuesFromPrintParametersModifiers();
+
+ void EditPrintParameters(OperationEditParameters operation);
+
+ /// <summary>
+ /// Rebuilds GCode based on current settings
+ /// </summary>
+ void RebuildGCode();
+
+ /// <summary>
+ /// Saves current configuration on input file
+ /// </summary>
+ /// <param name="progress"></param>
+ void Save(OperationProgress progress = null);
+
+ /// <summary>
+ /// Saves current configuration on a copy
+ /// </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>
+ void SaveAs(string filePath = null, OperationProgress progress = null);
+
+ /// <summary>
+ /// Converts this file type to another file type
+ /// </summary>
+ /// <param name="to">Target file format</param>
+ /// <param name="fileFullPath">Output path file</param>
+ /// <param name="progress"></param>
+ /// <returns>The converted file if successful, otherwise null</returns>
+ FileFormat Convert(Type to, string fileFullPath, OperationProgress progress = null);
+
+ /// <summary>
+ /// Converts this file type to another file type
+ /// </summary>
+ /// <param name="to">Target file format</param>
+ /// <param name="fileFullPath">Output path file</param>
+ /// <param name="progress"></param>
+ /// <returns>TThe converted file if successful, otherwise null</returns>
+ FileFormat Convert(FileFormat to, string fileFullPath, OperationProgress progress = null);
+
+ /// <summary>
+ /// Validate AntiAlias Level
+ /// </summary>
+ byte ValidateAntiAliasingLevel();
+
+ #endregion
+ }
+}
diff --git a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs
index 1bada24..7f5efd2 100644
--- a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs
+++ b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs
@@ -93,6 +93,7 @@ namespace UVtools.Core.FileFormats
/// <summary>
/// Gets the file mark placeholder
/// Fixed to "ANYCUBIC"
+ /// 00
/// </summary>
[FieldOrder(0)]
[FieldLength(MarkSize)]
@@ -101,37 +102,52 @@ namespace UVtools.Core.FileFormats
/// <summary>
/// Gets the file format version
+ /// 0C
/// </summary>
[FieldOrder(1)] public uint Version { get; set; } = 1;
/// <summary>
/// Gets the area num
+ /// 10
/// </summary>
[FieldOrder(2)] public uint AreaNum { get; set; } = 4;
/// <summary>
/// Gets the header start address
+ /// 14
/// </summary>
[FieldOrder(3)] public uint HeaderAddress { get; set; }
+ /// <summary>
+ /// 18
+ /// </summary>
[FieldOrder(4)] public uint Offset1 { get; set; }
/// <summary>
/// Gets the preview start offset
+ /// 1C
/// </summary>
[FieldOrder(5)] public uint PreviewAddress { get; set; }
+ /// <summary>
+ /// 20
+ /// </summary>
[FieldOrder(6)] public uint Offset2 { get; set; }
/// <summary>
/// Gets the layer definition start address
+ /// 24
/// </summary>
[FieldOrder(7)] public uint LayerDefinitionAddress { get; set; }
+ /// <summary>
+ /// 28
+ /// </summary>
[FieldOrder(8)] public uint Offset3 { get; set; }
/// <summary>
/// Gets layer image start address
+ /// 2C
/// </summary>
[FieldOrder(9)] public uint LayerImageAddress { get; set; }
@@ -207,34 +223,129 @@ namespace UVtools.Core.FileFormats
{
public const string SectionMark = "HEADER";
+ /// <summary>
+ /// 30
+ /// </summary>
[FieldOrder(0)] public SectionHeader Section { get; set; }
+
+ /// <summary>
+ /// 40
+ /// </summary>
[FieldOrder(1)] public float PixelSizeUm { get; set; } = 47.25f;
+
+ /// <summary>
+ /// Layer height in mm
+ /// 44
+ /// </summary>
[FieldOrder(2)] public float LayerHeight { get; set; }
+
+ /// <summary>
+ /// 48
+ /// </summary>
[FieldOrder(3)] public float LayerExposureTime { get; set; }
+
+ /// <summary>
+ /// 4C
+ /// </summary>
[FieldOrder(4)] public float LightOffDelay { get; set; } = 1;
+
+ /// <summary>
+ /// 50
+ /// </summary>
[FieldOrder(5)] public float BottomExposureSeconds { get; set; }
+
+ /// <summary>
+ /// 54
+ /// </summary>
[FieldOrder(6)] public float BottomLayersCount { get; set; }
+
+ /// <summary>
+ /// 58
+ /// </summary>
[FieldOrder(7)] public float LiftHeight { get; set; } = 6;
/// <summary>
/// Gets the lift speed in mm/s
+ /// 5C
/// </summary>
[FieldOrder(8)] public float LiftSpeed { get; set; } = 3; // mm/s
/// <summary>
/// Gets the retract speed in mm/s
+ /// 60
/// </summary>
[FieldOrder(9)] public float RetractSpeed { get; set; } = 3; // mm/s
+
+ /// <summary>
+ /// 64
+ /// </summary>
[FieldOrder(10)] public float VolumeMl { get; set; }
+
+ /// <summary>
+ /// 68
+ /// </summary>
[FieldOrder(11)] public uint AntiAliasing { get; set; } = 1;
+
+ /// <summary>
+ /// 6C
+ /// </summary>
[FieldOrder(12)] public uint ResolutionX { get; set; }
+
+ /// <summary>
+ /// 70
+ /// </summary>
[FieldOrder(13)] public uint ResolutionY { get; set; }
+
+ /// <summary>
+ /// 74
+ /// </summary>
[FieldOrder(14)] public float WeightG { get; set; }
+
+ /// <summary>
+ /// 78
+ /// </summary>
[FieldOrder(15)] public float Price { get; set; }
- [FieldOrder(16)] public uint PriceCurrencyDec { get; set; } // 0x24 $ or ¥ 0xC2A5
- [Ignore] public string PriceCurrencySymbol => char.ConvertFromUtf32((int) PriceCurrencyDec);
- [FieldOrder(17)] public uint PerLayerOverride { get; set; } = 1; // bool
+
+ /// <summary>
+ /// 24 00 00 00 $ or ¥ C2 A5 00 or € = E2 82 AC 00
+ /// 7C
+ /// </summary>
+ [FieldOrder(16)] public uint PriceCurrencyDec { get; set; } = 0x24;
+ [Ignore] public char PriceCurrencySymbol
+ {
+ get
+ {
+ switch (PriceCurrencyDec)
+ {
+ case 0x24:
+ return '$';
+ case 0xA5C2:
+ return '¥';
+ case 0x000020AC:
+ return '€';
+ default:
+ return '$';
+ }
+ }
+ }
+
+ /// <summary>
+ /// 80
+ /// </summary>
+ [FieldOrder(17)] public uint PerLayerOverride { get; set; } // bool
+
+ /// <summary>
+ /// 84
+ /// </summary>
[FieldOrder(18)] public uint PrintTime { get; set; }
+
+ /// <summary>
+ /// 88
+ /// </summary>
[FieldOrder(19)] public uint Offset1 { get; set; }
+
+ /// <summary>
+ /// 8C
+ /// </summary>
[FieldOrder(20)] public uint Offset2 { get; set; }
public Header()
@@ -262,20 +373,26 @@ namespace UVtools.Core.FileFormats
{
public const string SectionMark = "PREVIEW";
+ /// <summary>
+ /// 90
+ /// </summary>
[FieldOrder(0)] public SectionHeader Section { get; set; }
/// <summary>
- /// Gets the image width, in pixels.
+ /// Gets the image width, in pixels.
+ /// A0
/// </summary>
[FieldOrder(1)] public uint Width { get; set; } = 224;
/// <summary>
- /// Gets the resolution of the image, in dpi.
+ /// Gets the resolution of the image, in dpi.
+ /// A4
/// </summary>
[FieldOrder(2)] public uint Resolution { get; set; } = 42;
/// <summary>
- /// Gets the image height, in pixels.
+ /// Gets the image height, in pixels.
+ /// A8
/// </summary>
[FieldOrder(3)] public uint Height { get; set; } = 168;
@@ -732,6 +849,9 @@ namespace UVtools.Core.FileFormats
{
public const string SectionMark = "LAYERDEF";
+ /// <summary>
+ /// 1269C
+ /// </summary>
[FieldOrder(0)] public SectionHeader Section { get; set; }
[FieldOrder(1)] public uint LayerCount { get; set; }
@@ -1198,7 +1318,7 @@ namespace UVtools.Core.FileFormats
break;
}
- HeaderSettings.PerLayerOverride = 1;
+ HeaderSettings.PerLayerOverride = LayerManager.AllLayersHaveGlobalParameters ? 0 : 1;
uint currentOffset = FileMarkSettings.HeaderAddress = (uint) Helpers.Serializer.SizeOf(FileMarkSettings);
@@ -1402,7 +1522,7 @@ namespace UVtools.Core.FileFormats
FileFullPath = filePath;
}
- HeaderSettings.PerLayerOverride = 1;
+ HeaderSettings.PerLayerOverride = LayerManager.AllLayersHaveGlobalParameters ? 0 : 1;
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
outputFile.Seek(FileMarkSettings.HeaderAddress, SeekOrigin.Begin);
diff --git a/UVtools.Core/Layer/Layer.cs b/UVtools.Core/Layer/Layer.cs
index 5640096..9ea9b9b 100644
--- a/UVtools.Core/Layer/Layer.cs
+++ b/UVtools.Core/Layer/Layer.cs
@@ -315,7 +315,7 @@ namespace UVtools.Core
public string Filename => FormatFileName("layer");
/// <summary>
- /// Gets if layer has been modified
+ /// Gets if layer image has been modified
/// </summary>
public bool IsModified
{
@@ -323,6 +323,39 @@ namespace UVtools.Core
set => RaiseAndSetIfChanged(ref _isModified, value);
}
+ /// <summary>
+ /// Gets if this layer have same value parameters as global settings
+ /// </summary>
+ public bool HaveGlobalParameters
+ {
+ get
+ {
+ if (SlicerFile is null) return false; // Cant verify
+ if (IsBottomLayer)
+ {
+ if (ExposureTime != SlicerFile.BottomExposureTime ||
+ LiftHeight != SlicerFile.BottomLiftHeight ||
+ LiftSpeed != SlicerFile.BottomLiftSpeed ||
+ LightOffDelay != SlicerFile.BottomLightOffDelay ||
+ LightPWM != SlicerFile.BottomLightPWM
+ ) return false;
+ }
+ else
+ {
+ if (ExposureTime != SlicerFile.ExposureTime ||
+ LiftHeight != SlicerFile.LiftHeight ||
+ LiftSpeed != SlicerFile.LiftSpeed ||
+ LightOffDelay != SlicerFile.LightOffDelay ||
+ LightPWM != SlicerFile.LightPWM
+ ) return false;
+ }
+
+ if (RetractSpeed != SlicerFile.RetractSpeed) return false;
+
+ return true;
+ }
+ }
+
#endregion
#region Constructor
@@ -444,7 +477,7 @@ namespace UVtools.Core
public override string ToString()
{
- return $"{nameof(Index)}: {Index}, {nameof(Filename)}: {Filename}, {nameof(NonZeroPixelCount)}: {NonZeroPixelCount}, {nameof(BoundingRectangle)}: {BoundingRectangle}, {nameof(IsBottomLayer)}: {IsBottomLayer}, {nameof(IsNormalLayer)}: {IsNormalLayer}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(PositionZ)}: {PositionZ}, {nameof(ExposureTime)}: {ExposureTime}, {nameof(LightOffDelay)}: {LightOffDelay}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(LightPWM)}: {LightPWM}, {nameof(IsModified)}: {IsModified}";
+ return $"{nameof(Index)}: {Index}, {nameof(Filename)}: {Filename}, {nameof(NonZeroPixelCount)}: {NonZeroPixelCount}, {nameof(BoundingRectangle)}: {BoundingRectangle}, {nameof(IsBottomLayer)}: {IsBottomLayer}, {nameof(IsNormalLayer)}: {IsNormalLayer}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(PositionZ)}: {PositionZ}, {nameof(ExposureTime)}: {ExposureTime}, {nameof(LightOffDelay)}: {LightOffDelay}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(LightPWM)}: {LightPWM}, {nameof(IsModified)}: {IsModified}, {nameof(HaveGlobalParameters)}: {HaveGlobalParameters}";
}
#endregion
diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs
index c2180c6..ae9a023 100644
--- a/UVtools.Core/Layer/LayerManager.cs
+++ b/UVtools.Core/Layer/LayerManager.cs
@@ -108,6 +108,11 @@ namespace UVtools.Core
}
}
+ /// <summary>
+ /// Gets if all layers have same value parameters as global settings
+ /// </summary>
+ public bool AllLayersHaveGlobalParameters => Layers.Where(layer => layer is not null).All(layer => layer.HaveGlobalParameters);
+
//public float LayerHeight => Layers[0].PositionZ;
#endregion
@@ -280,6 +285,8 @@ namespace UVtools.Core
layer.PositionZ = SlicerFile.GetHeightFromLayer(layerIndex);
}
}
+
+ SlicerFile?.RebuildGCode();
}
public Rectangle GetBoundingRectangle(OperationProgress progress = null)
@@ -296,7 +303,7 @@ namespace UVtools.Core
this[layerIndex].GetBoundingRectangle();
- if (ReferenceEquals(progress, null)) return;
+ if (progress is null) return;
lock (progress.Mutex)
{
progress++;
@@ -456,8 +463,8 @@ namespace UVtools.Core
!overhangConfig.Enabled &&
(layer.Index == 0 ||
(
- (!ReferenceEquals(overhangConfig.WhiteListLayers, null) && !overhangConfig.WhiteListLayers.Contains(layer.Index)) &&
- (!ReferenceEquals(islandConfig.WhiteListLayers, null) && !islandConfig.WhiteListLayers.Contains(layer.Index))
+ (overhangConfig.WhiteListLayers is not null && !overhangConfig.WhiteListLayers.Contains(layer.Index)) &&
+ (islandConfig.WhiteListLayers is not null && !islandConfig.WhiteListLayers.Contains(layer.Index))
)
)
)
@@ -565,7 +572,7 @@ namespace UVtools.Core
if (islandConfig.Enabled)
{
- if (!ReferenceEquals(islandConfig.WhiteListLayers, null)) // Check white list
+ if (islandConfig.WhiteListLayers is not null) // Check white list
{
if (!islandConfig.WhiteListLayers.Contains(layer.Index))
{
@@ -669,7 +676,7 @@ namespace UVtools.Core
// Check for overhangs
if (overhangConfig.Enabled && !overhangConfig.IndependentFromIslands && island is null
- || !ReferenceEquals(island, null) && islandConfig.EnhancedDetection && pixelsSupportingIsland >= 10
+ || island is not null && islandConfig.EnhancedDetection && pixelsSupportingIsland >= 10
)
{
points.Clear();
@@ -713,7 +720,7 @@ namespace UVtools.Core
}
}
- if(!ReferenceEquals(island, null))
+ if(island is not null)
AddIssue(island);
}
@@ -724,7 +731,7 @@ namespace UVtools.Core
if (!islandConfig.Enabled && overhangConfig.Enabled ||
(islandConfig.Enabled && overhangConfig.Enabled && overhangConfig.IndependentFromIslands))
{
- if (!ReferenceEquals(overhangConfig.WhiteListLayers, null)) // Check white list
+ if (overhangConfig.WhiteListLayers is not null) // Check white list
{
if (!overhangConfig.WhiteListLayers.Contains(layer.Index))
{
@@ -1089,7 +1096,7 @@ namespace UVtools.Core
{
var mat = modifiedLayers.GetOrAdd(operation.LayerIndex, u => this[operation.LayerIndex].LayerMat);
- if (ReferenceEquals(layerContours, null))
+ if (layerContours is null)
{
layerContours = new VectorOfVectorOfPoint();
layerHierarchy = new Mat();
diff --git a/UVtools.Core/Managers/ClipboardManager.cs b/UVtools.Core/Managers/ClipboardManager.cs
index 4815521..364d5be 100644
--- a/UVtools.Core/Managers/ClipboardManager.cs
+++ b/UVtools.Core/Managers/ClipboardManager.cs
@@ -255,7 +255,9 @@ namespace UVtools.Core.Managers
}
Add(clip);
+ slicerFile.SuppressRebuildProperties = true;
CurrentIndex = 0;
+ slicerFile.SuppressRebuildProperties = false;
}
/// <summary>
diff --git a/UVtools.Core/Objects/Material.cs b/UVtools.Core/Objects/Material.cs
new file mode 100644
index 0000000..fed7392
--- /dev/null
+++ b/UVtools.Core/Objects/Material.cs
@@ -0,0 +1,220 @@
+/*
+ * 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;
+
+namespace UVtools.Core.Objects
+{
+ /// <summary>
+ /// Represents a material to feed in the printer
+ /// </summary>
+ public class Material : BindableBase
+ {
+ #region Members
+ private string _name;
+ private decimal _bottleVolume = 1000;
+ private decimal _density = 1;
+ private decimal _bottleCost = 30;
+ private int _bottlesInStock = 1;
+ private decimal _bottleRemainingVolume = 1000;
+ private decimal _totalConsumedVolume;
+ private double _totalPrintTime;
+
+ #endregion
+
+ #region Properties
+ public string Name
+ {
+ get => _name;
+ set => RaiseAndSetIfChanged(ref _name, value);
+ }
+
+ /// <summary>
+ /// Gets or sets the bottle volume in milliliters
+ /// </summary>
+ public decimal BottleVolume
+ {
+ get => _bottleVolume;
+ set
+ {
+ if(!RaiseAndSetIfChanged(ref _bottleVolume, value)) return;
+ RaisePropertyChanged(nameof(BottleWeight));
+ RaisePropertyChanged(nameof(TotalConsumedBottles));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the bottle weight in grams
+ /// </summary>
+ public decimal BottleWeight => _bottleVolume * _density;
+
+ /// <summary>
+ /// Gets or sets the material density in g/ml
+ /// </summary>
+ public decimal Density
+ {
+ get => _density;
+ set
+ {
+ if(!RaiseAndSetIfChanged(ref _density, value)) return;
+ RaisePropertyChanged(nameof(BottleWeight));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the bottle cost
+ /// </summary>
+ public decimal BottleCost
+ {
+ get => _bottleCost;
+ set => RaiseAndSetIfChanged(ref _bottleCost, value);
+ }
+
+ /// <summary>
+ /// Gets or sets the number of bottles in stock
+ /// </summary>
+ public int BottlesInStock
+ {
+ get => _bottlesInStock;
+ set => RaiseAndSetIfChanged(ref _bottlesInStock, value);
+ }
+
+ /// <summary>
+ /// Gets or sets the current bottle remaining material in milliliters
+ /// </summary>
+ public decimal BottleRemainingVolume
+ {
+ get => _bottleRemainingVolume;
+ set => RaiseAndSetIfChanged(ref _bottleRemainingVolume, value);
+ }
+
+ /// <summary>
+ /// Gets the number of consumed bottles
+ /// </summary>
+ public uint TotalConsumedBottles => (uint) Math.Floor(_totalConsumedVolume / _bottleVolume);
+
+ /// <summary>
+ /// Gets or sets the total number of consumed volume in milliliters
+ /// </summary>
+ public decimal TotalConsumedVolume
+ {
+ get => _totalConsumedVolume;
+ set => RaiseAndSetIfChanged(ref _totalConsumedVolume, value);
+ }
+
+ /// <summary>
+ /// Gets or sets the total print time using with material in hours
+ /// </summary>
+ public double TotalPrintTime
+ {
+ get => _totalPrintTime;
+ set => RaiseAndSetIfChanged(ref _totalPrintTime, value);
+ }
+
+ public TimeSpan TotalPrintTimeSpan => TimeSpan.FromHours(_totalPrintTime);
+
+ #endregion
+
+ #region Constructors
+ public Material() { }
+
+ public Material(string name, decimal bottleVolume = 1000, decimal density = 1, decimal bottleCost = 30, int bottlesInStock = 1)
+ {
+ _name = name;
+ _bottleVolume = bottleVolume;
+ _density = density;
+ _bottleCost = bottleCost;
+ _bottlesInStock = bottlesInStock;
+ }
+ #endregion
+
+ #region Overrides
+
+ protected bool Equals(Material other)
+ {
+ return _name == other._name;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != GetType()) return false;
+ return Equals((Material) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return (_name != null ? _name.GetHashCode() : 0);
+ }
+
+ public override string ToString()
+ {
+ return $"{nameof(Name)}: {Name}, {nameof(BottleVolume)}: {BottleVolume}ml, {nameof(BottleWeight)}: {BottleWeight}g, {nameof(Density)}: {Density}g/ml, {nameof(BottleCost)}: {BottleCost}, {nameof(BottlesInStock)}: {BottlesInStock}, {nameof(BottleRemainingVolume)}: {BottleRemainingVolume}ml, {nameof(TotalConsumedBottles)}: {TotalConsumedBottles}, {nameof(TotalConsumedVolume)}: {TotalConsumedVolume}ml, {nameof(TotalPrintTime)}: {TotalPrintTime:F4}h";
+ }
+
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Gets the cost for a given volume
+ /// </summary>
+ /// <param name="volume">Volume in ml</param>
+ /// <returns></returns>
+ public decimal GetVolumeCost(decimal volume) => _bottleVolume > 0 ? volume * _bottleCost / _bottleVolume : 0;
+
+ /// <summary>
+ /// Gets the grams for a given volume
+ /// </summary>
+ /// <param name="volume">Volume in ml</param>
+ /// <returns></returns>
+ public decimal GetVolumeGrams(decimal volume) => volume * _density;
+
+ /// <summary>
+ /// Consume material from current bottle and manage stock
+ /// </summary>
+ /// <param name="volume">Volume to consume in milliliters</param>
+ /// <param name="printSeconds">Time in seconds it took to print</param>
+ /// <returns>True if still have bottles in stock, otherwise false</returns>
+ public bool Consume(decimal volume, double printSeconds = 0)
+ {
+ if (volume <= 0 || _bottleVolume == 0) return true; // Safe check
+ int consumedBottles = (int) Math.Floor(volume / _bottleVolume);
+ decimal remainder = volume % _bottleVolume;
+
+ if (remainder > 0)
+ {
+ decimal remainingVolume = _bottleRemainingVolume - remainder;
+ if (remainingVolume < 0)
+ {
+ consumedBottles++;
+ remainingVolume += _bottleVolume;
+ }
+
+ BottleRemainingVolume = remainingVolume;
+ }
+
+ BottlesInStock -= consumedBottles;
+
+ AddPrintTime(printSeconds);
+
+ return _bottlesInStock > 0;
+ }
+
+ /// <summary>
+ /// Add print time with this material
+ /// </summary>
+ /// <param name="seconds">Seconds to add</param>
+ public void AddPrintTime(double seconds)
+ {
+ if (seconds <= 0) return;
+ TotalPrintTime += seconds / 60 / 60;
+ }
+ #endregion
+ }
+}
diff --git a/UVtools.Core/Operations/OperationEditParameters.cs b/UVtools.Core/Operations/OperationEditParameters.cs
index b59de70..16c61be 100644
--- a/UVtools.Core/Operations/OperationEditParameters.cs
+++ b/UVtools.Core/Operations/OperationEditParameters.cs
@@ -9,6 +9,7 @@
using System;
using System.Linq;
using System.Text;
+using System.Xml.Serialization;
using UVtools.Core.FileFormats;
using UVtools.Core.Objects;
@@ -85,6 +86,7 @@ namespace UVtools.Core.Operations
#region Propertiers
+ [XmlIgnore]
public FileFormat.PrintParameterModifier[] Modifiers { get; set; }
/// <summary>
@@ -161,6 +163,8 @@ namespace UVtools.Core.Operations
SlicerFile.SetValuesFromPrintParametersModifiers();
}
+ SlicerFile.RefreshPrintParametersModifiersValues();
+
return !progress.Token.IsCancellationRequested;
}
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index d6ef422..37302e0 100644
--- a/UVtools.Core/UVtools.Core.csproj
+++ b/UVtools.Core/UVtools.Core.csproj
@@ -10,7 +10,7 @@
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
- <Version>2.4.8</Version>
+ <Version>2.4.9</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
diff --git a/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml b/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml
index cc7cbe5..d7327a1 100644
--- a/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml
+++ b/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml
@@ -9,7 +9,7 @@
<CheckBox
IsChecked="{Binding Operation.PerLayerOverride}"
- IsVisible="{Binding SupportPerLayerSettings}"
+ IsVisible="{Binding SlicerFile.SupportPerLayerSettings}"
Content="Change settings per a layer range"/>
<StackPanel Orientation="Horizontal" Spacing="5" IsVisible="{Binding Operation.PerLayerOverride}">
diff --git a/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs
index d51bca0..0b88b49 100644
--- a/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs
+++ b/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs
@@ -18,7 +18,6 @@ namespace UVtools.WPF.Controls.Tools
public class ToolEditParametersControl : ToolControl
{
public OperationEditParameters Operation => BaseOperation as OperationEditParameters;
- public bool SupportPerLayerSettings => App.SlicerFile.SupportPerLayerSettings;
public RowControl[] RowControls;
private Grid grid;
@@ -122,9 +121,6 @@ namespace UVtools.WPF.Controls.Tools
}
grid = this.FindControl<Grid>("grid");
- PopulateGrid();
-
- Operation.PropertyChanged += OperationOnPropertyChanged;
}
public void PopulateGrid()
@@ -189,9 +185,12 @@ namespace UVtools.WPF.Controls.Tools
switch (callback)
{
case ToolWindow.Callbacks.Init:
+ case ToolWindow.Callbacks.ProfileLoaded:
ParentWindow.IsButton1Visible = true;
ParentWindow.SelectCurrentLayer();
ParentWindow.LayerRangeSync = true;
+ PopulateGrid();
+ Operation.PropertyChanged += OperationOnPropertyChanged;
break;
case ToolWindow.Callbacks.Button1:
foreach (var rowControl in RowControls)
@@ -204,9 +203,9 @@ namespace UVtools.WPF.Controls.Tools
private void OperationOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
- if (e.PropertyName == nameof(Operation.LayerIndexStart))
+ if (e.PropertyName == nameof(Operation.LayerIndexStart) && Operation.PerLayerOverride)
{
- App.SlicerFile.RefreshPrintParametersPerLayerModifiersValues(Operation.LayerIndexStart);
+ SlicerFile.RefreshPrintParametersPerLayerModifiersValues(Operation.LayerIndexStart);
PopulateGrid();
return;
}
@@ -215,12 +214,12 @@ namespace UVtools.WPF.Controls.Tools
if (Operation.PerLayerOverride)
{
Operation.Modifiers = App.SlicerFile.PrintParameterPerLayerModifiers;
- App.SlicerFile.RefreshPrintParametersPerLayerModifiersValues(Operation.LayerIndexStart);
+ SlicerFile.RefreshPrintParametersPerLayerModifiersValues(Operation.LayerIndexStart);
}
else
{
Operation.Modifiers = App.SlicerFile.PrintParameterModifiers;
- App.SlicerFile.RefreshPrintParametersModifiersValues();
+ SlicerFile.RefreshPrintParametersModifiersValues();
}
ParentWindow.LayerRangeVisible = Operation.PerLayerOverride;
diff --git a/UVtools.WPF/Structures/OperationProfiles.cs b/UVtools.WPF/Structures/OperationProfiles.cs
index 6300e69..b92fd97 100644
--- a/UVtools.WPF/Structures/OperationProfiles.cs
+++ b/UVtools.WPF/Structures/OperationProfiles.cs
@@ -67,7 +67,7 @@ namespace UVtools.WPF.Structures
#region Singleton
private static Lazy<OperationProfiles> _instanceHolder =
- new Lazy<OperationProfiles>(() => new OperationProfiles());
+ new(() => new OperationProfiles());
/// <summary>
/// Instance of <see cref="UserSettings"/> (singleton)
diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj
index fbf4dea..65e1c9a 100644
--- a/UVtools.WPF/UVtools.WPF.csproj
+++ b/UVtools.WPF/UVtools.WPF.csproj
@@ -12,7 +12,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
- <Version>2.4.8</Version>
+ <Version>2.4.9</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">