mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-19 23:16:26 +02:00
v2.4.7
* (Add) Computed used material milliliters for each layer, it will dynamic change if pixels are added or subtracted * (Add) Computed used material milliliters for whole model, it will dynamic change if pixels are added or subtracted * (Improvement) Round cost, material ml and grams from 2 to 3 decimals * (Improvement) Operation profiles: Allow to save and get a custom layer range instead of pre-defined ranges * **(Improvement)** PhotonWorkshop files: (#149) * Fill in the display width, height and MaxZ values for the printers * Fill in the xy pixel size values for the printers * Change ResinType to PriceCurrencyDec and Add PriceCurrencySymbol * Change Offset1 on header to PrintTime * Change Offset1 on layer table as NonZeroPixelCount, the number of white pixels on the layer * Fix LayerPositionZ to calculate the correct value based on each layer height and fix internal layer layer height which was been set to position z * Force PerLayerOverride to be always 1 after save the file * (Fix) Actions - Remove and clone layers was selecting all layer range instead of the current layer * (Fix) Redo last action was not getting back the layer range on some cases
This commit is contained in:
@@ -1,5 +1,22 @@
|
||||
# Changelog
|
||||
|
||||
## 17/02/2021 - v2.4.7
|
||||
|
||||
* (Add) Computed used material milliliters for each layer, it will dynamic change if pixels are added or subtracted
|
||||
* (Add) Computed used material milliliters for whole model, it will dynamic change if pixels are added or subtracted
|
||||
* (Improvement) Round cost, material ml and grams from 2 to 3 decimals
|
||||
* (Improvement) Operation profiles: Allow to save and get a custom layer range instead of pre-defined ranges
|
||||
* **(Improvement)** PhotonWorkshop files: (#149)
|
||||
* Fill in the display width, height and MaxZ values for the printers
|
||||
* Fill in the xy pixel size values for the printers
|
||||
* Change ResinType to PriceCurrencyDec and Add PriceCurrencySymbol
|
||||
* Change Offset1 on header to PrintTime
|
||||
* Change Offset1 on layer table as NonZeroPixelCount, the number of white pixels on the layer
|
||||
* Fix LayerPositionZ to calculate the correct value based on each layer height and fix internal layer layer height which was been set to position z
|
||||
* Force PerLayerOverride to be always 1 after save the file
|
||||
* (Fix) Actions - Remove and clone layers was selecting all layer range instead of the current layer
|
||||
* (Fix) Redo last action was not getting back the layer range on some cases
|
||||
|
||||
## 15/02/2021 - v2.4.6
|
||||
|
||||
* **(Improvement) Calibration - Elephant Foot:** (#145)
|
||||
|
||||
+2
-1
@@ -47,4 +47,5 @@
|
||||
* Chris Taatgen
|
||||
* Andrew Griffiths
|
||||
* Abhinav Sinha
|
||||
* Randy Savell
|
||||
* Randy Savell
|
||||
* Steve Clynes
|
||||
@@ -29,7 +29,7 @@ class FixedEncoder : System.Text.UTF8Encoding {
|
||||
####################################
|
||||
### Configuration ###
|
||||
####################################
|
||||
$enableMSI = $false
|
||||
$enableMSI = $true
|
||||
$buildOnly = $null
|
||||
#$buildOnly = "osx-x64"#"win-x64"
|
||||
# Profilling
|
||||
|
||||
@@ -20,20 +20,5 @@ namespace UVtools.Core.Extensions
|
||||
Math.Min(Math.Max(min, color.B * factor), max));
|
||||
return Color.FromArgb(r, g, b);
|
||||
}
|
||||
|
||||
public static int GetArea(this Rectangle rect)
|
||||
{
|
||||
return rect.Width * rect.Height;
|
||||
}
|
||||
|
||||
public static int GetArea(this Size size)
|
||||
{
|
||||
return size.Width * size.Height;
|
||||
}
|
||||
|
||||
public static int GetMaximum(this Size size)
|
||||
{
|
||||
return Math.Max(size.Width, size.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,5 +38,36 @@ namespace UVtools.Core.Extensions
|
||||
|
||||
public static Size Inflate(this Size size, int pixels) => new (size.Width + pixels, size.Height + pixels);
|
||||
public static Size Inflate(this Size size, int width, int height) => new (size.Width + width, size.Height + height);
|
||||
|
||||
public static int Area(this Rectangle rect)
|
||||
{
|
||||
return rect.Width * rect.Height;
|
||||
}
|
||||
|
||||
public static int Area(this Size size)
|
||||
{
|
||||
return size.Width * size.Height;
|
||||
}
|
||||
|
||||
public static int Max(this Size size)
|
||||
{
|
||||
return Math.Max(size.Width, size.Height);
|
||||
}
|
||||
|
||||
public static float Area(this RectangleF rect)
|
||||
{
|
||||
return rect.Width * rect.Height;
|
||||
}
|
||||
|
||||
public static float Area(this SizeF size)
|
||||
{
|
||||
return size.Width * size.Height;
|
||||
}
|
||||
|
||||
public static float Max(this SizeF size)
|
||||
{
|
||||
return Math.Max(size.Width, size.Height);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
|
||||
@@ -1270,11 +1270,16 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public override float MaterialMilliliters
|
||||
{
|
||||
get => (float) Math.Round(PrintParametersSettings.VolumeMl, 2);
|
||||
get
|
||||
{
|
||||
var materialMl = base.MaterialMilliliters;
|
||||
return materialMl > 0 ? materialMl : PrintParametersSettings.VolumeMl;
|
||||
}
|
||||
set
|
||||
{
|
||||
PrintParametersSettings.VolumeMl = (float) Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
if (value <= 0) value = base.MaterialMilliliters;
|
||||
PrintParametersSettings.VolumeMl = (float) Math.Round(value, 3);
|
||||
base.MaterialMilliliters = PrintParametersSettings.VolumeMl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1283,17 +1288,17 @@ namespace UVtools.Core.FileFormats
|
||||
get => PrintParametersSettings.WeightG;
|
||||
set
|
||||
{
|
||||
PrintParametersSettings.WeightG = (float)Math.Round(value, 2);
|
||||
PrintParametersSettings.WeightG = (float)Math.Round(value, 3);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialCost
|
||||
{
|
||||
get => (float) Math.Round(PrintParametersSettings.CostDollars, 2);
|
||||
get => (float) Math.Round(PrintParametersSettings.CostDollars, 3);
|
||||
set
|
||||
{
|
||||
PrintParametersSettings.CostDollars = (float) Math.Round(value, 2);
|
||||
PrintParametersSettings.CostDollars = (float) Math.Round(value, 3);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace UVtools.Core.FileFormats
|
||||
[DisplayName("fileName")] public string Filename { get; set; } = string.Empty;
|
||||
[DisplayName("machineType")] public string MachineType { get; set; } = "Default";
|
||||
[DisplayName("estimatedPrintTime")] public float EstimatedPrintTime { get; set; }
|
||||
[DisplayName("volume")] public float Volume { get; set; }
|
||||
[DisplayName("volume")] public float VolumeMl { get; set; }
|
||||
[DisplayName("resin")] public string Resin { get; set; } = "Normal";
|
||||
[DisplayName("weight")] public float WeightG { get; set; }
|
||||
[DisplayName("price")] public float Price { get; set; }
|
||||
@@ -344,30 +344,35 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public override float MaterialMilliliters
|
||||
{
|
||||
get => HeaderSettings.Volume;
|
||||
get
|
||||
{
|
||||
var materialMl = base.MaterialMilliliters;
|
||||
return materialMl > 0 ? materialMl : HeaderSettings.VolumeMl;
|
||||
}
|
||||
set
|
||||
{
|
||||
HeaderSettings.Volume = (float)Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
if (value <= 0) value = base.MaterialMilliliters;
|
||||
HeaderSettings.VolumeMl = (float)Math.Round(value, 3);
|
||||
base.MaterialMilliliters = HeaderSettings.VolumeMl;
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialGrams
|
||||
{
|
||||
get => HeaderSettings.WeightG;
|
||||
get => (float) Math.Round(HeaderSettings.WeightG, 3);
|
||||
set
|
||||
{
|
||||
HeaderSettings.WeightG = (float)Math.Round(value, 2);
|
||||
HeaderSettings.WeightG = (float)Math.Round(value, 3);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialCost
|
||||
{
|
||||
get => HeaderSettings.Price;
|
||||
get => (float) Math.Round(HeaderSettings.Price, 3);
|
||||
set
|
||||
{
|
||||
HeaderSettings.Price = (float)Math.Round(value, 2);
|
||||
HeaderSettings.Price = (float)Math.Round(value, 3);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -935,30 +935,35 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public override float MaterialMilliliters
|
||||
{
|
||||
get => (float) Math.Round(HeaderSettings.VolumeMl, 2);
|
||||
get
|
||||
{
|
||||
var materialMl = base.MaterialMilliliters;
|
||||
return materialMl > 0 ? materialMl : HeaderSettings.VolumeMl;
|
||||
}
|
||||
set
|
||||
{
|
||||
HeaderSettings.VolumeMl = (float)Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
if (value <= 0) value = base.MaterialMilliliters;
|
||||
HeaderSettings.VolumeMl = (float)Math.Round(value, 3);
|
||||
base.MaterialMilliliters = HeaderSettings.VolumeMl;
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialGrams
|
||||
{
|
||||
get => HeaderSettings.WeightG;
|
||||
get => (float)Math.Round(HeaderSettings.WeightG, 3);
|
||||
set
|
||||
{
|
||||
HeaderSettings.WeightG = (float)Math.Round(value, 2);
|
||||
HeaderSettings.WeightG = (float)Math.Round(value, 3);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialCost
|
||||
{
|
||||
get => (float) Math.Round(HeaderSettings.CostDollars, 2);
|
||||
get => (float) Math.Round(HeaderSettings.CostDollars, 3);
|
||||
set
|
||||
{
|
||||
HeaderSettings.CostDollars = (float)Math.Round(value, 2);
|
||||
HeaderSettings.CostDollars = (float)Math.Round(value, 3);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,6 +456,16 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
LayerCount = _layerManager.Count;
|
||||
}
|
||||
|
||||
// Recalculate changes
|
||||
PrintHeight = PrintHeight;
|
||||
PrintTime = PrintTimeComputed;
|
||||
MaterialMilliliters = 0;
|
||||
|
||||
if (SuppressRebuildProperties) return;
|
||||
if (LayerCount == 0 || this[LayerCount - 1] is null) return; // Not initialized
|
||||
LayerManager.RebuildLayersProperties();
|
||||
RebuildGCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,26 +584,55 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pixel width in millimeters
|
||||
/// </summary>
|
||||
public float PixelWidth => DisplayWidth > 0 ? (float) Math.Round(DisplayWidth / ResolutionX, 3) : 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the printer XY pixel resolution
|
||||
/// Gets the pixel height in millimeters
|
||||
/// </summary>
|
||||
public decimal XYResolution => DisplayWidth > 0 || DisplayHeight > 0 ?
|
||||
(decimal) Math.Round(Math.Max(
|
||||
DisplayWidth / ResolutionX,
|
||||
DisplayHeight / ResolutionY
|
||||
), 3)
|
||||
: 0;
|
||||
public float PixelHeight => DisplayHeight > 0 ? (float) Math.Round(DisplayHeight / ResolutionY, 3) : 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the printer XY pixel resolution in microns
|
||||
/// Gets the pixel size in millimeters
|
||||
/// </summary>
|
||||
public decimal XYResolutionUm => DisplayWidth > 0 || DisplayHeight > 0 ?
|
||||
(decimal)Math.Round(Math.Max(
|
||||
DisplayWidth / ResolutionX,
|
||||
DisplayHeight / ResolutionY
|
||||
), 3) * 1000
|
||||
: 0;
|
||||
public SizeF PixelSize => new(PixelWidth, PixelHeight);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum pixel between width and height in millimeters
|
||||
/// </summary>
|
||||
public float PixelSizeMax => PixelSize.Max();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pixel area in millimeters
|
||||
/// </summary>
|
||||
public float PixelArea => PixelSize.Area();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pixel width in microns
|
||||
/// </summary>
|
||||
public float PixelWidthMicrons => DisplayWidth > 0 ? (float)Math.Round(DisplayWidth / ResolutionX * 1000, 3) : 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pixel height in microns
|
||||
/// </summary>
|
||||
public float PixelHeightMicrons => DisplayHeight > 0 ? (float)Math.Round(DisplayHeight / ResolutionY * 1000, 3) : 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pixel size in microns
|
||||
/// </summary>
|
||||
public SizeF PixelSizeMicrons => new(PixelWidthMicrons, PixelHeightMicrons);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum pixel between width and height in microns
|
||||
/// </summary>
|
||||
public float PixelSizeMicronsMax => PixelSizeMicrons.Max();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pixel area in millimeters
|
||||
/// </summary>
|
||||
public float PixelAreaMicrons => PixelSizeMicrons.Area();
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this file have AntiAliasing
|
||||
@@ -796,7 +835,19 @@ namespace UVtools.Core.FileFormats
|
||||
/// <summary>
|
||||
/// Gets the estimate used material in ml
|
||||
/// </summary>
|
||||
public virtual float MaterialMilliliters { get; set; }
|
||||
public virtual float MaterialMilliliters {
|
||||
get
|
||||
{
|
||||
float pixelArea = PixelArea;
|
||||
float materialMl = 0;
|
||||
if (pixelArea <= 0) return materialMl;
|
||||
|
||||
materialMl = this.Where(layer => layer is not null).Sum(layer => pixelArea * LayerHeight * layer.NonZeroPixelCount);
|
||||
|
||||
return (float) Math.Round(materialMl / 1000, 3);
|
||||
}
|
||||
set => RaisePropertyChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the estimate material in grams
|
||||
@@ -853,20 +904,7 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(LayerCount))
|
||||
{
|
||||
PrintHeight = PrintHeight;
|
||||
}
|
||||
|
||||
if (SuppressRebuildProperties) return;
|
||||
if (e.PropertyName == nameof(LayerCount))
|
||||
{
|
||||
if (LayerCount == 0 || this[LayerCount - 1] is null) return; // Not initialized
|
||||
LayerManager.RebuildLayersProperties();
|
||||
RebuildGCode();
|
||||
PrintTime = PrintTimeComputed;
|
||||
return;
|
||||
}
|
||||
if (
|
||||
e.PropertyName == nameof(BottomLayerCount) ||
|
||||
e.PropertyName == nameof(BottomExposureTime) ||
|
||||
@@ -1048,11 +1086,11 @@ namespace UVtools.Core.FileFormats
|
||||
default:
|
||||
if (largest)
|
||||
{
|
||||
return Thumbnails[0].Size.GetArea() >= Thumbnails[1].Size.GetArea() ? Thumbnails[0] : Thumbnails[1];
|
||||
return Thumbnails[0].Size.Area() >= Thumbnails[1].Size.Area() ? Thumbnails[0] : Thumbnails[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return Thumbnails[0].Size.GetArea() <= Thumbnails[1].Size.GetArea() ? Thumbnails[0] : Thumbnails[1];
|
||||
return Thumbnails[0].Size.Area() <= Thumbnails[1].Size.Area() ? Thumbnails[0] : Thumbnails[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -953,30 +953,35 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public override float MaterialMilliliters
|
||||
{
|
||||
get => (float) Math.Round(HeaderSettings.VolumeMl, 2);
|
||||
get
|
||||
{
|
||||
var materialMl = base.MaterialMilliliters;
|
||||
return materialMl > 0 ? materialMl : HeaderSettings.VolumeMl;
|
||||
}
|
||||
set
|
||||
{
|
||||
HeaderSettings.VolumeMl = (float)Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
if (value <= 0) value = base.MaterialMilliliters;
|
||||
HeaderSettings.VolumeMl = (float)Math.Round(value, 3);
|
||||
base.MaterialMilliliters = HeaderSettings.VolumeMl;
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialGrams
|
||||
{
|
||||
get => HeaderSettings.WeightG;
|
||||
get => (float) Math.Round(HeaderSettings.WeightG, 3);
|
||||
set
|
||||
{
|
||||
HeaderSettings.WeightG = (float) Math.Round(value, 2);
|
||||
HeaderSettings.WeightG = (float) Math.Round(value, 3);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialCost
|
||||
{
|
||||
get => (float) Math.Round(HeaderSettings.CostDollars, 2);
|
||||
get => (float) Math.Round(HeaderSettings.CostDollars, 3);
|
||||
set
|
||||
{
|
||||
HeaderSettings.CostDollars = (float)Math.Round(value, 2);
|
||||
HeaderSettings.CostDollars = (float)Math.Round(value, 3);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace UVtools.Core.FileFormats
|
||||
[FieldOrder(8)] [FieldEndianness(Endianness.Big)] public double LiftHeight { get; set; } // mm
|
||||
[FieldOrder(9)] [FieldEndianness(Endianness.Big)] public double LiftSpeed { get; set; } // mm/s
|
||||
[FieldOrder(10)] [FieldEndianness(Endianness.Big)] public double RetractSpeed { get; set; } // mm/s
|
||||
[FieldOrder(11)] [FieldEndianness(Endianness.Big)] public double Volume { get; set; } // ml
|
||||
[FieldOrder(11)] [FieldEndianness(Endianness.Big)] public double VolumeMl { get; set; } // ml
|
||||
[FieldOrder(12)] [FieldEndianness(Endianness.Big)] public uint PreviewResolutionX { get; set; } = 225;
|
||||
[FieldOrder(13)] [FieldEndianness(Endianness.Big)] public uint Unknown2 { get; set; } = 42;
|
||||
[FieldOrder(14)] [FieldEndianness(Endianness.Big)] public uint PreviewResolutionY { get; set; } = 168;
|
||||
@@ -62,7 +62,7 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Tag1)}: {Tag1}, {nameof(Tag2)}: {Tag2}, {nameof(XYPixelSize)}: {XYPixelSize}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(ExposureSeconds)}: {ExposureSeconds}, {nameof(LightOffDelay)}: {LightOffDelay}, {nameof(BottomExposureSeconds)}: {BottomExposureSeconds}, {nameof(BottomLayerCount)}: {BottomLayerCount}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(Volume)}: {Volume}, {nameof(PreviewResolutionX)}: {PreviewResolutionX}, {nameof(Unknown2)}: {Unknown2}, {nameof(PreviewResolutionY)}: {PreviewResolutionY}, {nameof(Unknown4)}: {Unknown4}";
|
||||
return $"{nameof(Tag1)}: {Tag1}, {nameof(Tag2)}: {Tag2}, {nameof(XYPixelSize)}: {XYPixelSize}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(ExposureSeconds)}: {ExposureSeconds}, {nameof(LightOffDelay)}: {LightOffDelay}, {nameof(BottomExposureSeconds)}: {BottomExposureSeconds}, {nameof(BottomLayerCount)}: {BottomLayerCount}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(VolumeMl)}: {VolumeMl}, {nameof(PreviewResolutionX)}: {PreviewResolutionX}, {nameof(Unknown2)}: {Unknown2}, {nameof(PreviewResolutionY)}: {PreviewResolutionY}, {nameof(Unknown4)}: {Unknown4}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,11 +373,16 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public override float MaterialMilliliters
|
||||
{
|
||||
get => (float) HeaderSettings.Volume;
|
||||
get
|
||||
{
|
||||
var materialMl = base.MaterialMilliliters;
|
||||
return materialMl > 0 ? materialMl : (float) HeaderSettings.VolumeMl;
|
||||
}
|
||||
set
|
||||
{
|
||||
HeaderSettings.Volume = Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
if (value <= 0) value = base.MaterialMilliliters;
|
||||
HeaderSettings.VolumeMl = (float)Math.Round(value, 3);
|
||||
base.MaterialMilliliters = (float) HeaderSettings.VolumeMl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,7 +508,7 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
|
||||
HeaderSettings.LayerHeight = Math.Round(HeaderSettings.LayerHeight, 2);
|
||||
HeaderSettings.Volume = Math.Round(HeaderSettings.Volume, 2);
|
||||
HeaderSettings.VolumeMl = Math.Round(HeaderSettings.VolumeMl, 2);
|
||||
|
||||
int previewSize = (int) (HeaderSettings.PreviewResolutionX * HeaderSettings.PreviewResolutionY * 2);
|
||||
byte[] previewData = new byte[previewSize];
|
||||
|
||||
@@ -71,6 +71,16 @@ namespace UVtools.Core.FileFormats
|
||||
PWS,
|
||||
PW0
|
||||
}
|
||||
|
||||
public enum AnyCubicMachine : byte
|
||||
{
|
||||
AnyCubicPhotonS,
|
||||
AnyCubicPhotonZero,
|
||||
AnyCubicPhotonX,
|
||||
AnyCubicPhotonMono,
|
||||
AnyCubicPhotonMonoSE,
|
||||
AnyCubicPhotonMonoX,
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Sub Classes
|
||||
@@ -198,7 +208,7 @@ namespace UVtools.Core.FileFormats
|
||||
public const string SectionMark = "HEADER";
|
||||
|
||||
[FieldOrder(0)] public SectionHeader Section { get; set; }
|
||||
[FieldOrder(1)] public float PixelSize { get; set; } = 0.04725f;
|
||||
[FieldOrder(1)] public float PixelSizeUm { get; set; } = 47.25f;
|
||||
[FieldOrder(2)] public float LayerHeight { get; set; }
|
||||
[FieldOrder(3)] public float LayerExposureTime { get; set; }
|
||||
[FieldOrder(4)] public float LightOffDelay { get; set; } = 1;
|
||||
@@ -214,24 +224,25 @@ namespace UVtools.Core.FileFormats
|
||||
/// Gets the retract speed in mm/s
|
||||
/// </summary>
|
||||
[FieldOrder(9)] public float RetractSpeed { get; set; } = 3; // mm/s
|
||||
[FieldOrder(10)] public float Volume { get; set; }
|
||||
[FieldOrder(10)] public float VolumeMl { get; set; }
|
||||
[FieldOrder(11)] public uint AntiAliasing { get; set; } = 1;
|
||||
[FieldOrder(12)] public uint ResolutionX { get; set; }
|
||||
[FieldOrder(13)] public uint ResolutionY { get; set; }
|
||||
[FieldOrder(14)] public float WeightG { get; set; }
|
||||
[FieldOrder(15)] public float Price { get; set; }
|
||||
[FieldOrder(16)] public uint ResinType { get; set; } // 0x24 ?
|
||||
[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
|
||||
[FieldOrder(18)] public uint Offset1 { get; set; }
|
||||
[FieldOrder(19)] public uint Offset2 { get; set; }
|
||||
[FieldOrder(20)] public uint Offset3 { get; set; }
|
||||
[FieldOrder(18)] public uint PrintTime { get; set; }
|
||||
[FieldOrder(19)] public uint Offset1 { get; set; }
|
||||
[FieldOrder(20)] public uint Offset2 { get; set; }
|
||||
|
||||
public Header()
|
||||
{
|
||||
Section = new SectionHeader(SectionMark, this);
|
||||
}
|
||||
|
||||
public override string ToString() => $"{nameof(Section)}: {Section}, {nameof(PixelSize)}: {PixelSize}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(LayerExposureTime)}: {LayerExposureTime}, {nameof(LightOffDelay)}: {LightOffDelay}, {nameof(BottomExposureSeconds)}: {BottomExposureSeconds}, {nameof(BottomLayersCount)}: {BottomLayersCount}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(Volume)}: {Volume}, {nameof(AntiAliasing)}: {AntiAliasing}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(WeightG)}: {WeightG}, {nameof(Price)}: {Price}, {nameof(ResinType)}: {ResinType}, {nameof(PerLayerOverride)}: {PerLayerOverride}, {nameof(Offset1)}: {Offset1}, {nameof(Offset2)}: {Offset2}, {nameof(Offset3)}: {Offset3}";
|
||||
public override string ToString() => $"{nameof(Section)}: {Section}, {nameof(PixelSizeUm)}: {PixelSizeUm}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(LayerExposureTime)}: {LayerExposureTime}, {nameof(LightOffDelay)}: {LightOffDelay}, {nameof(BottomExposureSeconds)}: {BottomExposureSeconds}, {nameof(BottomLayersCount)}: {BottomLayersCount}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(VolumeMl)}: {VolumeMl}, {nameof(AntiAliasing)}: {AntiAliasing}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(WeightG)}: {WeightG}, {nameof(Price)}: {Price}, {nameof(PriceCurrencyDec)}: {PriceCurrencyDec}, {nameof(PerLayerOverride)}: {PerLayerOverride}, {nameof(PrintTime)}: {PrintTime}, {nameof(Offset1)}: {Offset1}, {nameof(Offset2)}: {Offset2}";
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
@@ -344,7 +355,7 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Section)}: {Section}, {nameof(Width)}: {Width}, {nameof(Resolution)}: {Resolution}, {nameof(Height)}: {Height}, {nameof(Data)}: {Data}";
|
||||
return $"{nameof(Section)}: {Section}, {nameof(Width)}: {Width}, {nameof(Resolution)}: {Resolution}, {nameof(Height)}: {Height}, {nameof(Data)}: {Data?.Length ?? 0}";
|
||||
}
|
||||
|
||||
public void Validate(int size)
|
||||
@@ -378,16 +389,16 @@ namespace UVtools.Core.FileFormats
|
||||
/// Gets the exposure time for this layer, in seconds.
|
||||
/// </summary>
|
||||
[FieldOrder(4)]
|
||||
public float LayerExposure { get; set; }
|
||||
public float ExposureTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the build platform Z position for this layer, measured in millimeters.
|
||||
/// Gets the layer height for this layer, measured in millimeters.
|
||||
/// </summary>
|
||||
[FieldOrder(5)]
|
||||
public float LayerPositionZ { get; set; }
|
||||
public float LayerHeight { get; set; }
|
||||
|
||||
[FieldOrder(6)] public float Offset1 { get; set; }
|
||||
[FieldOrder(7)] public float Offset2 { get; set; }
|
||||
[FieldOrder(6)] public uint NonZeroPixelCount { get; set; }
|
||||
[FieldOrder(7)] public uint Offset1 { get; set; }
|
||||
|
||||
[Ignore] public byte[] EncodedRle { get; set; }
|
||||
[Ignore] public PhotonWorkshopFile Parent { get; set; }
|
||||
@@ -404,10 +415,11 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public void RefreshLayerData(uint layerIndex)
|
||||
{
|
||||
LayerPositionZ = Parent[layerIndex].PositionZ;
|
||||
LayerExposure = Parent[layerIndex].ExposureTime;
|
||||
LayerHeight = Parent[layerIndex].LayerHeight;
|
||||
ExposureTime = Parent[layerIndex].ExposureTime;
|
||||
LiftHeight = Parent[layerIndex].LiftHeight;
|
||||
LiftSpeed = (float) Math.Round(Parent[layerIndex].LiftSpeed / 60, 2);
|
||||
NonZeroPixelCount = Parent[layerIndex].NonZeroPixelCount;
|
||||
}
|
||||
|
||||
public Mat Decode(bool consumeData = true)
|
||||
@@ -706,6 +718,11 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
return CRCRle4(EncodedRle);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(DataAddress)}: {DataAddress}, {nameof(DataLength)}: {DataLength}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(ExposureTime)}: {ExposureTime}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(NonZeroPixelCount)}: {NonZeroPixelCount}, {nameof(Offset1)}: {Offset1}, {nameof(EncodedRle)}: {EncodedRle?.Length ?? 0}";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -760,15 +777,15 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
#region Properties
|
||||
|
||||
public FileMark FileMarkSettings { get; protected internal set; } = new FileMark();
|
||||
public FileMark FileMarkSettings { get; protected internal set; } = new();
|
||||
|
||||
public Header HeaderSettings { get; protected internal set; } = new Header();
|
||||
public Header HeaderSettings { get; protected internal set; } = new();
|
||||
|
||||
public Preview PreviewSettings { get; protected internal set; } = new Preview();
|
||||
public Preview PreviewSettings { get; protected internal set; } = new();
|
||||
|
||||
public LayerDefinition LayersDefinition { get; protected internal set; } = new LayerDefinition();
|
||||
public LayerDefinition LayersDefinition { get; protected internal set; } = new();
|
||||
|
||||
public Dictionary<string, LayerData> LayersHash { get; } = new Dictionary<string, LayerData>();
|
||||
public Dictionary<string, LayerData> LayersHash { get; } = new();
|
||||
|
||||
public override FileFormatType FileType => FileFormatType.Binary;
|
||||
|
||||
@@ -830,12 +847,75 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public override float DisplayWidth
|
||||
{
|
||||
get => 0;
|
||||
get
|
||||
{
|
||||
switch (PrinterModel)
|
||||
{
|
||||
case AnyCubicMachine.AnyCubicPhotonS:
|
||||
return 68.04f;
|
||||
case AnyCubicMachine.AnyCubicPhotonZero:
|
||||
return 55.44f;
|
||||
case AnyCubicMachine.AnyCubicPhotonX:
|
||||
return 192;
|
||||
case AnyCubicMachine.AnyCubicPhotonMono:
|
||||
return 82.62f;
|
||||
case AnyCubicMachine.AnyCubicPhotonMonoSE:
|
||||
return 82.62f;
|
||||
case AnyCubicMachine.AnyCubicPhotonMonoX:
|
||||
return 192;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
set { }
|
||||
}
|
||||
public override float DisplayHeight
|
||||
{
|
||||
get => 0;
|
||||
get
|
||||
{
|
||||
switch (PrinterModel)
|
||||
{
|
||||
case AnyCubicMachine.AnyCubicPhotonS:
|
||||
return 120.96f;
|
||||
case AnyCubicMachine.AnyCubicPhotonZero:
|
||||
return 98.637f;
|
||||
case AnyCubicMachine.AnyCubicPhotonX:
|
||||
return 120;
|
||||
case AnyCubicMachine.AnyCubicPhotonMono:
|
||||
return 130.56f;
|
||||
case AnyCubicMachine.AnyCubicPhotonMonoSE:
|
||||
return 130.56f;
|
||||
case AnyCubicMachine.AnyCubicPhotonMonoX:
|
||||
return 120;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
set { }
|
||||
}
|
||||
|
||||
public override float MaxPrintHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (PrinterModel)
|
||||
{
|
||||
case AnyCubicMachine.AnyCubicPhotonS:
|
||||
return 165;
|
||||
case AnyCubicMachine.AnyCubicPhotonZero:
|
||||
return 150;
|
||||
case AnyCubicMachine.AnyCubicPhotonX:
|
||||
return 245;
|
||||
case AnyCubicMachine.AnyCubicPhotonMono:
|
||||
return 165;
|
||||
case AnyCubicMachine.AnyCubicPhotonMonoSE:
|
||||
return 160;
|
||||
case AnyCubicMachine.AnyCubicPhotonMonoX:
|
||||
return 245;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
set { }
|
||||
}
|
||||
|
||||
@@ -964,29 +1044,44 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialMilliliters
|
||||
public override float PrintTime
|
||||
{
|
||||
get => (float) Math.Round(HeaderSettings.Volume, 2);
|
||||
get => HeaderSettings.PrintTime;
|
||||
set
|
||||
{
|
||||
HeaderSettings.Volume = (float)Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
HeaderSettings.PrintTime = (uint)value;
|
||||
base.PrintTime = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialMilliliters
|
||||
{
|
||||
get
|
||||
{
|
||||
var materialMl = base.MaterialMilliliters;
|
||||
return materialMl > 0 ? materialMl : HeaderSettings.VolumeMl;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value <= 0) value = base.MaterialMilliliters;
|
||||
HeaderSettings.VolumeMl = (float)Math.Round(value, 3);
|
||||
base.MaterialMilliliters = HeaderSettings.VolumeMl;
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialGrams
|
||||
{
|
||||
get => HeaderSettings.WeightG;
|
||||
get => (float) Math.Round(HeaderSettings.WeightG, 3);
|
||||
set
|
||||
{
|
||||
HeaderSettings.WeightG = (float) Math.Round(value, 2);
|
||||
HeaderSettings.WeightG = (float) Math.Round(value, 3);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialCost
|
||||
{
|
||||
get => (float) Math.Round(HeaderSettings.Price, 2);
|
||||
get => (float) Math.Round(HeaderSettings.Price, 3);
|
||||
set
|
||||
{
|
||||
HeaderSettings.Price = (float)Math.Round(value, 2);
|
||||
@@ -998,37 +1093,23 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
get
|
||||
{
|
||||
if (FileFullPath.EndsWith(".pws") || FileFullPath.EndsWith($".pws{TemporaryFileAppend}"))
|
||||
switch (PrinterModel)
|
||||
{
|
||||
return "AnyCubic Photon S";
|
||||
case AnyCubicMachine.AnyCubicPhotonS:
|
||||
return "AnyCubic Photon S";
|
||||
case AnyCubicMachine.AnyCubicPhotonZero:
|
||||
return "AnyCubic Photon Zero";
|
||||
case AnyCubicMachine.AnyCubicPhotonX:
|
||||
return "AnyCubic Photon X";
|
||||
case AnyCubicMachine.AnyCubicPhotonMono:
|
||||
return "AnyCubic Photon Mono";
|
||||
case AnyCubicMachine.AnyCubicPhotonMonoSE:
|
||||
return "AnyCubic Photon Mono SE";
|
||||
case AnyCubicMachine.AnyCubicPhotonMonoX:
|
||||
return "AnyCubic Photon Mono X";
|
||||
default:
|
||||
return base.MachineName;
|
||||
}
|
||||
|
||||
if (FileFullPath.EndsWith(".pw0") || FileFullPath.EndsWith($".pw0{TemporaryFileAppend}"))
|
||||
{
|
||||
return "AnyCubic Photon Zero";
|
||||
}
|
||||
|
||||
if (FileFullPath.EndsWith(".pwx") || FileFullPath.EndsWith($".pwx{TemporaryFileAppend}"))
|
||||
{
|
||||
return "AnyCubic Photon X";
|
||||
}
|
||||
|
||||
if (FileFullPath.EndsWith(".pwmo") || FileFullPath.EndsWith($".pwmo{TemporaryFileAppend}"))
|
||||
{
|
||||
return "AnyCubic Photon Mono";
|
||||
}
|
||||
|
||||
if (FileFullPath.EndsWith(".pwms") || FileFullPath.EndsWith($".pwms{TemporaryFileAppend}"))
|
||||
{
|
||||
return "AnyCubic Photon Mono SE";
|
||||
}
|
||||
|
||||
if (FileFullPath.EndsWith(".pwmx") || FileFullPath.EndsWith($".pwmx{TemporaryFileAppend}"))
|
||||
{
|
||||
return "AnyCubic Photon Mono X";
|
||||
}
|
||||
|
||||
return base.MachineName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1039,6 +1120,43 @@ namespace UVtools.Core.FileFormats
|
||||
? LayerRleFormat.PWS
|
||||
: LayerRleFormat.PW0;
|
||||
|
||||
public AnyCubicMachine PrinterModel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (FileFullPath.EndsWith(".pws") || FileFullPath.EndsWith($".pws{TemporaryFileAppend}"))
|
||||
{
|
||||
return AnyCubicMachine.AnyCubicPhotonS;
|
||||
}
|
||||
|
||||
if (FileFullPath.EndsWith(".pw0") || FileFullPath.EndsWith($".pw0{TemporaryFileAppend}"))
|
||||
{
|
||||
return AnyCubicMachine.AnyCubicPhotonZero;
|
||||
}
|
||||
|
||||
if (FileFullPath.EndsWith(".pwx") || FileFullPath.EndsWith($".pwx{TemporaryFileAppend}"))
|
||||
{
|
||||
return AnyCubicMachine.AnyCubicPhotonX;
|
||||
}
|
||||
|
||||
if (FileFullPath.EndsWith(".pwmo") || FileFullPath.EndsWith($".pwmo{TemporaryFileAppend}"))
|
||||
{
|
||||
return AnyCubicMachine.AnyCubicPhotonMono;
|
||||
}
|
||||
|
||||
if (FileFullPath.EndsWith(".pwms") || FileFullPath.EndsWith($".pwms{TemporaryFileAppend}"))
|
||||
{
|
||||
return AnyCubicMachine.AnyCubicPhotonMonoSE;
|
||||
}
|
||||
|
||||
if (FileFullPath.EndsWith(".pwmx") || FileFullPath.EndsWith($".pwmx{TemporaryFileAppend}"))
|
||||
{
|
||||
return AnyCubicMachine.AnyCubicPhotonMonoX;
|
||||
}
|
||||
|
||||
return AnyCubicMachine.AnyCubicPhotonS;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
@@ -1058,9 +1176,36 @@ namespace UVtools.Core.FileFormats
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
LayersHash.Clear();
|
||||
|
||||
LayersDefinition = new LayerDefinition(LayerCount);
|
||||
|
||||
switch (PrinterModel)
|
||||
{
|
||||
case AnyCubicMachine.AnyCubicPhotonS:
|
||||
HeaderSettings.PixelSizeUm = 47.25f;
|
||||
break;
|
||||
case AnyCubicMachine.AnyCubicPhotonZero:
|
||||
HeaderSettings.PixelSizeUm = 115.5f;
|
||||
break;
|
||||
case AnyCubicMachine.AnyCubicPhotonX:
|
||||
HeaderSettings.PixelSizeUm = 75;
|
||||
break;
|
||||
case AnyCubicMachine.AnyCubicPhotonMono:
|
||||
HeaderSettings.PixelSizeUm = 51;
|
||||
break;
|
||||
case AnyCubicMachine.AnyCubicPhotonMonoSE:
|
||||
HeaderSettings.PixelSizeUm = 51;
|
||||
break;
|
||||
case AnyCubicMachine.AnyCubicPhotonMonoX:
|
||||
HeaderSettings.PixelSizeUm = 50;
|
||||
break;
|
||||
default:
|
||||
HeaderSettings.PixelSizeUm = 47.25f;
|
||||
break;
|
||||
}
|
||||
|
||||
HeaderSettings.PerLayerOverride = 1;
|
||||
|
||||
|
||||
uint currentOffset = FileMarkSettings.HeaderAddress = (uint) Helpers.Serializer.SizeOf(FileMarkSettings);
|
||||
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
|
||||
outputFile.Seek((int) currentOffset, SeekOrigin.Begin);
|
||||
@@ -1190,6 +1335,7 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
LayersDefinition[i] = Helpers.Deserialize<LayerData>(inputFile);
|
||||
LayersDefinition[i].Parent = this;
|
||||
Debug.WriteLine($"Layer {i}: {LayersDefinition[i]}");
|
||||
}
|
||||
|
||||
progress.Reset(OperationProgress.StatusGatherLayers, LayerCount);
|
||||
@@ -1219,8 +1365,8 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
this[layerIndex] = new Layer((uint) layerIndex, image, LayerManager)
|
||||
{
|
||||
PositionZ = LayersDefinition[(uint)layerIndex].LayerPositionZ,
|
||||
ExposureTime = LayersDefinition[(uint)layerIndex].LayerExposure,
|
||||
PositionZ = (float) Math.Round(LayersDefinition[(uint)layerIndex].LayerHeight, 2),
|
||||
ExposureTime = LayersDefinition[(uint)layerIndex].ExposureTime,
|
||||
LiftHeight = LayersDefinition[(uint)layerIndex].LiftHeight,
|
||||
LiftSpeed = (float)Math.Round(LayersDefinition[(uint)layerIndex].LiftSpeed * 60, 2),
|
||||
};
|
||||
@@ -1231,6 +1377,15 @@ namespace UVtools.Core.FileFormats
|
||||
progress++;
|
||||
}
|
||||
});
|
||||
|
||||
// Fix position z height values
|
||||
if (LayerCount > 0)
|
||||
{
|
||||
for (uint layerIndex = 1; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
this[layerIndex].PositionZ = (float)Math.Round(this[layerIndex-1].PositionZ + this[layerIndex].PositionZ, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
@@ -1252,6 +1407,8 @@ namespace UVtools.Core.FileFormats
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
HeaderSettings.PerLayerOverride = 1;
|
||||
|
||||
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
|
||||
outputFile.Seek(FileMarkSettings.HeaderAddress, SeekOrigin.Begin);
|
||||
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
|
||||
|
||||
@@ -441,21 +441,26 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public override float MaterialMilliliters
|
||||
{
|
||||
get => OutputConfigSettings.UsedMaterial;
|
||||
get
|
||||
{
|
||||
var materialMl = base.MaterialMilliliters;
|
||||
return materialMl > 0 ? materialMl : OutputConfigSettings.UsedMaterial;
|
||||
}
|
||||
set
|
||||
{
|
||||
OutputConfigSettings.UsedMaterial = (float)Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
if (value <= 0) value = base.MaterialMilliliters;
|
||||
OutputConfigSettings.UsedMaterial = (float)Math.Round(value, 3);
|
||||
base.MaterialMilliliters = OutputConfigSettings.UsedMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialGrams
|
||||
public override float MaterialGrams
|
||||
{
|
||||
get => (float) Math.Round(OutputConfigSettings.UsedMaterial * MaterialSettings.MaterialDensity, 2);
|
||||
get => (float) Math.Round(OutputConfigSettings.UsedMaterial * MaterialSettings.MaterialDensity, 3);
|
||||
set { }
|
||||
}
|
||||
|
||||
public override float MaterialCost => MaterialSettings.BottleVolume > 0 ? (float) Math.Round(OutputConfigSettings.UsedMaterial * MaterialSettings.BottleCost / MaterialSettings.BottleVolume, 2) : 0;
|
||||
public override float MaterialCost => MaterialSettings.BottleVolume > 0 ? (float) Math.Round(OutputConfigSettings.UsedMaterial * MaterialSettings.BottleCost / MaterialSettings.BottleVolume, 3) : 0;
|
||||
|
||||
public override string MaterialName
|
||||
{
|
||||
|
||||
@@ -333,20 +333,25 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
public override float MaterialMilliliters
|
||||
{
|
||||
get => ResinMetadataSettings.TotalMaterialVolumeUsed;
|
||||
get
|
||||
{
|
||||
var materialMl = base.MaterialMilliliters;
|
||||
return materialMl > 0 ? materialMl : ResinMetadataSettings.TotalMaterialVolumeUsed;
|
||||
}
|
||||
set
|
||||
{
|
||||
UserSettings.MaterialVolume = ResinMetadataSettings.TotalMaterialVolumeUsed = (float) Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
if (value <= 0) value = base.MaterialMilliliters;
|
||||
ResinMetadataSettings.TotalMaterialVolumeUsed = (float)Math.Round(value, 3);
|
||||
base.MaterialMilliliters = ResinMetadataSettings.TotalMaterialVolumeUsed;
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialGrams
|
||||
{
|
||||
get => ResinMetadataSettings.TotalMaterialWeightUsed;
|
||||
get => (float) Math.Round(ResinMetadataSettings.TotalMaterialWeightUsed, 3);
|
||||
set
|
||||
{
|
||||
ResinMetadataSettings.TotalMaterialWeightUsed = (float) Math.Round(value, 2);
|
||||
ResinMetadataSettings.TotalMaterialWeightUsed = (float) Math.Round(value, 3);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,13 @@ namespace UVtools.Core
|
||||
public uint NonZeroPixelCount
|
||||
{
|
||||
get => _nonZeroPixelCount;
|
||||
internal set => RaiseAndSetIfChanged(ref _nonZeroPixelCount, value);
|
||||
internal set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _nonZeroPixelCount, value)) return;
|
||||
RaisePropertyChanged(nameof(MaterialMilliliters));
|
||||
if (SlicerFile is null) return;
|
||||
SlicerFile.MaterialMilliliters = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -195,6 +201,18 @@ namespace UVtools.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the computed material milliliters spent on this layer
|
||||
/// </summary>
|
||||
public float MaterialMilliliters
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ParentLayerManager?.SlicerFile is null) return 0;
|
||||
return (float) Math.Round(ParentLayerManager.SlicerFile.PixelArea * LayerHeight * NonZeroPixelCount / 1000, 4);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets layer image compressed data
|
||||
/// </summary>
|
||||
@@ -393,7 +411,7 @@ namespace UVtools.Core
|
||||
|
||||
public Rectangle GetBoundingRectangle(Mat mat = null, bool reCalculate = false)
|
||||
{
|
||||
if (NonZeroPixelCount > 0 && !reCalculate)
|
||||
if (_nonZeroPixelCount > 0 && !reCalculate)
|
||||
{
|
||||
return BoundingRectangle;
|
||||
}
|
||||
|
||||
@@ -591,7 +591,7 @@ namespace UVtools.Core
|
||||
(int) ccStats.GetValue(i, (int) ConnectedComponentsTypes.Width),
|
||||
(int) ccStats.GetValue(i, (int) ConnectedComponentsTypes.Height));
|
||||
|
||||
if (rect.GetArea() < islandConfig.RequiredAreaToProcessCheck)
|
||||
if (rect.Area() < islandConfig.RequiredAreaToProcessCheck)
|
||||
continue;
|
||||
|
||||
if (previousImage is null)
|
||||
@@ -794,7 +794,7 @@ namespace UVtools.Core
|
||||
continue;
|
||||
|
||||
var rect = CvInvoke.BoundingRectangle(contours[i]);
|
||||
if(rect.GetArea() < resinTrapConfig.RequiredAreaToProcessCheck) continue;
|
||||
if(rect.Area() < resinTrapConfig.RequiredAreaToProcessCheck) continue;
|
||||
|
||||
listHollowArea.Add(new LayerHollowArea(contours[i].ToArray(),
|
||||
rect,
|
||||
|
||||
@@ -123,6 +123,9 @@ namespace UVtools.Core.Operations
|
||||
/// </summary>
|
||||
public virtual string ProgressAction => Id;
|
||||
|
||||
/// <summary>
|
||||
/// Gets if this operation have a action text
|
||||
/// </summary>
|
||||
public bool HaveAction => !string.IsNullOrEmpty(ProgressAction);
|
||||
|
||||
/// <summary>
|
||||
@@ -171,6 +174,12 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
|
||||
public bool HaveROI => !ROI.IsEmpty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets if this operation have been executed once
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public bool HaveExecuted { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
@@ -302,6 +311,7 @@ namespace UVtools.Core.Operations
|
||||
if (_slicerFile is null) throw new InvalidOperationException($"{Title} can't execute due the lacking of file parent.");
|
||||
progress ??= new OperationProgress();
|
||||
progress.Reset(ProgressAction, LayerRangeCount);
|
||||
HaveExecuted = true;
|
||||
|
||||
var result = ExecuteInternally(progress);
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
}
|
||||
|
||||
public uint CacheObjectCount => (uint) (_cacheRamSize * 1000000000L / SlicerFile.Resolution.GetArea() / ObjectsPerCache);
|
||||
public uint CacheObjectCount => (uint) (_cacheRamSize * 1000000000L / SlicerFile.Resolution.Area() / ObjectsPerCache);
|
||||
|
||||
public decimal CacheRAMSize
|
||||
{
|
||||
|
||||
@@ -120,11 +120,11 @@ namespace UVtools.Core.Operations
|
||||
var rectangle = CvInvoke.BoundingRectangle(contours[i]);
|
||||
if (AreaCheckType == AreaCheckTypes.More)
|
||||
{
|
||||
if (rectangle.GetArea() < MinimumArea) continue;
|
||||
if (rectangle.Area() < MinimumArea) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rectangle.GetArea() > MinimumArea) continue;
|
||||
if (rectangle.Area() > MinimumArea) continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.6</Version>
|
||||
<Version>2.4.7</Version>
|
||||
<Copyright>Copyright © 2020 PTRTECH</Copyright>
|
||||
<PackageIcon>UVtools.png</PackageIcon>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using UVtools.Core.FileFormats;
|
||||
using UVtools.Core.Objects;
|
||||
using UVtools.Core.Operations;
|
||||
using UVtools.WPF.Extensions;
|
||||
@@ -17,7 +16,8 @@ namespace UVtools.WPF.Controls.Tools
|
||||
get => _baseOperation;
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _baseOperation, value)) return;
|
||||
_baseOperation = value;
|
||||
RaisePropertyChanged();
|
||||
if (DataContext is null) return;
|
||||
ResetDataContext();
|
||||
}
|
||||
|
||||
@@ -344,20 +344,25 @@ namespace UVtools.WPF
|
||||
//CurrentLayerProperties.Add(new StringTag(nameof(layer.NonZeroPixelCount), layer.NonZeroPixelCount.ToString()));
|
||||
CurrentLayerProperties.Add(new StringTag(nameof(layer.ExposureTime), $"{layer.ExposureTime:F2}s"));
|
||||
|
||||
if (ReferenceEquals(SlicerFile.PrintParameterPerLayerModifiers, null)) return;
|
||||
if (SlicerFile.PrintParameterPerLayerModifiers is not null)
|
||||
{
|
||||
|
||||
if (SlicerFile.PrintParameterPerLayerModifiers.Contains(FileFormat.PrintParameterModifier.LiftHeight))
|
||||
CurrentLayerProperties.Add(new StringTag(nameof(layer.LiftHeight),
|
||||
$"{layer.LiftHeight.ToString(CultureInfo.InvariantCulture)}mm @ {layer.LiftSpeed.ToString(CultureInfo.InvariantCulture)}mm/min"));
|
||||
//CurrentLayerProperties.Adnew StringTagg>(nameof(layer.LiftSpeed), $"{layer.LiftSpeed.ToString(CultureInfo.InvariantCulture)}mm/min"));
|
||||
if (SlicerFile.PrintParameterPerLayerModifiers.Contains(FileFormat.PrintParameterModifier.RetractSpeed))
|
||||
CurrentLayerProperties.Add(new StringTag(nameof(layer.RetractSpeed),
|
||||
$"{layer.RetractSpeed.ToString(CultureInfo.InvariantCulture)}mm/min"));
|
||||
if (SlicerFile.PrintParameterPerLayerModifiers.Contains(FileFormat.PrintParameterModifier.LightOffDelay))
|
||||
CurrentLayerProperties.Add(new StringTag(nameof(layer.LightOffDelay),
|
||||
$"{layer.LightOffDelay.ToString(CultureInfo.InvariantCulture)}s"));
|
||||
if (SlicerFile.PrintParameterPerLayerModifiers.Contains(FileFormat.PrintParameterModifier.LightPWM))
|
||||
CurrentLayerProperties.Add(new StringTag(nameof(layer.LightPWM), layer.LightPWM.ToString()));
|
||||
if (SlicerFile.PrintParameterPerLayerModifiers.Contains(FileFormat.PrintParameterModifier.LiftHeight))
|
||||
CurrentLayerProperties.Add(new StringTag(nameof(layer.LiftHeight),
|
||||
$"{layer.LiftHeight.ToString(CultureInfo.InvariantCulture)}mm @ {layer.LiftSpeed.ToString(CultureInfo.InvariantCulture)}mm/min"));
|
||||
//CurrentLayerProperties.Adnew StringTagg>(nameof(layer.LiftSpeed), $"{layer.LiftSpeed.ToString(CultureInfo.InvariantCulture)}mm/min"));
|
||||
if (SlicerFile.PrintParameterPerLayerModifiers.Contains(FileFormat.PrintParameterModifier.RetractSpeed))
|
||||
CurrentLayerProperties.Add(new StringTag(nameof(layer.RetractSpeed),
|
||||
$"{layer.RetractSpeed}mm/min"));
|
||||
if (SlicerFile.PrintParameterPerLayerModifiers.Contains(FileFormat.PrintParameterModifier.LightOffDelay)
|
||||
)
|
||||
CurrentLayerProperties.Add(new StringTag(nameof(layer.LightOffDelay),
|
||||
$"{layer.LightOffDelay}s"));
|
||||
if (SlicerFile.PrintParameterPerLayerModifiers.Contains(FileFormat.PrintParameterModifier.LightPWM))
|
||||
CurrentLayerProperties.Add(new StringTag(nameof(layer.LightPWM), layer.LightPWM.ToString()));
|
||||
}
|
||||
|
||||
CurrentLayerProperties.Add(new StringTag(nameof(layer.MaterialMilliliters), $"{layer.MaterialMilliliters:F4}ml"));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -307,13 +307,13 @@ namespace UVtools.WPF
|
||||
}
|
||||
}
|
||||
|
||||
public string LayerBoundsStr => LayerCache.Layer is null ? "NS" : $"{LayerCache.Layer.BoundingRectangle} ({LayerCache.Layer.BoundingRectangle.GetArea()}px²)";
|
||||
public string LayerBoundsStr => LayerCache.Layer is null ? "NS" : $"{LayerCache.Layer.BoundingRectangle} ({LayerCache.Layer.BoundingRectangle.Area()}px²)";
|
||||
public string LayerROIStr
|
||||
{
|
||||
get
|
||||
{
|
||||
var roi = ROI;
|
||||
return roi.IsEmpty ? "NS" : $"{roi} ({roi.GetArea()}px²)";
|
||||
return roi.IsEmpty ? "NS" : $"{roi} ({roi.Area()}px²)";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<Version>2.4.6</Version>
|
||||
<Version>2.4.7</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Threading;
|
||||
@@ -109,7 +107,7 @@ namespace UVtools.WPF.Windows
|
||||
get => _layerIndexStart;
|
||||
set
|
||||
{
|
||||
if (!(ToolControl?.BaseOperation is null))
|
||||
if (ToolControl?.BaseOperation is not null)
|
||||
{
|
||||
ToolControl.BaseOperation.LayerRangeSelection = Enumerations.LayerRangeSelection.None;
|
||||
ToolControl.BaseOperation.LayerIndexStart = value;
|
||||
@@ -294,7 +292,17 @@ namespace UVtools.WPF.Windows
|
||||
operation.ProfileName = null;
|
||||
operation.SlicerFile = App.SlicerFile;
|
||||
ToolControl.BaseOperation = operation;
|
||||
SelectLayers(operation.LayerRangeSelection);
|
||||
switch (operation.LayerRangeSelection)
|
||||
{
|
||||
case Enumerations.LayerRangeSelection.None:
|
||||
LayerIndexStart = operation.LayerIndexStart;
|
||||
LayerIndexEnd = operation.LayerIndexEnd;
|
||||
break;
|
||||
default:
|
||||
SelectLayers(operation.LayerRangeSelection);
|
||||
break;
|
||||
}
|
||||
|
||||
ToolControl.Callback(Callbacks.ProfileLoaded);
|
||||
ToolControl.ResetDataContext();
|
||||
}
|
||||
@@ -504,15 +512,15 @@ namespace UVtools.WPF.Windows
|
||||
_buttonOkText = toolControl.BaseOperation.ButtonOkText;
|
||||
_buttonOkVisible = ButtonOkEnabled = toolControl.BaseOperation.HaveAction;
|
||||
|
||||
if (toolControl.BaseOperation.LayerIndexStart == 0 && toolControl.BaseOperation.LayerIndexEnd == 0)
|
||||
{
|
||||
SelectLayers(toolControl.BaseOperation.StartLayerRangeSelection);
|
||||
}
|
||||
else
|
||||
if (toolControl.BaseOperation.HaveExecuted) // Come from a redo or something
|
||||
{
|
||||
LayerIndexStart = toolControl.BaseOperation.LayerIndexStart;
|
||||
LayerIndexEnd = toolControl.BaseOperation.LayerIndexEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectLayers(toolControl.BaseOperation.StartLayerRangeSelection);
|
||||
}
|
||||
|
||||
//RaisePropertyChanged(nameof(IsContentVisible));
|
||||
//RaisePropertyChanged(nameof(IsROIVisible));
|
||||
|
||||
Reference in New Issue
Block a user