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>2020-11-19 07:23:37 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2020-11-19 07:23:37 +0300
commita4bdf8f9f3c5fd9f0f84b1a3470d478694b66644 (patch)
tree4f737f65c5c300f30a7dbbc5cf49fd408d3ae2ce
parent1d17f6ceb6ca3299b95746548ab681fd9f00ee75 (diff)
v1.3.2v1.3.2
* (Add) Tools: Warn where layer preview is critical for use the tool, must disable layer rotation first (#100) * (Add) CWS: Bottom lift speed property * (Add) CWS: Support Wanhao Workshop CWX and Wanhao Creation Workshop file types (#98) * (Add) CWS: Split format into virtual extensions (.cws, .rgb.cws, .xml.cws) to support diferent file formats and diferent printers under same main .cws extensions. That will affect file converts only to let UVtools know what type of encoding to use. Load and save a xxx.cws file will always auto decode/encode the file for the correct target format no matter the extension. * (Improvement) CWS: It no longer search for a specific filename in the zip file, instead it look for extension to get the files to ensure it always found them no matter the file name system * (Fix) CWS: When "Save as" the file were generating sub files with .cws extension, eg: filename0001.cws.png * (Change) Allow read empty layers without error from Anycubic files (PWS, PW0, PWxx) due a bug on slicer software under macOS
-rw-r--r--CHANGELOG.md10
-rw-r--r--UVtools.Core/FileFormats/CWSFile.cs513
-rw-r--r--UVtools.Core/FileFormats/ChituboxFile.cs8
-rw-r--r--UVtools.Core/FileFormats/ChituboxZipFile.cs8
-rw-r--r--UVtools.Core/FileFormats/PHZFile.cs8
-rw-r--r--UVtools.Core/FileFormats/PhotonWorkshopFile.cs12
-rw-r--r--UVtools.Core/FileFormats/SL1File.cs6
-rw-r--r--UVtools.Core/FileFormats/UVJFile.cs8
-rw-r--r--UVtools.Core/Layer/Layer.cs10
-rw-r--r--UVtools.Core/Operations/OperationCalculator.cs21
-rw-r--r--UVtools.Core/Operations/OperationFlip.cs3
-rw-r--r--UVtools.Core/Operations/OperationMove.cs3
-rw-r--r--UVtools.Core/Operations/OperationPattern.cs3
-rw-r--r--UVtools.Core/UVtools.Core.csproj2
-rw-r--r--UVtools.Installer/Code/Product.wxs2
-rw-r--r--UVtools.WPF/App.axaml.cs1
-rw-r--r--UVtools.WPF/MainWindow.axaml.cs2
-rw-r--r--UVtools.WPF/UVtools.WPF.csproj2
18 files changed, 479 insertions, 143 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0b841c0..f5eb11e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,15 @@
# Changelog
+## 19/11/2020 - v1.3.2
+
+* (Add) Tools: Warn where layer preview is critical for use the tool, must disable layer rotation first (#100)
+* (Add) CWS: Bottom lift speed property
+* (Add) CWS: Support Wanhao Workshop CWX and Wanhao Creation Workshop file types (#98)
+* (Add) CWS: Split format into virtual extensions (.cws, .rgb.cws, .xml.cws) to support diferent file formats and diferent printers under same main .cws extensions. That will affect file converts only to let UVtools know what type of encoding to use. Load and save a xxx.cws file will always auto decode/encode the file for the correct target format no matter the extension.
+* (Improvement) CWS: It no longer search for a specific filename in the zip file, instead it look for extension to get the files to ensure it always found them no matter the file name system
+* (Fix) CWS: When "Save as" the file were generating sub files with .cws extension, eg: filename0001.cws.png
+* (Change) Allow read empty layers without error from Anycubic files (PWS, PW0, PWxx) due a bug on slicer software under macOS
+
## 16/11/2020 - v1.3.1
* (Add) File format: PWX (AnyCubic Photon X) (#93)
diff --git a/UVtools.Core/FileFormats/CWSFile.cs b/UVtools.Core/FileFormats/CWSFile.cs
index 3dcbb25..b86efe2 100644
--- a/UVtools.Core/FileFormats/CWSFile.cs
+++ b/UVtools.Core/FileFormats/CWSFile.cs
@@ -7,6 +7,7 @@
*/
using System;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
@@ -16,6 +17,7 @@ using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
+using System.Xml.Serialization;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
@@ -24,18 +26,164 @@ using UVtools.Core.Operations;
namespace UVtools.Core.FileFormats
{
+ #region Wanhao
+
+ [Serializable]
+ [XmlRoot(ElementName = "manifest")]
+ public sealed class CWSManifest
+ {
+ public const string FileName = "manifest.xml";
+
+ [XmlAttribute]
+ public byte FileVersion { get; set; } = 1;
+
+ public sealed class Model
+ {
+ [XmlElement("name")]
+ public string Name { get; set; }
+
+ [XmlElement("tag")]
+ public string Tag { get; set; }
+ }
+
+ public sealed class Slice
+ {
+ [XmlElement("name")]
+ public string Name { get; set; }
+
+ public Slice()
+ {
+ }
+
+ public Slice(string name)
+ {
+ Name = name;
+ }
+ }
+
+ [XmlArrayItem("model")]
+ public Model[] Models { get; set; }
+ public Slice[] Slices { get; set; }
+
+ public Slice SliceProfile { get; set; } = new Slice();
+ public Slice GCode { get; set; } = new Slice();
+ }
+
+ [Serializable]
+ [XmlRoot(ElementName = "SliceBuildConfig")]
+ public sealed class CWSSliceBuildConfig
+ {
+ public const string GCODESTART =
+ ";********** Header Start ********\r\n" +
+ "G21 ; Set units to be mm\r\n" +
+ "G91 ; Relative Positioning\r\n" +
+ "M17 ; Enable motors\r\n" +
+ "; G28 Z ; Auto-home on print - commented by default";
+
+ public const string GCODEEND =
+ ";********** Footer ********\r\n" +
+ "@cmdCloseShutter ; UV off\r\n" +
+ "G4 P0 ; wait for last lift to complete\r\n" +
+ "G1 Z40.0 F150.0 ; lift model clear of resin\r\n" +
+ "G4 P0 ; sync\r\n" +
+ "M18 ; Disable Motors\r\n" +
+ ";&lt;Completed&gt;";
+
+ public const string GCODELIFT =
+ ";********** Lift Sequence %d$CURSLICE ********\r\n" +
+ "G1 Z($ZLiftDist * $ZDir) F{$CURSLICE &lt; $NumFirstLayers?$ZBottomLiftRate:$ZLiftRate}\r\n;" +
+ "&lt;Takes&gt; {$CURSLICE&lt;$NumFirstLayers?%d($ZLiftDist*1000*60/$ZBottomLiftRate):%d($ZLiftDist*1000*60/$ZLiftRate)}\r\n" +
+ "G4 P0 ; Wait for lift rise to complete\r\n;" +
+ "&lt;Delay&gt; %d$TopTime\r\n" +
+ "G1 Z(($LayerThickness-$ZLiftDist) * $ZDir) F$ZRetractRate\r\n" +
+ ";&lt;Takes&gt; %d(($ZLiftDist*1000-$LayerThickness*1000)*60/$ZRetractRate)";
+
+ public const string GCODELAYER =
+ ";********** Layer %d$CURSLICE ********\r\n" +
+ ";&lt;Slice&gt; %d$CURSLICE\r\n" +
+ "@cmdOpenShutter ; UV on\r\n" +
+ ";{$CURSLICE&lt;$NumFirstLayers?&lt;Delay&gt; %d$FirstLayerTime:&lt;Delay&gt; %d$LayerTime}\r\n" +
+ "@cmdCloseShutter ; UV off\r\n" +
+ ";&lt;Slice&gt; Blank\r\n" +
+ ";&lt;Delay&gt; %d$BlankTime";
+
+ public sealed class InkConfig
+ {
+ public string Name { get; set; }
+ public float SliceHeight { get; set; }
+ public uint LayerTime { get; set; }
+ public uint FirstLayerTime { get; set; }
+ public ushort NumberofBottomLayers { get; set; }
+ public float ResinPriceL { get; set; }
+ }
+
+ [XmlAttribute]
+ public byte FileVersion { get; set; } = 2;
+
+ public float DotsPermmX { get; set; } = 21.164f;
+ public float DotsPermmY { get; set; } = 21.164f;
+
+ public ushort XResolution { get; set; }
+ public ushort YResolution { get; set; }
+ public uint BlankTime { get; set; }
+ public uint TopTime { get; set; }
+ public uint PlatformTemp { get; set; } = 75;
+ public byte ExportSVG { get; set; }
+ public string Export { get; set; } = "False";
+ public string ExportPNG { get; set; } = "False";
+ public string CalcSliceSize { get; set; } = "False";
+ public uint XOffset { get; set; }
+ public uint YOffset { get; set; }
+ public string Direction { get; set; } = "Bottom_Up";
+ public float LiftDistance { get; set; } = 6;
+ public float SlideTiltValue { get; set; }
+ public uint SettleTime { get; set; } = 1600;
+ public string AntiAliasing { get; set; } = "True";
+ public string UseMainLiftGCode { get; set; } = "False";
+ public uint AntiAliasingValue { get; set; } = 4;
+ public float LiftFeedRate { get; set; } = 40;
+ public float BottomLiftFeedRate { get; set; } = 25;
+ public float LiftRetractRate { get; set; } = 80;
+ public string ExportOption { get; set; } = "ZIP";
+ public string RenderOutlines { get; set; } = "False";
+ public uint OutlineWidth_Inset { get; set; } = 2;
+ public uint OutlineWidth_Outset { get; set; }
+ public string FlipX { get; set; } = "False";
+ public string FlipY { get; set; } = "False";
+
+ public string Notes { get; set; } =
+ "Use these as a place to start; tune them for your specific printer and resins.\r\nAlways run a calibration on your resin to dial in for your machine.\r\nProfiles created by Earl Miller for CW v1.0.0.75.";
+
+ public string GCodeHeader { get; set; } = GCODESTART;
+ public string GCodeFooter { get; set; } = GCODEEND;
+ public string GCodeLift { get; set; } = GCODELIFT;
+ public string GCodeLayer { get; set; } = GCODELAYER;
+
+ [XmlElement("InkConfig")]
+ public List<InkConfig> InkConfigs { get; set; }
+
+ public string SelectedInk { get; set; }
+ public uint MinTestExposure { get; set; } = 5000;
+ public uint TestExposureStep { get; set; } = 100;
+ public string ExportPreview { get; set; } = "None";
+ public string UseMask { get; set; } = "False";
+ public string MaskFilename { get; set; } = "False";
+ }
+
+ #endregion
+
public class CWSFile : FileFormat
{
#region Constants
- public const string GCodeStart = "G28 ;Auto Home{0}" +
- "G21 ;Set units to be mm{0}" +
- "G91 ;Relative Positioning{0}" +
- "M17 ;Enable motors{0}" +
- "<Slice> Blank{0}" +
- "M106 S0{0}{0}";
+ public const string GCodeStart = "G28 ;Auto Home{0}" +
+ "G21 ;Set units to be mm{0}" +
+ "G91 ;Relative Positioning{0}" +
+ "M17 ;Enable motors{0}" +
+ "<Slice> Blank{0}" +
+ "M106 S0{0}{0}";
- public const string GCodeEnd = "M106 S0{0}" +
+ public const string GCodeEnd = "M106 S0{0} ; UV off" +
"G1 Z{1}{0}" +
"{0}M18 ;Disable Motors{0}" +
";<Completed>{0}";
@@ -43,6 +191,30 @@ namespace UVtools.Core.FileFormats
public const string GCodeKeywordSlice = ";<Slice>";
public const string GCodeKeywordSliceBlank = ";<Slice> Blank";
public const string GCodeKeywordDelay = ";<Delay>";
+ public const string GCodeKeywordTakes = ";<Takes>";
+
+ public const string WanhaoStartGCode =
+ ";********** Header Start ********{0}" +
+ "G21 ; Set units to be mm{0}" +
+ "G91 ; Relative Positioning{0}" +
+ "M17 ; Enable motors{0}" +
+ "; G28 Z ; Auto-home on print - commented by default{0}";
+
+ public const string WanhaoPreSliceGCode =
+ ";********** Pre-Slice {1} ********{0}" +
+ "G4 P0; Make sure any previous relative moves are complete{0}" +
+ ";<Delay> {2}{0}" +
+ ";********** Layer {1} ********{0}";
+
+ public const string WanhaoGCodeEnd =
+ ";********** Footer ********{0}" +
+ "M106 S0 ; UV off{0}" +
+ "G4 P0 ; wait for last lift to complete{0}" +
+ "G1 Z40.0 F150.0 ; lift model clear of resin{0}" +
+ "G4 P0 ; sync{0}" +
+ "M18 ; Disable Motors{0}" +
+ ";<Completed>{0}";
+
#endregion
#region Sub Classes
@@ -66,6 +238,7 @@ namespace UVtools.Core.FileFormats
[DisplayName("Lift Distance")] public float LiftDistance { get; set; } = 4;
[DisplayName("Slide/Tilt Value")] public byte TiltValue { get; set; }
[DisplayName("Use Mainlift GCode Tab")] public bool UseMainliftGCodeTab { get; set; }
+ [DisplayName("Settle Time")] public uint SettleTime { get; set; } = 1600;
[DisplayName("Anti Aliasing")] public bool AntiAliasing { get; set; } = true;
[DisplayName("Anti Aliasing Value")] public float AntiAliasingValue { get; set; } = 2;
[DisplayName("Z Lift Feed Rate")] public float ZLiftFeedRate { get; set; } = 120;
@@ -107,11 +280,14 @@ namespace UVtools.Core.FileFormats
[DisplayName("lift_when_finished")] public byte LiftWhenFinished { get; set; } = 80;
}
+
+
#endregion
#region Properties
public Slice SliceSettings { get; } = new Slice();
public Output OutputSettings { get; } = new Output();
+ public CWSSliceBuildConfig SliceBuildConfig { get; set; } = new CWSSliceBuildConfig();
public override FileFormatType FileType => FileFormatType.Archive;
@@ -120,14 +296,16 @@ namespace UVtools.Core.FileFormats
{
Unknown,
Elfin,
- BeneMono
+ BeneMono,
+ Wanhao,
}
public PrinterType Printer { get; set; } = PrinterType.Unknown;
public override FileExtension[] FileExtensions { get; } = {
new FileExtension("cws", "NovaMaker CWS"),
- //new FileExtension("cws", "NovaMaker Bene Mono CWS Files", "Bene")
+ new FileExtension("rgb.cws", "NovaMaker Bene4 Mono / Elfin2 Mono SE (CWS)"),
+ new FileExtension("xml.cws", "Creation Workshop X (CWS)"),
};
public override Type[] ConvertToFormats { get; } =
@@ -141,6 +319,7 @@ namespace UVtools.Core.FileFormats
PrintParameterModifier.ExposureSeconds,
+ PrintParameterModifier.BottomLiftSpeed,
PrintParameterModifier.LiftHeight,
PrintParameterModifier.RetractSpeed,
PrintParameterModifier.LiftSpeed,
@@ -164,20 +343,24 @@ namespace UVtools.Core.FileFormats
public override uint ResolutionX
{
- get => SliceSettings.Xres;
+ get => SliceSettings.Xres > 0 ? SliceSettings.Xres : SliceBuildConfig.XResolution;
set
{
- OutputSettings.XResolution = SliceSettings.Xres = (ushort) value;
+ SliceBuildConfig.XResolution =
+ OutputSettings.XResolution =
+ SliceSettings.Xres = (ushort) value;
RaisePropertyChanged();
}
}
public override uint ResolutionY
{
- get => SliceSettings.Yres;
+ get => SliceSettings.Yres > 0 ? SliceSettings.Yres : SliceBuildConfig.YResolution;
set
{
- OutputSettings.YResolution = SliceSettings.Yres = (ushort) value;
+ SliceBuildConfig.YResolution =
+ OutputSettings.YResolution =
+ SliceSettings.Yres = (ushort) value;
RaisePropertyChanged();
}
}
@@ -206,7 +389,7 @@ namespace UVtools.Core.FileFormats
public override float LayerHeight
{
- get => SliceSettings.Thickness;
+ get => SliceSettings.Thickness > 0 ? SliceSettings.Thickness : OutputSettings.LayerThickness;
set
{
OutputSettings.LayerThickness = SliceSettings.Thickness = value;
@@ -240,6 +423,7 @@ namespace UVtools.Core.FileFormats
get => (float) Math.Round(SliceSettings.HeadLayersExpoMs / 1000f, 2);
set
{
+ OutputSettings.BottomLayersTime =
SliceSettings.HeadLayersExpoMs = (uint) (value * 1000f);
RaisePropertyChanged();
}
@@ -250,16 +434,28 @@ namespace UVtools.Core.FileFormats
get => (float) Math.Round(SliceSettings.LayersExpoMs / 1000f, 2);
set
{
+ OutputSettings.LayerTime =
SliceSettings.LayersExpoMs = (uint) (value * 1000f);
RaisePropertyChanged();
}
}
+ public override float BottomLiftSpeed
+ {
+ get => OutputSettings.ZBottomLiftFeedRate;
+ set
+ {
+ OutputSettings.ZBottomLiftFeedRate = value;
+ RaisePropertyChanged();
+ }
+ }
+
public override float LiftHeight
{
get => SliceSettings.LiftDistance;
set
{
+ OutputSettings.LiftDistance =
SliceSettings.LiftDistance = value;
RaisePropertyChanged();
}
@@ -270,6 +466,8 @@ namespace UVtools.Core.FileFormats
get => SliceSettings.LiftDownSpeed;
set
{
+ OutputSettings.ZLiftFeedRate =
+ SliceSettings.LiftUpSpeed =
SliceSettings.LiftDownSpeed = value;
RaisePropertyChanged();
}
@@ -316,7 +514,7 @@ namespace UVtools.Core.FileFormats
public override string MachineName => "Unknown";*/
- public override object[] Configs => new object[] { SliceSettings, OutputSettings};
+ public override object[] Configs => Printer == PrinterType.Wanhao ? new object[] { SliceBuildConfig, OutputSettings } : new object[] { SliceSettings, OutputSettings};
#endregion
#region Methods
@@ -330,45 +528,88 @@ namespace UVtools.Core.FileFormats
public override void Encode(string fileFullPath, OperationProgress progress = null)
{
base.Encode(fileFullPath, progress);
- if (Printer == PrinterType.Unknown) Printer = PrinterType.Elfin;
+
+ //var filename = fileFullPath.EndsWith(TemporaryFileAppend) ? Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(fileFullPath)) : Path.GetFileNameWithoutExtension(fileFullPath);
+
+ if (Printer == PrinterType.Unknown)
+ {
+ Printer = PrinterType.Elfin;
+ for (int i = 0; i < FileExtensions.Length; i++)
+ {
+ if (!fileFullPath.EndsWith(FileExtensions[i].Extension) && !fileFullPath.EndsWith($"{FileExtensions[i].Extension}{TemporaryFileAppend}")) continue;
+ Printer = (PrinterType) i+1;
+ }
+ }
+
+ var filename = Path.GetFileName(fileFullPath);
+ filename = filename.Substring(0, filename.IndexOf('.'));
+
using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create))
{
- string arch = Environment.Is64BitOperatingSystem ? "64-bits" : "32-bits";
- var entry = outputFile.CreateEntry("slice.conf");
- var stream = entry.Open();
+ if (Printer == PrinterType.Wanhao)
+ {
+ var manifest = new CWSManifest
+ {
+ GCode = {Name = $"{filename}.gcode"},
+ Slices = new CWSManifest.Slice[LayerCount],
+ SliceProfile = {Name = $"{filename}.slicing"}
+ };
- using (TextWriter tw = new StreamWriter(stream))
+ for (int layerIndex = 0; layerIndex < LayerCount; layerIndex++)
+ {
+ manifest.Slices[layerIndex] = new CWSManifest.Slice(this[layerIndex].FormatFileName(filename));
+ }
+
+ XmlSerializer serializer = new XmlSerializer(manifest.GetType());
+ XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
+ ns.Add("", "");
+ var entry = outputFile.CreateEntry(CWSManifest.FileName);
+ using (var stream = entry.Open())
+ {
+ serializer.Serialize(stream, manifest, ns);
+ }
+
+ serializer = new XmlSerializer(SliceBuildConfig.GetType());
+ entry = outputFile.CreateEntry($"{filename}.slicing");
+ using (var stream = entry.Open())
+ {
+ serializer.Serialize(stream, SliceBuildConfig, ns);
+ }
+ }
+ else
{
-
- tw.WriteLine($"# {About.Website} {About.Software} {Assembly.GetExecutingAssembly().GetName().Version} {arch} {DateTime.Now}");
- tw.WriteLine("# conf version 1.0");
- tw.WriteLine("");
+ string arch = Environment.Is64BitOperatingSystem ? "64-bits" : "32-bits";
+ var entry = outputFile.CreateEntry("slice.conf");
- foreach (var propertyInfo in SliceSettings.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
+ using (TextWriter tw = new StreamWriter(entry.Open()))
{
- var displayNameAttribute = propertyInfo.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault();
- if (ReferenceEquals(displayNameAttribute, null)) continue;
- tw.WriteLine($"{displayNameAttribute.DisplayName.PadRight(24)}= {propertyInfo.GetValue(SliceSettings)}");
+
+ tw.WriteLine($"# {About.Website} {About.Software} {Assembly.GetExecutingAssembly().GetName().Version} {arch} {DateTime.Now}");
+ tw.WriteLine("# conf version 1.0");
+ tw.WriteLine("");
+
+ foreach (var propertyInfo in SliceSettings.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
+ {
+ var displayNameAttribute = propertyInfo.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault();
+ if (ReferenceEquals(displayNameAttribute, null)) continue;
+ tw.WriteLine($"{displayNameAttribute.DisplayName.PadRight(24)}= {propertyInfo.GetValue(SliceSettings)}");
+ }
}
}
+
//for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
Parallel.For(0, LayerCount,
- new ParallelOptions{MaxDegreeOfParallelism = Printer == PrinterType.Elfin ? 1 : Environment.ProcessorCount},
+ new ParallelOptions{MaxDegreeOfParallelism = Printer == PrinterType.BeneMono ? 1 : 1 },
layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
Layer layer = this[layerIndex];
- var layerImagePath =
- $"{Path.GetFileNameWithoutExtension(fileFullPath)}{layerIndex.ToString().PadLeft(LayerCount.ToString().Length, '0')}.png";
+ var layerImagePath = layer.FormatFileName(filename);
- if (Printer == PrinterType.Elfin)
- {
- outputFile.PutFileContent(layerImagePath, layer.CompressedBytes, ZipArchiveMode.Create);
- }
- else
+ if (Printer == PrinterType.BeneMono)
{
using (var mat = layer.LayerMat)
using (var matEncode = new Mat(mat.Height, mat.Step / 3, DepthType.Cv8U, 3))
@@ -389,17 +630,20 @@ namespace UVtools.Core.FileFormats
}
}
}
+ }
+ else
+ {
+ outputFile.PutFileContent(layerImagePath, layer.CompressedBytes, ZipArchiveMode.Create);
+ }
- lock (progress.Mutex)
- {
- progress++;
- }
-
+ lock (progress.Mutex)
+ {
+ progress++;
}
});
RebuildGCode();
- outputFile.PutFileContent($"{Path.GetFileNameWithoutExtension(fileFullPath)}.gcode", GCode.ToString(), ZipArchiveMode.Create);
+ outputFile.PutFileContent($"{filename}.gcode", GCode.ToString(), ZipArchiveMode.Create);
}
AfterEncode();
@@ -413,48 +657,71 @@ namespace UVtools.Core.FileFormats
FileFullPath = fileFullPath;
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
{
- var entry = inputFile.GetEntry("slice.conf");
- if (ReferenceEquals(entry, null))
+ var entry = inputFile.GetEntry("manifest.xml");
+ if (!ReferenceEquals(entry, null)) // Wanhao
{
- Clear();
- throw new FileLoadException("slice.conf not found", fileFullPath);
- }
-
-
+ //DecodeXML(fileFullPath, inputFile, progress);
+ Printer = PrinterType.Wanhao;
+ entry = inputFile.Entries.FirstOrDefault(e => e.Name.EndsWith(".slicing"));
- using (TextReader tr = new StreamReader(entry.Open()))
+ if (!(entry is null))
+ {
+ //Clear();
+ //throw new FileLoadException(".slicing file not found, unable to proceed.", fileFullPath);
+ try
+ {
+ var serializer = new XmlSerializer(typeof(CWSSliceBuildConfig));
+ using (var stream = entry.Open())
+ {
+ SliceBuildConfig = (CWSSliceBuildConfig)serializer.Deserialize(stream);
+ }
+ }
+ catch (Exception e)
+ {
+ Clear();
+ throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", fileFullPath);
+ }
+ }
+ }
+ else // Novamaker
{
- string line;
- while ((line = tr.ReadLine()) != null)
+ entry = inputFile.GetEntry("slice.conf");
+ if (ReferenceEquals(entry, null))
{
- line = line.Replace("# ", string.Empty);
- if (string.IsNullOrEmpty(line)) continue;
- //if(line[0] == '#') continue;
-
- var splitLine = line.Split('=');
- if(splitLine.Length < 2) continue;
+ Clear();
+ throw new FileLoadException("slice.conf not found", fileFullPath);
+ }
- foreach (var propertyInfo in SliceSettings.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
+ using (TextReader tr = new StreamReader(entry.Open()))
+ {
+ string line;
+ while ((line = tr.ReadLine()) != null)
{
- var displayNameAttribute = propertyInfo.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault();
- if(ReferenceEquals(displayNameAttribute, null)) continue;
- if(!splitLine[0].Trim().Equals(displayNameAttribute.DisplayName)) continue;
- Helpers.SetPropertyValue(propertyInfo, SliceSettings, splitLine[1].Trim());
+ line = line.Replace("# ", string.Empty);
+ if (string.IsNullOrEmpty(line)) continue;
+ //if(line[0] == '#') continue;
+
+ var splitLine = line.Split('=');
+ if (splitLine.Length < 2) continue;
+
+ foreach (var propertyInfo in SliceSettings.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
+ {
+ var displayNameAttribute = propertyInfo.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault();
+ if (ReferenceEquals(displayNameAttribute, null)) continue;
+ if (!splitLine[0].Trim().Equals(displayNameAttribute.DisplayName)) continue;
+ Helpers.SetPropertyValue(propertyInfo, SliceSettings, splitLine[1].Trim());
+ }
}
+ tr.Close();
}
- tr.Close();
}
- entry = inputFile.GetEntry($"{Path.GetFileNameWithoutExtension(fileFullPath)}.gcode");
+ entry = inputFile.Entries.FirstOrDefault(e => e.Name.EndsWith(".gcode"));
if (entry is null)
{
- entry = inputFile.GetEntry("slice.gcode");
- if (entry is null)
- {
- Clear();
- throw new FileLoadException($"{Path.GetFileNameWithoutExtension(fileFullPath)}.gcode nor slice.gcode was found",
- fileFullPath);
- }
+ Clear();
+ throw new FileLoadException("Unable to find .gcode file",
+ fileFullPath);
}
using (TextReader tr = new StreamReader(entry.Open()))
@@ -479,7 +746,7 @@ namespace UVtools.Core.FileFormats
var displayNameAttribute = propertyInfo.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault();
if (ReferenceEquals(displayNameAttribute, null)) continue;
if (!splitLine[0].Trim(' ', ';', '(').Equals(displayNameAttribute.DisplayName)) continue;
- Helpers.SetPropertyValue(propertyInfo, OutputSettings, splitLine[1].Trim(' ', ')', 'm', 'n', 's', '/'));
+ Helpers.SetPropertyValue(propertyInfo, OutputSettings, splitLine[1].Trim(' ', ')', 'p', 'x', 'm', 'n', 's', '/'));
//Debug.WriteLine(splitLine[1].Trim(' ', ')', 'm', 'n', '/'));
}
}
@@ -518,8 +785,12 @@ namespace UVtools.Core.FileFormats
var stripGcode =
gcode.Substring(gcode.IndexOf(startStr, StringComparison.InvariantCultureIgnoreCase) +
startStr.Length);
+
+ var endStr = $"{GCodeKeywordSlice} {layerIndex + 1}";
+ var endIndex = stripGcode.IndexOf(endStr, StringComparison.InvariantCulture);
+ if (endIndex < 0) endIndex = stripGcode.Length;
stripGcode = stripGcode
- .Substring(0, stripGcode.IndexOf(GCodeKeywordDelay, stripGcode.IndexOf(GCodeKeywordSlice)))
+ .Substring(0, endIndex)
.Trim(' ', '\n', '\r', '\t');
//var startCurrPos = stripGcode.Remove(0, ";currPos:".Length);
@@ -609,20 +880,7 @@ namespace UVtools.Core.FileFormats
}
- if (Printer == PrinterType.Elfin)
- {
- this[layerIndex] =
- new Layer(layerIndex, buffer, LayerManager)
- {
- ExposureTime = exposureTime,
- LiftHeight = liftHeight,
- LiftSpeed = liftSpeed,
- RetractSpeed = retractSpeed,
- LayerOffTime = lightOffDelay,
- LightPWM = pwm,
- };
- }
- else
+ if (Printer == PrinterType.BeneMono)
{
using (Mat mat = new Mat())
{
@@ -648,7 +906,19 @@ namespace UVtools.Core.FileFormats
};
}
}
-
+ }
+ else
+ {
+ this[layerIndex] =
+ new Layer(layerIndex, buffer, LayerManager)
+ {
+ ExposureTime = exposureTime,
+ LiftHeight = liftHeight,
+ LiftSpeed = liftSpeed,
+ RetractSpeed = retractSpeed,
+ LayerOffTime = lightOffDelay,
+ LightPWM = pwm,
+ };
}
progress++;
@@ -680,52 +950,85 @@ namespace UVtools.Core.FileFormats
}
GCode.AppendLine();
- GCode.AppendFormat(GCodeStart, Environment.NewLine);
+
+ GCode.AppendFormat(Printer == PrinterType.Wanhao ? WanhaoStartGCode : GCodeStart, Environment.NewLine);
float lastZPosition = 0;
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
{
Layer layer = this[layerIndex];
+
+ if (Printer == PrinterType.Wanhao)
+ {
+ GCode.AppendFormat(WanhaoPreSliceGCode, Environment.NewLine, layerIndex, OutputSettings.SettleTime);
+ }
+
GCode.AppendLine($"{GCodeKeywordSlice} {layerIndex}");
if (layer.ExposureTime > 0 && layer.LightPWM > 0)
{
- GCode.AppendLine($"M106 S{layer.LightPWM}");
+ GCode.AppendLine($"M106 S{layer.LightPWM} ; UV on");
GCode.AppendLine($"{GCodeKeywordDelay} {layer.ExposureTime * 1000}");
- GCode.AppendLine("M106 S0");
+ GCode.AppendLine("M106 S0 ; UV off");
}
GCode.AppendLine(GCodeKeywordSliceBlank);
+ if (Printer == PrinterType.Wanhao)
+ {
+ GCode.AppendLine($"{GCodeKeywordDelay} 0");
+ }
+
if (lastZPosition != layer.PositionZ)
{
if (layer.LiftHeight > 0)
{
+ float downPos = (float) Math.Round(layer.LiftHeight - layer.PositionZ + lastZPosition, 2);
+ if (Printer == PrinterType.Wanhao)
+ {
+ GCode.AppendLine($";********** Lift Sequence {layerIndex} ********");
+ }
GCode.AppendLine($"G1 Z{layer.LiftHeight} F{layer.LiftSpeed}");
- GCode.AppendLine($"G1 Z-{Math.Round(layer.LiftHeight - layer.PositionZ + lastZPosition, 2)} F{layer.RetractSpeed}");
+ if (Printer == PrinterType.Wanhao)
+ {
+ GCode.AppendLine($"{GCodeKeywordTakes} {OperationCalculator.LightOffDelayC.CalculateMillisecondsLiftOnly(layer.LiftHeight, layer.LiftSpeed)}");
+ GCode.AppendLine($"G4 P0 ; Wait for lift rise to complete");
+ GCode.AppendLine($"{GCodeKeywordDelay} 0");
+ }
+ GCode.AppendLine($"G1 Z-{downPos} F{layer.RetractSpeed}");
+ if (Printer == PrinterType.Wanhao)
+ {
+ GCode.AppendLine($"{GCodeKeywordTakes} {OperationCalculator.LightOffDelayC.CalculateMillisecondsLiftOnly(downPos, layer.RetractSpeed)}");
+ }
}
else
{
GCode.AppendLine($"G1 Z{Math.Round(layer.PositionZ - lastZPosition, 2)} F{layer.LiftSpeed}");
}
}
- // delay = max(extra['wait'], 500) + int(((int(lift)/(extra['lift_feed']/60)) + (int(lift)/(extra['lift_retract']/60)))*1000)
- uint extraDelay = OperationCalculator.LightOffDelayC.CalculateMilliseconds(layer.LiftHeight, layer.LiftSpeed, layer.RetractSpeed);
- if (layerIndex < BottomLayerCount)
- {
- extraDelay = (uint)Math.Max(extraDelay + 10000, layer.ExposureTime * 1000);
- }
- else
+
+ if (Printer != PrinterType.Wanhao)
{
- extraDelay += Math.Max(OutputSettings.BlankingLayerTime, 500);
- }
+ // delay = max(extra['wait'], 500) + int(((int(lift)/(extra['lift_feed']/60)) + (int(lift)/(extra['lift_retract']/60)))*1000)
+ uint extraDelay =
+ OperationCalculator.LightOffDelayC.CalculateMilliseconds(layer.LiftHeight, layer.LiftSpeed,
+ layer.RetractSpeed);
+ if (layerIndex < BottomLayerCount)
+ {
+ extraDelay = (uint) Math.Max(extraDelay + 10000, layer.ExposureTime * 1000);
+ }
+ else
+ {
+ extraDelay += Math.Max(OutputSettings.BlankingLayerTime, 500);
+ }
- GCode.AppendLine($"{GCodeKeywordDelay} {extraDelay}");
- GCode.AppendLine();
+ GCode.AppendLine($"{GCodeKeywordDelay} {extraDelay}");
+ GCode.AppendLine();
+ }
lastZPosition = layer.PositionZ;
}
- GCode.AppendFormat(GCodeEnd, Environment.NewLine, SliceSettings.LiftWhenFinished);
+ GCode.AppendFormat(Printer == PrinterType.Wanhao ? WanhaoGCodeEnd : GCodeEnd, Environment.NewLine, SliceSettings.LiftWhenFinished);
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
diff --git a/UVtools.Core/FileFormats/ChituboxFile.cs b/UVtools.Core/FileFormats/ChituboxFile.cs
index 4c12e2d..6dea713 100644
--- a/UVtools.Core/FileFormats/ChituboxFile.cs
+++ b/UVtools.Core/FileFormats/ChituboxFile.cs
@@ -1958,8 +1958,8 @@ namespace UVtools.Core.FileFormats
file.SliceSettings.Xppm = file.OutputSettings.PixPermmX = (float)Math.Round(ResolutionX / HeaderSettings.BedSizeX, 3);
file.SliceSettings.Yppm = file.OutputSettings.PixPermmY = (float)Math.Round(ResolutionY / HeaderSettings.BedSizeY, 3);
- file.SliceSettings.Xres = file.OutputSettings.XResolution = (ushort)ResolutionX;
- file.SliceSettings.Yres = file.OutputSettings.YResolution = (ushort)ResolutionY;
+ file.ResolutionX = (ushort)ResolutionX;
+ file.ResolutionY = (ushort)ResolutionY;
file.SliceSettings.Thickness = file.OutputSettings.LayerThickness = LayerHeight;
file.SliceSettings.LayersNum = file.OutputSettings.LayersNum = LayerCount;
file.SliceSettings.HeadLayersNum = file.OutputSettings.NumberBottomLayers = BottomLayerCount;
@@ -1985,9 +1985,9 @@ namespace UVtools.Core.FileFormats
file.OutputSettings.AntiAliasingValue = ValidateAntiAliasingLevel();
file.OutputSettings.AntiAliasing = file.OutputSettings.AntiAliasingValue > 1;
- file.Printer = MachineName.Contains("Bene4 Mono") ||
+ /*file.Printer = MachineName.Contains("Bene4 Mono") ||
FileFullPath.Contains("bene4_mono")
- ? CWSFile.PrinterType.BeneMono : CWSFile.PrinterType.Elfin;
+ ? CWSFile.PrinterType.BeneMono : CWSFile.PrinterType.Unknown;*/
file.Encode(fileFullPath, progress);
diff --git a/UVtools.Core/FileFormats/ChituboxZipFile.cs b/UVtools.Core/FileFormats/ChituboxZipFile.cs
index 39f9109..7fcaf1c 100644
--- a/UVtools.Core/FileFormats/ChituboxZipFile.cs
+++ b/UVtools.Core/FileFormats/ChituboxZipFile.cs
@@ -954,8 +954,8 @@ namespace UVtools.Core.FileFormats
file.SliceSettings.Xppm = file.OutputSettings.PixPermmX = (float)Math.Round(ResolutionX / HeaderSettings.MachineX, 3);
file.SliceSettings.Yppm = file.OutputSettings.PixPermmY = (float)Math.Round(ResolutionY / HeaderSettings.MachineY, 3);
- file.SliceSettings.Xres = file.OutputSettings.XResolution = (ushort)ResolutionX;
- file.SliceSettings.Yres = file.OutputSettings.YResolution = (ushort)ResolutionY;
+ file.ResolutionX = (ushort)ResolutionX;
+ file.ResolutionY = (ushort)ResolutionY;
file.SliceSettings.Thickness = file.OutputSettings.LayerThickness = LayerHeight;
file.SliceSettings.LayersNum = file.OutputSettings.LayersNum = LayerCount;
file.SliceSettings.HeadLayersNum = file.OutputSettings.NumberBottomLayers = BottomLayerCount;
@@ -981,9 +981,9 @@ namespace UVtools.Core.FileFormats
file.OutputSettings.AntiAliasingValue = ValidateAntiAliasingLevel();
file.OutputSettings.AntiAliasing = file.OutputSettings.AntiAliasingValue > 1;
- file.Printer = MachineName.Contains("Bene4 Mono") ||
+ /*file.Printer = MachineName.Contains("Bene4 Mono") ||
FileFullPath.Contains("bene4_mono")
- ? CWSFile.PrinterType.BeneMono : CWSFile.PrinterType.Elfin;
+ ? CWSFile.PrinterType.BeneMono : CWSFile.PrinterType.Elfin;*/
file.Encode(fileFullPath, progress);
diff --git a/UVtools.Core/FileFormats/PHZFile.cs b/UVtools.Core/FileFormats/PHZFile.cs
index b5f8c66..51bccb2 100644
--- a/UVtools.Core/FileFormats/PHZFile.cs
+++ b/UVtools.Core/FileFormats/PHZFile.cs
@@ -1481,8 +1481,8 @@ namespace UVtools.Core.FileFormats
file.SliceSettings.Xppm = file.OutputSettings.PixPermmX = (float)Math.Round(ResolutionX / HeaderSettings.BedSizeX, 3);
file.SliceSettings.Yppm = file.OutputSettings.PixPermmY = (float)Math.Round(ResolutionY / HeaderSettings.BedSizeY, 3);
- file.SliceSettings.Xres = file.OutputSettings.XResolution = (ushort)ResolutionX;
- file.SliceSettings.Yres = file.OutputSettings.YResolution = (ushort)ResolutionY;
+ file.ResolutionX = (ushort)ResolutionX;
+ file.ResolutionY = (ushort)ResolutionY;
file.SliceSettings.Thickness = file.OutputSettings.LayerThickness = LayerHeight;
file.SliceSettings.LayersNum = file.OutputSettings.LayersNum = LayerCount;
file.SliceSettings.HeadLayersNum = file.OutputSettings.NumberBottomLayers = BottomLayerCount;
@@ -1508,9 +1508,9 @@ namespace UVtools.Core.FileFormats
file.OutputSettings.AntiAliasingValue = ValidateAntiAliasingLevel();
file.OutputSettings.AntiAliasing = file.OutputSettings.AntiAliasingValue > 1;
- file.Printer = MachineName.Contains("Bene4 Mono") ||
+ /*file.Printer = MachineName.Contains("Bene4 Mono") ||
FileFullPath.Contains("bene4_mono")
- ? CWSFile.PrinterType.BeneMono : CWSFile.PrinterType.Elfin;
+ ? CWSFile.PrinterType.BeneMono : CWSFile.PrinterType.Elfin;*/
file.Encode(fileFullPath, progress);
diff --git a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs
index 5824dcb..617c92f 100644
--- a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs
+++ b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs
@@ -555,7 +555,7 @@ namespace UVtools.Core.FileFormats
for (int index = 0; index < EncodedRle.Length; index++)
{
byte b = EncodedRle[index];
- int code = (b >> 4);
+ int code = b >> 4;
uint reps = (uint) (b & 0xf);
byte color;
switch (code)
@@ -602,7 +602,7 @@ namespace UVtools.Core.FileFormats
}
}
- if (n != imageLength)
+ if (n > 0 && n != imageLength)
{
image.Dispose();
throw new FileLoadException($"Error image ended short: {n} of {imageLength}");
@@ -1413,8 +1413,8 @@ namespace UVtools.Core.FileFormats
//file.SliceSettings.Xppm = file.OutputSettings.PixPermmX = defaultFormat.OutputSettings.
//file.SliceSettings.Yppm = file.OutputSettings.PixPermmY = (float)Math.Round(ResolutionY / HeaderSettings.BedSizeY, 3);
- file.SliceSettings.Xres = file.OutputSettings.XResolution = (ushort)ResolutionX;
- file.SliceSettings.Yres = file.OutputSettings.YResolution = (ushort)ResolutionY;
+ file.ResolutionX = (ushort)ResolutionX;
+ file.ResolutionY = (ushort)ResolutionY;
file.SliceSettings.Thickness = file.OutputSettings.LayerThickness = LayerHeight;
file.SliceSettings.LayersNum = file.OutputSettings.LayersNum = LayerCount;
file.SliceSettings.HeadLayersNum = file.OutputSettings.NumberBottomLayers = BottomLayerCount;
@@ -1440,9 +1440,9 @@ namespace UVtools.Core.FileFormats
file.OutputSettings.AntiAliasingValue = ValidateAntiAliasingLevel();
file.OutputSettings.AntiAliasing = file.OutputSettings.AntiAliasingValue > 1;
- file.Printer = MachineName.Contains("Bene4 Mono") ||
+ /*file.Printer = MachineName.Contains("Bene4 Mono") ||
FileFullPath.Contains("bene4_mono")
- ? CWSFile.PrinterType.BeneMono : CWSFile.PrinterType.Elfin;
+ ? CWSFile.PrinterType.BeneMono : CWSFile.PrinterType.Elfin;*/
file.Encode(fileFullPath, progress);
diff --git a/UVtools.Core/FileFormats/SL1File.cs b/UVtools.Core/FileFormats/SL1File.cs
index 4c7a8d4..72a2672 100644
--- a/UVtools.Core/FileFormats/SL1File.cs
+++ b/UVtools.Core/FileFormats/SL1File.cs
@@ -1054,8 +1054,8 @@ namespace UVtools.Core.FileFormats
file.SliceSettings.Xppm = file.OutputSettings.PixPermmX = (float) Math.Round(LookupCustomValue<float>("Xppm", defaultFormat.SliceSettings.Xppm), 3);
file.SliceSettings.Yppm = file.OutputSettings.PixPermmY = (float) Math.Round(LookupCustomValue<float>("Yppm", defaultFormat.SliceSettings.Xppm), 3);
- file.SliceSettings.Xres = file.OutputSettings.XResolution = (ushort)ResolutionX;
- file.SliceSettings.Yres = file.OutputSettings.YResolution = (ushort)ResolutionY;
+ file.ResolutionX = (ushort)ResolutionX;
+ file.ResolutionY = (ushort)ResolutionY;
file.OutputSettings.PlatformXSize = PrinterSettings.DisplayWidth;
file.OutputSettings.PlatformYSize = PrinterSettings.DisplayHeight;
file.OutputSettings.PlatformZSize = PrinterSettings.MaxPrintHeight;
@@ -1096,7 +1096,7 @@ namespace UVtools.Core.FileFormats
file.Printer = LookupCustomValue<bool>("NOVAMAKER_GRAY2RGB_ENCODE", false, true) ||
MachineName.Contains("Bene4 Mono") ||
FileFullPath.Contains("bene4_mono")
- ? CWSFile.PrinterType.BeneMono : CWSFile.PrinterType.Elfin;
+ ? CWSFile.PrinterType.BeneMono : CWSFile.PrinterType.Unknown;
file.Encode(fileFullPath, progress);
diff --git a/UVtools.Core/FileFormats/UVJFile.cs b/UVtools.Core/FileFormats/UVJFile.cs
index c2f8f7f..c401235 100644
--- a/UVtools.Core/FileFormats/UVJFile.cs
+++ b/UVtools.Core/FileFormats/UVJFile.cs
@@ -798,8 +798,8 @@ namespace UVtools.Core.FileFormats
file.SliceSettings.Xppm = file.OutputSettings.PixPermmX = (float)Math.Round(ResolutionX / DisplayWidth, 3);
file.SliceSettings.Yppm = file.OutputSettings.PixPermmY = (float)Math.Round(ResolutionY / DisplayHeight, 3);
- file.SliceSettings.Xres = file.OutputSettings.XResolution = (ushort)ResolutionX;
- file.SliceSettings.Yres = file.OutputSettings.YResolution = (ushort)ResolutionY;
+ file.ResolutionX = (ushort)ResolutionX;
+ file.ResolutionY = (ushort)ResolutionY;
file.SliceSettings.Thickness = file.OutputSettings.LayerThickness = LayerHeight;
file.SliceSettings.LayersNum = file.OutputSettings.LayersNum = LayerCount;
file.SliceSettings.HeadLayersNum = file.OutputSettings.NumberBottomLayers = BottomLayerCount;
@@ -825,9 +825,9 @@ namespace UVtools.Core.FileFormats
file.OutputSettings.AntiAliasingValue = ValidateAntiAliasingLevel();
file.OutputSettings.AntiAliasing = file.OutputSettings.AntiAliasingValue > 1;
- file.Printer = MachineName.Contains("Bene4 Mono") ||
+ /*file.Printer = MachineName.Contains("Bene4 Mono") ||
FileFullPath.Contains("bene4_mono")
- ? CWSFile.PrinterType.BeneMono : CWSFile.PrinterType.Elfin;
+ ? CWSFile.PrinterType.BeneMono : CWSFile.PrinterType.Elfin;*/
file.Encode(fileFullPath, progress);
diff --git a/UVtools.Core/Layer/Layer.cs b/UVtools.Core/Layer/Layer.cs
index ae08f8b..ff55f16 100644
--- a/UVtools.Core/Layer/Layer.cs
+++ b/UVtools.Core/Layer/Layer.cs
@@ -162,7 +162,7 @@ namespace UVtools.Core
/// <summary>
/// Gets a computed layer filename, padding zeros are equal to layer count digits
/// </summary>
- public string Filename => $"layer{Index.ToString().PadLeft(ParentLayerManager.LayerDigits, '0')}.png";
+ public string Filename => FormatFileName("layer");
/// <summary>
/// Gets if layer has been modified
@@ -332,6 +332,11 @@ namespace UVtools.Core
#region Methods
+ public string FormatFileName(string name)
+ {
+ return $"{name}{Index.ToString().PadLeft(ParentLayerManager.LayerDigits, '0')}.png";
+ }
+
public Rectangle GetBoundingRectangle(Mat mat = null, bool reCalculate = false)
{
if (NonZeroPixelCount > 0 && !reCalculate)
@@ -1251,8 +1256,5 @@ namespace UVtools.Core
}
#endregion
-
-
-
}
}
diff --git a/UVtools.Core/Operations/OperationCalculator.cs b/UVtools.Core/Operations/OperationCalculator.cs
index b88274c..f5a086e 100644
--- a/UVtools.Core/Operations/OperationCalculator.cs
+++ b/UVtools.Core/Operations/OperationCalculator.cs
@@ -274,7 +274,26 @@ namespace UVtools.Core.Operations
}
public static uint CalculateMilliseconds(float liftHeight, float liftSpeed, float retract, float extraWaitTime = 0) =>
- (uint) (CalculateSeconds(liftHeight, liftSpeed, retract, extraWaitTime) * 1000);
+ (uint)(CalculateSeconds(liftHeight, liftSpeed, retract, extraWaitTime) * 1000);
+
+
+ public static float CalculateSecondsLiftOnly(float liftHeight, float liftSpeed, float extraWaitTime = 0)
+ {
+ try
+ {
+ return (float)Math.Round(liftHeight / (liftSpeed / 60f) + extraWaitTime, 2);
+ }
+ catch (Exception)
+ {
+ return 0;
+ }
+
+ }
+
+ public static uint CalculateMillisecondsLiftOnly(float liftHeight, float liftSpeed, float extraWaitTime = 0) =>
+ (uint)(CalculateSecondsLiftOnly(liftHeight, liftSpeed, extraWaitTime) * 1000);
+
+
}
}
}
diff --git a/UVtools.Core/Operations/OperationFlip.cs b/UVtools.Core/Operations/OperationFlip.cs
index aeadc67..7a63814 100644
--- a/UVtools.Core/Operations/OperationFlip.cs
+++ b/UVtools.Core/Operations/OperationFlip.cs
@@ -19,7 +19,8 @@ namespace UVtools.Core.Operations
public override string Title => "Flip";
public override string Description =>
- "Flip the layers of the model vertically and/or horizontally.";
+ "Flip the layers of the model vertically and/or horizontally.\n" +
+ "Note: Before perform this operation, un-rotate the layer preview to see the real orientation.";
public override string ConfirmationText =>
FlipDirection == Enumerations.FlipDirection.Both
diff --git a/UVtools.Core/Operations/OperationMove.cs b/UVtools.Core/Operations/OperationMove.cs
index 64956bd..24337a5 100644
--- a/UVtools.Core/Operations/OperationMove.cs
+++ b/UVtools.Core/Operations/OperationMove.cs
@@ -18,7 +18,8 @@ namespace UVtools.Core.Operations
{
public override string Title => "Move";
public override string Description =>
- "Change or copy the position of the model on the build plate.";
+ "Change or copy the position of the model on the build plate.\n" +
+ "Note: Before perform this operation, un-rotate the layer preview to see the real orientation.";
public override string ConfirmationText =>
(IsCutMove ? "move" : "copy") + $" model layers {LayerIndexStart} through {LayerIndexEnd} from " +
diff --git a/UVtools.Core/Operations/OperationPattern.cs b/UVtools.Core/Operations/OperationPattern.cs
index fcf8f4e..592aa18 100644
--- a/UVtools.Core/Operations/OperationPattern.cs
+++ b/UVtools.Core/Operations/OperationPattern.cs
@@ -31,7 +31,8 @@ namespace UVtools.Core.Operations
public override string Title => "Pattern";
public override string Description =>
- "Duplicates the model in a rectangular pattern around the build plate.";
+ "Duplicates the model in a rectangular pattern around the build plate.\n" +
+ "Note: Before perform this operation, un-rotate the layer preview to see the real orientation.";
public override string ConfirmationText =>
$"pattern the object across {Cols} columns and {Rows} rows?";
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index a0a27d9..954676b 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, repair, conversion and manipulation</Description>
- <Version>1.3.1</Version>
+ <Version>1.3.2</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
diff --git a/UVtools.Installer/Code/Product.wxs b/UVtools.Installer/Code/Product.wxs
index 314a9f0..1dcdb80 100644
--- a/UVtools.Installer/Code/Product.wxs
+++ b/UVtools.Installer/Code/Product.wxs
@@ -13,9 +13,9 @@
<Package InstallerVersion="301" Compressed="yes" InstallScope="perMachine" />
<MediaTemplate EmbedCab="yes" />
<!-- Major Upgrade Rule to disallow downgrades -->
+ <!-- AllowSameVersionUpgrades="yes" -->
<MajorUpgrade
AllowDowngrades="no"
- AllowSameVersionUpgrades="yes"
IgnoreRemoveFailure="no"
DowngradeErrorMessage="A newer version of [ProductName] is already installed."
Schedule="afterInstallInitialize" />
diff --git a/UVtools.WPF/App.axaml.cs b/UVtools.WPF/App.axaml.cs
index d628c8c..064c8ce 100644
--- a/UVtools.WPF/App.axaml.cs
+++ b/UVtools.WPF/App.axaml.cs
@@ -24,7 +24,6 @@ using Avalonia.ThemeManager;
using Emgu.CV;
using UVtools.Core;
using UVtools.Core.FileFormats;
-using UVtools.Core.Operations;
using UVtools.WPF.Extensions;
using UVtools.WPF.Structures;
diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs
index 75edcb7..6cde099 100644
--- a/UVtools.WPF/MainWindow.axaml.cs
+++ b/UVtools.WPF/MainWindow.axaml.cs
@@ -720,7 +720,7 @@ namespace UVtools.WPF
{
var result =
await this.MessageBoxQuestion(
- $"Do you like to auto-update {About.Software} v{App.Version} to v{VersionChecker.Version}?\n" +
+ $"Do you like to auto-update {About.Software} v{App.VersionStr} to v{VersionChecker.Version}?\n" +
"Yes: Auto update\n" +
"No: Manual update\n" +
"Cancel: No action\n\n" +
diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj
index 310e6fe..2b64aba 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>1.3.1</Version>
+ <Version>1.3.2</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">