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

github.com/sn4k3/UVtools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiago Conceição <Tiago_caza@hotmail.com>2021-07-03 03:16:17 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2021-07-03 03:16:17 +0300
commitac51b7c4e017f4e5abea87ad4def061584bc77f4 (patch)
tree8586e3cb34c97426e2824f07f6553c9738441fbd
parent2329074efb137136db3597c95c040b3a8afdeeab (diff)
v2.14.0v2.14.0
- **File Formats:** - (Add) SL1S: Prusa SL1S Speed - (Add) CTB v4 support (318570758) - (Improvement) PHOTON, CBDDLP, CTB v2, PHZ: Disallow per layer settings, beside the format support, printers never use it - (Improvement) Longer Orange format with new found keys - (Improvement) CXDLP: Fix the resolution from CL-60 and trigger an error when a invalid resolution was set and unable to detect the printer model - **Prusa Slicer:** - (Add) UVtools Prusa SL1S SPEED - (Add) Longer Orange 120 - (Fix) Creality HALOT-ONE CL-60: Flip resolution & display and remove mirror - (Fix) Creality HALOT-SKY CL-89: Remove mirror - (Improvement) Longer Orange printers with better default settings - (Add) Button on `Help - Sponsor`: Open github sponsor webpage
-rw-r--r--CHANGELOG.md16
-rw-r--r--PrusaSlicer/printer/Creality HALOT-ONE CL-60.ini14
-rw-r--r--PrusaSlicer/printer/Creality HALOT-SKY CL-89.ini4
-rw-r--r--PrusaSlicer/printer/Longer Orange 10.ini4
-rw-r--r--PrusaSlicer/printer/Longer Orange 120.ini38
-rw-r--r--PrusaSlicer/printer/Longer Orange 30.ini4
-rw-r--r--PrusaSlicer/printer/Longer Orange 4K.ini (renamed from PrusaSlicer/printer/Longer Orange4K.ini)6
-rw-r--r--PrusaSlicer/printer/UVtools Prusa SL1S SPEED.ini38
-rw-r--r--README.md13
-rw-r--r--Scripts/ImportPrusaSlicerData.bat120
-rw-r--r--Scripts/ctb.bt212
-rw-r--r--Scripts/lgs.bt2
-rw-r--r--UVtools.Core/About.cs1
-rw-r--r--UVtools.Core/EmguCV/Contour.cs240
-rw-r--r--UVtools.Core/Extensions/FileStreamExtensions.cs20
-rw-r--r--UVtools.Core/FileFormats/CWSFile.cs2
-rw-r--r--UVtools.Core/FileFormats/CXDLPFile.cs6
-rw-r--r--UVtools.Core/FileFormats/ChituboxFile.cs224
-rw-r--r--UVtools.Core/FileFormats/FileFormat.cs36
-rw-r--r--UVtools.Core/FileFormats/LGSFile.cs155
-rw-r--r--UVtools.Core/FileFormats/PHZFile.cs4
-rw-r--r--UVtools.Core/FileFormats/PhotonWorkshopFile.cs14
-rw-r--r--UVtools.Core/FileFormats/SL1File.cs4
-rw-r--r--UVtools.Core/Operations/OperationCalibrateExposureFinder.cs2
-rw-r--r--UVtools.Core/UVtools.Core.csproj2
-rw-r--r--UVtools.InstallerMM/UVtools.InstallerMM.wxs10
-rw-r--r--UVtools.WPF/Assets/Icons/heart-16x16.pngbin0 -> 189 bytes
-rw-r--r--UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml3
-rw-r--r--UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs2
-rw-r--r--UVtools.WPF/Controls/Tools/ToolDynamicLayerHeightControl.axaml.cs2
-rw-r--r--UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml.cs4
-rw-r--r--UVtools.WPF/MainWindow.axaml10
-rw-r--r--UVtools.WPF/UVtools.WPF.csproj2
33 files changed, 1008 insertions, 206 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 83b2cd3..a1a84c4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,21 @@
# Changelog
+## 03/06/2021 - v2.14.0
+
+- **File Formats:**
+ - (Add) SL1S: Prusa SL1S Speed
+ - (Add) CTB v4 support (318570758)
+ - (Improvement) PHOTON, CBDDLP, CTB v2, PHZ: Disallow per layer settings, beside the format support, printers never use it
+ - (Improvement) Longer Orange format with new found keys
+ - (Improvement) CXDLP: Fix the resolution from CL-60 and trigger an error when a invalid resolution was set and unable to detect the printer model
+- **Prusa Slicer:**
+ - (Add) UVtools Prusa SL1S SPEED
+ - (Add) Longer Orange 120
+ - (Fix) Creality HALOT-ONE CL-60: Flip resolution & display and remove mirror
+ - (Fix) Creality HALOT-SKY CL-89: Remove mirror
+ - (Improvement) Longer Orange printers with better default settings
+- (Add) Button on `Help - Sponsor`: Open github sponsor webpage
+
## 25/06/2021 - v2.13.4
- (Fix) ZCode: lcd.gcode was blank / not generating when converting from any file format
diff --git a/PrusaSlicer/printer/Creality HALOT-ONE CL-60.ini b/PrusaSlicer/printer/Creality HALOT-ONE CL-60.ini
index 7e49667..b653457 100644
--- a/PrusaSlicer/printer/Creality HALOT-ONE CL-60.ini
+++ b/PrusaSlicer/printer/Creality HALOT-ONE CL-60.ini
@@ -1,18 +1,18 @@
-# generated by PrusaSlicer 2.3.1+win64 on 2021-06-08 at 21:10:32 UTC
+# generated by PrusaSlicer 2.3.1+win64 on 2021-07-02 at 17:30:53 UTC
absolute_correction = 0
area_fill = 50
bed_custom_model =
bed_custom_texture =
-bed_shape = 0x0,130x0,130x82,0x82
+bed_shape = 0x0,81x0,81x128,0x128
default_sla_material_profile = Prusa Orange Tough 0.05
default_sla_print_profile = 0.05 Normal
-display_height = 82
-display_mirror_x = 1
+display_height = 128
+display_mirror_x = 0
display_mirror_y = 0
display_orientation = landscape
-display_pixels_x = 2560
-display_pixels_y = 1620
-display_width = 130
+display_pixels_x = 1620
+display_pixels_y = 2560
+display_width = 81
elefant_foot_compensation = 0.2
elefant_foot_min_width = 0.2
fast_tilt_time = 5
diff --git a/PrusaSlicer/printer/Creality HALOT-SKY CL-89.ini b/PrusaSlicer/printer/Creality HALOT-SKY CL-89.ini
index 353849b..2603ce7 100644
--- a/PrusaSlicer/printer/Creality HALOT-SKY CL-89.ini
+++ b/PrusaSlicer/printer/Creality HALOT-SKY CL-89.ini
@@ -1,4 +1,4 @@
-# generated by PrusaSlicer 2.3.0+win64 on 2021-04-14 at 04:53:05 UTC
+# generated by PrusaSlicer 2.3.1+win64 on 2021-07-02 at 17:32:15 UTC
absolute_correction = 0
area_fill = 50
bed_custom_model =
@@ -7,7 +7,7 @@ bed_shape = 0x0,192x0,192x120,0x120
default_sla_material_profile = Prusa Orange Tough 0.05
default_sla_print_profile = 0.05 Normal
display_height = 120
-display_mirror_x = 1
+display_mirror_x = 0
display_mirror_y = 0
display_orientation = landscape
display_pixels_x = 3840
diff --git a/PrusaSlicer/printer/Longer Orange 10.ini b/PrusaSlicer/printer/Longer Orange 10.ini
index 9c20964..43954f7 100644
--- a/PrusaSlicer/printer/Longer Orange 10.ini
+++ b/PrusaSlicer/printer/Longer Orange 10.ini
@@ -1,4 +1,4 @@
-# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 02:36:09 UTC
+# generated by PrusaSlicer 2.3.1+win64 on 2021-06-26 at 12:15:10 UTC
absolute_correction = 0
area_fill = 50
bed_custom_model =
@@ -26,7 +26,7 @@ min_exposure_time = 1
min_initial_exposure_time = 1
print_host =
printer_model = SL1
-printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_LONGER\nPRINTER_MODEL_ORANGE10\nFILEFORMAT_LGS\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_4\nLiftHeight_2\nBottomLiftSpeed_90\nLiftSpeed_150\nEND_CUSTOM_VALUES
+printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_LONGER\nPRINTER_MODEL_ORANGE10\nFILEFORMAT_LGS\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_4\nLiftHeight_4\nBottomLiftSpeed_90\nLiftSpeed_150\nEND_CUSTOM_VALUES
printer_settings_id =
printer_technology = SLA
printer_variant = default
diff --git a/PrusaSlicer/printer/Longer Orange 120.ini b/PrusaSlicer/printer/Longer Orange 120.ini
new file mode 100644
index 0000000..b29b1f7
--- /dev/null
+++ b/PrusaSlicer/printer/Longer Orange 120.ini
@@ -0,0 +1,38 @@
+# generated by PrusaSlicer 2.3.1+win64 on 2021-06-26 at 11:55:17 UTC
+absolute_correction = 0
+area_fill = 50
+bed_custom_model =
+bed_custom_texture =
+bed_shape = 0x0,68.04x0,68.04x120.96,0x120.96
+default_sla_material_profile = Prusa Orange Tough 0.05
+default_sla_print_profile = 0.05 Normal
+display_height = 120.96
+display_mirror_x = 1
+display_mirror_y = 0
+display_orientation = landscape
+display_pixels_x = 1440
+display_pixels_y = 2560
+display_width = 68.04
+elefant_foot_compensation = 0.2
+elefant_foot_min_width = 0.2
+fast_tilt_time = 5
+gamma_correction = 1
+host_type = octoprint
+inherits = Original Prusa SL1
+max_exposure_time = 120
+max_initial_exposure_time = 300
+max_print_height = 150
+min_exposure_time = 1
+min_initial_exposure_time = 1
+print_host =
+printer_model = SL1
+printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_LONGER\nPRINTER_MODEL_ORANGE120\nFILEFORMAT_LGS120\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_4\nLiftHeight_4\nBottomLiftSpeed_90\nLiftSpeed_150\nEND_CUSTOM_VALUES
+printer_settings_id =
+printer_technology = SLA
+printer_variant = default
+printer_vendor =
+printhost_apikey =
+printhost_cafile =
+relative_correction = 1,1
+slow_tilt_time = 8
+thumbnails = 400x400,800x480
diff --git a/PrusaSlicer/printer/Longer Orange 30.ini b/PrusaSlicer/printer/Longer Orange 30.ini
index 7a32e4b..cc91c42 100644
--- a/PrusaSlicer/printer/Longer Orange 30.ini
+++ b/PrusaSlicer/printer/Longer Orange 30.ini
@@ -1,4 +1,4 @@
-# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 03:51:46 UTC
+# generated by PrusaSlicer 2.3.1+win64 on 2021-06-26 at 11:58:44 UTC
absolute_correction = 0
area_fill = 50
bed_custom_model =
@@ -26,7 +26,7 @@ min_exposure_time = 1
min_initial_exposure_time = 1
print_host =
printer_model = SL1
-printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_LONGER\nPRINTER_MODEL_ORANGE30\nFILEFORMAT_LGS30\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_2\nLiftHeight_2\nBottomLiftSpeed_48\nLiftSpeed_150\nEND_CUSTOM_VALUES
+printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_LONGER\nPRINTER_MODEL_ORANGE30\nFILEFORMAT_LGS30\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_4\nLiftHeight_4\nBottomLiftSpeed_90\nLiftSpeed_150\nEND_CUSTOM_VALUES
printer_settings_id =
printer_technology = SLA
printer_variant = default
diff --git a/PrusaSlicer/printer/Longer Orange4K.ini b/PrusaSlicer/printer/Longer Orange 4K.ini
index b02931f..b41bded 100644
--- a/PrusaSlicer/printer/Longer Orange4K.ini
+++ b/PrusaSlicer/printer/Longer Orange 4K.ini
@@ -1,4 +1,4 @@
-# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 02:35:56 UTC
+# generated by PrusaSlicer 2.3.1+win64 on 2021-06-28 at 08:59:40 UTC
absolute_correction = 0
area_fill = 50
bed_custom_model =
@@ -21,12 +21,12 @@ host_type = octoprint
inherits = Original Prusa SL1
max_exposure_time = 120
max_initial_exposure_time = 300
-max_print_height = 170
+max_print_height = 190
min_exposure_time = 1
min_initial_exposure_time = 1
print_host =
printer_model = SL1
-printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_LONGER\nPRINTER_MODEL_ORANGE30\nFILEFORMAT_LGS\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_2\nLiftHeight_2\nBottomLiftSpeed_90\nLiftSpeed_150\nEND_CUSTOM_VALUES
+printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_LONGER\nPRINTER_MODEL_ORANGE4K\nFILEFORMAT_LGS4K\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_4\nLiftHeight_4\nBottomLiftSpeed_90\nLiftSpeed_150\nEND_CUSTOM_VALUES
printer_settings_id =
printer_technology = SLA
printer_variant = default
diff --git a/PrusaSlicer/printer/UVtools Prusa SL1S SPEED.ini b/PrusaSlicer/printer/UVtools Prusa SL1S SPEED.ini
new file mode 100644
index 0000000..8589fd6
--- /dev/null
+++ b/PrusaSlicer/printer/UVtools Prusa SL1S SPEED.ini
@@ -0,0 +1,38 @@
+# generated by PrusaSlicer 2.3.1+win64 on 2021-07-02 at 10:34:03 UTC
+absolute_correction = 0
+area_fill = 45
+bed_custom_model =
+bed_custom_texture =
+bed_shape = 0.5x0.5,127.5x0.5,127.5x80.5,0.5x80.5
+default_sla_material_profile = Prusa Orange Tough @0.05 SL1S
+default_sla_print_profile = 0.05 Normal @SL1S
+display_height = 81
+display_mirror_x = 1
+display_mirror_y = 0
+display_orientation = landscape
+display_pixels_x = 1620
+display_pixels_y = 2560
+display_width = 128
+elefant_foot_compensation = 0.2
+elefant_foot_min_width = 0.2
+fast_tilt_time = 2.5
+gamma_correction = 1
+host_type = octoprint
+inherits = Original Prusa SL1S SPEED
+max_exposure_time = 120
+max_initial_exposure_time = 300
+max_print_height = 150
+min_exposure_time = 1
+min_initial_exposure_time = 1
+print_host =
+printer_model = SL1S
+printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1S\n
+printer_settings_id =
+printer_technology = SLA
+printer_variant = default
+printer_vendor =
+printhost_apikey =
+printhost_cafile =
+relative_correction = 1,1
+slow_tilt_time = 5
+thumbnails = 400x400,800x480
diff --git a/README.md b/README.md
index 6a70b96..c3eeeee 100644
--- a/README.md
+++ b/README.md
@@ -55,6 +55,7 @@ But also, i need victims for test subject. Proceed at your own risk!
# Known File Formats
* SL1 (PrusaSlicer)
+* SL1S (PrusaSlicer)
* Zip (Chitubox)
* Photon (Chitubox)
* Photons (Chitubox)
@@ -78,6 +79,8 @@ But also, i need victims for test subject. Proceed at your own risk!
* CXDLP (Creality Box)
* LGS (Longer Orange 10)
* LGS30 (Longer Orange 30)
+* LGS120 (Longer Orange 120)
+* LGS4K (Longer Orange 4K & mono)
* VDA.ZIP (Voxeldance Additive)
* VDT (Voxeldance Tango)
* UVJ (Zip file format for manual manipulation)
@@ -139,8 +142,8 @@ But also, i need victims for test subject. Proceed at your own risk!
* LD-002R
* LD-002H
* LD-006
+ * HALOT-ONE CL-60
* HALOT-SKY CL-89
- * HALOT-SKY CL-60
* **Voxelab**
* Polaris 5.5
* Proxima 6
@@ -148,7 +151,8 @@ But also, i need victims for test subject. Proceed at your own risk!
* **Longer**
* Orange 10
* Orange 30
- * Orange4K
+ * Orange 120
+ * Orange 4K
* **Uniz IBEE**
* **Zortrax Inkspire**
@@ -437,7 +441,7 @@ The fastest way to compile the project is by run the `build/CompileWindows.bat`,
# TODO
* More file formats
-* Clean up (always)
+* Clean up & performance (always)
* See features request under Github
# Support my work / Donate
@@ -445,4 +449,5 @@ The fastest way to compile the project is by run the `build/CompileWindows.bat`,
All my work here is given for free (OpenSource), it took some hours to build, test and polish the program.
If you're happy to contribute for a better program and for my work i will appreciate the tip.
-PP: https://paypal.me/SkillTournament
+Sponsor: https://github.com/sponsors/sn4k3
+PayPal: https://paypal.me/SkillTournament
diff --git a/Scripts/ImportPrusaSlicerData.bat b/Scripts/ImportPrusaSlicerData.bat
index 4fe6b5d..47c8f42 100644
--- a/Scripts/ImportPrusaSlicerData.bat
+++ b/Scripts/ImportPrusaSlicerData.bat
@@ -8,65 +8,67 @@ SET PRINT_DIR=sla_print
SET PRINTER_DIR=printer
SET files[0]=UVtools Prusa SL1.ini
-SET files[1]=EPAX E6 Mono.ini
-SET files[2]=EPAX E10 Mono.ini
-SET files[3]=EPAX X1.ini
-SET files[4]=EPAX X10.ini
-SET files[5]=EPAX X10 4K Mono.ini
-SET files[6]=EPAX X133 4K Mono.ini
-SET files[7]=EPAX X156 4K Color.ini
-SET files[8]=EPAX X1K 2K Mono.ini
-SET files[9]=Zortrax Inkspire.ini
-SET files[10]=Nova3D Elfin.ini
-SET files[11]=Nova3D Bene4 Mono.ini
-SET files[12]=AnyCubic Photon.ini
-SET files[13]=AnyCubic Photon S.ini
-SET files[14]=AnyCubic Photon Zero.ini
-SET files[15]=AnyCubic Photon X.ini
-SET files[16]=AnyCubic Photon Mono.ini
-SET files[17]=AnyCubic Photon Mono SE.ini
-SET files[18]=AnyCubic Photon Mono X.ini
-SET files[19]=Elegoo Mars.ini
-SET files[20]=Elegoo Mars 2 Pro.ini
-SET files[21]=Elegoo Mars C.ini
-SET files[22]=Elegoo Saturn.ini
-SET files[23]=Peopoly Phenom.ini
-SET files[24]=Peopoly Phenom L.ini
-SET files[25]=Peopoly Phenom Noir.ini
-SET files[26]=Peopoly Phenom XXL.ini
-SET files[27]=QIDI Shadow5.5.ini
-SET files[28]=QIDI Shadow6.0 Pro.ini
-SET files[29]=QIDI S-Box.ini
-SET files[30]=QIDI I-Box Mono.ini
-SET files[31]=Phrozen Shuffle.ini
-SET files[32]=Phrozen Shuffle Lite.ini
-SET files[33]=Phrozen Shuffle XL.ini
-SET files[34]=Phrozen Shuffle XL Lite.ini
-SET files[35]=Phrozen Shuffle 16.ini
-SET files[36]=Phrozen Shuffle 4K.ini
-SET files[37]=Phrozen Sonic.ini
-SET files[38]=Phrozen Sonic 4K.ini
-SET files[39]=Phrozen Sonic Mighty 4K.ini
-SET files[40]=Phrozen Sonic Mini.ini
-SET files[41]=Phrozen Sonic Mini 4K.ini
-SET files[42]=Phrozen Transform.ini
-SET files[43]=Kelant S400.ini
-SET files[44]=Wanhao D7.ini
-SET files[45]=Wanhao D8.ini
-SET files[46]=Wanhao CGR Mini Mono.ini
-SET files[47]=Wanhao CGR Mono.ini
-SET files[48]=Creality LD-002R.ini
-SET files[49]=Creality LD-002H.ini
-SET files[50]=Creality LD-006.ini
-SET files[51]=Creality HALOT-ONE CL-60.ini
-SET files[52]=Creality HALOT-SKY CL-89.ini
-SET files[53]=Voxelab Polaris 5.5.ini
-SET files[54]=Voxelab Proxima 6.ini
-SET files[55]=Voxelab Ceres 8.9.ini
-SET files[56]=Longer Orange 10.ini
-SET files[57]=Longer Orange 30.ini
-SET files[58]=Longer Orange4K.ini
-SET files[59]=Uniz IBEE.ini
+SET files[1]=UVtools Prusa SL1S Speed.ini
+SET files[2]=EPAX E6 Mono.ini
+SET files[3]=EPAX E10 Mono.ini
+SET files[4]=EPAX X1.ini
+SET files[5]=EPAX X10.ini
+SET files[6]=EPAX X10 4K Mono.ini
+SET files[7]=EPAX X133 4K Mono.ini
+SET files[8]=EPAX X156 4K Color.ini
+SET files[9]=EPAX X1K 2K Mono.ini
+SET files[10]=Zortrax Inkspire.ini
+SET files[11]=Nova3D Elfin.ini
+SET files[12]=Nova3D Bene4 Mono.ini
+SET files[13]=AnyCubic Photon.ini
+SET files[14]=AnyCubic Photon S.ini
+SET files[15]=AnyCubic Photon Zero.ini
+SET files[16]=AnyCubic Photon X.ini
+SET files[17]=AnyCubic Photon Mono.ini
+SET files[18]=AnyCubic Photon Mono SE.ini
+SET files[19]=AnyCubic Photon Mono X.ini
+SET files[20]=Elegoo Mars.ini
+SET files[21]=Elegoo Mars 2 Pro.ini
+SET files[22]=Elegoo Mars C.ini
+SET files[23]=Elegoo Saturn.ini
+SET files[24]=Peopoly Phenom.ini
+SET files[25]=Peopoly Phenom L.ini
+SET files[26]=Peopoly Phenom Noir.ini
+SET files[27]=Peopoly Phenom XXL.ini
+SET files[28]=QIDI Shadow5.5.ini
+SET files[29]=QIDI Shadow6.0 Pro.ini
+SET files[30]=QIDI S-Box.ini
+SET files[31]=QIDI I-Box Mono.ini
+SET files[32]=Phrozen Shuffle.ini
+SET files[33]=Phrozen Shuffle Lite.ini
+SET files[34]=Phrozen Shuffle XL.ini
+SET files[35]=Phrozen Shuffle XL Lite.ini
+SET files[36]=Phrozen Shuffle 16.ini
+SET files[37]=Phrozen Shuffle 4K.ini
+SET files[38]=Phrozen Sonic.ini
+SET files[39]=Phrozen Sonic 4K.ini
+SET files[40]=Phrozen Sonic Mighty 4K.ini
+SET files[41]=Phrozen Sonic Mini.ini
+SET files[42]=Phrozen Sonic Mini 4K.ini
+SET files[43]=Phrozen Transform.ini
+SET files[44]=Kelant S400.ini
+SET files[45]=Wanhao D7.ini
+SET files[46]=Wanhao D8.ini
+SET files[47]=Wanhao CGR Mini Mono.ini
+SET files[48]=Wanhao CGR Mono.ini
+SET files[49]=Creality LD-002R.ini
+SET files[50]=Creality LD-002H.ini
+SET files[51]=Creality LD-006.ini
+SET files[52]=Creality HALOT-ONE CL-60.ini
+SET files[53]=Creality HALOT-SKY CL-89.ini
+SET files[54]=Voxelab Polaris 5.5.ini
+SET files[55]=Voxelab Proxima 6.ini
+SET files[56]=Voxelab Ceres 8.9.ini
+SET files[57]=Longer Orange 10.ini
+SET files[58]=Longer Orange 30.ini
+SET files[59]=Longer Orange 120.ini
+SET files[60]=Longer Orange 4K.ini
+SET files[61]=Uniz IBEE.ini
echo PrusaSlicer Printers Instalation
echo This will replace printers, all changes will be discarded
diff --git a/Scripts/ctb.bt b/Scripts/ctb.bt
new file mode 100644
index 0000000..ac8f4a4
--- /dev/null
+++ b/Scripts/ctb.bt
@@ -0,0 +1,212 @@
+//------------------------------------------------
+//--- 010 Editor v8.0.1 Binary Template
+//
+// File: ctb, cbddlp, photon
+// Authors: Tiago Conceição
+//------------------------------------------------
+
+LittleEndian();
+
+struct HEADER {
+ uint Magic <fgcolor=cBlack, bgcolor=cRed>;
+ uint Version <fgcolor=cBlack, bgcolor=cRed>;
+
+ float BedSizeX <fgcolor=cBlack, bgcolor=cRed>;
+ float BedSizeY <fgcolor=cBlack, bgcolor=cRed>;
+ float BedSizeZ <fgcolor=cBlack, bgcolor=cRed>;
+
+ uint Unknown1 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown2 <fgcolor=cBlack, bgcolor=cRed>;
+
+ float TotalHeightMilimeter <fgcolor=cBlack, bgcolor=cRed>;
+ float LayerHeightMilimeter <fgcolor=cBlack, bgcolor=cRed>;
+ float LayerExposureSeconds <fgcolor=cBlack, bgcolor=cRed>;
+ float BottomExposureSeconds <fgcolor=cBlack, bgcolor=cRed>;
+ float LightOffDelay <fgcolor=cBlack, bgcolor=cRed>;
+ uint BottomLayersCount <fgcolor=cBlack, bgcolor=cRed>;
+ uint ResolutionX <fgcolor=cBlack, bgcolor=cRed>;
+ uint ResolutionY <fgcolor=cBlack, bgcolor=cRed>;
+ uint PreviewLargeOffsetAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint LayersDefinitionOffsetAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint LayerCount <fgcolor=cBlack, bgcolor=cRed>;
+ uint PreviewSmallOffsetAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint PrintTime <fgcolor=cBlack, bgcolor=cRed>;
+ uint ProjectorType <fgcolor=cBlack, bgcolor=cRed>;
+ uint PrintParametersOffsetAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint PrintParametersSize <fgcolor=cBlack, bgcolor=cRed>;
+ uint AntiAliasLevel <fgcolor=cBlack, bgcolor=cRed>;
+ ushort LightPWM <fgcolor=cBlack, bgcolor=cRed>;
+ ushort BottomLightPWM <fgcolor=cBlack, bgcolor=cRed>;
+ uint EncryptionKey <fgcolor=cBlack, bgcolor=cRed>;
+ uint SlicerOffset <fgcolor=cBlack, bgcolor=cRed>;
+ uint SlicerSize <fgcolor=cBlack, bgcolor=cRed>;
+} header;
+
+struct PREVIEW {
+ uint ResolutionX <fgcolor=cBlack, bgcolor=cRed>;
+ uint ResolutionY <fgcolor=cBlack, bgcolor=cRed>;
+ uint ImageOffset <fgcolor=cBlack, bgcolor=cRed>;
+ uint ImageLength <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown1 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown2 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown3 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown4 <fgcolor=cBlack, bgcolor=cRed>;
+
+ byte Data[ImageLength] <fgcolor=cBlack, bgcolor=cRed>;
+};
+
+struct PRINT_PARAMETERS {
+ float BottomLiftHeight <fgcolor=cBlack, bgcolor=cRed>;
+ float BottomLiftSpeed <fgcolor=cBlack, bgcolor=cRed>;
+ float LiftHeight <fgcolor=cBlack, bgcolor=cRed>;
+ float LiftSpeed <fgcolor=cBlack, bgcolor=cRed>;
+ float RetractSpeed <fgcolor=cBlack, bgcolor=cRed>;
+ float VolumeMl <fgcolor=cBlack, bgcolor=cRed>;
+ float WeightG <fgcolor=cBlack, bgcolor=cRed>;
+ float CostDollars <fgcolor=cBlack, bgcolor=cRed>;
+ float BottomLightOffDelay <fgcolor=cBlack, bgcolor=cRed>;
+ float LightOffDelay <fgcolor=cBlack, bgcolor=cRed>;
+
+ uint BottomLayerCount <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding1 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding2 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding3 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding4 <fgcolor=cBlack, bgcolor=cRed>;
+};
+
+struct SLICER_INFO {
+ float BottomLiftDistance2 <fgcolor=cBlack, bgcolor=cRed>;
+ float BottomLiftSpeed2 <fgcolor=cBlack, bgcolor=cRed>;
+ float LiftHeight2 <fgcolor=cBlack, bgcolor=cRed>;
+ float LiftSpeed2 <fgcolor=cBlack, bgcolor=cRed>;
+ float RetractHeight2 <fgcolor=cBlack, bgcolor=cRed>;
+ float RetractSpeed2 <fgcolor=cBlack, bgcolor=cRed>;
+ float RestTimeAfterLift <fgcolor=cBlack, bgcolor=cRed>;
+
+ uint MachineNameAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint MachineNameSize <fgcolor=cBlack, bgcolor=cRed>;
+ uint EncryptionMode <fgcolor=cBlack, bgcolor=cRed>; // 0/8 for cbddlp files, 0xF (15) for ctb files, 0x2000000F (536870927) for v3 ctb files allow per layer parameters
+ uint MysteriousId <fgcolor=cBlack, bgcolor=cRed>; // v3 = 305419896 | v4 = 27087675
+ uint AntiAliasLevel <fgcolor=cBlack, bgcolor=cRed>;
+ uint SoftwareVersion <fgcolor=cBlack, bgcolor=cRed>; // ctb v3 = 17171200 | ctb v4 = 16777216
+ float RestTimeAfterRetract <fgcolor=cBlack, bgcolor=cRed>;
+ float RestTimeAfterLift2 <fgcolor=cBlack, bgcolor=cRed>;
+ uint TransitionLayerCount <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding1 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding2 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding3 <fgcolor=cBlack, bgcolor=cRed>;
+
+ if(MachineNameAddress > 0 && MachineNameSize > 0)
+ {
+ char MachineName[MachineNameSize] <fgcolor=cBlack, bgcolor=cRed>;
+ }
+};
+
+
+if(header.PreviewLargeOffsetAddress > 0)
+{
+ FSeek(header.PreviewLargeOffsetAddress);
+ PREVIEW previewLarge <fgcolor=cBlack, bgcolor=cYellow>;
+}
+if(header.PreviewSmallOffsetAddress > 0)
+{
+ FSeek(header.PreviewSmallOffsetAddress);
+ PREVIEW previewSmall <fgcolor=cBlack, bgcolor=cYellow>;
+}
+
+if(header.PrintParametersOffsetAddress > 0){
+ FSeek(header.PrintParametersOffsetAddress);
+ PRINT_PARAMETERS parameters <fgcolor=cBlack, bgcolor=cYellow>;
+}
+
+if(header.SlicerOffset > 0){
+ FSeek(header.SlicerOffset);
+ SLICER_INFO SlicerInfo <fgcolor=cBlack, bgcolor=cYellow>;
+}
+
+if(header.Version >= 4)
+{
+ struct PRINT_PARAMETERS_V4
+ {
+ char Disclaimer[320] <fgcolor=cBlack, bgcolor=cYellow>;
+ float BottomRetractSpeed <fgcolor=cWhite, bgcolor=cBlue>;
+ float BottomRetractSpeed2 <fgcolor=cWhite, bgcolor=cBlue>;
+ uint Padding1 <fgcolor=cWhite, bgcolor=cBlue>;
+ float Four1 <fgcolor=cWhite, bgcolor=cBlue>; // 4?
+ uint Padding2 <fgcolor=cWhite, bgcolor=cBlue>;
+ float Four2 <fgcolor=cWhite, bgcolor=cBlue>; // 4?
+ float RestTimeAfterRetract <fgcolor=cWhite, bgcolor=cBlue>;
+ float RestTimeAfterLift <fgcolor=cWhite, bgcolor=cBlue>;
+ float RestTimeBeforeLift <fgcolor=cWhite, bgcolor=cBlue>;
+ float BottomRetractHeight2 <fgcolor=cWhite, bgcolor=cBlue>;
+ float Unknown1 <fgcolor=cWhite, bgcolor=cBlue>; // 2955.996 or uint:1161347054 but changes
+ uint Unknown2 <fgcolor=cWhite, bgcolor=cBlue>; // 73470 but changes
+ uint Unknown3 <fgcolor=cWhite, bgcolor=cBlue>; // 5?
+ uint Unknown4 <fgcolor=cWhite, bgcolor=cBlue>; // 139 but changes
+ uint Padding3 <fgcolor=cWhite, bgcolor=cBlue>;
+ uint Padding4 <fgcolor=cWhite, bgcolor=cBlue>;
+ uint Padding5 <fgcolor=cWhite, bgcolor=cBlue>;
+ uint Padding6 <fgcolor=cWhite, bgcolor=cBlue>;
+ uint Unknown5 <fgcolor=cWhite, bgcolor=cBlue>; // 23047 but changes
+ uint Unknown6 <fgcolor=cWhite, bgcolor=cBlue>; // 320 but changes
+ byte Reserved[420] <fgcolor=cWhite, bgcolor=cBlue>;
+ } printParametersV4;
+}
+
+typedef struct() {
+ float LayerPositionZ <fgcolor=cBlack, bgcolor=cRed>;
+ float LayerExposure <fgcolor=cBlack, bgcolor=cRed>;
+ float LightOffSeconds <fgcolor=cBlack, bgcolor=cRed>;
+ uint DataAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint DataSize <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown1 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown2 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown3 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown4 <fgcolor=cBlack, bgcolor=cRed>;
+} LAYER_DATA;
+
+typedef struct() {
+ LAYER_DATA LayerData <fgcolor=cBlack, bgcolor=cRed>;
+ uint TotalSize <fgcolor=cBlack, bgcolor=cRed>;
+ float LiftHeight <fgcolor=cBlack, bgcolor=cRed>;
+ float LiftSpeed <fgcolor=cBlack, bgcolor=cRed>;
+ float LiftHeight2 <fgcolor=cBlack, bgcolor=cRed>;
+ float LiftSpeed2 <fgcolor=cBlack, bgcolor=cRed>;
+ float RetractSpeed <fgcolor=cBlack, bgcolor=cRed>;
+ float RetractHeight2 <fgcolor=cBlack, bgcolor=cRed>;
+ float RetractSpeed2 <fgcolor=cBlack, bgcolor=cRed>;
+ float RestTimeBeforeLift <fgcolor=cBlack, bgcolor=cRed>;
+ float RestTimeAfterLift <fgcolor=cBlack, bgcolor=cRed>;
+ float RestTimeAfterRetract <fgcolor=cBlack, bgcolor=cRed>;
+ float LightPWM <fgcolor=cBlack, bgcolor=cRed>;
+} LAYER_DATAEX;
+
+
+typedef struct(int size) {
+ byte layerDataBlock[size] <fgcolor=cBlack, bgcolor=cGreen>;
+} LAYER_RLE;
+
+FSeek(header.LayersDefinitionOffsetAddress);
+struct LAYERS {
+ local int aa;
+ local int i;
+ local uint currentPos;
+
+ for( aa = 0; aa < header.AntiAliasLevel; aa++)
+ {
+ for( i = 0; i < header.LayerCount; i++ ){
+ LAYER_DATA layerData <fgcolor=cBlack, bgcolor=cYellow>;
+ currentPos = FTell();
+
+ if(header.Version >= 3)
+ {
+ FSeek(layerData.DataAddress - 84);
+ LAYER_DATAEX layerDataEx;
+ }
+
+ FSeek(layerData.DataAddress);
+ LAYER_RLE layerRLE(layerData.DataSize);
+ FSeek(currentPos);
+ }
+ }
+} layers;
diff --git a/Scripts/lgs.bt b/Scripts/lgs.bt
index 3b9b9b9..1f9e630 100644
--- a/Scripts/lgs.bt
+++ b/Scripts/lgs.bt
@@ -17,7 +17,7 @@ typedef struct(int size) {
} rgbPreviewImageRawData;
struct HEADER {
- char name[8] <fgcolor=cBlack, bgcolor=cWhite>;
+ char Name[8] <fgcolor=cBlack, bgcolor=cWhite>;
uint32 Uint_08 <fgcolor=cBlack, bgcolor=cRed>;
uint32 Uint_0C <fgcolor=cBlack, bgcolor=cRed>;
uint32 PrinterModel <fgcolor=cBlack, bgcolor=cRed>;
diff --git a/UVtools.Core/About.cs b/UVtools.Core/About.cs
index 35373a1..ba904d5 100644
--- a/UVtools.Core/About.cs
+++ b/UVtools.Core/About.cs
@@ -7,7 +7,6 @@
*/
using System;
-using System.IO;
using System.Reflection;
namespace UVtools.Core
diff --git a/UVtools.Core/EmguCV/Contour.cs b/UVtools.Core/EmguCV/Contour.cs
new file mode 100644
index 0000000..20d216e
--- /dev/null
+++ b/UVtools.Core/EmguCV/Contour.cs
@@ -0,0 +1,240 @@
+/*
+ * GNU AFFERO GENERAL PUBLIC LICENSE
+ * Version 3, 19 November 2007
+ * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ * Everyone is permitted to copy and distribute verbatim copies
+ * of this license document, but changing it is not allowed.
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using Emgu.CV;
+using Emgu.CV.CvEnum;
+using Emgu.CV.Structure;
+using Emgu.CV.Util;
+using UVtools.Core.Extensions;
+
+namespace UVtools.Core.EmguCV
+{
+ /// <summary>
+ /// A contour cache for OpenCV
+ /// </summary>
+ public class Contour : IReadOnlyCollection<Point>, IDisposable
+ {
+ #region Members
+
+ private VectorOfPoint _points;
+ private Rectangle? _bounds;
+ private RotatedRect? _boundsBestFit;
+ private CircleF? _minEnclosingCircle;
+ private bool? _isConvex;
+ private double _area = double.NaN;
+ private double _perimeter = double.NaN;
+ private Moments _moments;
+ private Point? _centroid;
+
+ #endregion
+
+ #region Properties
+ public int XMin => Bounds.X;
+
+ public int YMin => Bounds.Y;
+
+ public int XMax => Bounds.Right;
+
+ public int YMax => Bounds.Bottom;
+
+ public Rectangle Bounds => _bounds ??= CvInvoke.BoundingRectangle(_points);
+
+ public RotatedRect BoundsBestFit => _boundsBestFit ??= CvInvoke.MinAreaRect(_points);
+
+ public CircleF MinEnclosingCircle => _minEnclosingCircle ??= CvInvoke.MinEnclosingCircle(_points);
+
+ public bool IsConvex => _isConvex ??= CvInvoke.IsContourConvex(_points);
+
+ /// <summary>
+ /// Gets the area of the contour
+ /// </summary>
+ public double Area
+ {
+ get
+ {
+ if (double.IsNaN(_area))
+ {
+ _area = CvInvoke.ContourArea(_points);
+ }
+
+ return _area;
+ }
+ }
+
+ /// <summary>
+ /// Gets the perimeter of the contours
+ /// </summary>
+ public double Perimeter
+ {
+ get
+ {
+ if (double.IsNaN(_perimeter))
+ {
+ _perimeter = CvInvoke.ArcLength(_points, true);
+ }
+ return _perimeter;
+ }
+ }
+
+ public Moments Moments => _moments ??= CvInvoke.Moments(_points);
+
+ /// <summary>
+ /// Gets the centroid of the contour
+ /// </summary>
+ public Point Centroid => _centroid ??= Moments.M00 == 0 ? Point.Empty :
+ new Point(
+ (int)Math.Round(_moments.M10 / _moments.M00),
+ (int)Math.Round(_moments.M01 / _moments.M00));
+
+ /// <summary>
+ /// Gets or sets the contour <see cref="Point"/>
+ /// </summary>
+ public VectorOfPoint Points
+ {
+ get => _points;
+ set
+ {
+ Dispose();
+ _points = value ?? throw new ArgumentNullException(nameof(Points));
+ }
+ }
+
+
+ /// <summary>
+ /// Gets if this contour have any point
+ /// </summary>
+ public bool IsEmpty => _points.Size == 0;
+ #endregion
+
+ #region Constructor
+ public Contour(VectorOfPoint points) : this(points.ToArray())
+ { }
+
+ public Contour(Point[] points)
+ {
+ Points = new VectorOfPoint(points);
+ }
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Checks if a given <see cref="Point"/> is inside the contour rectangle bounds
+ /// </summary>
+ /// <param name="point"></param>
+ /// <returns></returns>
+ public bool IsInsideBounds(Point point) => Bounds.Contains(point);
+
+ /// <summary>
+ /// Gets if a given <see cref="Point"/> is inside the contour
+ /// </summary>
+ /// <param name="point"></param>
+ /// <returns></returns>
+ public bool IsInside(Point point)
+ {
+ if (!IsInsideBounds(point)) return false;
+ return CvInvoke.PointPolygonTest(_points, point, false) >= 0;
+ }
+
+ public double MeasureDist(Point point)
+ {
+ if (!IsInsideBounds(point)) return -1;
+ return CvInvoke.PointPolygonTest(_points, point, true);
+ }
+
+ public IOutputArray ContourApproximation(double epsilon = 0.1)
+ {
+ var mat = new Mat();
+ CvInvoke.ApproxPolyDP(_points, mat, epsilon*Perimeter, true);
+ return mat;
+ }
+
+ /*
+ /// <summary>
+ /// Calculate the X/Y min/max boundary
+ /// </summary>
+ private void CalculateMinMax()
+ {
+ Bounds = Rectangle.Empty;
+
+ if (_contourPoints.Length == 0)
+ {
+ _xMin = -1;
+ _yMin = -1;
+ _xMax = -1;
+ _yMax = -1;
+ return;
+ }
+
+ _xMin = int.MaxValue;
+ _yMin = int.MaxValue;
+ _xMax = int.MinValue;
+ _yMax = int.MinValue;
+
+ for (int i = 0; i < _contourPoints.Length; i++)
+ {
+ _xMin = Math.Min(_xMin, _contourPoints[i].X);
+ _yMin = Math.Min(_yMin, _contourPoints[i].Y);
+
+ _xMax = Math.Max(_xMax, _contourPoints[i].X);
+ _yMax = Math.Max(_yMax, _contourPoints[i].Y);
+ }
+
+ Bounds = new Rectangle(_xMin, _yMin, _xMax - _xMin, _yMax - _yMin);
+ }
+ */
+
+ public void FitCircle(Mat src, MCvScalar color, int thickness = 1, LineType lineType = LineType.EightConnected, int shift = 0)
+ {
+ CvInvoke.Circle(src,
+ MinEnclosingCircle.Center.ToPoint(),
+ (int) Math.Round(MinEnclosingCircle.Radius),
+ color,
+ thickness,
+ lineType,
+ shift);
+ }
+
+ /*public void FitEllipse(Mat src, MCvScalar color, int thickness = 1, LineType lineType = LineType.EightConnected, int shift = 0)
+ {
+ var ellipse = CvInvoke.FitEllipse(_points);
+ CvInvoke.Ellipse(src, ellipse.Center.ToPoint(), ellipse.Size.ToSize(), ellipse.Angle, 0, 0);
+ }*/
+ #endregion
+
+ #region Implementations
+
+ public IEnumerator<Point> GetEnumerator()
+ {
+ return (IEnumerator<Point>) _points.ToArray().GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public int Count => _points.Size;
+
+ public Point this[int index] => _points[index];
+ public Point this[uint index] => _points[(int) index];
+ public Point this[long index] => _points[(int) index];
+ public Point this[ulong index] => _points[(int) index];
+
+ public void Dispose()
+ {
+ _points?.Dispose();
+ _moments?.Dispose();
+ }
+ #endregion
+ }
+}
diff --git a/UVtools.Core/Extensions/FileStreamExtensions.cs b/UVtools.Core/Extensions/FileStreamExtensions.cs
index b0370f2..02fba02 100644
--- a/UVtools.Core/Extensions/FileStreamExtensions.cs
+++ b/UVtools.Core/Extensions/FileStreamExtensions.cs
@@ -24,6 +24,26 @@ namespace UVtools.Core.Extensions
return buffer;
}
+ public static uint ReadUShortLittleEndian(this FileStream fs, int offset = 0)
+ {
+ return BitExtensions.ToUShortLittleEndian(fs.ReadBytes(2, offset));
+ }
+
+ public static uint ReadUShortBigEndian(this FileStream fs, int offset = 0)
+ {
+ return BitExtensions.ToUShortBigEndian(fs.ReadBytes(2, offset));
+ }
+
+ public static uint ReadUIntLittleEndian(this FileStream fs, int offset = 0)
+ {
+ return BitExtensions.ToUIntLittleEndian(fs.ReadBytes(4, offset));
+ }
+
+ public static uint ReadUIntBigEndian(this FileStream fs, int offset = 0)
+ {
+ return BitExtensions.ToUIntBigEndian(fs.ReadBytes(4, offset));
+ }
+
public static uint WriteStream(this FileStream fs, MemoryStream stream, int offset = 0)
{
return fs.WriteBytes(stream.ToArray(), offset);
diff --git a/UVtools.Core/FileFormats/CWSFile.cs b/UVtools.Core/FileFormats/CWSFile.cs
index 832628a..192f5a2 100644
--- a/UVtools.Core/FileFormats/CWSFile.cs
+++ b/UVtools.Core/FileFormats/CWSFile.cs
@@ -532,7 +532,7 @@ namespace UVtools.Core.FileFormats
Printer = PrinterType.Elfin;
for (int i = 0; i < FileExtensions.Length; i++)
{
- if (!fileFullPath.EndsWith(FileExtensions[i].Extension) && !fileFullPath.EndsWith($"{FileExtensions[i].Extension}{TemporaryFileAppend}")) continue;
+ if (!FileEndsWith(FileExtensions[i].Extension)) continue;
Printer = (PrinterType) i+1;
}
}
diff --git a/UVtools.Core/FileFormats/CXDLPFile.cs b/UVtools.Core/FileFormats/CXDLPFile.cs
index 5d0d881..aaabbbf 100644
--- a/UVtools.Core/FileFormats/CXDLPFile.cs
+++ b/UVtools.Core/FileFormats/CXDLPFile.cs
@@ -560,7 +560,7 @@ namespace UVtools.Core.FileFormats
{
using var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write);
- if (ResolutionX == 2560 && ResolutionY == 1620)
+ if (ResolutionX == 1620 && ResolutionY == 2560)
{
MachineName = "CL-60";
}
@@ -568,6 +568,10 @@ namespace UVtools.Core.FileFormats
{
MachineName = "CL-89";
}
+ else if (!MachineName.StartsWith("CL-"))
+ {
+ throw new Exception("Unable to detect printer model from resolution, check if resolution is well defined on slicer for your printer model.");
+ }
var pageBreak = PageBreak.Bytes;
diff --git a/UVtools.Core/FileFormats/ChituboxFile.cs b/UVtools.Core/FileFormats/ChituboxFile.cs
index 4e0cbc6..05cf03f 100644
--- a/UVtools.Core/FileFormats/ChituboxFile.cs
+++ b/UVtools.Core/FileFormats/ChituboxFile.cs
@@ -14,6 +14,7 @@ using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
+using System.Text;
using System.Threading.Tasks;
using BinarySerialization;
using Emgu.CV;
@@ -29,6 +30,7 @@ namespace UVtools.Core.FileFormats
#region Constants
private const uint MAGIC_CBDDLP = 0x12FD0019; // 318570521
private const uint MAGIC_CBT = 0x12FD0086; // 318570630
+ private const uint MAGIC_CBTv4 = 0x12FD0106; // 318570758
private const ushort REPEATRGB15MASK = 0x20;
private const byte RLE8EncodingLimit = 0x7d; // 125;
@@ -36,7 +38,11 @@ namespace UVtools.Core.FileFormats
private const uint ENCRYPTYION_MODE_CBDDLP = 0x8; // 0 or 8
private const uint ENCRYPTYION_MODE_CTBv2 = 0xF; // 15 for ctb v2 files
- private const uint ENCRYPTYION_MODE_CTBv3 = 0x2000000F; // 536870927 for ctb v3 files (This allow per layer settings, while 0xF don't)
+ private const uint ENCRYPTYION_MODE_CTBv3 = 536870927; // 536870927 for ctb v3 files (This allow per layer settings, while 15 don't)
+ private const uint ENCRYPTYION_MODE_CTBv4 = 1073741839; // 1073741839 for ctb v3 files (This allow per layer settings, while 15 don't)
+
+ private const string CTBv4_DISCLAIMER = "Layout and record format for the ctb and cbddlp file types are the copyrighted programs or codes of CBD Technology (China) Inc..The Customer or User shall not in any manner reproduce, distribute, modify, decompile, disassemble, decrypt, extract, reverse engineer, lease, assign, or sublicense the said programs or codes.";
+ private const ushort CTBv4_DISCLAIMER_SIZE = 320;
#endregion
#region Sub Classes
@@ -270,13 +276,13 @@ namespace UVtools.Core.FileFormats
public class SlicerInfo
{
private string _machineName;
- [FieldOrder(0)] public uint Padding1 { get; set; }
- [FieldOrder(1)] public uint Padding2 { get; set; }
- [FieldOrder(2)] public uint Padding3 { get; set; }
- [FieldOrder(3)] public uint Padding4 { get; set; }
- [FieldOrder(4)] public uint Padding5 { get; set; }
- [FieldOrder(5)] public uint Padding6 { get; set; }
- [FieldOrder(6)] public uint Padding7 { get; set; }
+ [FieldOrder(0)] public float BottomLiftDistance2 { get; set; }
+ [FieldOrder(1)] public float BottomLiftSpeed2 { get; set; }
+ [FieldOrder(2)] public float LiftHeight2 { get; set; }
+ [FieldOrder(3)] public float LiftSpeed2 { get; set; }
+ [FieldOrder(4)] public float RetractHeight2 { get; set; }
+ [FieldOrder(5)] public float RetractSpeed2 { get; set; }
+ [FieldOrder(6)] public float RestTimeAfterLift { get; set; }
/// <summary>
/// Gets the machine name offset to a string naming the machine type, and its length in bytes.
@@ -290,14 +296,14 @@ namespace UVtools.Core.FileFormats
/// <summary>
/// Gets the parameter used to control encryption.
- /// Not totally understood. 0/8 for cbddlp files, 0xF (15) for ctb files, 0x2000000F (536870927) for v3 ctb files allow per layer parameters
+ /// Not totally understood. 0/8 for cbddlp files, 0xF (15) for ctb files, 0x2000000F (536870927) for v3 ctb and 1073741839 for v4 ctb files to allow per layer parameters
/// </summary>
[FieldOrder(9)] public uint EncryptionMode { get; set; } = ENCRYPTYION_MODE_CTBv3;
/// <summary>
/// Gets a number that increments with time or number of models sliced, or both. Zeroing it in output seems to have no effect. Possibly a user tracking bug.
/// </summary>
- [FieldOrder(10)] public uint MysteriousId { get; set; }
+ [FieldOrder(10)] public uint MysteriousId { get; set; } = 305419896; // v3 = 305419896 | v4 = 27087675
/// <summary>
/// Gets the user-selected antialiasing level. For cbddlp files this will match the level_set_count. For ctb files, this number is essentially arbitrary.
@@ -309,13 +315,13 @@ namespace UVtools.Core.FileFormats
/// (No provision is made to name the software being used, so this assumes that only one software package can generate the files.
/// Probably best to hardcode it at 0x01060300.)
/// </summary>
- [FieldOrder(12)] public uint SoftwareVersion { get; set; } = 0x01060300;
- [FieldOrder(13)] public uint Unknown1 { get; set; }
- [FieldOrder(14)] public uint Padding8 { get; set; }
+ [FieldOrder(12)] public uint SoftwareVersion { get; set; } = 0x01060300; // ctb v3 = 17171200 | ctb v4 = 16777216
+ [FieldOrder(13)] public float RestTimeAfterRetract { get; set; }
+ [FieldOrder(14)] public float RestTimeAfterLift2 { get; set; }
[FieldOrder(15)] public uint TransitionLayerCount { get; set; } // CTB not all printers
- [FieldOrder(16)] public uint Padding10 { get; set; }
- [FieldOrder(17)] public uint Padding11 { get; set; }
- [FieldOrder(18)] public uint Padding12 { get; set; }
+ [FieldOrder(16)] public uint Padding1 { get; set; }
+ [FieldOrder(17)] public uint Padding2 { get; set; }
+ [FieldOrder(18)] public uint Padding3 { get; set; }
/// <summary>
/// Gets the machine name. string is not nul-terminated.
@@ -337,12 +343,90 @@ namespace UVtools.Core.FileFormats
public override string ToString()
{
- return $"{nameof(Padding1)}: {Padding1}, {nameof(Padding2)}: {Padding2}, {nameof(Padding3)}: {Padding3}, {nameof(Padding4)}: {Padding4}, {nameof(Padding5)}: {Padding5}, {nameof(Padding6)}: {Padding6}, {nameof(Padding7)}: {Padding7}, {nameof(MachineNameAddress)}: {MachineNameAddress}, {nameof(MachineNameSize)}: {MachineNameSize}, {nameof(EncryptionMode)}: {EncryptionMode}, {nameof(MysteriousId)}: {MysteriousId}, {nameof(AntiAliasLevel)}: {AntiAliasLevel}, {nameof(SoftwareVersion)}: {SoftwareVersion}, {nameof(Unknown1)}: {Unknown1}, {nameof(Padding8)}: {Padding8}, {nameof(TransitionLayerCount)}: {TransitionLayerCount}, {nameof(Padding10)}: {Padding10}, {nameof(Padding11)}: {Padding11}, {nameof(Padding12)}: {Padding12}, {nameof(MachineName)}: {MachineName}";
+ return $"{nameof(BottomLiftDistance2)}: {BottomLiftDistance2}, {nameof(BottomLiftSpeed2)}: {BottomLiftSpeed2}, {nameof(LiftHeight2)}: {LiftHeight2}, {nameof(LiftSpeed2)}: {LiftSpeed2}, {nameof(RetractHeight2)}: {RetractHeight2}, {nameof(RetractSpeed2)}: {RetractSpeed2}, {nameof(RestTimeAfterLift)}: {RestTimeAfterLift}, {nameof(MachineNameAddress)}: {MachineNameAddress}, {nameof(MachineNameSize)}: {MachineNameSize}, {nameof(EncryptionMode)}: {EncryptionMode}, {nameof(MysteriousId)}: {MysteriousId}, {nameof(AntiAliasLevel)}: {AntiAliasLevel}, {nameof(SoftwareVersion)}: {SoftwareVersion}, {nameof(RestTimeAfterRetract)}: {RestTimeAfterRetract}, {nameof(RestTimeAfterLift2)}: {RestTimeAfterLift2}, {nameof(TransitionLayerCount)}: {TransitionLayerCount}, {nameof(Padding1)}: {Padding1}, {nameof(Padding2)}: {Padding2}, {nameof(Padding3)}: {Padding3}, {nameof(MachineName)}: {MachineName}";
}
}
#endregion
+ #region PrintParametersV4
+ public sealed class PrintParametersV4
+ {
+ [FieldOrder(1)]
+ [FieldLength(CTBv4_DISCLAIMER_SIZE)]
+ public string Disclaimer { get; set; } = CTBv4_DISCLAIMER; // 320 bytes
+
+ [FieldOrder(2)]
+ public float BottomRetractSpeed { get; set; }
+
+ [FieldOrder(3)]
+ public float BottomRetractSpeed2 { get; set; }
+
+ [FieldOrder(4)]
+ public uint Padding1 { get; set; }
+
+ [FieldOrder(5)]
+ public float Four1 { get; set; } = 4; // 4?
+
+ [FieldOrder(6)]
+ public uint Padding2 { get; set; }
+
+ [FieldOrder(7)]
+ public float Four2 { get; set; } = 4; // ?
+
+ [FieldOrder(8)]
+ public float RestTimeAfterRetract { get; set; }
+
+ [FieldOrder(9)]
+ public float RestTimeAfterLift { get; set; }
+
+ [FieldOrder(10)]
+ public float RestTimeBeforeLift { get; set; }
+
+ [FieldOrder(11)]
+ public float BottomRetractHeight2 { get; set; }
+
+ [FieldOrder(12)]
+ public float Unknown1 { get; set; } // 2955.996 or uint:1161347054 but changes
+
+ [FieldOrder(13)]
+ public uint Unknown2 { get; set; } // 73470 but changes
+
+ [FieldOrder(14)]
+ public uint Unknown3 { get; set; } = 5; // 5?
+
+ [FieldOrder(15)]
+ public uint Unknown4 { get; set; } // 139 but changes
+
+ [FieldOrder(16)]
+ public uint Padding3 { get; set; }
+
+ [FieldOrder(17)]
+ public uint Padding4 { get; set; }
+
+ [FieldOrder(18)]
+ public uint Padding5 { get; set; }
+
+ [FieldOrder(19)]
+ public uint Padding6 { get; set; }
+
+ [FieldOrder(20)]
+ public uint Unknown5 { get; set; } // 23047 but changes
+
+ [FieldOrder(21)]
+ public uint Unknown6 { get; set; } // 320 but changes
+
+ [FieldOrder(22)]
+ [FieldCount(420)]
+ private byte[] Reserved { get; set; } = new byte[420]; // 420 bytes
+
+ public override string ToString()
+ {
+ return $"{nameof(Disclaimer)}: {Disclaimer}, {nameof(BottomRetractSpeed)}: {BottomRetractSpeed}, {nameof(BottomRetractSpeed2)}: {BottomRetractSpeed2}, {nameof(Padding1)}: {Padding1}, {nameof(Four1)}: {Four1}, {nameof(Padding2)}: {Padding2}, {nameof(Four2)}: {Four2}, {nameof(RestTimeAfterRetract)}: {RestTimeAfterRetract}, {nameof(RestTimeAfterLift)}: {RestTimeAfterLift}, {nameof(RestTimeBeforeLift)}: {RestTimeBeforeLift}, {nameof(BottomRetractHeight2)}: {BottomRetractHeight2}, {nameof(Unknown1)}: {Unknown1}, {nameof(Unknown2)}: {Unknown2}, {nameof(Unknown3)}: {Unknown3}, {nameof(Unknown4)}: {Unknown4}, {nameof(Padding3)}: {Padding3}, {nameof(Padding4)}: {Padding4}, {nameof(Padding5)}: {Padding5}, {nameof(Padding6)}: {Padding6}, {nameof(Unknown5)}: {Unknown5}, {nameof(Unknown6)}: {Unknown6}, {nameof(Reserved)}: {Reserved}";
+ }
+ }
+ #endregion
+
#region Preview
/// <summary>
/// The files contain two preview images.
@@ -524,8 +608,6 @@ namespace UVtools.Core.FileFormats
[Ignore] public byte[] EncodedRle { get; set; }
[Ignore] public ChituboxFile Parent { get; set; }
- [Ignore] public uint Version { get; set; } = 2;
-
public LayerData()
{
}
@@ -814,7 +896,6 @@ namespace UVtools.Core.FileFormats
rawData.Add((byte)(stride >> 8));
rawData.Add((byte)stride);
}
-
}
@@ -864,7 +945,7 @@ namespace UVtools.Core.FileFormats
/// <summary>
/// Gets a copy of layer data defenition
/// </summary>
- [FieldOrder(0)] public LayerData LayerData { get; set; } = new LayerData();
+ [FieldOrder(0)] public LayerData LayerData { get; set; } = new();
/// <summary>
/// Gets the total size of ctbImageInfo and Image data
@@ -872,14 +953,14 @@ namespace UVtools.Core.FileFormats
[FieldOrder(1)] public uint TotalSize { get; set; }
[FieldOrder(2)] public float LiftHeight { get; set; }
[FieldOrder(3)] public float LiftSpeed { get; set; }
- [FieldOrder(4)] public uint Unknown6 { get; set; }
- [FieldOrder(5)] public uint Unknown7 { get; set; }
+ [FieldOrder(4)] public float LiftHeight2 { get; set; }
+ [FieldOrder(5)] public float LiftSpeed2 { get; set; }
[FieldOrder(6)] public float RetractSpeed { get; set; }
- [FieldOrder(7)] public uint Unknown8 { get; set; }
- [FieldOrder(8)] public uint Unknown9 { get; set; }
- [FieldOrder(9)] public uint Unknown10 { get; set; }
- [FieldOrder(10)] public uint Unknown11 { get; set; }
- [FieldOrder(11)] public uint Unknown12 { get; set; } = 28672; // 28672 v3?
+ [FieldOrder(7)] public float RetractHeight2 { get; set; }
+ [FieldOrder(8)] public float RetractSpeed2 { get; set; }
+ [FieldOrder(9)] public float RestTimeBeforeLift { get; set; }
+ [FieldOrder(10)] public float RestTimeAfterLift { get; set; }
+ [FieldOrder(11)] public float RestTimeAfterRetract { get; set; } // 28672 v3?
[FieldOrder(12)] public float LightPWM { get; set; }
public LayerDataEx()
@@ -905,7 +986,7 @@ namespace UVtools.Core.FileFormats
public override string ToString()
{
- return $"{nameof(LayerData)}: {LayerData}, {nameof(TotalSize)}: {TotalSize}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(Unknown6)}: {Unknown6}, {nameof(Unknown7)}: {Unknown7}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(Unknown8)}: {Unknown8}, {nameof(Unknown9)}: {Unknown9}, {nameof(Unknown10)}: {Unknown10}, {nameof(Unknown11)}: {Unknown11}, {nameof(Unknown12)}: {Unknown12}, {nameof(LightPWM)}: {LightPWM}";
+ return $"{nameof(LayerData)}: {LayerData}, {nameof(TotalSize)}: {TotalSize}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(LiftHeight2)}: {LiftHeight2}, {nameof(LiftSpeed2)}: {LiftSpeed2}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(RetractHeight2)}: {RetractHeight2}, {nameof(RetractSpeed2)}: {RetractSpeed2}, {nameof(RestTimeBeforeLift)}: {RestTimeBeforeLift}, {nameof(RestTimeAfterLift)}: {RestTimeAfterLift}, {nameof(RestTimeAfterRetract)}: {RestTimeAfterRetract}, {nameof(LightPWM)}: {LightPWM}";
}
}
@@ -965,10 +1046,11 @@ namespace UVtools.Core.FileFormats
#region Properties
- public Header HeaderSettings { get; protected internal set; } = new Header();
- public PrintParameters PrintParametersSettings { get; protected internal set; } = new PrintParameters();
+ public Header HeaderSettings { get; protected internal set; } = new();
+ public PrintParameters PrintParametersSettings { get; protected internal set; } = new();
- public SlicerInfo SlicerInfoSettings { get; protected internal set; } = new SlicerInfo();
+ public SlicerInfo SlicerInfoSettings { get; protected internal set; } = new();
+ public PrintParametersV4 PrintParametersV4Settings { get; protected internal set; } = new();
public Preview[] Previews { get; protected internal set; }
@@ -1005,6 +1087,7 @@ namespace UVtools.Core.FileFormats
public override PrintParameterModifier[] PrintParameterPerLayerModifiers {
get
{
+ if (!IsCbtFile) return null; // Only ctb files
if (HeaderSettings.Version >= 3)
{
return new[]
@@ -1018,14 +1101,15 @@ namespace UVtools.Core.FileFormats
};
}
- if (HeaderSettings.Version <= 2)
+ /* Disable for v2 beside the fields on format they are not used
+ if (HeaderSettings.Version <= 2)
{
return new[]
{
PrintParameterModifier.ExposureSeconds,
PrintParameterModifier.LightOffDelay,
};
- }
+ }*/
return null;
}
@@ -1192,7 +1276,7 @@ namespace UVtools.Core.FileFormats
public override float RetractSpeed
{
get => PrintParametersSettings.RetractSpeed;
- set => base.RetractSpeed = PrintParametersSettings.RetractSpeed = (float)Math.Round(value, 2);
+ set => base.RetractSpeed = PrintParametersV4Settings.BottomRetractSpeed = PrintParametersSettings.RetractSpeed = (float)Math.Round(value, 2);
}
public override byte BottomLightPWM
@@ -1249,10 +1333,22 @@ namespace UVtools.Core.FileFormats
}
}
- public override object[] Configs => new[] { (object)HeaderSettings, PrintParametersSettings, SlicerInfoSettings };
+ public override object[] Configs
+ {
+ get
+ {
+ if (HeaderSettings.Version <= 1)
+ return new object[] { HeaderSettings };
+
+ if (HeaderSettings.Version <= 3)
+ return new object[] {HeaderSettings, PrintParametersSettings, SlicerInfoSettings};
+
+ return new object[] { HeaderSettings, PrintParametersSettings, SlicerInfoSettings, PrintParametersV4Settings };
+ }
+ }
public bool IsCbddlpFile => HeaderSettings.Magic == MAGIC_CBDDLP;
- public bool IsCbtFile => HeaderSettings.Magic == MAGIC_CBT;
+ public bool IsCbtFile => HeaderSettings.Magic is MAGIC_CBT or MAGIC_CBTv4;
public bool CanHash => !IsCbtFile && HeaderSettings.Version <= 2;
#endregion
@@ -1281,7 +1377,7 @@ namespace UVtools.Core.FileFormats
{
LayersHash.Clear();
- HeaderSettings.Magic = fileFullPath.EndsWith(".ctb") || fileFullPath.EndsWith($".ctb{TemporaryFileAppend}") ? MAGIC_CBT : MAGIC_CBDDLP;
+ HeaderSettings.Magic = FileEndsWith(".ctb") ? MAGIC_CBT : MAGIC_CBDDLP;
HeaderSettings.PrintParametersSize = (uint)Helpers.Serializer.SizeOf(PrintParametersSettings);
if (IsCbtFile)
@@ -1295,23 +1391,33 @@ namespace UVtools.Core.FileFormats
if (HeaderSettings.Version <= 2)
{
- if (SlicerInfoSettings.Unknown1 == 0)
- SlicerInfoSettings.Unknown1 = 0x200; // 512 for v2 | 0 for v3
+ //if (SlicerInfoSettings.RestTimeAfterRetract == 0)
+ //SlicerInfoSettings.RestTimeAfterRetract = 0x200; // 512 for v2 | 0 for v3
SlicerInfoSettings.EncryptionMode = ENCRYPTYION_MODE_CTBv2;
PrintParametersSettings.Padding4 = 0x1234; // 4660
+
+ if (SlicerInfoSettings.MysteriousId == 0)
+ SlicerInfoSettings.MysteriousId = 305419896;
}
- else
+ else if(HeaderSettings.Version == 3)
{
SlicerInfoSettings.EncryptionMode = ENCRYPTYION_MODE_CTBv3;
+
+ if (SlicerInfoSettings.MysteriousId == 0)
+ SlicerInfoSettings.MysteriousId = 305419896;
+ }
+ else
+ {
+ SlicerInfoSettings.EncryptionMode = ENCRYPTYION_MODE_CTBv4;
+
+ if (SlicerInfoSettings.MysteriousId == 0)
+ SlicerInfoSettings.MysteriousId = 27087820;
}
-
- if(SlicerInfoSettings.MysteriousId == 0)
- SlicerInfoSettings.MysteriousId = 0x12345678;
if (HeaderSettings.EncryptionKey == 0)
{
- Random rnd = new();
+ var rnd = new Random();
HeaderSettings.EncryptionKey = (uint)rnd.Next(byte.MaxValue, int.MaxValue);
}
}
@@ -1374,6 +1480,11 @@ namespace UVtools.Core.FileFormats
currentOffset += Helpers.SerializeWriteFileStream(outputFile, SlicerInfoSettings);
+
+ if (HeaderSettings.Version >= 4)
+ {
+ currentOffset += Helpers.SerializeWriteFileStream(outputFile, PrintParametersV4Settings);
+ }
}
HeaderSettings.LayersDefinitionOffsetAddress = currentOffset;
@@ -1449,6 +1560,7 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine(Previews[1]);
Debug.WriteLine(PrintParametersSettings);
Debug.WriteLine(SlicerInfoSettings);
+ Debug.WriteLine(PrintParametersV4Settings);
Debug.WriteLine("-End-");
}
@@ -1459,9 +1571,14 @@ namespace UVtools.Core.FileFormats
//HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile);
//HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header))));
HeaderSettings = Helpers.Deserialize<Header>(inputFile);
- if (HeaderSettings.Magic != MAGIC_CBDDLP && HeaderSettings.Magic != MAGIC_CBT)
+
+ /*if (HeaderSettings.Magic == MAGIC_CBTv4)
{
- throw new FileLoadException("Not a valid CBDDLP nor CTB nor Photon file!", fileFullPath);
+ throw new FileLoadException("CTB v4 not supported!", fileFullPath);
+ }*/
+ if (HeaderSettings.Magic is not MAGIC_CBDDLP and not MAGIC_CBT and not MAGIC_CBTv4)
+ {
+ throw new FileLoadException($"Not a valid PHOTON nor CBDDLP nor CTB file! Magic Value: {HeaderSettings.Magic}", fileFullPath);
}
if (HeaderSettings.Version == 1 || HeaderSettings.AntiAliasLevel == 0)
@@ -1521,6 +1638,13 @@ namespace UVtools.Core.FileFormats
Debug.WriteLine($"{nameof(MachineName)}: {MachineName}");*/
//}
+ if (HeaderSettings.Version >= 4)
+ {
+ PrintParametersV4Settings = Helpers.Deserialize<PrintParametersV4>(inputFile);
+ Debug.Write("Print Parameters V4 -> ");
+ Debug.WriteLine(PrintParametersV4Settings);
+ }
+
LayerDefinitions = new LayerData[HeaderSettings.AntiAliasLevel, HeaderSettings.LayerCount];
var LayerDefinitionsEx = HeaderSettings.Version >= 3 ? new LayerDataEx[HeaderSettings.LayerCount] : null;
@@ -1652,6 +1776,12 @@ namespace UVtools.Core.FileFormats
Helpers.SerializeWriteFileStream(outputFile, new LayerDataEx(LayerDefinitions[0, layerIndex], layerIndex));
}
}
+
+ if (HeaderSettings.Version >= 4)
+ {
+ outputFile.Seek(SlicerInfoSettings.MachineNameAddress + SlicerInfoSettings.MachineNameSize, SeekOrigin.Begin);
+ Helpers.SerializeWriteFileStream(outputFile, PrintParametersV4Settings);
+ }
}
#endregion
diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs
index c98eef2..a639fae 100644
--- a/UVtools.Core/FileFormats/FileFormat.cs
+++ b/UVtools.Core/FileFormats/FileFormat.cs
@@ -367,12 +367,12 @@ namespace UVtools.Core.FileFormats
public abstract FileExtension[] FileExtensions { get; }
/// <summary>
- /// Gets the available <see cref="FileFormat.PrintParameterModifier"/>
+ /// Gets the available <see cref="PrintParameterModifier"/>
/// </summary>
public virtual PrintParameterModifier[] PrintParameterModifiers => null;
/// <summary>
- /// Gets the available <see cref="FileFormat.PrintParameterModifier"/> per layer
+ /// Gets the available <see cref="PrintParameterModifier"/> per layer
/// </summary>
public virtual PrintParameterModifier[] PrintParameterPerLayerModifiers => null;
@@ -385,12 +385,12 @@ namespace UVtools.Core.FileFormats
PrintParameterModifiers is not null && PrintParameterModifiers.Contains(modifier);
/// <summary>
- /// Checks if a <see cref="PrintParameterModifier"/> exists on print parameters
+ /// Checks if a <see cref="PrintParameterModifier"/> exists on layer parameters
/// </summary>
/// <param name="modifier"></param>
/// <returns>True if exists, otherwise false</returns>
- public bool HavePrintParameterPerLayerModifier(PrintParameterModifier modifier) =>
- PrintParameterPerLayerModifiers is not null && PrintParameterPerLayerModifiers.Contains(modifier);
+ public bool HaveLayerParameterModifier(PrintParameterModifier modifier) =>
+ SupportPerLayerSettings && PrintParameterPerLayerModifiers.Contains(modifier);
/// <summary>
/// Gets the file filter for open and save dialogs
@@ -917,7 +917,7 @@ namespace UVtools.Core.FileFormats
public bool CanUseAnyLiftHeight => CanUseBottomLiftHeight || CanUseLiftHeight;
public bool CanUseBottomLiftSpeed => HavePrintParameterModifier(PrintParameterModifier.BottomLiftSpeed);
- public bool CanUseLiftSpeed => HavePrintParameterModifier(PrintParameterModifier.LiftHeight);
+ public bool CanUseLiftSpeed => HavePrintParameterModifier(PrintParameterModifier.LiftSpeed);
public bool CanUseAnyLiftSpeed => CanUseBottomLiftSpeed || CanUseLiftSpeed;
public bool CanUseRetractSpeed => HavePrintParameterModifier(PrintParameterModifier.RetractSpeed);
@@ -930,6 +930,13 @@ namespace UVtools.Core.FileFormats
public bool CanUseLightPWM => HavePrintParameterModifier(PrintParameterModifier.LightPWM);
public bool CanUseAnyLightPWM => CanUseBottomLightPWM || CanUseLightPWM;
+ public bool CanUseLayerExposureTime => HaveLayerParameterModifier(PrintParameterModifier.ExposureSeconds);
+ public bool CanUseLayerLiftHeight => HaveLayerParameterModifier(PrintParameterModifier.LiftHeight);
+ public bool CanUseLayerLiftSpeed => HaveLayerParameterModifier(PrintParameterModifier.LiftSpeed);
+ public bool CanUseLayerRetractSpeed => HaveLayerParameterModifier(PrintParameterModifier.RetractSpeed);
+ public bool CanUseLayerLightOffDelay => HaveLayerParameterModifier(PrintParameterModifier.LightOffDelay);
+ public bool CanUseLayerLightPWM => HaveLayerParameterModifier(PrintParameterModifier.LightPWM);
+
public string ExposureRepresentation
{
get
@@ -1368,6 +1375,13 @@ namespace UVtools.Core.FileFormats
return result;
}
+ public bool FileEndsWith(string extension)
+ {
+ if (extension[0] != '.') extension = $".{extension}";
+ return FileFullPath.EndsWith(extension, StringComparison.OrdinalIgnoreCase) ||
+ FileFullPath.EndsWith($"{extension}{TemporaryFileAppend}", StringComparison.OrdinalIgnoreCase);
+ }
+
/// <summary>
/// Gets a thumbnail by it height or lower
/// </summary>
@@ -1617,15 +1631,15 @@ namespace UVtools.Core.FileFormats
tw.WriteLine($"{nameof(layer.PositionZ)}: {layer.PositionZ}");
tw.WriteLine($"{nameof(layer.ExposureTime)}: {layer.ExposureTime}");
- if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LightOffDelay))
+ if (HaveLayerParameterModifier(PrintParameterModifier.LightOffDelay))
tw.WriteLine($"{nameof(layer.LightOffDelay)}: {layer.LightOffDelay}");
- if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LiftHeight))
+ if (HaveLayerParameterModifier(PrintParameterModifier.LiftHeight))
tw.WriteLine($"{nameof(layer.LiftHeight)}: {layer.LiftHeight}");
- if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LiftSpeed))
+ if (HaveLayerParameterModifier(PrintParameterModifier.LiftSpeed))
tw.WriteLine($"{nameof(layer.LiftSpeed)}: {layer.LiftSpeed}");
- if (HavePrintParameterPerLayerModifier(PrintParameterModifier.RetractSpeed))
+ if (HaveLayerParameterModifier(PrintParameterModifier.RetractSpeed))
tw.WriteLine($"{nameof(layer.RetractSpeed)}: {layer.RetractSpeed}");
- if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LightPWM))
+ if (HaveLayerParameterModifier(PrintParameterModifier.LightPWM))
tw.WriteLine($"{nameof(layer.LightPWM)}: {layer.LightPWM}");
var materialMillilitersPercent = layer.MaterialMillilitersPercent;
diff --git a/UVtools.Core/FileFormats/LGSFile.cs b/UVtools.Core/FileFormats/LGSFile.cs
index 9e88da8..ecffe6e 100644
--- a/UVtools.Core/FileFormats/LGSFile.cs
+++ b/UVtools.Core/FileFormats/LGSFile.cs
@@ -6,6 +6,7 @@
* of this license document, but changing it is not allowed.
*/
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
@@ -28,17 +29,16 @@ namespace UVtools.Core.FileFormats
public class Header
{
public const string NameValue = "Longer3D";
- //[FieldOrder(0)] public uint Offset1 { get; set; }
-
+
/// <summary>
/// Gets the model name
/// </summary>
[FieldOrder(0)] [FieldLength(8)] public string Name { get; set; } = NameValue; // 0x00:
- [FieldOrder(1)] public uint Uint_08 { get; set; } = 4278190081; // 0x08: 0xff000001 ?
+ [FieldOrder(1)] public uint Uint_08 { get; set; } = 1; // 0x08: 0xff000001 ?
[FieldOrder(2)] public uint Uint_0c { get; set; } = 1; // 0x0c: 1 ?
- [FieldOrder(3)] public uint Uint_10 { get; set; } = 30; // 0x10: 30 ?
+ [FieldOrder(3)] public uint PrinterModel { get; set; } = 30; // 10, 30, 120, 4000 (4k), 4500 (4k mono)
[FieldOrder(4)] public uint Uint_14 { get; set; } = 0; // 0x14: 0 ?
- [FieldOrder(5)] public uint Uint_18 { get; set; } = 34; // 0x18: 34 ?
+ [FieldOrder(5)] public uint MagicKey { get; set; } = 34; // 0x18: 34
[FieldOrder(6)] public float PixelPerMmX { get; set; } = 15.404f;
[FieldOrder(7)] public float PixelPerMmY { get; set; } = 4.866f;
[FieldOrder(8)] public float ResolutionX { get; set; }
@@ -69,7 +69,7 @@ namespace UVtools.Core.FileFormats
[FieldOrder(33)] public float Float_88 { get; set; } = 6; // 0x88: 6?
[FieldOrder(34)] public float Float_8c { get; set; } = 150; // 0x8c: 150 ?
[FieldOrder(35)] public float Float_90 { get; set; } = 1001; // 0x90: 1001 ?
- [FieldOrder(36)] public float Float_94 { get; set; } = 140;// 0x94: 140 for lgs10, 170 for lgs30, 190 for lgs4k
+ [FieldOrder(36)] public float MachineZ { get; set; } = 140;// 0x94: 140 for lgs10, 170 for lgs30, 150 for lgs120, 190 for lgs4k
[FieldOrder(37)] public uint Uint_98 { get; set; } // 0x98: 0 ?
[FieldOrder(38)] public uint Uint_9c { get; set; } // 0x9c: 0 ?
[FieldOrder(39)] public uint Uint_a0 { get; set; } // 0xa0: 0 ?
@@ -81,6 +81,45 @@ namespace UVtools.Core.FileFormats
#endregion
+ #region LGS120PngPreview
+
+ public class LGS120PngPreview
+ {
+ public const ushort ResolutionX = 1200;
+ public const ushort ResolutionY = 1600;
+
+ [FieldOrder(0)] public uint DataSize { get; set; }
+
+ [FieldOrder(1)]
+ [FieldLength(nameof(DataSize))]
+ public byte[] EncodedRle { get; set; }
+
+ public void Encode(Mat mat)
+ {
+ if (mat.Width != ResolutionX || mat.Height != ResolutionY)
+ {
+ using var resizeMat = new Mat();
+ CvInvoke.Resize(mat, resizeMat, new Size(ResolutionX, ResolutionY));
+ EncodedRle = resizeMat.GetPngByes();
+ }
+ else
+ {
+ EncodedRle = mat.GetPngByes();
+ }
+ }
+
+ public Mat Decode(bool consumeRle = true)
+ {
+ var mat = new Mat();
+ CvInvoke.Imdecode(EncodedRle, ImreadModes.AnyColor, mat);
+ if (consumeRle)
+ EncodedRle = null;
+ return mat;
+ }
+ }
+
+ #endregion
+
#region LayerData
public class LayerData
@@ -200,12 +239,14 @@ namespace UVtools.Core.FileFormats
#region Properties
- public Header HeaderSettings { get; protected internal set; } = new Header();
+ public Header HeaderSettings { get; protected internal set; } = new();
public override FileFormatType FileType => FileFormatType.Binary;
public override FileExtension[] FileExtensions { get; } = {
new ("lgs", "Longer Orange 10"),
new ("lgs30", "Longer Orange 30"),
+ //new ("lgs120", "Longer Orange 120"),
+ //new ("lgs4k", "Longer Orange 4k"),
};
public override PrintParameterModifier[] PrintParameterModifiers { get; } =
@@ -276,6 +317,12 @@ namespace UVtools.Core.FileFormats
set { }
}
+ public override float MachineZ
+ {
+ get => HeaderSettings.MachineZ > 0 ? HeaderSettings.MachineZ : base.MachineZ;
+ set => base.MachineZ = HeaderSettings.MachineZ = (float)Math.Round(value, 2);
+ }
+
public override bool MirrorDisplay
{
get => true;
@@ -389,6 +436,7 @@ namespace UVtools.Core.FileFormats
public override string MaterialName => "Unknown";
public override string MachineName => null;*/
+
public override object[] Configs => new object[] { HeaderSettings };
#endregion
@@ -450,18 +498,34 @@ namespace UVtools.Core.FileFormats
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
{
- if (ResolutionY >= 2560) // Longer Orange 30
+ if (FileEndsWith(".lgs")) // Longer Orange 10
{
- HeaderSettings.Float_94 = 170;
+ MachineZ = 140;
+ HeaderSettings.PrinterModel = 10;
}
-
+ else if (FileEndsWith(".lgs30")) // Longer Orange 30
+ {
+ MachineZ = 170;
+ HeaderSettings.PrinterModel = 30;
+ }
+ else if (FileEndsWith(".lgs120")) // Longer Orange 120
+ {
+ MachineZ = 150;
+ HeaderSettings.PrinterModel = 120;
+ }
+ else if (FileEndsWith(".lgs4k")) // Longer Orange 4K & Mono
+ {
+ MachineZ = 190;
+ if(HeaderSettings.PrinterModel is not 4000 and not 4500) HeaderSettings.PrinterModel = 4500;
+ }
+
//uint currentOffset = (uint)Helpers.Serializer.SizeOf(HeaderSettings);
using (var outputFile = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write))
{
outputFile.WriteSerialize(HeaderSettings);
outputFile.WriteBytes(PreviewEncode(Thumbnails[0]));
- LayerData[] layerData = new LayerData[LayerCount];
+ var layerData = new LayerData[LayerCount];
Parallel.For(0, LayerCount, layerIndex =>
{
@@ -493,47 +557,51 @@ namespace UVtools.Core.FileFormats
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
{
- using (var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
+ using var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read);
+ HeaderSettings = Helpers.Deserialize<Header>(inputFile);
+ if (HeaderSettings.Name != Header.NameValue)
{
- HeaderSettings = Helpers.Deserialize<Header>(inputFile);
- if (HeaderSettings.Name != Header.NameValue)
- {
- throw new FileLoadException("Not a valid LGS file!", fileFullPath);
- }
+ throw new FileLoadException("Not a valid LGS file!", fileFullPath);
+ }
- // Fix inconsistencies found of different version of plugin and slicers
- if (ResolutionX > ResolutionY)
- {
- var oldX = ResolutionX;
- ResolutionX = ResolutionY;
- ResolutionY = oldX;
- }
+ // Fix inconsistencies found of different version of plugin and slicers
+ if (ResolutionX > ResolutionY)
+ {
+ var oldX = ResolutionX;
+ ResolutionX = ResolutionY;
+ ResolutionY = oldX;
+ }
- int previewSize = (int) (HeaderSettings.PreviewSizeX * HeaderSettings.PreviewSizeY * 2);
- byte[] previewData = new byte[previewSize];
+ int previewSize = (int) (HeaderSettings.PreviewSizeX * HeaderSettings.PreviewSizeY * 2);
+ byte[] previewData = new byte[previewSize];
- uint currentOffset = (uint) Helpers.Serializer.SizeOf(HeaderSettings);
- currentOffset += inputFile.ReadBytes(previewData);
- Thumbnails[0] = PreviewDecode(previewData);
+ uint currentOffset = (uint) Helpers.Serializer.SizeOf(HeaderSettings);
+ currentOffset += inputFile.ReadBytes(previewData);
+ Thumbnails[0] = PreviewDecode(previewData);
+
+ if (FileEndsWith(".lgs120"))
+ {
+ var pngPreview = Helpers.Deserialize<LGS120PngPreview>(inputFile);
+ }
- LayerData[] layerData = new LayerData[HeaderSettings.LayerCount];
- progress.Reset(OperationProgress.StatusGatherLayers, HeaderSettings.LayerCount);
+ LayerData[] layerData = new LayerData[HeaderSettings.LayerCount];
+ progress.Reset(OperationProgress.StatusGatherLayers, HeaderSettings.LayerCount);
- for (int layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++)
- {
- progress.Token.ThrowIfCancellationRequested();
- layerData[layerIndex] = Helpers.Deserialize<LayerData>(inputFile);
- layerData[layerIndex].Parent = this;
- }
+ for (int layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++)
+ {
+ progress.Token.ThrowIfCancellationRequested();
+ layerData[layerIndex] = Helpers.Deserialize<LayerData>(inputFile);
+ layerData[layerIndex].Parent = this;
+ }
- LayerManager.Init(HeaderSettings.LayerCount);
- progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
+ LayerManager.Init(HeaderSettings.LayerCount);
+ progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
- Parallel.For(0, LayerCount,
- //new ParallelOptions{MaxDegreeOfParallelism = 1},
- layerIndex =>
+ Parallel.For(0, LayerCount,
+ //new ParallelOptions{MaxDegreeOfParallelism = 1},
+ layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
@@ -543,8 +611,7 @@ namespace UVtools.Core.FileFormats
progress.LockAndIncrement();
});
- LayerManager.RebuildLayersProperties();
- }
+ LayerManager.RebuildLayersProperties();
}
public override void SaveAs(string filePath = null, OperationProgress progress = null)
diff --git a/UVtools.Core/FileFormats/PHZFile.cs b/UVtools.Core/FileFormats/PHZFile.cs
index 92cac2b..59c9eb7 100644
--- a/UVtools.Core/FileFormats/PHZFile.cs
+++ b/UVtools.Core/FileFormats/PHZFile.cs
@@ -710,10 +710,10 @@ namespace UVtools.Core.FileFormats
PrintParameterModifier.LightPWM,
};
- public override PrintParameterModifier[] PrintParameterPerLayerModifiers { get; } = {
+ /*public override PrintParameterModifier[] PrintParameterPerLayerModifiers { get; } = {
PrintParameterModifier.ExposureSeconds,
PrintParameterModifier.LightOffDelay,
- };
+ };*/
public override Size[] ThumbnailsOriginalSize { get; } =
{
diff --git a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs
index f4a7220..4003f8a 100644
--- a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs
+++ b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs
@@ -1187,7 +1187,7 @@ namespace UVtools.Core.FileFormats
public override object[] Configs => new object[] { FileMarkSettings, HeaderSettings, PreviewSettings, LayersDefinition };
public LayerRleFormat LayerFormat =>
- FileFullPath.EndsWith(".pws") || FileFullPath.EndsWith($".pws{TemporaryFileAppend}")
+ FileEndsWith(".pws")
? LayerRleFormat.PWS
: LayerRleFormat.PW0;
@@ -1195,32 +1195,32 @@ namespace UVtools.Core.FileFormats
{
get
{
- if (FileFullPath.EndsWith(".pws") || FileFullPath.EndsWith($".pws{TemporaryFileAppend}"))
+ if (FileEndsWith(".pws"))
{
return AnyCubicMachine.AnyCubicPhotonS;
}
- if (FileFullPath.EndsWith(".pw0") || FileFullPath.EndsWith($".pw0{TemporaryFileAppend}"))
+ if (FileEndsWith(".pw0"))
{
return AnyCubicMachine.AnyCubicPhotonZero;
}
- if (FileFullPath.EndsWith(".pwx") || FileFullPath.EndsWith($".pwx{TemporaryFileAppend}"))
+ if (FileEndsWith(".pwx"))
{
return AnyCubicMachine.AnyCubicPhotonX;
}
- if (FileFullPath.EndsWith(".pwmo") || FileFullPath.EndsWith($".pwmo{TemporaryFileAppend}"))
+ if (FileEndsWith(".pwmo"))
{
return AnyCubicMachine.AnyCubicPhotonMono;
}
- if (FileFullPath.EndsWith(".pwms") || FileFullPath.EndsWith($".pwms{TemporaryFileAppend}"))
+ if (FileEndsWith(".pwms"))
{
return AnyCubicMachine.AnyCubicPhotonMonoSE;
}
- if (FileFullPath.EndsWith(".pwmx") || FileFullPath.EndsWith($".pwmx{TemporaryFileAppend}"))
+ if (FileEndsWith(".pwmx"))
{
return AnyCubicMachine.AnyCubicPhotonMonoX;
}
diff --git a/UVtools.Core/FileFormats/SL1File.cs b/UVtools.Core/FileFormats/SL1File.cs
index 97e34eb..fca0818 100644
--- a/UVtools.Core/FileFormats/SL1File.cs
+++ b/UVtools.Core/FileFormats/SL1File.cs
@@ -264,6 +264,7 @@ namespace UVtools.Core.FileFormats
var now = DateTime.Now;
return $"{now.Year}-{now.Month:D2}-{now.Day:D2} at {now.Hour:D2}:{now.Minute:D2}:{now.Second:D2} {now.Kind}";
}
+ set{}
}
public float LayerHeight { get; set; }
public string MaterialName { get; set; } = About.Software;
@@ -303,7 +304,8 @@ namespace UVtools.Core.FileFormats
public override FileFormatType FileType => FileFormatType.Archive;
public override FileExtension[] FileExtensions { get; } = {
- new("sl1", "PrusaSlicer SL1")
+ new("sl1", "PrusaSlicer SL1"),
+ new("sl1s", "PrusaSlicer SL1S Speed")
};
public override PrintParameterModifier[] PrintParameterModifiers { get; } = {
PrintParameterModifier.BottomLayerCount,
diff --git a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs
index bdcc7ec..2da010f 100644
--- a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs
+++ b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs
@@ -980,7 +980,7 @@ namespace UVtools.Core.Operations
if (_multipleBrightnessGenExposureTime == 0)
_multipleBrightnessGenExposureTime = (decimal)SlicerFile.ExposureTime;
- if (!SlicerFile.HavePrintParameterPerLayerModifier(FileFormat.PrintParameterModifier.ExposureSeconds))
+ if (!SlicerFile.HaveLayerParameterModifier(FileFormat.PrintParameterModifier.ExposureSeconds))
{
_multipleLayerHeight = false;
_multipleExposures = false;
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index 1b7ca18..1e4bc6c 100644
--- a/UVtools.Core/UVtools.Core.csproj
+++ b/UVtools.Core/UVtools.Core.csproj
@@ -10,7 +10,7 @@
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
- <Version>2.13.4</Version>
+ <Version>2.14.0</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
diff --git a/UVtools.InstallerMM/UVtools.InstallerMM.wxs b/UVtools.InstallerMM/UVtools.InstallerMM.wxs
index dd0a02c..4e2602a 100644
--- a/UVtools.InstallerMM/UVtools.InstallerMM.wxs
+++ b/UVtools.InstallerMM/UVtools.InstallerMM.wxs
@@ -960,11 +960,14 @@
<Component Id="owc7B488E0A9D9B2656D06620E0CEEFDA13" Guid="7c2fe9e4-adb9-72d1-c0f4-ee7311cabadf">
<File Id="owf7B488E0A9D9B2656D06620E0CEEFDA13" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\Longer Orange 10.ini" KeyPath="yes" />
</Component>
+ <Component Id="owc81404C7F01EDBA07B087B424DAA40376" Guid="aaee9d27-478d-5d85-c09b-e2b2c8f61633">
+ <File Id="owf81404C7F01EDBA07B087B424DAA40376" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\Longer Orange 120.ini" KeyPath="yes" />
+ </Component>
<Component Id="owc227006E17D85BD8103B64C6480AF8A6F" Guid="33dff0a8-a2a6-7ad5-51b1-a91bc258b227">
<File Id="owf227006E17D85BD8103B64C6480AF8A6F" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\Longer Orange 30.ini" KeyPath="yes" />
</Component>
- <Component Id="owcCF42E79995933F0457692A2F239FCBB5" Guid="fa18ff15-0e8a-1624-2359-2a9fc30791f0">
- <File Id="owfCF42E79995933F0457692A2F239FCBB5" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\Longer Orange4K.ini" KeyPath="yes" />
+ <Component Id="owc6FE42BDB3CE927703AA1E9971366D810" Guid="b3fd97c9-d3b8-b5db-942f-f7ab9d2195e5">
+ <File Id="owf6FE42BDB3CE927703AA1E9971366D810" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\Longer Orange 4K.ini" KeyPath="yes" />
</Component>
<Component Id="owc60E90B40E8992C21339B84C28DFE9891" Guid="e8e24d92-2cb1-0bec-3963-817532a4c171">
<File Id="owf60E90B40E8992C21339B84C28DFE9891" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\Nova3D Bene4 Mono.ini" KeyPath="yes" />
@@ -1038,6 +1041,9 @@
<Component Id="owcD0FD9259BE924EB58AE9F7A85AE0A9E8" Guid="360b089c-8765-92db-0c8f-367d80202d8f">
<File Id="owfD0FD9259BE924EB58AE9F7A85AE0A9E8" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\UVtools Prusa SL1.ini" KeyPath="yes" />
</Component>
+ <Component Id="owc92527EBFC9C5B568C8D66A882C08D0B5" Guid="dcca948b-ff91-af94-7363-d77b50dde1a5">
+ <File Id="owf92527EBFC9C5B568C8D66A882C08D0B5" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\UVtools Prusa SL1S SPEED.ini" KeyPath="yes" />
+ </Component>
<Component Id="owc2D767EDC65A9490BE5587F5807220F67" Guid="1b34ea21-cadd-c887-3f4e-8655903ef11a">
<File Id="owf2D767EDC65A9490BE5587F5807220F67" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\Voxelab Ceres 8.9.ini" KeyPath="yes" />
</Component>
diff --git a/UVtools.WPF/Assets/Icons/heart-16x16.png b/UVtools.WPF/Assets/Icons/heart-16x16.png
new file mode 100644
index 0000000..ba3658d
--- /dev/null
+++ b/UVtools.WPF/Assets/Icons/heart-16x16.png
Binary files differ
diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml
index 612f590..0a95292 100644
--- a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml
+++ b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml
@@ -811,7 +811,8 @@
Content="Enable - For advanced users only!"
IsChecked="{Binding Operation.MultipleExposures}"/>
- <StackPanel Orientation="Horizontal" Spacing="20">
+ <StackPanel Orientation="Horizontal" Spacing="20"
+ IsVisible="{Binding SlicerFile.CanUseLayerLiftHeight}">
<CheckBox
ToolTip.Tip="The lift height will be set to 0 for sequential layers that share same z position, saving moves and time.
diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs
index 52aaf61..8b331d7 100644
--- a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs
+++ b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs
@@ -31,7 +31,7 @@ namespace UVtools.WPF.Controls.Calibrators
set => RaiseAndSetIfChanged(ref _previewImage, value);
}
- public bool CanSupportPerLayerSettings => SlicerFile.HavePrintParameterPerLayerModifier(FileFormat.PrintParameterModifier.ExposureSeconds);
+ public bool CanSupportPerLayerSettings => SlicerFile.HaveLayerParameterModifier(FileFormat.PrintParameterModifier.ExposureSeconds);
public CalibrateExposureFinderControl()
{
diff --git a/UVtools.WPF/Controls/Tools/ToolDynamicLayerHeightControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolDynamicLayerHeightControl.axaml.cs
index 10398aa..040ef78 100644
--- a/UVtools.WPF/Controls/Tools/ToolDynamicLayerHeightControl.axaml.cs
+++ b/UVtools.WPF/Controls/Tools/ToolDynamicLayerHeightControl.axaml.cs
@@ -44,7 +44,7 @@ namespace UVtools.WPF.Controls.Tools
return;
}
- if (!SlicerFile.HavePrintParameterPerLayerModifier(FileFormat.PrintParameterModifier.ExposureSeconds))
+ if (!SlicerFile.HaveLayerParameterModifier(FileFormat.PrintParameterModifier.ExposureSeconds))
{
App.MainWindow.MessageBoxWaring($"Your printer seems to not support this tool, still you are allowed to run it for analyze, packing layers or simulation.\n" +
$"Do not print this file after run this tool on a not compatible printer, it will result in malformed model and height violation.\n" +
diff --git a/UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml.cs
index ef0e742..3e6b548 100644
--- a/UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml.cs
+++ b/UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml.cs
@@ -14,8 +14,8 @@ namespace UVtools.WPF.Controls.Tools
{
InitializeComponent();
BaseOperation = new OperationDynamicLifts(SlicerFile);
- if (!SlicerFile.HavePrintParameterPerLayerModifier(FileFormat.PrintParameterModifier.LiftHeight) ||
- !SlicerFile.HavePrintParameterPerLayerModifier(FileFormat.PrintParameterModifier.LiftSpeed))
+ if (!SlicerFile.HaveLayerParameterModifier(FileFormat.PrintParameterModifier.LiftHeight) ||
+ !SlicerFile.HaveLayerParameterModifier(FileFormat.PrintParameterModifier.LiftSpeed))
{
App.MainWindow.MessageBoxInfo("Your printer/format does not support this tool.", "Dynamic lifts - Printer not supported");
CanRun = false;
diff --git a/UVtools.WPF/MainWindow.axaml b/UVtools.WPF/MainWindow.axaml
index 478ecd4..9e0efbc 100644
--- a/UVtools.WPF/MainWindow.axaml
+++ b/UVtools.WPF/MainWindow.axaml
@@ -191,13 +191,21 @@
<MenuItem
Header="_Donate"
- InputGesture="Ctrl + Shift + F1" HotKey="Ctrl + Shift + F1"
Command="{Binding OpenDonateWebsite}">
<MenuItem.Icon>
<Image Source="\Assets\Icons\donate-16x16.png"/>
</MenuItem.Icon>
</MenuItem>
+ <MenuItem
+ Header="_Sponsor"
+ Command="{Binding OpenWebsite}"
+ CommandParameter="https://github.com/sponsors/sn4k3">
+ <MenuItem.Icon>
+ <Image Source="\Assets\Icons\heart-16x16.png"/>
+ </MenuItem.Icon>
+ </MenuItem>
+
<Separator/>
<MenuItem
diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj
index 8af7821..cc83180 100644
--- a/UVtools.WPF/UVtools.WPF.csproj
+++ b/UVtools.WPF/UVtools.WPF.csproj
@@ -12,7 +12,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
- <Version>2.13.4</Version>
+ <Version>2.14.0</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">